阻止WinForm上的回车键触发事件

5
我有一个基本的自定义对话框,用于在WinForms应用程序中与各种控件一起使用。对话框如下:
对于各种原因,我不希望用户能够使用“Enter”键选择“Yes”选项(buttonYes)。以前我想要这个行为,我相应地设置了Yes按钮(buttonYes)的AcceptButton属性。现在我已经删除了它,将buttonYes的AcceptButton属性设置为“None”,但是当按下“Enter”键时,该窗体仍然会触发buttonYes.Click事件。我还尝试处理KeyPress或KeyDown事件,但是当使用Enter键时,这些事件不会被触发。这很基础且很烦人,请问有没有人遇到过这种情况,我该怎么实现我想要的功能?
8个回答

13

这里所有的答案都是错误的或强调得不对。

enter image description here

为了理解发生了什么,你需要基本理解Form.ShowDialog(...)是如何实现的。在幕后,ShowDialog进入自己的消息循环。该消息循环具有硬编码逻辑,特别地处理Enter键。

对话框 并没有 关闭是因为OK按钮被选中,发生了Enter键按下事件,然后WinForms执行了OK按钮点击逻辑,关闭了窗口。对话框之所以关闭是因为Enter按下消息从正在运行在调用栈顶部的消息循环中被取出、消耗,并导致ShowDialog跳出其循环并关闭窗口…… 因此,你不能通过在按钮上处理按键按下事件来获取想要的功能; Enter键按下事件从未被分派。通过KeyPreview传递的事件只是获取相同事件的另一种方式,因此也没有帮助。

唯一有效的方法是将窗体的AcceptButton属性设置为(无)。 OK按钮仍然可以将其DialogResult属性设置为OK,因此这样做不会破坏对话框,但是将AcceptButton设置为none后,WinForms会忽略来自ShowDialog内部的Enter点击。


这是正确的答案!!(jwezorek,我添加了一张图片到你的答案中,以便人们更容易地看到和理解)希望它最终能够得到超过“被接受”的错误答案的赞成。 :-) - mike
即使我的答案获得了更高的赞同,我仍然相信这是应该使用的正确方法。 - Marshal
正确的答案,顺便提一下,如果您的表单中有一个包含WPF控件的ElementHost,则该控件需要拥有自己的按钮“IsDefault”= false,否则您会得到相同的行为。 - Zyo

8
为了解决这个问题,将TabStop属性设置为False,并使用以下代码: ```` ``` ```
private void form1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
    if (e.KeyChar == (char)Keys.Enter)
        e.Handled = true;
}

如果像你说的那样,无法在 KeyPressEvent 中中断操作,您需要处理 ProcessKeyPreview。

protected override bool ProcessKeyPreview(ref System.Windows.Forms.Message m)
{
    int _ENTER = 13;

    if (m.Msg == _ENTER)
    {
        //Do nothing
    }
    return base.ProcessKeyPreview(ref m);
}

这两种方法都没有起作用(我之前尝试过第一种)。我对第二种方法抱有希望,但它也没有被触发。我对此感到困惑... - MoonKnight
@Killercam:感谢您的更正。您的表单KeyPreview属性是否设置为true?如果没有,请设置它。 - Marshal
我也尝试过了。上面的“overridden”事件没有触发。 - MoonKnight
@Killercam:如果它被放置在对话框 cs 文件的 codebehind 中,它必须会触发。确保你没有将它放置在调用对话框的文件中。 - Marshal
当然,我理解这个。谢谢。显然发生了一些非常奇怪的事情... - MoonKnight
显示剩余4条评论

4

另外,如果您希望确保用户必须点击按钮而非使用键盘,则可以将按钮的 TabStop 属性设置为 False


这与问题无关。 - default
为什么不呢?他不希望用户使用回车键来选择按钮。如果他将按钮的TabStop设置为false,他甚至不需要关心按下的键。 - Anderson Pimentel
Tabstop 只影响 TabStop,与 Enter 有什么关系? - default
1
回车键只是提交按钮,因为它具有焦点。如果按钮从未获得焦点,则无法通过键盘触发它们。 - Anderson Pimentel
TabStop 属性设置为 False 导致 KeyPress 事件重新启用了!现在我可以捕获和处理此事件并相应地处理它。然而,我宁愿不这样做。如果我没有设置 AcceptButton 属性,我就不必这样做。 - MoonKnight
1
事件将会存在,你不需要编写任何代码来处理它,因为它不会按下按钮,因为它们没有焦点。 - Anderson Pimentel

1

既然您已经更改了Accept按钮的属性,那么表单的KeyPreview属性呢?它设置为false还是true?也许您在某个地方将其设置为了true,并忘记了它。将其设置为false。


1

我刚刚也遇到了这个问题,但是提供的解决方案都不起作用,所以我处理Click事件的方式如下:

private void yes_Click( object sender, EventArgs e )
{
    if( e.Equals( EventArgs.Empty ) )
        return;  // ignore "Enter" key press

    // process mouse click...
}

0

简单解决方案 我尝试了许多以上的解决方案,以下是对我有效的方法。

在InitializeComponent中,请确保未设置AcceptButton。 删除或注释掉以下代码:
// this.AcceptButton = this.btnClose;\

并在按钮上添加:
this.btnClose.TabStop = false; (有人在上面提到过这个)

如果这不起作用,您还可以尝试将焦点从按钮移开,并移到窗口框架上。 this.Focus()


0
你应该查看 *.resx 或 *.ressources 文件。 搜索 AcceptButton 属性。它可能已经在这些文件中设置了。

他为什么应该看一下它们? - default
这些文件中设置了一些属性。他应该澄清没有设置任何这些属性。 - gimbar

0

我尝试了各种方法来做这件事,但只有一种方法适用于我:

  1. 删除 AcceptButton。

  2. 为您的按钮创建一个点击事件。

  3. 在事件中编写以下代码:

    this.DialogResult = DialogResult.OK;


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