我有一个带有CancelButton和AcceptButton的表单(名为btnCancel和btnOK)。我有一些ComboBoxes作为输入字段。
ComboBoxes阻止我的AcceptButton和CancelButton接收转义和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事件中的Escape和Enter键,因为它们是在键盘预处理阶段-Control.IsInputKey和Control.ProcessDialogKey处理的。通常,控件会为您执行此操作,但是当ComboBox
为DropDownStyle
时,在Simple
实现中似乎存在错误。
要获得所需的行为,请创建并使用您自己的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);
}
}
附言当然,不要忘记删除KeyDown事件处理程序。
关于c# - 如何防止控件捕获模式窗体打开时的KeyDown事件?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34021050/