关键事件:ProcessCmdKey

3Pi*_*3Pi 14 .net c# winforms

我试图在一个小的测试Windows窗体应用程序上发生一些键盘响应,我有一个粗略的解决方案,它是覆盖ProcessCmdKey.但是,我遇到了几个问题,而且我发现了一些不一致的问题.

不同的事件:在参数中ref Message msg, Keys keyData,有没有办法告诉Even是KeyDown,KeyUp还是KeyPress?

KeyPress:我看过的所有地方都说KeyPress,即重复的键盘输入,只发生在字符键上,箭头键不是.但是,事件处理程序被频繁地调用,并且在相同的mannor /具有相同的行为中,箭头键作为字符键.这是面对KeyPress事件,还是其他什么?

理想情况下,我喜欢在表单级别处理所有键盘事件而不让它们传递给表单上的控件的方法.但是,所有文档都让我很困惑,并且错过了关键点,因此我无法完成此操作.

欢迎任何这些主题的帮助.谢谢!

Han*_*ant 47

覆盖表单中的ProcessCmdKey明确旨在允许您在按钮和菜单项中的内置助记符处理之外实现自定义快捷键击处理.

具有焦点的控件获得KeyDown事件并且无论哪个客户端控件具有焦点之前,它都只被调用一个按键事件.因此与KeyUp无关,与KeyPress无关.执行快捷方式功能后,在识别密钥时从覆盖返回true.这可以防止密钥被进一步处理,它不会生成任何KeyDown/Press/Up事件.

使用该方法的msg参数是非常罕见的,msg.Msg值将只是WM_KEYDOWN或WM_SYSKEYDOWN,当用户按住Alt键时产生后一条消息.您不关心哪个,因为您始终可以从keyData参数获取.像这样:

    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);
    }
Run Code Online (Sandbox Code Playgroud)

您可能想要使用|检查的其他修饰符 这里使用的运算符是Keys.Shift和Keys.Control.所以(Keys.Shift | Keys.Control | Keys.F1)检查Ctrl + Shift + F1.你可以当你想要做一些不寻常比如检查重复键解释味精数据.检查MSDN文档以获取WM_KEYDOWN通知.msg.LParam值包含有关键击的一堆信息.

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

键重复是键盘控制器的一个功能,不仅限于键入键.按住时,箭头和功能键肯定会重复.您想在此方案中忽略KeyPress.但是如果你为一个同时也是键入键的键(如Keys.F)分配一个快捷键,那么你总是要检查一个修饰键,这样你就不会破坏像TextBox这样的控件.

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


Fré*_*idi 13

传递给ProcessCmdKey()Message结构在其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(),它处理子控件接收的所有键盘消息.