У меня есть приложение 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();
}
}
}
Как я могу гарантировать, что диалоговое окно подтверждения отображается только один раз при закрытии формы?
Есть ли более эффективный способ закрытия нескольких форм и отображения диалогового окна подтверждения только один раз?
Диалоговое окно подтверждения предназначено для подтверждения того, хочет ли пользователь закрыть все приложение.
В приложении открыты и другие формы, которые также следует закрыть при закрытии основной формы.
нам нужно знать, где находится размещенный код (в какой форме) и связь между всеми различными открытыми формами (какая форма какую открывает)
Это должно работать, если вы поместите этот код только в основную форму. В противном случае у вас может быть глобальное поле/свойство (например, ClosingDialogConfirmed), которое можно установить один раз, а затем просто использовать его для остальных форм...
Сначала я пропустил ссылку на ваше изображение, но когда я ее преобразовал, понял, что здесь может быть задействован вход в систему. Таким образом, в дополнение к общему случаю, описанному в моем ответе ниже, эти ответы «может или не может» дают дополнительную ясность относительно уникальных проблем, которые возникают, когда вы показываете логин или заставку до отображения основной формы: stackoverflow.com/a /75534137/5438626 stackoverflow.com/a/74736871/5438626
Внимательно читая ваш код и элементы маркеров, я понимаю, что у вас есть основная форма для приложения и «несколько форм», которые могут отображаться одновременно и немодально, видимость которых может появляться и исчезать по усмотрению пользователя. Минимальный пример общего случая может выглядеть так:
Таким образом, вы можете поэкспериментировать с упрощением MainForm.OnFormClosing()
, которое будет вызываться «любым» Application.Exit
вызовом из любого места кода. Здесь не должно быть никакой необходимости проверять CloseReason
, и, передав this
в Show(this)
, это гарантирует, что дочерние формы останутся поверх основной формы в Z-порядке и удалятся, когда MainForm
это сделает (как запишет отладочная запись ). Чтобы уточнить это, нет необходимости вызывать ApplicationExit()
здесь, потому что, если закрывается основная форма, а подсказка не отменяет ее, приложение закроется.
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
is из приложения или какое-либо другое завершение работы системы.
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;
}
}
}
Надеемся, что этот базовый пример затронет большинство пунктов вашего вопроса. Установка указателя this
при отображении других форм будет иметь большое значение для того, чтобы окна вели себя так, как вы ожидаете.
Вот код, который я использовал для проверки этого ответа, если это поможет. Клон
Я попытался воссоздать проблему, и ваш код работает отлично. Думаю, проблема в другом. Была ли форма входа в систему вашей формой запуска (основной)?
вот код, который совпадает с вашим, однако я пропустил
Application.Exit();
поскольку это не требуется, если вы на самом деле закрываете основную форму, однако, если вы вызываете ее из дочерней формы, это вызовет событие FormClosing в других формах, включая вход в систему (если он не основной)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
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;
}
}
}
}
Это форма администратора сайта, вызывающая все диалоговые окна подтверждения, или диалоги происходят из нескольких разных форм?