.NET Winforms 按钮 KeyDown 用于箭头键

use*_*111 1 .net vb.net winforms

当按钮处于活动控制状态时,我需要根据箭头按下来调节程序流程。像这样:

Private Sub btn_OK_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles btn_OK.KeyDown

    If e.KeyCode = Keys.Up Then
        If mode = mymodes.first Then
            firstcontrol.Focus()
        Else
            secondcontrol.Focus()
        End If
    End If
End Sub
Run Code Online (Sandbox Code Playgroud)

正如我所看到的,按下任何箭头键根本不会触发 KeyDown 事件。相反,程序会执行一些内部功能,并通过使用表单的 Tab 键顺序(看起来是这样)来移动焦点。KeyPreview 在实际表单中设置为 true。

这里有什么方法可以使用箭头键获得所需的功能,而不需要子类化按钮并使用 ProcessCmdKey 吗?

Mar*_*ans 5

好吧,我做了一些研究,有效地,在处理之前捕获了箭头键的 key_down 事件......

这是它开始的来源: http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Control.cs,7765d3efe64d5539

怎么运行的

当按下某个键时,以下是控件内部发生的情况的列表:

该函数PreProcessControlMessageInternal被调用。

此函数将引发控件上的 PreviewKeyDown 事件。然后它会调用PreProcessMessage.

该函数PreProcessMessage被调用。

该函数实际上检查是否有人想要使用已按下的键。在我们的例子中,(WM_KEYDOWN):

  • 控件首先调用ProcessCmdKey:如果有人想确定这是一个命令键,请返回 True 并使用该键。其他人不会看到该键已被按下

  • 然后 Control 调用IsInputKey():如果有人确定这是一个输入键(例如 TextBoxes),则返回 True 并处理您的键。

  • 然后它调用ProcessDialogKey():[来自参考源的字面意思]

调用以检查对话框键,例如 TAB、箭头键和助记符

该怎么办

就您而言,您有三种可能性,最后一种是最好的(也是最简单的):

ProcessDialogKey()收到消息后处理:

Protected Overrides Function ProcessDialogKey(keyData As Keys) As Boolean
    If keyData = Keys.Up Or keyData = Keys.Down Or keyData = Keys.Left Or keyData = Keys.Right Then
        'Do whatever you want with the key
        Return True 'So the processing will stop
    End If
    Return MyBase.ProcessDialogKey(keyData)
End Function
Run Code Online (Sandbox Code Playgroud)

防止处理此密钥,以便您可以在Button_keyDown()

Protected Overrides Function ProcessDialogKey(keyData As Keys) As Boolean
    If keyData = Keys.Up Or keyData = Keys.Down Or keyData = Keys.Left Or keyData = Keys.Right Then
        Return False
    End If
    Return MyBase.ProcessDialogKey(keyData)
End Function


Private Sub btn_OK_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles btn_OK.KeyDown

    If e.KeyCode = Keys.Up Then
        If mode = mymodes.first Then
            firstcontrol.Focus()
        Else
            secondcontrol.Focus()
        End If
    End If
End Sub
Run Code Online (Sandbox Code Playgroud)

最好的办法

所以实际上(根据 Zohar Peled 的评论),最好的方法是处理 PreviewKeyDown 事件,因此您不必重写任何其他方法:

Private Sub Form1_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles MyBase.PreviewKeyDown
    'Do whatever here, all the keydown events will fall into this sub.
End Sub
Run Code Online (Sandbox Code Playgroud)