模態對話方塊和非模態對話方塊的建立與銷燬
首先宣告:在網上看了很多資料,很多內容也是從別人那裡學到的,只是結合自己的使用寫下來。
在VS中對話方塊分兩種:模態對話方塊和非模態對話方塊。
模態對話方塊就是一旦我被打開了,就得完全做我的事情,只有把我關了,你才能做其他的事情。
非模態對話方塊就是你把我打開了,可以去幹點別的,什麼時候想起我來了,就用用,甚至可以直接把我滅了。
- 不管要哪種對話方塊,以下兩步必須得做:
1、在資源中(或者其他地方)新增一個Dialog資源;
圖1. 新建對話方塊資源
2、右鍵 在【Add class 】,為你新建的對話方塊加新建一個類,為什麼要新增類呢?因為面向物件程式設計,後續你要使用這個對話方塊,總得有個東西代表這個對話方塊吧!
圖2中①處寫對話方塊類的名稱,一般以C****,代表類。
②處選擇類的基類,我只選過CDialog和CDialogEx,後者是前者的派生,介面更美化了點。
③處世自動產生的兩個關於這個類的檔案。
圖2. 新增對話方塊類
下一步就是如何呼叫?如何銷燬?
- 對話方塊的呼叫。
模態:
CTestDlg d1; d1.DoModal();//推薦使用
兩句就可以了,建立顯示都自動完成。也可以用CTestDlg *d1=new CTestDlg;d1->DoModal();,但是要顯示的在後面新增delete d1.
非模態:
CTestDlg *pDlg=new CTestDlg;
pDlg->Create
pDlg->ShowWindow(SW_SHOW);
對於非模態對話方塊最好使用new建立物件,如果是直接建立一個區域性物件,在函式結束時對話方塊就消失了,因為非模態對話方塊是一建立好就返回,而模態對話方塊是要等到關閉了對話方塊才返回,所以模態對話方塊可以使用區域性物件。也可以採用全域性物件來解決非模態對話方塊的作用域問題。
- 對話方塊的銷燬
一個對話方塊關閉時,根據關閉的方法不同,會呼叫OnOK(剛開始建立對話方塊預設的【確定】按鈕裡面的呼叫的這個函式)或OnCancle(剛開始建立對話方塊預設的【取消】按鈕裡面的呼叫的這個函式)或者OnClose(右上角的×),然後會呼叫OnDestroy()——OnNcDestroy()——PostNcDestroy(),完全結束
關閉模態對話方塊,只需要使用預設的函式就能正常關閉。刪除動態建立的物件就像上面下劃線標記即可。
MFC應用程式中關閉模式對話方塊的順序
1.OnClose() 訊息響應函式,響應WM_CLOSE訊息,當"關閉"按鈕被單擊的時候,該函式被呼叫
2.OnKillFocus() 訊息響應函式,響應WM_KILLFOCUS訊息,當一個視窗即將失去鍵盤輸入焦點以前被髮送
3.OnDestroy() 訊息響應函式,響應WM_DESTROY訊息,當一個視窗即將被銷燬時,被髮送
4.OnNcDestroy() 訊息響應函式,響應WM_NCDESTROY訊息,當一個視窗被銷燬以後被髮送
5.PostNcDestroy() 過載函式,作為處理OnNcDestroy()函式的最後動作被CWnd呼叫
對於非模態對話方塊,新新增的對話方塊類必須過載 OnCancel() 和 PostNcDestroy()函式。
預設的CDialog::OnOK和CDialog::OnCancel函式均呼叫EndDialog,故程式設計師必須編寫自己的OnOK和OnCancel函式並且在函式中呼叫DestroyWindow來關閉對話方塊。在OnCancel()函式中刪除原來的,重新新增DestroyWindow();。
在螢幕上一個視窗被刪除後,框架會呼叫CWnd::PostNcDestroy,這是一個虛擬函式,程式可以在該函式中完成刪除視窗物件的工作。在PostNcDestroy() 函式的程式碼中新增delete this。
MFC應用程式關閉視窗的順序(非模態視窗)
1.OnClose() 訊息響應函式,響應視窗的WM_CLOSE訊息,當關閉按鈕被單擊的時候傳送此訊息
2.OnDestroy() 訊息響應函式,響應視窗的WM_DESTROY訊息,當一個視窗將被銷燬時,傳送此訊息
3.OnNcDestroy() 訊息響應函式,響應視窗的WM_NCDESTROY訊息,當一個視窗被銷燬後傳送此訊息
4.PostNcDestroy() 過載函式,作為處理OnNcDestroy()函式的最後動作,被CWnd呼叫
注意:如果一個對話方塊還有一個子對話方塊,那就更要注意了。如果子對話方塊還在顯示的時候,父對話方塊由於某種原因關閉了(如從其他執行緒接收到了WM_CLOSE訊息),父對話方塊在執行完OnClose函式後會等待,直到子對話方塊銷燬了,才會繼續執行自己的如第一段所說的關閉過程。所以如果子對話方塊使用的是指標並且父視窗被先關閉了,就要在OnClose()後面執行的函式(比如PostNcDestroy())中delete了。