簡體   English   中英

如何防止控件捕獲模式窗體打開時的KeyDown事件?

[英]How to prevent controls from capturing KeyDown events while a modal form is open?

我有一個帶有CancelButton和AcceptButton的表單(名為btnCancel和btnOK)。 我有一些ComboBoxes作為輸入字段。

ComboBoxes阻止我的AcceptButton和CancelButton接收Escape和Enter鍵,因此我將以下代碼添加到所有字段的KeyDown事件中:

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事件中的代碼:

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鍵時,btnOK_Clicked 在其顯示其MessageBox時才再次調用Fields_KeyDown(在if的其他部分)。 恰好在MessageBox.Show(...)被調用之后,KeyDown事件被第二次無故調用。

這是首次通話的通話堆棧:

這是第一次通話的通話堆棧

這是第二個:

這是第二次通話的通話堆棧

完全不應該進行第二次呼叫。 在第二個調用堆棧中,第一個btnOK_Click(第三行)再次從MessageBox.Show(...)調用Fields_KeyDown(第二行 這怎么可能? 我糊塗了...

第二個呼叫的呼叫堆棧,外部代碼可見:

可見外部代碼的調用堆棧

雖然我不知道這種行為背后的主要原因。

但是在這種情況下,顯然KeyDown事件將觸發2次。 (設置一個斷點,您將看到。)

由於需要在代碼中處理它,因此可以嘗試忽略Enter鍵之一:

bool handled = true;
private void comboBox1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Enter)
    {
        /*Prevent handling the Enter key twice*/
        handled = !handled;
        if(handled)
            return;

        //Rest of logic
        //OkButton.PerformClick();
    }
}

您無法正確處理KeyDown事件中的Escape和Enter鍵,因為它們是在鍵盤預處理階段-Control.IsInputKeyControl.ProcessDialogKey處理的 通常,控件會為您執行此操作,但是當DropDownStyleSimple時, ComboBox實現中似乎存在錯誤。

要獲得所需的行為,請創建並使用您自己的ComboBox子類,如下所示

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);
    }
}

PS當然,不要忘記刪除KeyDown事件處理程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM