C#中使用Escape按钮关闭Windows Forms窗体

100

我已经尝试了以下方法:

private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
    if ((Keys) e.KeyValue == Keys.Escape)
        this.Close();
}

但它不起作用。

然后我尝试了这个:

protected override void OnKeyDown(KeyEventArgs e)
{
    base.OnKeyDown(e);
    if (e.KeyCode == Keys.Escape)
        this.Close();
}

但仍然没有任何作用。

在我的Windows Forms窗体属性中,KeyPreview设置为true...我做错了什么?


1
你尝试在这些方法中设置断点了吗?事件处理程序是否被触发? - Steve Danner
1
不要将取消按钮命名为表单属性“CancelButton”。否则似乎无法设置CancelButton。 - Jonas Middendorf
@SteveDanner,事件没有被触发。可能是在InitializeComponent()中缺少声明。 - Rookie Programmer Aravind
我认为它不起作用的原因是因为表单内的其他控件获得了焦点... - itsho
8个回答

206

无论事件处理程序分配正确与否,KeyPreviewCancelButton等,这将始终起作用:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
    if (keyData == Keys.Escape) {
        this.Close();
        return true;
    }
    return base.ProcessCmdKey(ref msg, keyData);
}

12
使用表单的CancelButton属性是正确的方法。 - ABCD
14
唉,1980年代打来电话了,他们想要回收他们的对话框。 - Hans Passant
1
你也可以在 ProcessCmdKey 中返回 true 来表示该键已被处理,从而防止“叮”的声音。 - Spooky
9
只有在表单上实际有一个按钮(或IButtonControl接口对象)时,才能使用表单的CancelButton属性。 - David
2
为什么这种方法比CancelButton属性更受欢迎? - AdamMc331
3
这个选项不错。CancelButton 需要在表单上额外添加一个可见的“取消”按钮,这是冗余的渲染+代码等。 - V319

67

您只需要将表单的CancelButton属性设置为您的取消按钮,然后您就不需要编写任何代码。


3
我做了那件事,但按ESC键时它没有触发,为什么? - Mihai Bratulescu
这对我非常有效。对于小型表单来说更好。 - knut
请记住,您设置CancelButton的按钮需要可见。 - Sal

16
假设您有一个“取消”按钮,设置表单的CancelButton属性(无论是在设计器中还是在代码中)都会自动处理此问题。只需将关闭代码放置在按钮的Click事件中即可。

10

接受的答案确实是正确的,我已经使用这种方法多次。突然间,它不再起作用了,所以我觉得很奇怪。主要是因为我的断点不会被触发 ESC 键,但它会被其他键触发。

调试后,我发现我的表单中的一个控件正在覆盖 ProcessCmdKey 方法,并使用以下代码:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    // ...
    if (keyData == (Keys.Escape))
    {
        Close();
        return true;
    }
    return base.ProcessCmdKey(ref msg, keyData);
}

...这导致我的表单无法接收ESC按键(请注意return true)。因此,请确保没有子控件夺取输入权。


光凭记忆,我不确定您是否需要将表单KeyPreview属性设置为true - http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview(v=vs.110).aspx - Andez
我在我的winform上似乎遇到了ListView控件的问题。不知道你是否也在ListView上遇到了这个问题? - raddevus

3

您可以在表单选项中将KeyPreview设置为true,然后添加Keypress事件。在keypress事件中,输入以下内容:

private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == 27)
    {
        Close();
    }
}

key.Char == 27是ASCII码中Escape键的值。


这是一个很好的解决方法。我有一个带有ListView控件的表单,在这种情况下,它们似乎会吞噬CancelButton(当按下Esc键时)。我添加了这段代码,问题得到了解决。 - raddevus
这个可以运行,但你需要将 KeyPreview 设置为 true 才能在窗体上使用。 - Maris B.

0

您还可以触发其他表单。

例如,如果您编辑表单的CancelButton属性并设置按钮为Cancel,则可以触发取消按钮。

在代码中,您可以按以下方式处理取消按钮以关闭表单:

    private void btnCancel_Click(object sender, EventArgs e)
    {
        this.DialogResult = DialogResult.Abort;
    }

0
你需要把这个添加到“KeyUp”事件中。
    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        if(e.KeyCode == Keys.Escape)
        {
            this.Close();
        }
    }

-2

你说的“Escape button”是指“Esc”键吗?根据你的代码,我认为这就是你想要的。你也可以尝试使用Application.Exit(),但Close应该也可以工作。你有一个工作线程吗?如果有一个非后台线程正在运行,这可能会使应用程序保持打开状态。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接