如何防止控件在模态窗体打开时捕获KeyDown事件? [英] How to prevent controls from capturing KeyDown events while a modal form is open?

查看:177
本文介绍了如何防止控件在模态窗体打开时捕获KeyDown事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有CancelButton和AcceptButton(名为btnCancel和btnOK)的表单。我有一些ComboBoxes作为输入字段。

I have a form with CancelButton and AcceptButton (named btnCancel and btnOK). And I have some ComboBoxes as input fields.

ComboBox阻止我的AcceptButton和CancelButton接收Escape和Enter键,所以我添加这个代码到所有字段的KeyDown事件: / p>

ComboBoxes prevent my AcceptButton and CancelButton to receive Escape and Enter keys, so I added this code to KeyDown event for all fields:

if (e.KeyData == Keys.Escape)
{
    ComboBox field = (ComboBox)sender;
    if ((field.DropDownStyle == ComboBoxStyle.Simple) || (!field.DroppedDown))
    {
        e.SuppressKeyPress = true;
        btnCancel.PerformClick();
    }
}
else if (e.KeyData == Keys.Enter)
{
    ComboBox field = (ComboBox)sender;
    if ((field.DropDownStyle == ComboBoxStyle.Simple) || (!field.DroppedDown))
    {
        e.SuppressKeyPress = true;
        btnOK.PerformClick();
    }
}

这是OK按钮的Clicked事件中的代码:

This is the code in Clicked event of OK button:

if (!changesAreSaved)
{
    SaveChangesToNode();
}

List<int> invalidIndices = ValidateAndRefineNodes(true);

if (invalidIndices.Count == 0)
{
    this.DialogResult = DialogResult.OK;
    this.Close();
}
else
{
    MessageBox.Show(this, "Enter correct values for all fields before you press OK.", "Cannot Save Information",
        MessageBoxButtons.OK, MessageBoxIcon.Error);
}

一切正常,但当一个ComboBox有Focus并按Enter键键盘,当它显示其MessageBox(if的if部分)时,btnOK_Clicked再次调用Fields_KeyDown 。正好在正在调用MessageBox.Show(...)之后,没有任何原因第二次调用KeyDown事件。

Everything is OK but when a ComboBox has Focus and I press Enter key on my keyboard, btnOK_Clicked calls Fields_KeyDown again only when it shows its MessageBox (on else part of if). Exactly right after MessageBox.Show(...) is being called, KeyDown event is being called for second time without any reason.

这是第一次调用的Call Stack:

This is Call Stack for first call:

这是第二个:

第二次调用不应该发生。在第二个调用堆栈中,第一个btnOK_Click(第三行)再次调用Fields_KeyDown(第二行) from MessageBox.Show(...)。这怎么可能?我很困惑...

Second call should not occur at all. In second Call Stack, first btnOK_Click (third line) again calls Fields_KeyDown (second line) from MessageBox.Show(...). How is this possible? I'm confused...

使用外部代码调用堆栈第二次调用可见:

Call Stack for second call with External Code visible:

推荐答案

您无法在KeyDown事件中正确处理Escape和Enter键,在键盘预处理阶段处理 - Control.IsInputKey Control.ProcessDialogKey 。通常,控件会为您执行此操作,但是当 DropDownStyle 是<$ c $时,看起来像 ComboBox c>简单。

You cannot correctly process Escape and Enter key in KeyDown event because they are handled during the keyboard preprocessing phase - Control.IsInputKey and Control.ProcessDialogKey. Normally controls do that for you, but looks like there is a bug in ComboBox implementation when DropDownStyle is Simple.

要获得所需的行为,请像下面这样创建和使用您自己的 ComboBox 子类

To get the desired behavior, create and use your own ComboBox subclass like this

public class MyComboBox : ComboBox
{
    protected override bool IsInputKey(Keys keyData)
    {
        if (DropDownStyle == ComboBoxStyle.Simple)
        {
            switch (keyData & (Keys.KeyCode | Keys.Alt))
            {
                case Keys.Return:
                case Keys.Escape:
                    return false;
            }
        }
        return base.IsInputKey(keyData);
    }
}

当然不要忘记删除您的KeyDown事件处理程序。

P.S. And of course don't forget to remove your KeyDown event handlers.

这篇关于如何防止控件在模态窗体打开时捕获KeyDown事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆