如何在按下 ESC 键时关闭窗体,但前提是没有 Control 处理它?

发布于 2024-10-09 08:09:14 字数 494 浏览 7 评论 0原文

我有一个表单,当按下 ESC 键时它会自行关闭,这要归功于 KeyPreviewProcessKeyEventArgsProcessCmdKey 或其他。但是我在该表单上有一个控件,当按下 ESC 时(它会隐藏自己),它会执行非常相关的操作,并且当发生这种情况时不应关闭表单。

该控件使用 KeyDown 事件并将 SuppressKeyPress 标志设置为 true,但这发生在上述表单键预览之后,因此没有效果。

有某种 KeyPostview 吗?

当控件有相关的按键使用时,如何不关闭窗体?

编辑: 处理 ESC 的控件是嵌入在手持 ListView 中的文本框。当用户单击单元格时会出现文本框,从而启用编辑。要验证新文本,按 ENTER 会很好(这已经可以工作了,因为可以将焦点放在其他内容上)。要取消版本,ESC似乎是最自然的。

I have a Form that closes itself when the ESC key is pressed, thanks to KeyPreview, ProcessKeyEventArgs, ProcessCmdKey or whatever. But I have a Control on that form that does very relevant things when ESC is pressed (it hides itself) and the Form should not be closed when that happens.

The control uses the KeyDown event and sets the SuppressKeyPress flag to true, but that happens after the aforementioned form key preview, thus having no effect.

Is there some sort KeyPostview ?

How do I not close the form when a Control has a relevant use of a key hit ?

Edit: The control handling ESC is a textbox embedded in a hand-maid ListView. The textbox appears when the user clicks a cell, enabling edition. To validate the new text, ENTER would be nice (that already works, as giving the focus to anything else). To cancel edition, ESC seems most natural.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

皇甫轩 2024-10-16 08:09:14

您正在与 Escape 键展开激烈的竞争。与 Enter 键一样,它是标准 Windows 用户界面中非常重要的键。只需在窗体上放置一个按钮并将窗体的 CancelButton 属性设置为其他某个按钮,这会将击键吸收到该按钮。

为了与之竞争,您必须创建一个控件来告诉 Winforms 您确实认为 Escape 键重要。这需要重写 IsInputKey 属性。像这样:

using System;
using System.Windows.Forms;

class MyTexBox : TextBox {
    protected override bool IsInputKey(Keys keyData) {
        if (keyData == Keys.Escape) return true;
        return base.IsInputKey(keyData);
    }
    protected override void OnKeyDown(KeyEventArgs e) {
        if (e.KeyData == Keys.Escape) {
            this.Text = "";   // for example
            e.SuppressKeyPress = true;
            return;
        }
        base.OnKeyDown(e);
    }
}

You are competing Big Time over the Escape key. Along with the Enter key, that's a very important key in the standard Windows user interface. Just drop a button on form and set the form's CancelButton property to some other button, that will suck the keystroke to that button.

To compete with that, you have to create a control that tells Winforms that you really think that the Escape key is more important. That requires overriding the IsInputKey property. Like this:

using System;
using System.Windows.Forms;

class MyTexBox : TextBox {
    protected override bool IsInputKey(Keys keyData) {
        if (keyData == Keys.Escape) return true;
        return base.IsInputKey(keyData);
    }
    protected override void OnKeyDown(KeyEventArgs e) {
        if (e.KeyData == Keys.Escape) {
            this.Text = "";   // for example
            e.SuppressKeyPress = true;
            return;
        }
        base.OnKeyDown(e);
    }
}
甜嗑 2024-10-16 08:09:14

好的 - 这有效:

class CustomTB : TextBox
{
    public CustomTB()
        : base()
    {
        CustomTB.SuppressEscape = false;
    }

    public static bool SuppressEscape { get; set; }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        CustomTB.SuppressEscape = (e.KeyCode == Keys.Escape);
        base.OnKeyUp(e);
    }
}

以您的形式:

    public Form1()
    {
        InitializeComponent();
        this.KeyPreview = true;
    }

    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Escape && !CustomTB.SuppressEscape)
        {
            this.Close();
        }
        CustomTB.SuppressEscape = false;
    }

OK - this works:

class CustomTB : TextBox
{
    public CustomTB()
        : base()
    {
        CustomTB.SuppressEscape = false;
    }

    public static bool SuppressEscape { get; set; }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        CustomTB.SuppressEscape = (e.KeyCode == Keys.Escape);
        base.OnKeyUp(e);
    }
}

In your form:

    public Form1()
    {
        InitializeComponent();
        this.KeyPreview = true;
    }

    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Escape && !CustomTB.SuppressEscape)
        {
            this.Close();
        }
        CustomTB.SuppressEscape = false;
    }
我一向站在原地 2024-10-16 08:09:14

您可以检查一下哪个控件首先获得焦点吗?如果窗体上只有一个控件执行与转义键相关的操作,请在关闭窗体之前检查该控件是否具有焦点。

Can you check to see what control has the focus first? If there's only one control on your form that does something relevant with the escape key, check to see if that's the control that has the focus before you close the form.

时光礼记 2024-10-16 08:09:14

基本问题是,当调用 Close 时,会调用窗体的 Dispose 方法,因此窗体将关闭,而您对此无能为力。

我可以通过让 UserControl 实现一个标记接口来解决这个问题,比如 ISuppressEsc。然后,窗体的 KeyUp 处理程序可以找到当前获得焦点的控件,并在焦点控件实现 ISuppressEsc 的情况下取消关闭。请注意,您将必须做额外的工作 找到焦点控件(如果它可能是嵌套控件)。

public interface ISuppressEsc
{
    // marker interface, no declarations
}

public partial class UserControl1 : UserControl, ISuppressEsc
{
    public UserControl1()
    {
        InitializeComponent();
    }

    private void textBox1_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Escape)
        {
            textBox1.Text = DateTime.Now.ToLongTimeString();
        }
    }
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        KeyPreview = true;
    }

    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        var activeCtl = ActiveControl;
        if (!(activeCtl is ISuppressEsc) && e.KeyCode == Keys.Escape)
        {
            Close();
        }
    }
}

The basic problem is that the form's Dispose method is called when Close is called, so the form is going to close and there's not much you can do about it.

I would get around this by having the UserControl implement a marker interface, say ISuppressEsc. The form's KeyUp handler can then locate the currently focused control and cancel the close if the focused control implements ISuppressEsc. Be aware that you will have to do extra work to find the focused control if it may be a nested control.

public interface ISuppressEsc
{
    // marker interface, no declarations
}

public partial class UserControl1 : UserControl, ISuppressEsc
{
    public UserControl1()
    {
        InitializeComponent();
    }

    private void textBox1_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Escape)
        {
            textBox1.Text = DateTime.Now.ToLongTimeString();
        }
    }
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        KeyPreview = true;
    }

    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        var activeCtl = ActiveControl;
        if (!(activeCtl is ISuppressEsc) && e.KeyCode == Keys.Escape)
        {
            Close();
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文