为什么我的 C# WinForms window 没有响应 Enter 键而关闭?
Why is my C# WinForms window not closing in response to Enter key?
我有一个基本的 WinForms 项目,用户可以在其中单击一个按钮。这将打开另一个表格,如下所示:
form2 myForm2 = new form2();
myForm2.ShowDialog();
在这个新表单中,有四个代表值的按钮。用户按 SPACE 键在按钮之间跳转,然后按 ENTER 键到 select 一个。当用户按下按钮上的 ENTER 键时,我希望关闭表单。为此,我使用 'this.Close()'。这对除 ENTER 以外的每个键都非常有效。我正在使用 visual studio 所以我插入了一个断点并跳过了代码。成功检测到 ENTER 键,我可以跨过代码 'this.Close()' 但 window 永远不会关闭。我的代码如下:
private void button1_KeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
// Change colour of the button you are on. This works fine.
}
else if (e.KeyCode == Keys.Enter)
{
this.Close();
// This will close the form with all keys other than the Enter key. Yet the enter key is
// successfully detected and the program enters this else if statement.
}
}
非常感谢任何帮助,谢谢。
我会覆盖 ProcessCmdKey()
并使 space 键的作用类似于 select 下一个控件的 Tab 键。然后像平常一样处理每个按钮的每个点击事件。按钮的点击处理程序将在用户按下回车键时触发:
public partial class form2 : Form
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
Button btn = this.ActiveControl as Button;
if (btn != null)
{
if (keyData == Keys.Space)
{
// possibly do something else with "btn"?...
this.SelectNextControl(btn, true, true, true, true);
return true; // suppress default handling of space
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void button1_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button1");
this.DialogResult = DialogResult.OK;
}
private void button2_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button2");
this.DialogResult = DialogResult.OK;
}
private void button3_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button3");
this.DialogResult = DialogResult.OK;
}
private void button4_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button4");
this.DialogResult = DialogResult.OK;
}
}
另一种方法是像这样在 ProcessCmdKey()
中捕获回车键:
public partial class Form2 : Form
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
Button btn = this.ActiveControl as Button;
if (btn != null)
{
if (keyData == Keys.Space)
{
Console.WriteLine("Space -> Tab");
// possibly do something else with "btn"?...
this.SelectNextControl(btn, true, true, true, true);
return true; // suppress default handling of space
}
else if (keyData == Keys.Enter)
{
Console.WriteLine("Enter in ProcessCmdKey() for " + btn.Name);
// possibly do something else with "btn"?...
this.Close();
// < or >
this.DialogResult = DialogResult.OK;
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
查看处理程序的签名 (object sender, PreviewKeyDownEventArgs e)
显然 OP 已经在处理 PreviewKeyDown
事件。
我重现并解决了问题
当您使用 Show
或 ShowDialog
打开表单时,行为有所不同。使用 Show
时一切正常,但使用 ShowDialog
时,要关闭 PreviewKeyDown
中的表单,您需要使用以下选项之一:
private void button1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
e.IsInputKey = true;
this.Close();
// OR
// if (e.KeyData == Keys.Enter)
// this.BeginInvoke(new Action(() => this.Close()));
// OR first hide, then close, without calling BeginInvoke
// this.Hide();
// this.Close();
}
模型消息循环应该有一些东西。我没有详细追踪,但您可能会发现以下链接有用:
附带说明:如果 Enter 应在表单级别处理,则设置表单的 AcceptButton
或覆盖 ProcessKeyDown
或 ProcessDialogKey
的形式是要走的路。
我有一个基本的 WinForms 项目,用户可以在其中单击一个按钮。这将打开另一个表格,如下所示:
form2 myForm2 = new form2();
myForm2.ShowDialog();
在这个新表单中,有四个代表值的按钮。用户按 SPACE 键在按钮之间跳转,然后按 ENTER 键到 select 一个。当用户按下按钮上的 ENTER 键时,我希望关闭表单。为此,我使用 'this.Close()'。这对除 ENTER 以外的每个键都非常有效。我正在使用 visual studio 所以我插入了一个断点并跳过了代码。成功检测到 ENTER 键,我可以跨过代码 'this.Close()' 但 window 永远不会关闭。我的代码如下:
private void button1_KeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
// Change colour of the button you are on. This works fine.
}
else if (e.KeyCode == Keys.Enter)
{
this.Close();
// This will close the form with all keys other than the Enter key. Yet the enter key is
// successfully detected and the program enters this else if statement.
}
}
非常感谢任何帮助,谢谢。
我会覆盖 ProcessCmdKey()
并使 space 键的作用类似于 select 下一个控件的 Tab 键。然后像平常一样处理每个按钮的每个点击事件。按钮的点击处理程序将在用户按下回车键时触发:
public partial class form2 : Form
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
Button btn = this.ActiveControl as Button;
if (btn != null)
{
if (keyData == Keys.Space)
{
// possibly do something else with "btn"?...
this.SelectNextControl(btn, true, true, true, true);
return true; // suppress default handling of space
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void button1_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button1");
this.DialogResult = DialogResult.OK;
}
private void button2_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button2");
this.DialogResult = DialogResult.OK;
}
private void button3_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button3");
this.DialogResult = DialogResult.OK;
}
private void button4_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button4");
this.DialogResult = DialogResult.OK;
}
}
另一种方法是像这样在 ProcessCmdKey()
中捕获回车键:
public partial class Form2 : Form
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
Button btn = this.ActiveControl as Button;
if (btn != null)
{
if (keyData == Keys.Space)
{
Console.WriteLine("Space -> Tab");
// possibly do something else with "btn"?...
this.SelectNextControl(btn, true, true, true, true);
return true; // suppress default handling of space
}
else if (keyData == Keys.Enter)
{
Console.WriteLine("Enter in ProcessCmdKey() for " + btn.Name);
// possibly do something else with "btn"?...
this.Close();
// < or >
this.DialogResult = DialogResult.OK;
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
查看处理程序的签名 (object sender, PreviewKeyDownEventArgs e)
显然 OP 已经在处理 PreviewKeyDown
事件。
我重现并解决了问题
当您使用 Show
或 ShowDialog
打开表单时,行为有所不同。使用 Show
时一切正常,但使用 ShowDialog
时,要关闭 PreviewKeyDown
中的表单,您需要使用以下选项之一:
private void button1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
e.IsInputKey = true;
this.Close();
// OR
// if (e.KeyData == Keys.Enter)
// this.BeginInvoke(new Action(() => this.Close()));
// OR first hide, then close, without calling BeginInvoke
// this.Hide();
// this.Close();
}
模型消息循环应该有一些东西。我没有详细追踪,但您可能会发现以下链接有用:
附带说明:如果 Enter 应在表单级别处理,则设置表单的 AcceptButton
或覆盖 ProcessKeyDown
或 ProcessDialogKey
的形式是要走的路。