C# FormClosing事件在使用退出按钮后激发两次

C# FormClosing事件在使用退出按钮后激发两次,c#,winforms,C#,Winforms,我有一个退出表单的按钮,这是代码 DialogResult dialogResult = MessageBox.Show("Are you sure you want to exit?", "Exit Program?", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.No) { } else { Application.Exit(); } 我尝试使用

我有一个退出表单的按钮,这是代码

    DialogResult dialogResult = MessageBox.Show("Are you sure you want to exit?", "Exit Program?", MessageBoxButtons.YesNo);
    if (dialogResult == DialogResult.No)
    {
    }
    else
    {
        Application.Exit();
    }
我尝试使用调试器模式,单击“是”后,它将通过Application.Exit(),然后触发FormClosing事件,然后运行相同的对话框

我还尝试删除FormClosing事件中的代码,使其仅包含Application.Exit(),但使用Alt+F4或单击X按钮将自动退出应用程序

我的问题是,如果用户想退出程序,但不想启动对话框两次,我如何询问用户


提前谢谢,我要告诉大家我只是一个初学者,这是我最大的项目,所以我想把它做好。

实现这一点有两种方法

  • 通过取消订阅“偶数”按钮,单击
  • 正如stuartd的回答中所建议的,检查关闭的原因(但他的回答中有一个问题,因此在fix中也添加了这种方法,因此它将帮助未来的人。)
我假设,在这两种情况下,您都需要这个确认,button click和'x'button click,您在这两个处理程序中都放了相同的代码

方法一

在按钮的处理程序中,当您请求用户确认并且用户是否单击“是”时,单击按钮。 在排队之前

Application.Exit();
您应该取消订阅表单关闭事件。这样,它在执行Application.Exit()时不能引发窗体关闭事件

假设您的表单是MainForm,事件是MainForm\u Closing,它看起来像

    private void btnClose_Click(object sender, EventArgs e)
    {
        DialogResult dialogResult = MessageBox.Show("Are you sure you want to exit?", "Exit Program?", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            this.FormClosing -= MainForm_FormClosing;
            Application.Exit();
        }
    }
因此,在执行
Application.Exit()
时,它不会引发表单关闭事件,因此您的问题将得到解决

方法二

正如stuartd所建议的(我认为这是一种更为简洁的方式,+1),您可以在
表单关闭
事件处理程序中检查表单关闭原因

注意他的示例代码中有一个小问题(bug)[您已经接受了这个答案!!]。错误点击
'x'按钮
Alt+F4
后;如果用户单击确认消息上的“否”,则由于没有对else条件的处理,所以也将关闭too表单。正确的解决方案如下

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                DialogResult dialogResult = MessageBox.Show("Are you sure you want to exit?", "Exit Program?", MessageBoxButtons.YesNo);
                if (dialogResult == DialogResult.Yes)
                    Application.Exit();
                else
                    e.Cancel = true;    //stopping Form Close perocess.
            }
        }

有两种方法可以实现这一点

  • 通过取消订阅“偶数”按钮,单击
  • 正如stuartd的回答中所建议的,检查关闭的原因(但他的回答中有一个问题,因此在fix中也添加了这种方法,因此它将帮助未来的人。)
我假设,在这两种情况下,您都需要这个确认,button click和'x'button click,您在这两个处理程序中都放了相同的代码

方法一

在按钮的处理程序中,当您请求用户确认并且用户是否单击“是”时,单击按钮。 在排队之前

Application.Exit();
您应该取消订阅表单关闭事件。这样,它在执行Application.Exit()时不能引发窗体关闭事件

假设您的表单是MainForm,事件是MainForm\u Closing,它看起来像

    private void btnClose_Click(object sender, EventArgs e)
    {
        DialogResult dialogResult = MessageBox.Show("Are you sure you want to exit?", "Exit Program?", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            this.FormClosing -= MainForm_FormClosing;
            Application.Exit();
        }
    }
因此,在执行
Application.Exit()
时,它不会引发表单关闭事件,因此您的问题将得到解决

方法二

正如stuartd所建议的(我认为这是一种更为简洁的方式,+1),您可以在
表单关闭
事件处理程序中检查表单关闭原因

注意他的示例代码中有一个小问题(bug)[您已经接受了这个答案!!]。错误点击
'x'按钮
Alt+F4
后;如果用户单击确认消息上的“否”,则由于没有对else条件的处理,所以也将关闭too表单。正确的解决方案如下

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                DialogResult dialogResult = MessageBox.Show("Are you sure you want to exit?", "Exit Program?", MessageBoxButtons.YesNo);
                if (dialogResult == DialogResult.Yes)
                    Application.Exit();
                else
                    e.Cancel = true;    //stopping Form Close perocess.
            }
        }

这里有一个例子。它只要求用户确认关闭是否是由用户发起的-您可能不希望在Windows重新启动时弹出消息框

private void form_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.UserClosing)
    {
        DialogResult dialogResult = MessageBox.Show("Are you sure you want to exit?", "Exit Program?", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            Application.Exit();
        }
    }
    else 
    {
        // Cancel the close
        e.Cancel = true;
    }
 }

这里有一个例子。它只要求用户确认关闭是否是由用户发起的-您可能不希望在Windows重新启动时弹出消息框

private void form_FormClosing(object sender, FormClosingEventArgs e)
{
    if (e.CloseReason == CloseReason.UserClosing)
    {
        DialogResult dialogResult = MessageBox.Show("Are you sure you want to exit?", "Exit Program?", MessageBoxButtons.YesNo);
        if (dialogResult == DialogResult.Yes)
        {
            Application.Exit();
        }
    }
    else 
    {
        // Cancel the close
        e.Cancel = true;
    }
 }

这个问题有点不清楚:您发布的代码是在按钮处理程序中,还是在
FormClosed
处理程序中,还是在两者中?如果不同,请显示
FormClosed
处理程序。如果是相同的,那么问题就显而易见了。对传递给您的对象的属性添加一个检查。如果是
ApplicationExitCall
,则不显示对话框。它们具有相同的代码,然后我尝试删除代码,只保留应用程序。退出,然后我运行程序并单击X或关闭按钮,它将自动关闭,无对话框检查描述表单关闭事件原因的事件参数。IMHO,要求确认关闭的应用程序对我来说似乎很烦人,除非在某些用例中有未保存的数据延迟,我在您的示例中没有看到。这个问题有点不清楚:您发布的代码是在按钮处理程序中,还是在
表单关闭处理程序中,还是在两者中?如果不同,请显示
FormClosed
处理程序。如果是相同的,那么问题就显而易见了。对传递给您的对象的属性添加一个检查。如果是
ApplicationExitCall
,则不显示对话框。它们具有相同的代码,然后我尝试删除代码,只保留应用程序。退出,然后我运行程序并单击X或关闭按钮,它将自动关闭,无对话框检查描述表单关闭事件原因的事件参数。IMHO,要求确认关闭的应用程序对我来说似乎很烦人,除非在某些情况下有未保存的数据延迟,我在您的示例中没有看到。我尝试取消订阅该事件,但使用Alt+F4或单击X按钮将显示任何对话框以进行确认。任何对话框是什么意思?如果在取消订阅eve后,与您在表单关闭事件中放置的相同