對話框有兩種創建方式:DoModal和Creat。 其中DoModal創建的是模態的對話框,而Creat創建的是非模態的對話框下面總結下他們的不同。
對於模態的對話框,在該對話框被關閉前,用戶將不能在同一應用程序的其他地方進行工作(例如open file對話框),而對於非模態的對話框,在它留在屏幕上的同時可以在其他的地方進行工作,(例如find file對話框)
Create的Dialog一般是modalless,如果你的程序本身就是只有一個Dialog,就無所謂了,看不出modalless的效果。modalless本來就是讓有機會切換到本程序的其他窗口。
下面摘抄一部分,很基礎,很全面
非模態對話框的特點
與模態對話框不同,非模態對話框不壟斷用戶的輸入,用戶打開非模態對話框后,仍然可以與其它界面進行交互。
非模態對話框的設計與模態對話框基本類似,也包括設計對話框模板和設計CDialog類的派生類兩部分。但是,在對話框的創建和刪除過程中,非模態對話框與模態對話框相比有下列不同之處:
-
非模態對話框的模板必須具有Visible風格,否則對話框將不可見,而模態對話框則無需設置該項風格。更保險的辦法是調用CWnd::ShowWindow(SW_SHOW)來顯示對話框,而不管對話框是否具有Visible風格。
-
非模態對話框對象是用new操作符在堆中動態創建的,而不是以成員變量的形式嵌入到別的對象中或以局部變量的形式構建在堆棧上。通常應在對話框的擁有者窗口類內聲明一個指向對話框類的指針成員變量,通過該指針可訪問對話框對象。
-
通過調用CDialog::Create函數來啟動對話框,而不是CDialog::DoModal,這是模態對話框的關鍵所在。由於Create函數不會啟動新的消息循環,對話框與應用程序共用同一個消息循環,這樣對話框就不會壟斷用戶的輸入。Create在顯示了對話框后就立即返回,而DoModal是在對話框被關閉后才返回的。眾所周知,在MFC程序中,窗口對象的生存期應長於對應的窗口,也就是說,不能在未關閉屏幕上窗口的情況下先把對應的窗口對象刪除掉。由於在Create返回后,不能確定對話框是否已關閉,這樣也就無法確定對話框對象的生存期,因此只好在堆中構建對話框對象,而不能以局部變量的形式來構建之。
-
必須調用CWnd::DestroyWindow而不是CDialog::EndDialog來關閉非模態對話框。調用CWnd::DestroyWindow是直接刪除窗口的一般方法。由於缺省的CDialog::OnOK和CDialog::OnCancel函數均調用EndDialog,故程序員必須編寫自己的OnOK和OnCancel函數並且在函數中調用DestroyWindow來關閉對話框。
-
因為是用new操作符構建非模態對話框對象,因此必須在對話框關閉后,用delete操作符刪除對話框對象。在屏幕上一個窗口被刪除后,框架會調用CWnd::PostNcDestroy,這是一個虛擬函數,程序可以在該函數中完成刪除窗口對象的工作,具體代碼如下
void CModelessDialog::PostNcDestroy
{
delete this; //刪除對象本身
}
這樣,在刪除屏幕上的對話框后,對話框對象將被自動刪除。擁有者對象就不必顯式的調用delete來刪除對話框對象了。 -
必須有一個標志表明非模態對話框是否是打開的。這樣做的原因是用戶有可能在打開一個模態對話框的情況下,又一次選擇打開命令。程序根據標志來決定是打開一個新的對話框,還是僅僅把原來打開的對話框激活。通常可以用擁有者窗口中的指向對話框對象的指針作為這種標志,當對話框關閉時,給該指針賦NULL值,以表明對話框對象已不存在了。
提示:在C++編程中,判斷一個位於堆中的對象是否存在的常用方法是判斷指向該對象的指針是否為空。這種機制要求程序員將指向該對象的指針初始化為NULL值,在創建對象時將返回的地址賦給該指針,而在刪除對象時將該指針置成NULL值。 |
根據上面的分析,我們很容易把Register程序中的登錄數據對話框改成非模態對話框。這樣做的好處在於如果用戶在輸入數據時發現編輯視圖中有錯誤的數據,那么不必關閉對話框,就可以在編輯視圖中進行修改。
窗口對象的自動清除
一個MFC窗口對象包括兩方面的內容:一是窗口對象封裝的窗口,即存放在m_hWnd成員中的HWND(窗口句柄),二是窗口對象本身是一個C++對象。要刪除一個MFC窗口對象,應該先刪除窗口對象封裝的窗口,然后刪除窗口對象本身。
刪除窗口最直接方法是調用CWnd::DestroyWindow或::DestroyWindow,前者封裝了后者的功能。前者不僅會調用后者,而且會使成員m_hWnd保存的HWND無效(NULL)。如果DestroyWindow刪除的是一個父窗口或擁有者窗口,則該函數會先自動刪除所有的子窗口或被擁有者,然后再刪除父窗口或擁有者。在一般情況下,在程序中不必直接調用DestroyWindow來刪除窗口,因為MFC會自動調用DestroyWindow來刪除窗口。例如,當用戶退出應用程序時,會產生WM_CLOSE消息,該消息會導致MFC自動調用CWnd::DestroyWindow來刪除主框架窗口,當用戶在對話框內按了OK或Cancel按鈕時,MFC會自動調用CWnd::DestroyWindow來刪除對話框及其控件。
窗口對象本身的刪除則根據對象創建方式的不同,分為兩種情況。在MFC編程中,會使用大量的窗口對象,有些窗口對象以變量的形式嵌入在別的對象內或以局部變量的形式創建在堆棧上,有些則用new操作符創建在堆中。對於一個以變量形式創建的窗口對象,程序員不必關心它的刪除問題,因為該對象的生命期總是有限的,若該對象是某個對象的成員變量,它會隨着父對象的消失而消失,若該對象是一個局部變量,那么它會在函數返回時被清除。
對於一個在堆中動態創建的窗口對象,其生命期卻是任意長的。初學者在學習C++編程時,對new操作符的使用往往不太踏實,因為用new在堆中創建對象,就不能忘記用delete刪除對象。讀者在學習MFC的例程時,可能會產生這樣的疑問,為什么有些程序用new創建了一個窗口對象,卻未顯式的用delete來刪除它呢?問題的答案就是有些MFC窗口對象具有自動清除的功能。
如前面講述非模態對話框時所提到的,當調用CWnd::DestroyWindow或::DestroyWindow刪除一個窗口時,被刪除窗口的PostNcDestroy成員函數會被調用。缺省的PostNcDestroy什么也不干,但有些MFC窗口類會覆蓋該函數並在新版本的PostNcDestroy中調用delete this來刪除對象,從而具有了自動清除的功能。此類窗口對象通常是用new操作符創建在堆中的,但程序員不必操心用delete操作符去刪除它們,因為一旦調用DestroyWindow刪除窗口,對應的窗口對象也會緊接着被刪除。
不具有自動清除功能的窗口類如下所示。這些窗口對象通常是以變量的形式創建的,無需自動清除功能。
所有標准的Windows控件類。
從CWnd類直接派生出來的子窗口對象(如用戶定制的控件)。
切分窗口類CSplitterWnd。
缺省的控制條類(包括工具條、狀態條和對話條)。
模態對話框類。
具有自動清除功能的窗口類如下所示,這些窗口對象通常是在堆中創建的。
主框架窗口類(直接或間接從CFrameWnd類派生)。
視圖類(直接或間接從CView類派生)。
讀者在設計自己的派生窗口類時,可根據窗口對象的創建方法來決定是否將窗口類設計成可以自動清除的。例如,對於一個非模態對話框來說,其對象是創建在堆中的,因此應該具有自動清除功能。
綜上所述,對於MFC窗口類及其派生類來說,在程序中一般不必顯式刪除窗口對象。也就是說,既不必調用DestroyWindow來刪除窗口對象封裝的窗口,也不必顯式地用delete操作符來刪除窗口對象本身。只要保證非自動清除的窗口對象是以變量的形式創建的,自動清除的窗口對象是在堆中創建的,MFC的運行機制就可以保證窗口對象的徹底刪除。
如果需要手工刪除窗口對象,則應該先調用相應的函數(如CWnd::DestroyWindow)刪除窗口,然后再刪除窗口對象.對於以變量形式創建的窗口對象,窗口對象的刪除是框架自動完成的.對於在堆中動態創建了的非自動清除的窗口對象,必須在窗口被刪除后,顯式地調用delete來刪除對象(一般在擁有者或父窗口的析構函數中進行).對於具有自動清除功能的窗口對象,只需調用CWnd::DestroyWindow即可刪除窗口和窗口對象。注意,對於在堆中創建的窗口對象,不要在窗口還未關閉的情況下就用delete操作符來刪除窗口對象.
提示:在非模態對話框的OnCancel函數中可以不調用CWnd::DestroyWindow,取而代之的是調用CWnd::ShowWindow(SW_HIDE)來隱藏對話框.在下次打開對話框時就不必調用Create了,只需調用CWnd::ShowWindow(SW_SHOW)來顯示對話框.這樣做的好處在於對話框中的數據可以保存下來,供以后使用.由於擁有者窗口在被關閉時會調用DestroyWindow刪除每一個所屬窗口,故只要非模態對話框是自動清除的,程序員就不必擔心對話框對象的刪除問題. |
以下是一點資料供參考,非模態對話框的銷毀順序:
MFC應用程序中處理消息的順序
1.AfxWndProc() 該函數負責接收消息,找到消息所屬的CWnd對象,然后調用AfxCallWndProc
2.AfxCallWndProc() 該函數負責保存消息(保存的內容主要是消息標識符和消息參數)供應用程序以后使用,
然后調用WindowProc()函數
3.WindowProc() 該函數負責發送消息到OnWndMsg()函數,如果未被處理,則調用DefWindowProc()函數
4.OnWndMsg() 該函數的功能首先按字節對消息進行排序,對於WM_COMMAND消息,調用OnCommand()消息
響應函數,對於WM_NOTIFY消息
調用OnNotify()消息響應函數。任何被遺漏的消息將是一個窗口消息。OnWndMsg()函數搜
索類的消息映像,以找到一個
能處理任何窗口消息的處理函數。如果OnWndMsg()函數不能找到這樣的處理函數的話,則
把消息返回到WindowProc()函數,由它將消息發送給DefWindowProc()函數
5.OnCommand() 該函數查看這是不是一個控件通知(lParam參數不為NULL,如果lParam參數為空的話,說明
該消息不是控件通知),如果它是,OnCommand()函數會試圖將消息映射到制造通知的控件;
如果他不是一個控件通知(或者如果控件拒絕映射的消息)OnCommand()就會調用OnCmdMsg()函數
6.OnCmdMsg() 根據接收消息的類,OnCmdMsg()函數將在一個稱為命令傳遞(Command Routing)的過程中潛在的
傳遞命令消息和控件通知。
例如:如果擁有該窗口的類是一個框架類,則命令和通知消息也被傳遞到視圖和文檔類,並為該
類尋找一個消息處理函數
MFC應用程序創建窗口的過程
1.PreCreateWindow() 該函數是一個重載函數,在窗口被創建前,可以在該重載函數中改變創建參數
(可以設置窗口風格等等)
2.PreSubclassWindow() 這也是一個重載函數,允許首先子分類一個窗口
3.OnGetMinMaxInfo() 該函數為消息響應函數,響應的是WM_GETMINMAXINFO消息,允許設置窗口的最大或者
最小尺寸
4.OnNcCreate() 該函數也是一個消息響應函數,響應WM_NCCREATE消息,發送消息以告訴窗口的客戶區
即將被創建
5.OnNcCalcSize() 該函數也是消息響應函數,響應WM_NCCALCSIZE消息,作用是允許改變窗口客戶區大小
6.OnCreate() 該函數也是一個消息響應函數,響應WM_CREATE消息,發送消息告訴一個窗口已經被創建
7.OnSize() 該函數也是一個消息響應函數,響應WM_SIZE消息,發送該消息以告訴該窗口大小已經
發生變化
8.OnMove() 消息響應函數,響應WM_MOVE消息,發送此消息說明窗口在移動
9.OnChildNotify() 該函數為重載函數,作為部分消息映射被調用,告訴父窗口即將被告知一個窗口剛剛被
創建
MFC應用程序關閉窗口的順序(非模態窗口)
1.OnClose() 消息響應函數,響應窗口的WM_CLOSE消息,當關閉按鈕被單擊的時候發送此消息
2.OnDestroy() 消息響應函數,響應窗口的WM_DESTROY消息,當一個窗口將被銷毀時,發送此消息
3.OnNcDestroy() 消息響應函數,響應窗口的WM_NCDESTROY消息,當一個窗口被銷毀后發送此消息
4.PostNcDestroy() 重載函數,作為處理OnNcDestroy()函數的最后動作,被CWnd調用
MFC應用程序中打開模式對話框的函數調用順序
1.DoModal() 重載函數,重載DoModal()成員函數
2.PreSubclassWindow() 重載函數,允許首先子分類一個窗口
3.OnCreate() 消息響應函數,響應WM_CREATE消息,發送此消息以告訴一個窗口已經被創建
4.OnSize() 消息響應函數,響應WM_SIZE消息,發送此消息以告訴窗口大小發生變化
5.OnMove() 消息響應函數,響應WM_MOVE消息,發送此消息,以告訴窗口正在移動
6.OnSetFont() 消息響應函數,響應WM_SETFONT消息,發送此消息,以允許改變對話框中控件的字體
7.OnInitDialog() 消息響應函數,響應WM_INITDIALOG消息,發送此消息以允許初始化對話框中的控件,
或者是創建新控件
8.OnShowWindow() 消息響應函數,響應WM_SHOWWINDOW消息,該函數被ShowWindow()函數調用
9.OnCtlColor() 消息響應函數,響應WM_CTLCOLOR消息,被父窗口發送已改變對話框或對話框上面控件
的顏色
10. OnChildNotify() 重載函數,作為WM_CTLCOLOR消息的結果發送
MFC應用程序中關閉模式對話框的順序
1.OnClose() 消息響應函數,響應WM_CLOSE消息,當"關閉"按鈕被單擊的時候,該函數被調用
2.OnKillFocus() 消息響應函數,響應WM_KILLFOCUS消息,當一個窗口即將失去鍵盤輸入焦點以前被發送
3.OnDestroy() 消息響應函數,響應WM_DESTROY消息,當一個窗口即將被銷毀時,被發送
4.OnNcDestroy() 消息響應函數,響應WM_NCDESTROY消息,當一個窗口被銷毀以后被發送
5.PostNcDestroy() 重載函數,作為處理OnNcDestroy()函數的最后動作被CWnd調用
打開無模式對話框的順序
1.PreSubclassWindow() 重載函數,允許用戶首先子分類一個窗口
2.OnCreate() 消息響應函數,響應WM_CREATE消息,發送此消息以告訴一個窗口已經被創建
3.OnSize() 消息響應函數,響應WM_SIZE消息,發送此消息以告訴窗口大小發生變化
4.OnMove() 消息響應函數,響應WM_MOVE消息,發送此消息以告訴窗口正在移動
5.OnSetFont() 消息響應函數,響應WM_SETFONT消息,發送此消息以允許改變對話框中控件的字體
http://blog.csdn.net/kl222/article/details/1447985