?? 07.2.2 非模態對話框的創建.txt
字號:
7.2.2 非模態對話框的創建
如果要創建非模態對話框,則需要利用 CDialog類的 Create成員函數。該函數具有以下兩種形式的聲明:
BOOL Create( LPCTSTR lpsZTemplateName, CWnd* pParentWnd = NULL );
BOOL Create( UINT n工 DTemplate, CWnd* pParentWnd = NULL );
也就是說, Create函數的第一個參數可以是對話框資源的 ID ( nIDTemplate參數 ),或者也可以是對話框模板的名稱 ( lpszTemplateName參數)。這個函數的第二個參數指定了對話框的父窗口,如果其值是 NULL,對話框的父窗口就是主應用程序窗口。對本例來說,如果這個父窗口參數值是 NULL,對話框的父窗口就是框架窗口。這里,我們仍在 CMyboleView類 OnDialog函數中實現創建非模態對話框的功能,則首先需要將上面例 7-4所示代碼中創建模態對話框的代碼注釋起來,然后在其后面添加創建非模態對話框的代
碼,結果如例 7-6所示。
void CMyboleView: :OnDialog()
// TODO : Add your command handler code here /1 CTestDlg dlg; // dlg.DoModal();
CTestDlg dlg;
dlg.Create(IDD_DIALOG1,this) ;
Build井運行Mybole程序,單擊程序菜單欄上的【對話框】菜單,發現并未出現測試對話框窗口。這里,讀者一定要注意,當利用 Create畫數創建非模態對話框時,還需要調用ShowWindow函數將這個對話框顯示出來。那為什么上面利用DoModal函數創建對話框時不需要呢?這是因為DoModal函數本身就有顯示模態對話框的作用,所以對模態對話框來說,不需要再調用ShowWindow函數來顯示對話框了,但非模態對話框需要調用此函數。因此,我們在上述例7-6所示OnDialog函數的最后再加上下面這行代碼:
dlg.ShowWindow(SW_SHOW);
Build井運行Mybole程序,單擊程序菜單欄上的【對話框】菜單,發現仍沒有出現測試對話框。問題出在哪里呢?我們回頭看看上面的代碼,發現這里創建的非模態對話框對象 (dlg)是一個局部對象,當程序執行時,會依次執行各條代碼,當OnDialog函數的右大括號執行結束時, dlg這個對象的生命周期也就結束了,它就會銷毀與之相關聯的對話框資源。那為什么上面創建模態對話框時就可以使用局部對象呢?上面已經講過,在創建模態對話框時,當執行到調用DoModal函數以顯示這個對話框時,程序就會暫停執行,直到模態對話框關閉之后,程序才繼續向下執行。也就是說,當模態對話框顯示時,程序中創建的dlg這個對象的生命周期并未結束。因此,在創建非模態對話框時,不能把對話框對象定義為局部對象。對于這個問題,有兩種解決辦法:一種就是把這個對話框對象定義為視類的成員變量:另一種方式是將它定義為指針,在堆上分配內存。我們知道,在堆上分配的內存,與程序的整個生命周期是一致的,當然這里是指程序中不主動銷毀的情況。這里,我們采用后一種方式,修改己有代碼,結果如例7-7所示。
例7-7
void CMyboleView : :OnDialog()
.
// TODO: Add your command handler code here 11 CTestDlg dlg ; // dlg . DoModal();
CTestDlg *pDlg = new CTestDlg;
pDlg->Create(IDD_DIALOG1, this);
pDlg->ShowWindow(SW_SHOW) ;
因為這里定義的對話時象是指針類型,所有調用其成員函數時應該
用->操作符。
Build并運行Mybole程序,單擊程序菜單欄上的【對話框】菜單,測試對話框出現了,這時可以試著單擊程序的菜單項,將會發現可以進行這項操作,如圖7.11所示。這就是非模態對話框的特點。因為程序顯示非模態對話框時,并不會停留在某條語句處,所以 CMyboleView類的 OnDialog函數內部的代碼就會順序地被執行,直到該函數執行結束,. 這時,程序就可以執行其他任務了,例如響應菜單項的單擊操作。
圖 7.11非模態對話框的顯示
可是,上述例7-7所示的這段程序仍有問題,首先,我們定義的pDlg這個指針變量是一個局部對象,這樣當它的生命周期結束時,它所保存的內存地址就丟失了,那么在程序中也就無法再引用到它所指向的那塊內存了。這個問題的解決辦法有兩種:一是將這個指針變量定義為視類 C CMyboleView )的成員變量,然后在CMyboleView類的析構函數中調用 delete函數來釋放這個指針變量所指向的那塊內存:二是在 CTestDlg類中重載 PostNcDestroy虛函數,釋放this指針所指向的內存,代碼如例7-8所示,其中加灰顯示的代碼是我們添加的代碼。
~~ 7-8
void CTestDlg :: PostNcDestroy()
// TODO: Add your specialized code here and/ or call the base class delete this; CDialog : :PostNcDestroy();
另外,讀者會發現上述示例中無論創建的是模態對話框,還是非模態對話框,當單擊對話框上的【OK】按鈕時,對話框都會消失。但有一點需要提醒讀者注意,對模態對話框而言,此時對話框窗口對象被銷毀了。而對非模態對話框來說,對話框窗口對象并未被銷毀,只是隱藏起來了。我們來分析一下在非模態對話框中單擊OK按鈕后,程序所發生的事情。這時,程序會調用基類 CCDialog)的 OnOK函數,這是一個虛函數。后者又會
調用EndDialog函數,這個函數用于終止模態對話框,而對于非模態對話框,這個函數只是使對話框窗口不可見,并不銷毀它。因此,對非模態對話框來說,如果有一個 E值為 IDOK的按鈕,就必須重寫基類的 OnOK這個虛函數,并在重寫的函數中調用 DestroyWindow函數,以完成銷毀對話框的工作,同時注意不要再調用基類的OnOK函數。同樣地,如果非模態對話框中有一個 ID值為 IDCANCEL的按鈕,也必須重寫基類的 OnCancel虛函數,并在重寫的函數中調用Des位oyWindow函數,銷毀對話框,同時注意不要再調用基類的OnCancel函數。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -