关键事件:进程CmdKey

本文关键字:进程 CmdKey 事件 | 更新日期: 2023-09-27 18:33:15

我正在尝试在一个小测试Windows表单应用程序上获得一些键盘响应,我有一个粗略的解决方案,即覆盖ProcessCmdKey。但是,我遇到了几个问题,并且我发现了不一致之处。

不同的事件:有没有办法在参数ref Message msg, Keys keyData中判断偶数是 KeyDown、KeyUp 还是 KeyPress?

按键

我看过的任何地方都说按键,即重复的键盘输入,只发生在字符键上,而箭头键不是。但是,对于箭头键和字符键,事件处理程序被频繁地调用,并且在同一人/具有相同的行为中。这是面对KeyPress事件,还是别的什么?

理想情况下,我希望有一种在窗体级别处理所有键盘事件的方法,而无需将它们传递给窗体上的控件。但是,所有文档都使我感到困惑,并且错过了关键点,因此我无法完成此操作。

感谢有关任何这些主题的帮助。谢谢!

关键事件:进程CmdKey

重写窗体中的 ProcessCmdKey 明确旨在允许您实现按钮和菜单项中的内置助记符处理之外的自定义快捷键击键处理。

它仅在具有焦点的控件获取 KeyDown 事件之前,并且无论哪个客户端控件具有焦点之前,才会在按下键事件上调用。 所以与KeyUp无关,也不与KeyPress相关联。 执行快捷函数后,当您识别密钥时,您可以从覆盖中返回 true。 这可以防止进一步处理密钥,它不会生成任何 KeyDown/Press/Up 事件。

很少使用该方法的 msg 参数,即 msg。消息值只会WM_KEYDOWN或WM_SYSKEYDOWN用户按住 Alt 键时生成的后一条消息。 你不关心,因为你总是可以从keyData参数中得到if。 喜欢这个:

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
        if (keyData == (Keys.Alt | Keys.F)) {
            // Alt+F pressed
            doSomething();
            return true;
        }
        return base.ProcessCmdKey(ref msg, keyData);
    }

您可能希望使用 | 运算符检查的其他修饰符(此处使用(是 Keys.Shift 和 Keys.Control。 所以(键移 |按键控制 |Keys.F1( 检查 Ctrl+Shift+F1。 当您想要执行一些不寻常的操作(例如检查重复键(时,可以解释 msg 数据。 查看 MSDN 文档中的WM_KEYDOWN通知。 味精。LParam 值包含一堆有关击键的信息。

请注意,在此方法中只能获取虚拟密钥。 Keys.F 是英文键盘布局上的 F 键,但不一定是用户布局上同一位置的键的相同字母。 支持功能键以避免文档难题。

按键重复是键盘控制器的一项功能,不仅限于键入按键。 按住箭头和功能键肯定会重复。 在这种情况下,您要忽略按键。 但是,如果为同时也是键入键的键(如 Keys.F(分配快捷键,则希望始终检查修饰键,以免破坏 TextBox 等控件。

最后但并非最不重要的一点是,不要忘记按钮和菜单项控件中对助记符的内置支持。 像&OK一样编写其 Text 属性会生成一个自记录快捷方式,而无需任何代码。 由用户操作,在此示例中,通过键入 Alt+O。

传递给 ProcessCmdKey(( 的消息结构在其 Msg 属性中包含 WINAPI 消息编号:

  • WM_KEYDOWN0x100(256(,
  • WM_KEYUP0x101(257(,
  • WM_CHAR(大致相当于KeyPress(是0x102(258(,
  • WM_SYSKEYDOWN0x104(260(,
  • WM_SYSKEYUP0x105(261(。
关于

您关于KeyPress的问题,确实,诸如箭头键之类的非字符键不会在内部生成WM_CHAR消息,但它们确实会生成WM_KEYDOWN,并且该消息也会多次发送以进行重复输入。

另请注意,我不确定ProcessCmdKey()是实现您想要的正确方法。文档将其描述为仅处理main menu command keys and MDI accelerators,这可能只是您要捕获的键的子集。您可能希望重写 ProcessKeyPreview((,它将处理子控件接收的所有键盘消息。