的KeyEvents只能结合CTRL

问题描述:

代码:的KeyEvents只能结合CTRL

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属性已启用。

问题:

此代码不会做任何事情,除非我按住Ctrl键。任何人都可以解释吗? :)

这是因为在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 

我假设你有你的窗体上的按钮。当按钮具有焦点时,用户可以通过使用表单上的按钮之间的箭头按钮进行导航来更改焦点。这就是当按下箭头键时按钮没有收到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 
+0

这可能会起作用,但如果可能的话,您应该在容器控制的更高级别上处理此问题。它使得代码更加优雅和可维护。 – 2011-01-08 15:02:29

发生了什么事是,箭头键导航控件的形式,很像标签关键。每按一次方向键,焦点就从当前激活的控制移动到与箭头键相同的相对方向的下一个控制。

箭头键的这种解释在比您要处理的表单的KeyDown事件更高的级别上执行。每个按键实际上都被ProcessDialogKey function消耗,这防止了该关键事件被传递到您的KeyHandling方法以用于任何进一步处理。

,当你想到当按Ctrl键被按下一切工作的原因是ProcessDialogKey功能不消耗这些事件,允许它们被传递到您的事件处理程序方法。方法的documentation告诉我们:

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


如果你不想箭头键你的控件之间只有“点击”恰如其命名按钮导航,解决方案应该是显而易见的:你需要重写ProcessDialogKey方法,添加自定义密钥处理逻辑,并返回“True”值以表示您自己处理密钥。否则,您将继续前往基类,以免中断标准处理如标签输入。同样,documentation令人耳目一新这里清楚:

当重写在派生类中的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 
+0

很好的解释!非常感谢你 – Jeroen 2011-01-08 15:01:22

您需要提供更多的信息。

对于初学者来说,您需要处理哪些形式的事件。您显示具有非标准处理程序名称的处理程序,但不显示它与哪个事件关联。你如何将它与事件联系起来?

在窗体设计器中,查看属性窗口中的事件选项卡。 KeyDown或KeyPress下有什么?这就是它需要的地方。

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

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

+0

你必须滚动才能看到它,但方法声明的最后一行告诉你它处理的是什么事件:`处理Me.KeyDown`。它已经适用于该方法。你必须检查标签 - 这不是C#。 – 2011-01-08 14:59:49