В MSDN я узнал CloseReason.UserClosing
, что пользователь решил закрыть форму, но я предполагаю, что это то же самое, как при нажатии кнопки X, так и при нажатии кнопки закрытия. Итак, как я могу различить эти два в моем коде?
Спасибо всем.
В MSDN я узнал CloseReason.UserClosing
, что пользователь решил закрыть форму, но я предполагаю, что это то же самое, как при нажатии кнопки X, так и при нажатии кнопки закрытия. Итак, как я могу различить эти два в моем коде?
Спасибо всем.
Ответы:
Предполагая, что вы запрашиваете WinForms, вы можете использовать событие FormClosing () . Событие FormClosing () запускается каждый раз, когда форма закрывается.
Чтобы определить, щелкнул ли пользователь X или вашу CloseButton, вы можете получить его через объект-отправитель. Попробуйте передать отправителя как элемент управления Button и, возможно, проверьте его имя, например, «CloseButton».
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
if (string.Equals((sender as Button).Name, @"CloseButton"))
// Do something proper to CloseButton.
else
// Then assume that X has been clicked and act accordingly.
}
В противном случае мне никогда не приходилось различать, был ли нажат X или CloseButton, поскольку я хотел выполнить что-то конкретное в событии FormClosing, например, закрыть все MdiChildren перед закрытием MDIContainerForm или проверить события на наличие несохраненных изменений. В этих обстоятельствах, по моему мнению, нам не нужно различать ни одну из кнопок.
Закрытие с помощью ALT+ F4также вызовет событие FormClosing (), поскольку оно отправляет в форму сообщение о закрытии. Вы можете отменить событие, установив
FormClosingEventArgs.Cancel = true.
В нашем примере это будет выглядеть так:
e.Cancel = true.
Обратите внимание на разницу между событиями FormClosing () и FormClosed () .
FormClosing происходит, когда форма получила сообщение, которое нужно закрыть, и проверяет, есть ли у нее что-то делать, прежде чем она будет закрыта.
FormClosed возникает, когда форма фактически закрыта, то есть после закрытия.
Это помогает?
CloseReason
Перечисление вы нашли на MSDN только с целью проверки закрыта ли пользователь приложение, или это было связано с простою, или закрывается менеджером задач, и т.д ...
Вы можете выполнять разные действия в зависимости от причины, например:
void Form_FormClosing(object sender, FormClosingEventArgs e)
{
if(e.CloseReason == CloseReason.UserClosing)
// Prompt user to save his data
if(e.CloseReason == CloseReason.WindowsShutDown)
// Autosave and clear up ressources
}
Но, как вы уже догадались, нет никакой разницы между нажатием кнопки x, щелчком правой кнопкой мыши на панели задач и щелчком «закрыть», или нажатием Alt F4и т. Д. Все это заканчивается CloseReason.UserClosing
причиной.
Кнопка «X» регистрируется, DialogResult.Cancel
поэтому еще один вариант - оценить DialogResult
.
Если у вас есть несколько кнопок в вашей форме, вы, вероятно, уже связываете разные DialogResult
s с каждой, и это предоставит вам средства, чтобы определить разницу между каждой кнопкой.
(Пример: btnSubmit.DialogResult = DialogResult.OK
, btnClose.DialogResult = Dialogresult.Abort
)
public Form1()
{
InitializeComponent();
this.FormClosing += Form1_FormClosing;
}
/// <summary>
/// Override the Close Form event
/// Do something
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
//In case windows is trying to shut down, don't hold the process up
if (e.CloseReason == CloseReason.WindowsShutDown) return;
if (this.DialogResult == DialogResult.Cancel)
{
// Assume that X has been clicked and act accordingly.
// Confirm user wants to close
switch (MessageBox.Show(this, "Are you sure?", "Do you still want ... ?", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
//Stay on this form
case DialogResult.No:
e.Cancel = true;
break;
default:
break;
}
}
}
DialogResult
остается None
. В чем может быть проблема?
X
заставляет DialogResult
сдерживать Cancel
, а не None
. Назначение None
вашей кнопке - то же самое, что и отсутствие установки ее .DialogResult
свойства, и если вы вызываете form.Close()
из обработчика событий вашей кнопки, он form.DialogResult
будет содержать Cancel
. Только присвоение значения, отличного от None
или Cancel
для всех кнопок закрытия формы, позволит вам сделать желаемое различие.
Close()
кода?Вы не можете полагаться на причину закрытия аргументов события закрытия формы, потому что, если пользователь нажимает кнопку X в строке заголовка или закрывает форму с помощью Alt + F4 или использует системное меню, чтобы закрыть форму, или форма закрывается путем вызова Close()
метода, все все Вышеуказанные случаи, причина закрытия будет закрыта пользователем, что не является желаемым результатом.
Чтобы определить, закрыта ли форма кнопкой X или Close
методом, вы можете использовать любой из следующих вариантов:
WM_SYSCOMMAND
проверить SC_CLOSE
и установить флаг.StackTrace
содержит ли какой-либо из кадров Close
вызов метода.Пример 1 - Ручка WM_SYSCOMMAND
public bool ClosedByXButtonOrAltF4 {get; private set;}
private const int SC_CLOSE = 0xF060;
private const int WM_SYSCOMMAND = 0x0112;
protected override void WndProc(ref Message msg)
{
if (msg.Msg == WM_SYSCOMMAND && msg.WParam.ToInt32() == SC_CLOSE)
ClosedByXButtonOrAltF4 = true;
base.WndProc(ref msg);
}
protected override void OnShown(EventArgs e)
{
ClosedByXButtonOrAltF4 = false;
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (ClosedByXButtonOrAltF4)
MessageBox.Show("Closed by X or Alt+F4");
else
MessageBox.Show("Closed by calling Close()");
}
Пример 2 - Проверка StackTrace
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (new StackTrace().GetFrames().Any(x => x.GetMethod().Name == "Close"))
MessageBox.Show("Closed by calling Close()");
else
MessageBox.Show("Closed by X or Alt+F4");
}
StackTrace()
и это решило проблему.
Он определяет, когда закрыть приложение, если форма закрыта (если ваше приложение не привязано к определенной форме).
private void MyForm_FormClosed(object sender, FormClosedEventArgs e)
{
if (Application.OpenForms.Count == 0) Application.Exit();
}
Я всегда использую метод закрытия формы в своих приложениях, который улавливает alt + x от моей кнопки выхода, alt + f4 или другое событие закрытия формы было инициировано. Все мои классы имеют имя класса, определенное mstrClsTitle = "grmRexcel"
в данном случае как частная строка , метод Exit, который вызывает метод закрытия формы и метод закрытия формы. У меня также есть заявление о методе закрытия формы - this.FormClosing = My Form Closing Form Closing method name
.
Код для этого:
namespace Rexcel_II
{
public partial class frmRexcel : Form
{
private string mstrClsTitle = "frmRexcel";
public frmRexcel()
{
InitializeComponent();
this.FormClosing += frmRexcel_FormClosing;
}
/// <summary>
/// Handles the Button Exit Event executed by the Exit Button Click
/// or Alt + x
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnExit_Click(object sender, EventArgs e)
{
this.Close();
}
/// <summary>
/// Handles the Form Closing event
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void frmRexcel_FormClosing(object sender, FormClosingEventArgs e)
{
// ---- If windows is shutting down,
// ---- I don't want to hold up the process
if (e.CloseReason == CloseReason.WindowsShutDown) return;
{
// ---- Ok, Windows is not shutting down so
// ---- either btnExit or Alt + x or Alt + f4 has been clicked or
// ---- another form closing event was intiated
// *) Confirm user wants to close the application
switch (MessageBox.Show(this,
"Are you sure you want to close the Application?",
mstrClsTitle + ".frmRexcel_FormClosing",
MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
// ---- *) if No keep the application alive
//---- *) else close the application
case DialogResult.No:
e.Cancel = true;
break;
default:
break;
}
}
}
}
}
Вы можете попробовать добавить обработчик событий из дизайна следующим образом: откройте форму в режиме просмотра, откройте окно свойств или нажмите F4, нажмите кнопку панели инструментов событий, чтобы просмотреть события в объекте Form, найдите событие FormClosing в группе Behavior и дважды щелкните его. Ссылка: https://social.msdn.microsoft.com/Forums/vstudio/en-US/9bdee708-db4b-4e46-a99c-99726fa25cfb/how-do-i-add-formclosing-event?forum=csharpgeneral
if (this.DialogResult == DialogResult.Cancel)
{
}
else
{
switch (e.CloseReason)
{
case CloseReason.UserClosing:
e.Cancel = true;
break;
}
}
Если условие будет выполнено, когда пользователь щелкнет «X» или кнопку закрытия формы. Else можно использовать, когда пользователь нажимает Alt + F4 для любой другой цели.
namespace Test
{
public partial class Member : Form
{
public Member()
{
InitializeComponent();
}
private bool xClicked = true;
private void btnClose_Click(object sender, EventArgs e)
{
xClicked = false;
Close();
}
private void Member_FormClosing(object sender, FormClosingEventArgs e)
{
if (xClicked)
{
// user click the X
}
else
{
// user click the close button
}
}
}
}
Я согласен с DialogResult
-Решением, как с более прямым.
Однако в VB.NET требуется приведение типов для получения CloseReason
-Property
Private Sub MyForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
Dim eCast As System.Windows.Forms.FormClosingEventArgs
eCast = TryCast(e, System.Windows.Forms.FormClosingEventArgs)
If eCast.CloseReason = Windows.Forms.CloseReason.None Then
MsgBox("Button Pressed")
Else
MsgBox("ALT+F4 or [x] or other reason")
End If
End Sub
Мне также пришлось зарегистрировать закрывающую функцию внутри метода формы "InitializeComponent ()":
private void InitializeComponent() {
// ...
this.FormClosing += FrmMain_FormClosing;
// ...
}
Моя функция "FormClosing" похожа на данный ответ ( https://stackoverflow.com/a/2683846/3323790 ):
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e) {
if (e.CloseReason == CloseReason.UserClosing){
MessageBox.Show("Closed by User", "UserClosing");
}
if (e.CloseReason == CloseReason.WindowsShutDown){
MessageBox.Show("Closed by Windows shutdown", "WindowsShutDown");
}
}
Еще одна вещь, о которой стоит упомянуть: существует также функция "FormClosed", которая появляется после "FormClosing". Чтобы использовать эту функцию, зарегистрируйте ее, как показано ниже:
this.FormClosed += MainPage_FormClosed;
private void MainPage_FormClosing(object sender, FormClosingEventArgs e)
{
// your code after the form is closed
}