Приложение остается открытым при использовании Owner.Show() для основной формы
Я получил две формы, основную и вторую. Поскольку я хочу легко перемещаться между ними, избегая создания нескольких экземпляров каждого, я использовал это в главной форме:
Form2 secondForm = new Form2();
private void btnForm2_Click(object sender, EventArgs e)
{
secondForm.Show(this);
Hide();
}
и код ниже во второй форме:
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
e.cancel = true;
Owner.Show();
Hide();
}
Все работает просто отлично, кроме того, что я не могу закрыть приложение. Когда я перехожу во вторую форму и возвращаюсь к основному, кнопка закрытия вообще ничего не работает.
Как я могу закрыть программу, пока я все еще использую этот код?
Я также попробовал этот код, чтобы увидеть, работает ли кнопка закрытия сама:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
MessageBox.Show("Closing");
}
MessageBox был показан, но после этого ничего не произошло.
4 ответа
Это происходит потому, что вторая форма не закрыта - вы используете для нее e.cancel = true. Добавьте следующую строку, если вы хотите принудительно закрыть все окна приложения
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
System.Windows.Forms.Application.Exit();
}
затем в form2 вы можете проверить, направлено ли закрытие от пользователя или из приложения:
void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
//close button click by user on form 2
if(e.CloseReason == CloseReason.UserClosing)
e.cancel = true //cancel event
else
e.cancel = false //close this form
}
Или вы можете использовать CloseReason.UserClosing для направления вашей отмены в зависимости от родства. Например:
void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
//check if closing signal is from parent
if (e.CloseReason == CloseReason.UserClosing.FormOwnerClosing)
e.cancel = false //close this form
else
e.cancel = true
}
Я предпочитаю простые решения.
В Form1_FormClosing используйте:
secondForm.Close();
А вот и изюминка. В Form2_FormClosing оберните код, который у вас уже есть:
if (this.Visible)
{
...
}
И это работает для меня. Когда я закрываю основную форму, она закрывается, поскольку Form2 не видна и не знает, чтобы отменить закрытие.
Поскольку в ответе указана Environment.Exit(0); получил голосование, см. winforms - Как правильно выйти из приложения C#? - Переполнение стека. Он цитирует MSDN, говоря, что это для консольных приложений. Я не вижу этого в текущей документации, но она все еще актуальна. Также см. Application.Exit() против Application.ExitThread() против Environment.Exit (). Похоже, что соглашение между Environment.Exit, Application.ExitTread и Application.Exit, Application.Exit представляется наилучшим. Однако я не буду использовать ни один из них, кроме как ненормально прекратить работу моего приложения, например, из-за ошибки.
Закрытие Form1 "пытается" закрыть форму2. Запускает событие Form2_Closing, которое отменяет закрытие и запускает form1.
Код с отменой подписки на события (быстрый и грязный), обратите внимание на внутренний модификатор в Form2. Вы можете рассмотреть вопрос о том, чтобы сделать подписку "Стоп / начать" в качестве методов
private void btnForm2_Click(object sender, EventArgs e)
{
secondForm.FormClosing += secondForm.Form2_FormClosing;
secondForm.Show(this);
Hide();
}
internal void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
FormClosing -= Form2_FormClosing;
Owner.Show();
Hide();
}
После публикации я понял, что вы можете использовать свойство FormClosingEventArgs.CloseReason для более простого решения:
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.FormOwnerClosing) { return; }
e.Cancel = true;
Owner.Show();
Hide();
}