表单不响应KeyDown事件


82

我在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!");
    }
}

我这样做是一种很好的方法,即打开Visual Studio设计器的“属性”面板,然后双击表单的KeyDown事件以生成Form1_KeyDown事件处理程序。但是在测试我的应用程序时,该表单完全不响应Ctrl+ Alt+O键盘快捷键。但是,Visual Studio设计器确实生成了将事件处理程序绑定到表单的代码:

private void InitializeComponent()
{
    // ...

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

    // ...
}

因此,我尝试向Console.WriteLine()处理程序添加一个调用,以检查该调用是否已被调用,但也没有运气。

另外,我尝试在事件绑定调用上设置一个断点(如上图所示),发现程序可以很好地达到该断点。但是,我无法在方法定义本身中设置的任何断点都不会到达。

为了确保我正确地执行了前几个步骤,我尝试使用以下命令重复执行这些步骤:

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

  • 全新的WinForms解决方案。
    它工作正常:出现消息对话框(Console.WriteLine()呼叫也可以)。

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

Answers:


173

您的表单的KeyPreview属性设置为true吗?

Form.KeyPreview属性

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

http://msdn.microsoft.com/zh-CN/library/system.windows.forms.form.keypreview.aspx


19
这是一个黑客,可以使VB6程序员满意。它具有执行顺序问题,请改用ProcessCmdKey()。
汉斯·帕桑

@HansPassant,我找不到任何能解释执行顺序问题的信息。KeyDown + KeyPreview将看不到所有键,这就足够了,但是执行顺序有什么问题呢?
kdbanman 2015年

1
有许多替代方法可以检测快捷键。按顺序执行,KeyPreview + KeyDown最后停止。
汉斯·帕桑

54

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

KeyDown事件上触发Form,只要其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);
}

这样,所有键对于该方法都是可见的,并且该方法排在第一位以查看事件。

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


1
这是正确的答案,尤其是如果您发现在KeyPreview设置为true的情况下完全无法启动PreviewKeyDown的情况。
蒂姆(Tim)

23

尝试将KeyPreview表单上的属性设置为true。这对我来说很适合注册按键。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.