Per chiudere un form in linea generale sono disponibili due modi :
invocare il metodo Close();
premere il pulsante di chiusura in alto a destra, che invia il comando di chiusura del Windows Menu (formalmente concito come system o control menu);
In realtà la form può chiudersi anche per altri motivi ad esempio se viene richiesto un riavvio.
Nel .NET Framework 2.0 l'oggetto FormClosingEventArgs dell'evento FormClosing ha una proprietà CloseReason che ci permette di identificare il motivo che scatenato la chiusura (per maggior informazioni si veda il seguente link Enumerazione CloseReason (System.Windows.Forms). Questo enumerativo sebbene ci consenta di capire cosa ha scatenato la chiusura del form non ci consente di discriminare in quale dei due modi è avvenuta. Infatti in entrambi i casi la proprietà CloseReason vale UserClosing.
Una soluzione, funzionante con tutte le versioni del framework, per discriminare se la chiusura del form è avvenuta tramite il pulsante Chiudi della finestra è quella di ricorrere al metodo WndProc (ereditato dalla classe Control) come mostrato nel seguente esempio:
VB.NET
Private Const SC_CLOSE As Integer = &HF060
Private Const WM_SYSCOMMAND As Integer = &H112
Private _closeClick As Boolean = False
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
If m.Msg = WM_SYSCOMMAND And m.WParam.ToInt32 = SC_CLOSE Then
Me._closeClick = True
End If
MyBase.WndProc(m)
End Sub
Private Sub Form1_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
If Me._closeClick Then
MessageBox.Show("X button pressed!")
End If
End Sub
C#
private int SC_CLOSE = 0xF060;
private int WM_SYSCOMMAND = 0x112;
private bool _closeClick = false;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_SYSCOMMAND & m.WParam.ToInt32() == SC_CLOSE)
{
this._closeClick = true;
}
base.WndProc(ref m);
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (this._closeClick)
{
MessageBox.Show("X button pressed!");
}
}