基本上,我有一个带有自定义控件的表单(没有别的).自定义控件完全为空,表单将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事件.我认为这样做的副作用是我不能再使用我的键盘来导航表格(在这种情况下不是很大,因为它是一个游戏,这个练习的全部目的是实现键盘导航!)
如果有办法,问题仍然是关于如何“正确”禁用这个问题……
解决方法
我做了一些广泛的测试,我已经把所有的东西都弄清楚了.
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消息,同时仍然进行正常的对话导航.