我有一个 WinForms 应用程序,我需要在关闭表单时显示一个确认对话框,并且它应该关闭整个应用程序。但是,关闭应用程序时会多次出现确认对话框,这不是所需的行为。
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
DialogResult result = MessageBox.Show("Are you sure you want to close the application?", "Confirm Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.No)
{
e.Cancel = true; // Cancel the form closing
return;
}
else
{
// Close the entire application
Application.Exit();
}
}
}
如何确保关闭表单时确认对话框只显示一次?
是否有更有效的方法来处理关闭多个表单并仅显示一次确认对话框?
确认对话框旨在确认用户是否要关闭整个应用程序。
应用程序中还打开了其他表单,这些表单也应在主表单关闭时关闭。
仔细阅读您的代码和项目符号项目,我的理解是您有一个应用程序的主表单,并且有可以同时和非模式显示的“多个表单”,其可见性可以根据用户认为合适的方式来来去去。一般情况下的最小示例可能如下所示:
因此,您可以尝试简化
MainForm.OnFormClosing()
,它将由代码中任何位置的“任何”Application.Exit
调用调用。不需要在这里检查 CloseReason
,通过在 this
中传递 Show(this)
,可以确保子窗体在 Z 顺序中保持在主窗体的顶部,并在 MainForm
时进行处理确实如此(调试写入将证明)。
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
buttonShowFormA.Click += (sender, e) => _formA.Show(this);
buttonShowFormB.Click += (sender, e) => _formB.Show(this);
_formA.VisibleChanged += (sender, e) => buttonShowFormA.Enabled = !_formA.Visible;
_formB.VisibleChanged += (sender, e) => buttonShowFormB.Enabled = !_formB.Visible;
#if DEBUG
_formA.Disposed += (sender, e) => Debug.WriteLine("Disposing Form A");
_formB.Disposed += (sender, e) => Debug.WriteLine("Disposing Form B");
#endif
}
ChildFormA _formA = new() { StartPosition = FormStartPosition.Manual };
ChildFormB _formB = new () { StartPosition = FormStartPosition.Manual };
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_formA.Location = new() { X = Right + 10, Y = Top };
_formB.Location = new() { X = Right + 10, Y = Top + _formA.Height + 10 };
_formA.Show(this);
_formB.Show(this);
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
DialogResult result = MessageBox.Show("Are you sure you want to close the application?", "Confirm Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.No)
{
e.Cancel = true; // Cancel the form closing
return;
}
}
}
CloseReason
在子窗体中很重要,因为我们需要更改窗体关闭时窗口 Form
所处理的 Handle
行为(当能够循环子窗体时,这是一个大问题)需要反复形成可见性)。
处理此问题的常见方法是取消
Close
并将其转换为 Hide
形式,只有当 Close
是应用程序退出或其他与系统相关的关闭时才允许 CloseReason
继续进行。
public partial class ChildFormA : Form
{
public ChildFormA()
{
InitializeComponent();
buttonClose.Click += (sender, e) => Close();
buttonExit.Click += (sender, e) => Application.Exit();
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
switch (e.CloseReason)
{
case CloseReason.UserClosing:
e.Cancel = true;
Hide();
break;
}
}
}
这个基本示例应该能够触及您问题中的大部分要点。