模态對話框和非模态對話框差別
按工作方式不同,可将對話框分成兩類:
模式對話框(ModalDialog Box,模态對話框):在關閉模式對話框之前,程式不能進行其他工作(如一般的“打開檔案”對話框);
無模式對話框(ModelessDialog Box,非模态對話框):模式對話框打開後,程式仍然能夠進行其他工作(如一般的“查找與替換”對話框)。
兩者的差別:
1.非模态對話框的模闆必須具有Visible風格(Visible=True),否則對話框将不可見,而模态對話框則無需設定該項風格。在實際程式設計中更加保險的辦法是調用CWnd::ShowWindow(SW_SHOW)來顯示對話框,而不管對話框是否具有Visible風格;
2.非模态對話框對象是用new操作符來動态建立的,而不是以成員變量的形式嵌入到别的對象中或以局部變量的形式建構的。通常應在對話框的擁有者視窗類内聲明一個指向對話框類的指針成員變量,通過該指針可通路對話框對象;
3.通過調用CDialog::Create函數來啟動對話框,而不是CDialog::DoModal,這是兩者之間差別的關鍵所在。由于Create函數不會啟動新的消息循環,對話框與應用程式共用同一個消息循環,這樣對話框就不會壟斷使用者輸入。Create在顯示了對話框後就立即傳回,而DoModal是在對話框被關閉後才傳回的。由于在Create傳回後,不能确定對話框是否已關閉,這樣也就無法确定對話框對象的生存期,是以隻好在堆棧中建構對話框對象,而不能以局部變量的形式來建構之;
4.必須調用CWnd::DestroyWindow而不是CDialog::EndDialog來關閉非模态對話框。調用CWnd::DestroyWindow是直接删除視窗的一般方法。由于預設的CDialog::OnOK和CDialog::OnCancel函數均調用EndDialog,故程式員必須編寫自己的OnOK和OnCancel函數并且在函數中調用DestroyWindow來關閉對話框;
5.因為是用new操作符建構非模态對話框對象,是以必須在對話框關閉後,用delete操作符删除對話框對象。在螢幕上一個視窗被删除後,架構會調用CWnd::PostNcDestroy,這是一個虛拟函數,程式可以在該函數中完成删除視窗對象的工作,具體代碼如下:
Void CModelessDialog::PostNcDestroy
{delete this; //删除對象}
這樣,在删除螢幕上的對話框後,對話框對象将被自動删除。擁有者就不必顯式地調用delete來删除對話框對象了;
6.必須有一個标志表明非模态對話框是否打開的。這樣做的原因是使用者有可能在打開一個模态對話框的情況下,又一次選擇打開指令。程式根據标志來決定是打開一個新的對話框,還是僅僅把原來打開的對話框激活。通常可以用擁有者視窗中的指向對話框對象的指針作為這種标志,當對話框關閉時,給該指針賦NULL值,以表明對話框對象已不存在了;
例如:
建立模态對話框
CTestDlg dlg;
dlg.DoModal();
建立非模态對話框
CTestDlg * dlg = new CTestDlg;
dlg->Create(IDD_TEST_DLG);
dlg->ShowWindow(SW_SHOW);