MFC 點擊按鈕,彈出另一個對話框(模態及非模態對話框)


1. 模態對話框
 資源視圖->Dialog->右鍵->添加資源->新建->對話框->右鍵->添加類。
 例如:在A_dialog中點擊按鈕彈出B_dialog
 先添加B_dialog類,然后在A_dialog.cpp中先要添加頭文件"B_dialog.h",  然后在按鈕觸發事件
 中:
void A_dialog::OnBnClickedButton1()
{
 B_dialog Dlg;
 Dlg.DoModal();
}
2. 非模態對話框
資源視圖--Dialog--右鍵--添加資源--新建--對話框--右鍵--添加類。
還是相同的例子,先添加B_dialog.h頭文件,然后再A_dialog.cpp中的按鈕觸發事件中:
void A_dialog::OnBnClickedButton1()
{
 B_dialog *pDlg = new B_dialog;
 pDlg->Create(IDD_DIALOG2, this); //IDD_DIALOG2就是剛才添加資源的Dialog的ID
 pDlg->ShowWindow(SW_SHOW);
}

------------------------------------------------分割線-------------------------------------------

關於“模態對話框”和“非模態對話框”的區別:

模態對話框:
在程序運行的過程中,若出現模態對話框,那么主窗口將無法發送消息,直到模態對話框退出才可以發送。
點擊模態對話框中的ok按鈕,模態對話框會被銷毀。
創建一個模態對話框的代碼:
CTestDialog td;
td.DoModal();

其中CTestDialog為自己所新建和一個對話框資源相關聯的對話框類。
可以創建一個布局模態對話框變量,不用擔心它會隨着所在函數返回而被銷毀。
因為DoModal()函數的一個功能是:當前只能運行此模態對話框,且停止主窗口的運行,直到模態對話框退出,才允許主窗口運行。
 DoModal()函數也有顯示對話框的功能,所以也無需調用其他函數來顯示對話框。

 

非模態對話框(modaless dialog box):
在程序運行的過程中,若出現了非模態對話框,主窗口還可以發送消息。
點擊非模態對話框中的OK按鈕,非模態對話框沒有銷毀,只是隱藏了。若想點擊OK按鈕時,非模態對話框也銷毀,那么CTestDialog類必須重載其基類CDialog的虛函數OnOK(),在此函數里調用DestroyWindow()來銷毀此對話框。
若和上面一樣的方式創建一個非模態對話框:
CTestDialog td; 
td.Create(IDD_DIALOG1); //創建一個非模態對話框 
td.ShowWindow(SW_SHOWNORMAL); //顯示非模態對話框 

那么,在運行時,你會發現此對話框無法顯示。這是因為你聲明的對話框變量td是局部變量,
但這個函數返回時,td也被析構了,所以無法顯示此對話框。
創建非模態對話框,必須聲明一個指向CTestDialog類的指針變量,且需要顯示的調用ShowWindow()才能將對話框顯示出來。有兩種創建方法:
1.//采用局部變量創建一個非模態對話框 
CTestDialog *pTD = new CTestDialog(); 
pTD->Create(IDD_DIALOG1); //創建一個非模態對話框 
pTD->ShowWindow(SW_SHOWNORMAL); //顯示非模態對話框 
因為指針在聲明的時候是被放在堆棧中,只有整個應用程序關閉后才會被銷毀,所以可以正常顯示對話框。
這種方法雖然不影響程序的運行,可是指針pTD所指向的內存卻導致不可用,這樣的編程很不好。

 

2.//采用成員變量創建一個非模態對話框
首先在你所要編寫的類的頭文件中聲明一個指針變量:
private: 
    CTestDialog *pTD; 
然后再在相應的CPP文件,在你要創建對話框的位置添加如下代碼:

//采用成員變量創建一個非模態對話框 
pTD = new CTestDialog(); //給指針分配內存 
pTD->Create(IDD_DIALOG1); //創建一個非模態對話框 
pTD->ShowWindow(SW_SHOWNORMAL); //顯示非模態對話框 
        最后在所在類的析構函數中收回pTD所指向的內存:
delete pTD; 


兩者的區別:
  一. 非模態對話框的模板必須具有Visible風格(Visible=True),否則對話框將不可見,
而模態對話框則無需設置該項風格。
在實際編程中更加保險的辦法是調用CWnd::ShowWindow(SW_SHOW)來顯示對話框,
而不管對話框是否具有Visible風格。
  
  二. 非模態對話框對象是用new操作符來動態創建的,
而不是以成員變量的形式嵌入到別的對象中或以局部變量的形式構建的。
通常應在對話框的擁有者窗口類內聲明一個指向對話框類的指針成員變量,
通過該指針可訪問對話框對象。
  
  三. 通過調用CDialog::Create函數來啟動對話框,而不是CDialog::DoModal,
這是兩者之間區別的關鍵所在。由於Create函數不會啟動新的消息循環,
對話框與應用程序共用同一個消息循環,這樣對話框就不會壟斷用戶輸入。
Create在顯示了對話框后就立即返回,而DoModal是在對話框被關閉后才返回的。
由於在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值,
以表明對話框對象已不存在了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM