为什么`ProcessCmdKey`为组合框发射两次但对文本框发射一次?

时间:2017-02-22 13:13:38

标签: .net winforms

我有一个winforms应用程序,其中包含3个控件:GroupBox gb1,其中包含ComboBox cmb1TextBox tb1

Form1.cs我有以下代码:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (comboBox1.Focused)
        MessageBox.Show("Cmb Focus");
    else if (textBox1.Focused)
        MessageBox.Show("Txtbox Focus");

    return base.ProcessCmdKey(ref msg, keyData);
}

如果我关注文本框并按一个键,我会看到一个MessageBox显示。随着组合框的集中,我得到2个弹出窗口。

我最初偶然发现this question一年半前发现问题的人接受了我的解决方案,该解决方案仅引用了MSDN:

  

ProcessCmdKey方法首先确定控件是否具有ContextMenu,如果是,则启用ContextMenu来处理命令键。如果命令键不是菜单快捷方式且控件具有父级,则该键将传递给父级的ProcessCmdKey方法。实际效果是命令键在控制层次结构中“冒泡”。

我明白它在说什么,但与此同时我不理解我的应用程序的“实际”行为。

两个控件都没有上下文菜单。两个控件都有1个父对象(组框)。那他们为什么表现得不一样呢?

我尝试了一些方法来帮助我理解:

1)如果我将代码更改为return true;,则两个控件仅显示1个消息框。如果我将其更改为return false;,我会得到与最初描述的相同的行为。

2)我认为这可能是Combobox object继承自System.Windows.Forms.ListControl这一事实的“副作用”。所以我尝试添加第三个控件ListBox,它也继承自System.Windows.Forms.ListControl。但是当我关注这个ListBox时,我仍然只得到1个消息框。

3)我将comboBox1.Items.Add("1");添加到Form1()构造函数中,然后按下键盘上的 1 键。我想,“也许如果我按下一个键'对应'组合框的Items集合中的一个项目,它只会显示1个弹出窗口。”但不,它仍然显示两次。

在用户评论我在上面链接的问题中发布的答案后,昨天引起了我的注意,但是我无法弄清楚为什么会发生这种情况。

1 个答案:

答案 0 :(得分:2)

这有点怪癖,特别是ComboBox。它的消息处理程序中有calls ProcessCmdKey as well。不是100%肯定它为什么这样做,但几乎肯定与下拉菜单而不是文本框收到的击键有关。

除了本机组合框处理消息的方式的副作用之外,如果它们不用于选择下拉列表中的项目,它会将WM_KEYDOWN消息从下拉列表转发到文本框。在"默认组合框行为"中描述the SDK doc page的部分。并且没有办法告诉它来自何处,因此Winforms无法使其具有选择性。

是的,当你处理击键时,你肯定应该return true;,总是必要的。我不能告诉你为什么跳过这个但它确实解决了这个问题。也许IMessageFilter可以解决您的问题(没有尝试过),但问题并没有给出任何暗示真实问题的暗示。