Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在按下ESC键时关闭窗体,但前提是没有控件处理它?_C#_Winforms_Hotkeys_Keydown_Keypreview - Fatal编程技术网

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

C# 如何在按下ESC键时关闭窗体,但前提是没有控件处理它?,c#,winforms,hotkeys,keydown,keypreview,C#,Winforms,Hotkeys,Keydown,Keypreview,我有一个表单,当按下ESC键时会自动关闭,这要感谢KeyPreview、ProcessKeyEventArgs、ProcessCmdKey或其他功能。但是我在表单上有一个控件,当按下ESC时,它会做一些非常相关的事情(它会隐藏自己),在这种情况下表单不应该关闭 控件使用KeyDown事件,并将SuppressKeyPress标志设置为true,但这发生在前面提到的表单键预览之后,因此没有效果 是否有某种类型的KeyPostview 当控件使用了相关的键点击时,如何不关闭窗体 编辑:处理ESC的控

我有一个表单,当按下ESC键时会自动关闭,这要感谢
KeyPreview
ProcessKeyEventArgs
ProcessCmdKey
或其他功能。但是我在表单上有一个控件,当按下ESC时,它会做一些非常相关的事情(它会隐藏自己),在这种情况下表单不应该关闭

控件使用
KeyDown
事件,并将
SuppressKeyPress
标志设置为true,但这发生在前面提到的表单键预览之后,因此没有效果

是否有某种类型的KeyPostview

当控件使用了相关的键点击时,如何不关闭窗体


编辑:处理ESC的控件是嵌入在手持设备列表视图中的文本框。当用户单击单元格时,文本框出现,启用编辑。要验证新文本,输入就好了(这已经起作用了,因为它将焦点放在了其他内容上)。要取消该版本,ESC似乎是最自然的

你能先检查一下哪个控件有焦点吗?如果窗体上只有一个控件执行与escape键相关的操作,请在关闭窗体之前检查该控件是否具有焦点。

确定-此操作:

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;
    }

基本问题是在调用Close时调用表单的Dispose方法,因此表单将要关闭,您对此无能为力

我将通过让UserControl实现一个标记接口(比如iSuppressSC)来解决这个问题。然后,表单的键控处理程序可以定位当前焦点控件,并在该焦点控件实现iSuppressSC时取消关闭。请注意,如果它可能是嵌套控件,则必须对其进行额外的操作

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();
        }
    }
}

你在争夺逃生钥匙。在标准Windows用户界面中,除了Enter键外,这也是一个非常重要的键。只需在窗体上放置一个按钮,并将窗体的CancelButton属性设置为其他按钮,这将吸收对该按钮的击键

为了与之竞争,您必须创建一个控件,告诉Winforms您确实认为转义键更重要。这需要重写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);
    }
}

首先,我对这个设计有点怀疑。普通用户是否愿意使用Esc键做两件截然不同的事情?他们是否充分理解“焦点”和“主动控制”的概念,从而能够预期会发生什么?至少要确保你是从用户的角度考虑这一点,而不仅仅是从开发人员的角度考虑这一点。双击单元格时,可以对其进行编辑。ESC将取消该版本。但是,当您按您描述的应用程序所做的那样git ESC时,excel不会关闭。我不希望表单检查该特定控件(实际上是一个UserControl)。我希望能够在窗体上删除该控件,并且不做任何操作,希望它能够正常工作。但是,我愿意改变KeyPreview的东西,这看起来像是一条死胡同。看起来两行就可以了,再简单不过了。无论如何,我必须同意上面的Cody。是的,我就是这么想的。再一次,我不想在Form_KeyUp中检查特定控件,这太容易忘记了。我的新代码也很有效。如果你担心忘记,那么做一个自定义控件。这个新版本看起来很棒!我马上测试一下(:嗯,我不能让textbox和表单都可以访问变量,因为textbox嵌入在UserControl中,它的PreviewKeyDown事件发生在另一个类中,也就是说,不是form子类。新代码按照您的意愿工作。无需检查每个控件,它在所有自定义控件中使用一个静态变量来跟踪您可以使用多个相同的自定义控件,因为只有一个控件可以具有焦点(因此可以激发)一次可以创造奇迹。但是有两个问题。1.我必须在表单上有一个按钮来处理CancelButton的事情。这对我来说没什么大不了的,因为我的所有表单上都有一个按钮,但这可能会给其他程序员带来麻烦。2.该按钮必须同时启用和可见。为了避免在设计时出现混乱,它应该是有效的在设计时可见,因此在运行时可见。通过将其移出表单OnLoad的边界来隐藏它可能是另一个麻烦。这仍然是目前对我来说最好的解决方案,因为它不涉及任何关闭表单的检查。\o/重写表单的ProcessCmdKey()。