我的作業系統是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 #endregion using 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 - FormClosing事件- CloseReason.UserClosing
窗體B - Forma. MdiFormClosing
窗體A - FormClosed事件- CloseReason.UserClosing
3、如果窗體A是窗體B的owner,那麼事件的調用順序是:
窗體B - FormsClosing- CloseReason.Form體A - FormClosing事件- CloseReason.UserClosing
窗體B - FormClosed事件- CloseReason.FormOwnerClosing
窗體A - FormClosed事件- CloseReason.UserClosing
窗體A - FormClosed事件- CloseReason.UserClosing