C# 替代Windows窗体中的标准关闭(X)按钮

C# 替代Windows窗体中的标准关闭(X)按钮,c#,winforms,C#,Winforms,如何更改用户在Windows窗体应用程序(C#)中单击关闭(红色X)按钮时发生的情况?覆盖该方法 注意:您需要检查关闭原因,只有在用户关闭时才改变行为。您不应该在此处放置任何会使Windows关机例程暂停的内容 这是来自。覆盖?这是一个非常常见的问题。一个很好的答案是: 如果您不愿意将代码放在Form_Closing事件中,那么我知道的唯一其他选择就是我使用过一两次的“hack”。不必求助于此黑客,但它是: 不要使用正常的关闭按钮。相反,创建表单,使其没有控制框。您可以通过在表单上设置C

如何更改用户在Windows窗体应用程序(C#)中单击关闭(红色X)按钮时发生的情况?

覆盖该方法

注意:您需要检查关闭原因,只有在用户关闭时才改变行为。您不应该在此处放置任何会使Windows关机例程暂停的内容


这是来自。

覆盖?

这是一个非常常见的问题。一个很好的答案是:


如果您不愿意将代码放在Form_Closing事件中,那么我知道的唯一其他选择就是我使用过一两次的“hack”。不必求助于此黑客,但它是:


不要使用正常的关闭按钮。相反,创建表单,使其没有控制框。您可以通过在表单上设置ControlBox=false来实现这一点,在这种情况下,表单顶部仍然会有一个普通条,或者您可以将表单的FormBorderStyle设置为”“没有。如果您走第二条路线,则顶部将没有横过的条或任何其他可见边界,因此您必须通过在窗体上绘制或通过艺术性地使用面板控件来模拟这些条

然后,您可以添加一个标准按钮,使其看起来像一个关闭按钮,并将清理代码放在其中。在按钮事件结束时,只需调用
this.Close()
(C#)或
Me.Close()
(VB)

您可以重写以执行此操作。只是要小心,不要做太意外的事情,因为单击“X”关闭是一种众所周知的行为

protected override void OnFormClosing(FormClosingEventArgs e)
{
    base.OnFormClosing(e);

    if (e.CloseReason == CloseReason.WindowsShutDown) return;

    // Confirm user wants to close
    switch (MessageBox.Show(this, "Are you sure you want to close?", "Closing", MessageBoxButtons.YesNo))
    {
    case DialogResult.No:
        e.Cancel = true;
        break;
    default:
        break;
    }        
}
重写或注册事件

这是在派生表单中重写OnFormClosing函数的示例:

protected override void OnFormClosing(FormClosingEventArgs e)
{
   e.Cancel = true;
}
这是阻止窗体关闭的事件处理程序的示例,可以在任何类中:

private void FormClosing(object sender,FormClosingEventArgs e)
{  
   e.Cancel = true;
}

要获得更高级的功能,请检查FormClosingEventArgs上的CloseReason属性,以确保执行适当的操作。您可能只希望在用户试图关闭表单时执行替代操作。

处理x按钮单击事件非常有用的一种情况是,您使用的表单是MDI容器。原因是关闭和关闭事件首先与子事件一起引发,最后与父事件一起引发。因此,在一个场景中,用户单击x按钮关闭应用程序,MDI父级请求确认继续。如果他决定不关闭应用程序,但继续他正在做的任何事情,那么孩子们将已经处理了关闭事件,可能会丢失任何信息/工作。 一种解决方案是在主应用程序窗体(即关闭的窗体,终止应用程序)中拦截来自Windows消息循环的WM_CLOSE消息,如下所示:


这些答案中缺少的一点,也是新手们可能正在寻找的,就是尽管举办活动很好:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    // do something
}
它不会做任何事,除非你。将其放入类构造函数中:

this.FormClosing += Form1_FormClosing;

正如Jon B所说,但您还需要检查
ApplicationExitCall
TaskManager关闭的原因:

protected override void OnFormClosing(FormClosingEventArgs e)
{
    if (  e.CloseReason == CloseReason.WindowsShutDown 
        ||e.CloseReason == CloseReason.ApplicationExitCall
        ||e.CloseReason == CloseReason.TaskManagerClosing) { 
       return; 
    }
    e.Cancel = true;
    //assuming you want the close-button to only hide the form, 
    //and are overriding the form's OnFormClosing method:
    this.Hide();
}

被接受的答案相当有效。我使用的另一种方法是为主窗体创建FormClosing方法。这与覆盖非常相似。我的示例是一个应用程序,当单击表单上的“关闭”按钮时,该应用程序将最小化到系统托盘

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (e.CloseReason == CloseReason.ApplicationExitCall)
        {
            return;
        }
        else
        {
            e.Cancel = true;
            WindowState = FormWindowState.Minimized;
        }            
    }

这将允许ALT+F4或应用程序中调用Application.Exit()的任何内容在单击(X)时按正常操作将最小化应用程序。

我猜他想最小化到托盘,但你从我那里得到+1,因为我说小心。@Jon B-你应该检查关闭原因。如果Windows正在关闭,您不希望显示消息框。我将它设置为一个switch语句,这样我就不必向右滚动来阅读
=
=
@Philip:那要看情况而定。每次相关时(有更改)都应显示“是否保存”框,取消应取消关机。例如,VS就是这样。应该显示一个恼人的“您想关闭吗”。。。理想情况下,永远不会,但如果你这样做,你应该在关机时绕过它。@Phillip-真的建议这样做吗?我相信大多数应用程序都会问你是否想保存对修改过的文件的更改,而不管关闭的原因是什么。为什么人们在处理关闭事件时会感到不舒服?IMHO添加一个自定义(但令人信服的)关闭按钮并不是那么简单(特别是当你考虑到过渡效果和Aero效果时,你通常不会感到痛苦)。在我链接的答案中,提出问题的人出于某种原因不想使用Form_关闭事件。我不知道他的理由是什么,但他不想使用它。在我使用黑客的时候,我只想要一个外观不同的关闭按钮。换句话说,另一个答案是链接到(足够公平)和复制粘贴的,这就是为什么有一半的答案是不相关的,其余的则推荐一些没有任何理由的东西。如果你要求用户在关机前保存工作,他们是否会提供一个例外?
protected override void OnFormClosing(FormClosingEventArgs e)
{
    if (  e.CloseReason == CloseReason.WindowsShutDown 
        ||e.CloseReason == CloseReason.ApplicationExitCall
        ||e.CloseReason == CloseReason.TaskManagerClosing) { 
       return; 
    }
    e.Cancel = true;
    //assuming you want the close-button to only hide the form, 
    //and are overriding the form's OnFormClosing method:
    this.Hide();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (e.CloseReason == CloseReason.ApplicationExitCall)
        {
            return;
        }
        else
        {
            e.Cancel = true;
            WindowState = FormWindowState.Minimized;
        }            
    }