表单没有响应KeyDown事件

Bol*_*ock 68 .net c# winforms

我已经在我的Windows Forms项目上工作了一段时间,我决定尝试使用键盘快捷键.经过一些阅读后,我想我必须编写一个事件处理程序并将其绑定到表单的KeyDown事件:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control && e.Alt && e.KeyCode == Keys.O)
    {
        MessageBox.Show("Ctrl+Alt+O: magic!");
    }
}
Run Code Online (Sandbox Code Playgroud)

我这样做是打开Visual Studio设计器的Properties面板的好方法,然后双击我的表单的KeyDown事件来生成Form1_KeyDown事件处理程序.但在测试我的应用程序时,表单根本不响应Ctrl+ Alt+ O键盘快捷键.Visual Studio设计器确实生成了将事件处理程序绑定到表单的代码:

private void InitializeComponent()
{
    // ...

    this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);

    // ...
}
Run Code Online (Sandbox Code Playgroud)

所以我尝试添加一个Console.WriteLine()对处理程序的调用来检查它是否被调用,但也没有运气.

此外,我试图在事件绑定调用上设置一个断点(如上所示),并发现程序到达该断点就好了.但是我从未在方法定义中设置任何断点.

为了确保我正确地执行了前几个步骤,我尝试重复它们:

  • 同一解决方案中的新表单.
    同样的问题:当我按下Ctrl+ Alt+ O键盘快捷键并且调试器甚至没有进入事件处理程序时,表单没有响应. 再次尝试这一点,它的工作原理.

  • 全新的WinForms解决方案.
    它完美运行:出现消息对话框(Console.WriteLine()调用也有效).

所以我在这里迷失了.是什么阻止了这个项目中的所有表单接收KeyDown事件?

STO*_*STO 151

您的表单是否将KeyPreview属性设置为true?

Form.KeyPreview属性

获取或设置一个值,该值指示在将事件传递给具有焦点的控件之前表单是否将接收键事件.

http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx

  • 这是一个黑客,可以让VB6程序员高兴.它有执行顺序问题,改为覆盖ProcessCmdKey(). (19认同)

kdb*_*man 39

建议对StackOverflow上和MSDN这个问题最常见的一块1,2(这里包括接受的答案)是快速和容易:

KeyDownForm只要其KeyPreview属性设置为,就会触发事件true

这对于大多数用途来说都是足够的,但由于两个原因,它有风险:

  1. KeyDown处理程序看不到所有键.具体来说,"您无法看到用于导航的击键类型.如光标键和Tab,Escape和Enter用于对话框."

  2. 拦截关键事件有几种不同的方法,它们都按顺序发生. 最后KeyDown处理.因此,并不是一个预览,事件可能会在途中的几个站点沉默.KeyPreview

(感谢@HansPassant获得这些积分.)

相反,覆盖ProcessCmdKey你的Form:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
    if (keyData == Keys.Up)
    {
        // Handle key at form level.
        // Do not send event to focused control by returning true.
        return true;
    }
  return base.ProcessCmdKey(ref msg, keyData);
}
Run Code Online (Sandbox Code Playgroud)

这样,方法可以看到所有键,并且该方法首先排队查看事件.

请注意,您仍然可以控制焦点控件是否看到该KeyDown事件.刚刚回归true阻止随后的KeyDown事件,而不是设置KeyPressEventArgs.Handledtrue,你会在一个KeyDown事件处理程序. 是一篇有更多细节的文章.

  • 这是正确的答案,特别是如果您发现将 KeyPreview 设置为 true 时 PreviewKeyDown 根本不会触发。 (2认同)

Seb*_*rot 19

尝试将KeyPreview表单上的属性设置为true.这对我来说是注册按键的.