代码之家  ›  专栏  ›  技术社区  ›  Mike Caron

箭头键事件未到达

  •  6
  • Mike Caron  · 技术社区  · 14 年前

    基本上,我有一个表单,上面有一个自定义控件(没有其他控件)。自定义控件完全为空,表单的keypreview设置为true。

    使用此设置,我不会接收任何箭头键或选项卡的任何按键事件。我键盘上的每一把钥匙都能用。我有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);
    }
    

    当我重写它时,窗体就没有机会做它的脏工作,因此我得到了我所期望的按键事件。我认为这样做的一个副作用是我不能再使用我的键盘来导航表单(在这种情况下不算什么,因为它是一个游戏,而这个练习的全部目的是实现键盘导航!)

    问题仍然是如何“适当地”禁用这个,如果有一种方法…

    2 回复  |  直到 8 年前
        1
  •  10
  •   Mike Caron    14 年前

    我已经做了一些广泛的测试,我已经解决了所有问题。 I wrote a blog post detailing the solution.

    简而言之,您希望重写表单中的processDialogKey方法:

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

    这将导致箭头键(和制表符)作为正常的按键事件传递。然而!这也会导致正常的对话键功能(使用选项卡导航控件等)失败。如果要保留该项,但仍获得keydown事件,请使用此项:

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

    这将在进行正常对话导航的同时发送一条按键信息。

        2
  •  0
  •   George Johnston    14 年前

    如果焦点是你的问题,并且你不能让你的用户控制来获得焦点并保持它,那么一个简单的解决方法就是将事件回送到你的用户控制中,让它回送到你所关心的关键事件上。订阅窗体的keydown或keypress事件,然后让该事件向用户控件引发事件。

    所以从本质上来说,form1-keypress会调用usercontrol1-keypress,其中包含发送方和来自form1-keypress的事件参数。

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

    否则,您可能需要走很长的路并重写wndproc事件以获得您想要的功能。