【问题标题】:Arrow key events not arriving箭头键事件未到达
【发布时间】:2010-07-21 15:27:55
【问题描述】:

基本上,我有一个带有自定义控件的表单(仅此而已)。自定义控件完全为空,并且表单的 KeyPreview 设置为 true。

使用此设置,我没有收到任何箭头键或 Tab 的任何 KeyDown 事件。我键盘上的所有其他键都可以使用。我将 KeyDown 事件处理程序连接到所有具有此类事件的事物,所以我确信我没有遗漏任何东西。

另外值得注意的是,如果我删除(完全为空的)自定义控件,我会得到箭头键事件。

这到底是怎么回事?

编辑:

我将它添加到表单和控件中,但我仍然没有得到箭头键:

protected override void WndProc(ref Message m) {
    switch (m.Msg) {
        case 0x100: //WM_KEYDOWN
            //this is the control's version. In the form, it's this.Text
            ParentForm.Text = ((Keys)m.WParam).ToString();
            break;
    }
    base.WndProc(ref m);
}

我还检查了 Spy++,并确定表单本身没有收到任何 WM_KEYDOWN 消息,它们都进入了控件。但是,也就是说,控件正在获取箭头键 WM_KEYDOWN 消息。叹息。

编辑 2:我还使用此版本更新了 ZIP 文件。请看一下,如果你想帮助...

编辑 3:

我已经想通了,有点。该形式正在吃箭头键,可能是为了保持其孩子的注意力。事实证明,如果表单为空,我确实会收到事件。

无论如何,如果我将此代码添加到表单中,我会再次开始获取事件:

public override bool PreProcessMessage(ref Message msg) {
    switch (msg.Msg) {
        case 0x100: //WM_KEYDOWN
            return false;
    }
    return base.PreProcessMessage(ref msg);
}

当我覆盖它时,表单没有机会做它的脏活,所以我得到了我期望的 KeyDown 事件。我假设这样做的一个副作用是我不能再使用我的键盘来导航表单(在这种情况下没什么大不了的,因为它是一个游戏,而且这个练习的全部目的是实现键盘导航!)

如果有办法,如何“正确”禁用这个问题仍然存在......

【问题讨论】:

  • 听起来您的用户控件所在的表单正在捕获事件并将其设置为在您的 UserControl 接收之前处理。您是否确保按下键时您的用户控件具有焦点?

标签: c# winforms custom-controls arrow-keys


【解决方案1】:

我已经进行了一些广泛的测试,并且我已经弄清楚了一切。 I wrote a blog post detailing the solution.

简而言之,就是要覆盖表单中的 ProcessDialogKey 方法:

protected override bool ProcessDialogKey(Keys keyData) {
    return false;
}

这将导致箭头键(和制表符)作为正常的 KeyDown 事件传递。然而!这也将导致正常的对话键功能(使用 Tab 导航控件等)失败。如果您想保留它,但仍然获得 KeyDown 事件,请改用它:

protected override bool ProcessDialogKey(Keys keyData) {
    OnKeyDown(new KeyEventArgs(keyData));
    return base.ProcessDialogKey(keyData);
}

这将传递一个 KeyDown 消息,同时仍然进行正常的对话导航。

【讨论】:

  • 你的博客链接失效了?!?
【解决方案2】:

如果焦点是您的问题,并且您无法让用户控件获得焦点并保持它,一个简单的变通解决方案是将事件回显到您关注的关键事件上的用户控件.订阅您的表单 keydown 或 keypress 事件,然后让该事件向您的用户控件引发事件。

所以本质上,Form1_KeyPress 将使用来自 Form1_KeyPress 的发送者和事件参数调用 UserControl1_KeyPress,例如

protected void Form1_KeyPress(object sender, KeyEventArgs e)
{
    UserControl1_KeyPress(sender, e);
}

否则,您可能必须走很长的路并覆盖您的 WndProc 事件才能获得所需的功能。

【讨论】:

  • UserControl 为空,无法获得焦点 (AFAIK)。因此,表单本身应该接收 KeyDown 事件。然而,事实并非如此。正如我在问题中所说,我有事件处理程序连接到所有有事件的东西,但没有得到事件。我可能会尝试覆盖 WndProc,但我真的不应该...
  • 我已经用我的覆盖 WndProc 的结果更新了 OP
猜你喜欢
  • 2023-03-15
  • 2015-08-14
  • 2013-07-22
  • 1970-01-01
  • 2011-02-03
  • 1970-01-01
  • 2012-05-03
  • 2021-12-28
  • 1970-01-01
相关资源
最近更新 更多