0

代码:

Private Sub KeyHandling(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
    Select Case e.KeyCode
      Case Keys.Left
        btnPrev.PerformClick()
      Case Keys.Right
        btnNext.PerformClick()
      Case Keys.Up
        btnFirst.PerformClick()
      Case Keys.Down
        btnLast.PerformClick()
    End Select
End Sub

我的表单的 KeyPreview 属性已启用。

问题:

这段代码不会做任何事情,除非我按住控制键。谁能解释一下?:)

4

4 回答 4

0

我假设您的表单上有按钮。当按钮具有焦点时,用户可以通过使用表单上按钮之间的箭头按钮导航来更改焦点。这就是为什么在按下箭头键时按钮不会收到 KeyDown 事件的原因。

以下技巧将帮助您避免这种情况。对于表单上的每个按钮,将 PreviewKeyDown 事件设置为以下内容:

Private Sub Button1_PreviewKeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles Button1.PreviewKeyDown
        e.IsInputKey = True
End Sub
于 2011-01-08T14:53:33.963 回答
0

发生的事情是箭头键正在导航表单上的控件,就像Tab键一样。每次按下箭头键都会将焦点从当前活动控件移动到与该箭头键相同的相对方向的下一个控件。

KeyDown这种对箭头键的解释是在比您正在处理的表单事件更高的级别上实现的。每个按键实际上都被ProcessDialogKeyfunction消耗,这会阻止该按键事件被传递给您的KeyHandling方法以进行任何进一步的处理。

按下键时一切都按预期工作的原因Ctrl是该ProcessDialogKey函数不使用这些事件,从而允许将它们传递给您的事件处理程序方法。该方法的文档告诉我们:

该方法不对包含 ALT 或 CONTROL 修饰符的击键执行任何处理。


如果您不希望箭头键在控件之间导航而只是“单击”恰当命名的按钮,那么解决方案应该很明显:您需要覆盖该ProcessDialogKey方法,添加您的自定义键处理逻辑,并返回一个值“True”表示您自己处理了密钥。否则,您将继续调用基类,以免破坏对 和 之类的标准Tab处理Enter。同样,这里的文档非常清晰:

当重写ProcessDialogKey派生类中的方法时,控件应返回 true 以指示它已处理键。ProcessDialogChar对于控件未处理的键,应返回调用基类方法的结果。

只需将以下代码添加到您的表单中,然后删除KeyHandling您现在拥有的方法:

Protected Overrides Function ProcessDialogKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
    Select Case keyData
        Case Keys.Left
            btnPrev.PerformClick()
            Return True
        Case Keys.Right
            btnNext.PerformClick()
            Return True
        Case Keys.Up
            btnFirst.PerformClick()
            Return True
        Case Keys.Down
            btnLast.PerformClick()
            Return True
    End Select

    Return MyBase.ProcessDialogKey(keyData)
End Function
于 2011-01-08T14:53:35.100 回答
0

您需要提供更多信息。

对于初学者,您正在处理哪个表单事件。您显示一个具有非标准处理程序名称的处理程序,但您没有显示它与哪个事件相关联。您如何将其与事件相关联?

在表单设计器中,查看“属性”窗口中的事件选项卡。您在 KeyDown 或 KeyPress 下有任何内容吗?这就是它需要的地方。

其次,它没有做任何事情是因为你没有将它连接起来形成键盘事件,还是因为它运行但没有做你想做的事情?设置断点。代码是否被调用过?

根据上述问题的答案,您可能需要在处理 KeyDown 或 KeyPress 事件之间切换,具体取决于您要检测的字符。

于 2011-01-08T14:53:49.410 回答
0

这是因为光标键在 KeyDown 事件触发之前被提前拦截。Winforms 使用它来移动焦点,就像 Tab 一样。当您按住 Ctrl 键时,它不再是导航键,您的 KeyDown 事件可以看到它。

您通常会通过覆盖 IsInputKey() 来解决这个问题,但如果表单有任何控件,这将不起作用。如果您将 KeyPreview 设置为 true,他们可能会这样做。表单永远不会获得焦点,控件会。您需要放弃 KeyPreview,无论如何它都是旧的 VB6 时代错误,您可以通过覆盖 ProcessCmdKey() 来捕获光标键。像这样:

Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
    If keyData = Keys.Left Then
        Console.WriteLine("left")
        Return True
    End If
    Return MyBase.ProcessCmdKey(msg, keyData)
End Function
于 2011-01-08T14:55:43.980 回答