为什么我的 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 事件。

我重现并解决了问题

当您使用 ShowShowDialog 打开表单时,行为有所不同。使用 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 或覆盖 ProcessKeyDownProcessDialogKey 的形式是要走的路。