箭头键事件未到达

时间:2010-07-21 15:27:55

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

基本上,我有一个带有自定义控件的表单(没有别的)。自定义控件完全为空,表单将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消息,它们都是控件。但是,也就是说,控件IS获取箭头键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事件。我认为这样的副作用是我不能再使用我的键盘来导航表格(在这种情况下不是很重要,因为它是一个游戏,这个练习的全部目的是实现键盘导航!)< / p>

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

2 个答案:

答案 0 :(得分:10)

我做了一些广泛的测试,而且我已经把一切都搞清楚了。 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消息,同时仍然进行正常的对话导航。

答案 1 :(得分:0)

如果焦点是您的问题,并且您无法让您的用户控制以获得焦点并保留它,那么一个简单的解决方案就是将事件回显给您关注的关键事件的用户控件。订阅您的表单keydown或keypress事件,然后让该事件向您的用户控件发出一个事件。

基本上,Form1_KeyPress会使用Form1_KeyPress中的sender和event args调用UserControl1_KeyPress,例如

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

否则,你可能需要走很长的路线并覆盖你的WndProc事件才能获得你想要的功能。