[英]C#, WinForms: What would prevent KeyDown events from chaining up from focused control up to main Form? Only leaf controls KeyDown works for me
[英]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.IsInputKey和Control.ProcessDialogKey處理的 。 通常,控件會為您執行此操作,但是當DropDownStyle
為Simple
時, 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.