我的作業系統是Win7旗艦版,VS版本是VS2012,.NET版本為.NET Framework 4.5。
在表單的FormClosing事件,第二個參數(FormClosingEventArgs類型)下有一個枚舉變數CloseReason,在表單的FormClosed事件,第二個參數(FormClosedEventArgs類型)下也有一個枚舉變數CloseReason 。這個CloseReason枚舉在命名空間System.Windows.Forms下。
如下段代碼所示,CloseReason在表單FormClosing事件的FormClosingEventArgs類型變數e中。
private void FormMain_FormClosing(object sender, FormClosingEventArgs e){ switch (e.CloseReason) { case CloseReason.None: { MessageBox.Show("Closing: CloseReason.None"); } break; case CloseReason.WindowsShutDown: { MessageBox.Show("Closing: CloseReason.WindowsShutDown"); } break; case CloseReason.MdiFormClosing: { MessageBox.Show("Closing: CloseReason.MdiFormClosing"); } break; case CloseReason.UserClosing: { MessageBox.Show("Closing: CloseReason.UserClosing"); } break; case CloseReason.TaskManagerClosing: { MessageBox.Show("Closing: CloseReason.TaskManagerClosing"); } break; case CloseReason.FormOwnerClosing: { MessageBox.Show("Closing: CloseReason.FormOwnerClosing"); } break; case CloseReason.ApplicationExitCall: { MessageBox.Show("Closing: CloseReason.ApplicationExitCall"); } break; }}
從中繼資料看,該枚舉一共有下面7個枚舉值:
#region 程式集 System.Windows.Forms.dll, v4.0.0.0// C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Windows.Forms.dll#endregionusing System;namespace System.Windows.Forms{ // 摘要: // 指定表單關閉的原因。 public enum CloseReason { // 摘要: // 關閉原因未定義或者無法確定。 None = 0, // // 摘要: // 作業系統正在關閉所有應用程式以便準備關機。 WindowsShutDown = 1, // // 摘要: // 此多重文件介面 (MDI) 表單的父表單正在關閉。 MdiFormClosing = 2, // // 摘要: // 使用者正在通過使用者介面 (UI) 關閉該表單,例如通過單擊表單視窗上的“關閉”按鈕,通過選擇視窗控制功能表上的“關閉”按鈕,或者通過按 Alt+F4 // 等方式關閉。 UserClosing = 3, // // 摘要: // Microsoft Windows 工作管理員正在關閉應用程式。 TaskManagerClosing = 4, // // 摘要: // 所有者表單正在關閉。 FormOwnerClosing = 5, // // 摘要: // System.Windows.Forms.Application 類的 System.Windows.Forms.Application.Exit() // 方法被調用。 ApplicationExitCall = 6, }}
該枚舉的MSDN可以參考頁面:
https://msdn.microsoft.com/en-us/library/system.windows.forms.closereason(v=vs.110).aspx
除去None類型,本文對6種枚舉值都進行了測試,在此記錄下測試的結果。
1、CloseReason.WindowsShutDown
當Windows被登出、關閉時觸發此CloseReason,不過不要在這裡加入MessageBox等元素,因為一旦Windows發現當前程式遲遲關不掉,就會將此程式強制關閉。
2、CloseReason.MdiFormClosing
當前表單為Mdi子表單時,Mdi容器表單被關閉時,在觸發當前的FormClosing和FormClosed事件時提示此CloseReason。
將當前表單作為MdiParent開啟另一表單的方法:
FormChild formChild = new FormChild();formChild.MdiParent = this;formChild.Show();
(需要將本表單的IsMdiContainer設定為True)
3、CloseReason.UserClosing
使用者手動關閉當前程式,比如調用Close()函數,或點擊程式右上方的“×”,關閉原因都是CloseReason.UserClosing。
4、CloseReason.TaskManagerClosing
由工作管理員關閉視窗時,會觸發此事件,但我在測試的時候發現,工作管理員關閉視窗具有一定的強制性。設定斷點後可發現,FormClosing事件觸發後不久程式就會被工作管理員強制關閉,這個時間非常短,因此不適合在此做一些諸如彈出MessageBox的事情(因為沒有用)。
5、CloseReason.FormOwnerClosing
類似CloseReason.MdiFormClosing,如果表單A是表單B的owner,則表單A關閉時,表單B觸發FormClosing和FormClosed事件時使用此CloseReason。
關於表單作為owner的問題,可以參考MSDN頁面:
https://msdn.microsoft.com/en-us/library/system.windows.window.owner(v=vs.110).aspx
將當前表單作為Owner開啟另一個表單的方法:
FormChild formChild2 = new FormChild();formChild2.Owner = this;formChild2.Show();
6、CloseReason.ApplicationExitCall
調用Application.Exit()方法退出程式時,CloseReason為此值。
最後再說下FormClosing、FormClosed事件的調用順序:
1、FormClosing事件在表單關閉前觸發,FormClosed事件在表單關閉後觸發
2、如果表單A是mdi容器,表單B的mdi-parent是表單A,那麼事件的調用順序是:
表單B - FormClosing事件 - CloseReason.MdiFormClosing
表單A - FormClosing事件 - CloseReason.UserClosing
表單B - FormClosed事件 - CloseReason.MdiFormClosing
表單A - FormClosed事件 - CloseReason.UserClosing
3、如果表單A是表單B的owner,那麼事件的調用順序是:
表單B - FormClosing事件 - CloseReason.FormOwnerClosing
表單A - FormClosing事件 - CloseReason.UserClosing
表單B - FormClosed事件 - CloseReason.FormOwnerClosing
表單A - FormClosed事件 - CloseReason.UserClosing