免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
MFC 創(chuàng)建非模態(tài)對話框和銷毀過程

今天項目中遇到的問題,記錄下來,做個總結。

一個簡單的目的是創(chuàng)建一個非模態(tài)對話框并在對話框關閉后將其銷毀。

這里的銷毀包括:銷毀對話框對象資源和對話框對象指針;

首先說創(chuàng)建對話框:

一、模態(tài)對話框(model dialog box)

在程序運行的過程中,若出現(xiàn)了模態(tài)對話框,那么主窗口將無法發(fā)送消息,直到模態(tài)對話框退出才可以發(fā)送。

點擊模態(tài)對話框中的OK按鈕,模態(tài)對話框會被銷毀。創(chuàng)建一個模態(tài)對話框的代碼:

  1. //創(chuàng)建一個模態(tài)對話框  
  2. CTestDialog td;  
  3. td.DoModal();   
其中CTestDialog為所要創(chuàng)建的對話框類。而這個對話框是在另個類中創(chuàng)建。

因為DoModal()函數(shù)的一個功能是,當前只能運行此模態(tài)對話框,且停止主窗口的運行,直到模態(tài)對話框退出,才允許主窗口運行。

 DoModal()函數(shù)也有顯示對話框的功能,所以也無需調(diào)用其他函數(shù)來顯示對話框。(這里就關系到DoModal中的函數(shù)調(diào)用順序,后面會有順序的說明

二、非模態(tài)對話框(modaless dialog box)

 創(chuàng)建非模態(tài)對話框,必須聲明一個指向CTestDialog類的指針變量,且需要顯示的調(diào)用ShowWindow()才能將對話框顯示出來。有兩種創(chuàng)建方法:

(1)采用局部變量創(chuàng)建一個非模態(tài)對話框

  1. //采用局部變量創(chuàng)建一個非模態(tài)對話框  
  2. CTestDialog *pTD = new CTestDialog();  
  3. pTD->Create(IDD_DIALOG1); //創(chuàng)建一個非模態(tài)對話框  
  4. pTD->ShowWindow(SW_SHOWNORMAL); //顯示非模態(tài)對話框 其中參數(shù)用swp_SHOWNOMAL,  SW_SHOW, SW_VISION 好像效果是一樣的 
這種方式創(chuàng)建的對話框,如果對話框對象指針是局部的,那么離開作用域,指針就消失掉,所以當釋放對話框對象指針所指的內(nèi)存時就無法在創(chuàng)建對話框的類中進行釋放,若不做處理,則會造成內(nèi)存泄露。打開很多個對話框則會導致內(nèi)存耗盡程序奔潰。

可以有兩種解決辦法:

1) 在創(chuàng)建對話框的類中,將對話框對象指針存儲起來,然后釋放對應指針,一般可以定義一個全局的或者成員變量來存儲(用map)                         

2)將對話框對象指針的釋放交給對話框自身去維護,在上層類中之創(chuàng)建出來即可。具體方法是:在對話框類中重寫PostNcDestory方法,該方法中delete this即可。具體順序后面介紹。

(2)采用成員變量創(chuàng)建一個非模態(tài)對話框

        首先在你所要編寫的類的頭文件中聲明一個指針變量:

  1. private:  
  2.     CTestDialog *pTD;  

 然后再在相應的CPP文件,在你要創(chuàng)建對話框的位置添加如下代碼:

  1. //采用成員變量創(chuàng)建一個非模態(tài)對話框  
  2. pTD = new CTestDialog(); //給指針分配內(nèi)存  
  3. pTD->Create(IDD_DIALOG1); //創(chuàng)建一個非模態(tài)對話框  
  4. pTD->ShowWindow(SW_SHOWNORMAL); //顯示非模態(tài)對話框  

        最后在所在類的析構函數(shù)中收回pTD所指向的內(nèi)存:

  1. delete pTD;  

但這樣的方法只能創(chuàng)建一個對話框,若是再打開一個對話框,則之前的指針丟失(會造成內(nèi)存不好釋放)。

若要用這種方式創(chuàng)建多個對話框可以用一個map管理存儲指針,釋放時對應釋放,關閉了哪個對話框就把那個對應指針釋放掉,但這樣做很麻煩。

我的做法是第一種方法,在對話框類中維護釋放和關閉對話框。下面會將方法寫出來。

一個非模態(tài)的MFC 窗口的銷毀過程:

假設自己通過new創(chuàng)建了一個窗口對象pWnd,然后pWnd->Create。則銷毀窗口的調(diào)用次序:

1.      手工調(diào)用pWnd->DestroyWindow(); // 一般在對話框類中的OnCancle函數(shù)中postMessage(WM_DESTORY)或者直接調(diào)用

2.       DestroyWindow會發(fā)送WM_DESTROY;

3.       WM_DESTROY對應的消息處理函數(shù)是OnDestroy();

4.       DestroyWindow會發(fā)送WM_NCDESTROY;

5.       WM_NCDESTROY對應的消息處理函數(shù)是OnNcDestroy;

6.       OnNcDestroy最后會調(diào)用PostNcDestroy;

7.       PostNcDestroy經(jīng)常被用戶重載以提供釋放內(nèi)存操作。例如可以使用delete this;

通過這種方式,窗口對象對應的窗口和窗口對象本身都被釋放了。

注:   銷毀窗口對象對應的窗口和釋放窗口對象指針 ,可以通過DestroyWindow,這是比較好的方法,因為最后MFC會自動相應WM_CLOSE導致CframWnd::DestroyWindow被調(diào)用,然后會一次釋放所有子窗口的句柄。用戶需要做的是在PostNcDestroy中釋放堆窗口對象指針。但因為某些對象是在棧中申請的,所以delete this可能出錯。這就要保證寫程序時自己創(chuàng)建的窗口盡量使用堆申請。

一個MFC窗口對象包括兩方面的內(nèi)容:一是窗口對象封裝的窗口,即存放在m_hWnd成員中的HWND(窗口句柄),二是窗口對象本身是一個C++對象。要刪除一個MFC窗口對象,應該先刪除窗口對象封裝的窗口,然后刪除窗口對象本身。

刪除窗口最直接方法是調(diào)用CWnd::DestroyWindow::DestroyWindow,前者封裝了后者的功能。前者不僅會調(diào)用后者,而且會使成員m_hWnd保存的HWND無效(NULL)。如果DestroyWindow刪除的是一個父窗口或擁有者窗口,則該函數(shù)會先自動刪除所有的子窗口或被擁有者,然后再刪除父窗口或擁有者。在一般情況下,在程序中不必直接調(diào)用DestroyWindow來刪除窗口,因為MFC會自動調(diào)用DestroyWindow來刪除窗口。例如,當用戶退出應用程序時,會產(chǎn)生WM_CLOSE消息,該消息會導致MFC自動調(diào)用CWnd::DestroyWindow來刪除主框架窗口,當用戶在對話框內(nèi)按了OKCancel按鈕時,MFC會自動調(diào)用CWnd::DestroyWindow來刪除對話框及其控件。


對于一個在堆中動態(tài)創(chuàng)建的窗口對象,其生命期卻是任意長的。所以可能會產(chǎn)生這樣的疑問,為什么有些程序用new創(chuàng)建了一個窗口對象,卻未顯式的用delete來刪除它呢?問題的答案就是有些MFC窗口對象具有自動清除的功能。

如前面講述非模態(tài)對話框時所提到的,當調(diào)用CWnd::DestroyWindow::DestroyWindow刪除一個窗口時,被刪除窗口的PostNcDestroy成員函數(shù)會被調(diào)用。缺省的PostNcDestroy什么也不干,但有些MFC窗口類會覆蓋該函數(shù)并在新版本的PostNcDestroy中調(diào)用delete this來刪除對象,從而具有了自動清除的功能。此類窗口對象通常是用new操作符創(chuàng)建在堆中的,但程序員不必操心用delete操作符去刪除它們,因為一旦調(diào)用DestroyWindow刪除窗口,對應的窗口對象也會緊接著被刪除。

對于在堆中動態(tài)創(chuàng)建了的非自動清除的窗口對象,必須在窗口被刪除后,顯式地調(diào)用delete來刪除對象(一般在擁有者或父窗口的析構函數(shù)中進行).對于具有自動清除功能的窗口對象,只需調(diào)用CWnd::DestroyWindow即可刪除窗口和窗口對象。注意,對于在堆中創(chuàng)建的窗口對象,不要在窗口還未關閉的情況下就用delete操作符來刪除窗口對象。


下面總結一下MFC對話框創(chuàng)建和銷毀的函數(shù)調(diào)用順序:

非模態(tài)對話框

MFC應用程序創(chuàng)建窗口的過程

1.PreCreateWindow()   該函數(shù)是一個重載函數(shù),在窗口被創(chuàng)建前,可以在該重載函數(shù)中改變創(chuàng)建參數(shù)   (可以設置窗口風格等等)

2.PreSubclassWindow()  這也是一個重載函數(shù),允許首先子分類一個窗口

3.OnGetMinMaxInfo()   該函數(shù)為消息響應函數(shù),響應的是WM_GETMINMAXINFO消息,允許設置窗口的最大或者最小尺寸

4.OnNcCreate()        該函數(shù)也是一個消息響應函數(shù),響應WM_NCCREATE消息,發(fā)送消息以告訴窗口的客戶區(qū) 即將被創(chuàng)建

5.OnNcCalcSize()      該函數(shù)也是消息響應函數(shù),響應WM_NCCALCSIZE消息,作用是允許改變窗口客戶區(qū)大小

6.OnCreate()          該函數(shù)也是一個消息響應函數(shù),響應WM_CREATE消息,發(fā)送消息告訴一個窗口已經(jīng)被創(chuàng)建

7.OnSize()            該函數(shù)也是一個消息響應函數(shù),響應WM_SIZE消息,發(fā)送該消息以告訴該窗口大小已經(jīng) 發(fā)生變化

8.OnMove()            消息響應函數(shù),響應WM_MOVE消息,發(fā)送此消息說明窗口在移動

9.OnChildNotify()     該函數(shù)為重載函數(shù),作為部分消息映射被調(diào)用,告訴父窗口即將被告知一個窗口剛剛被創(chuàng)建

MFC應用程序關閉窗口的順序(非模態(tài)窗口)

1.OnClose()       消息響應函數(shù),響應窗口的WM_CLOSE消息,當關閉按鈕被單擊的時候發(fā)送此消息

2.OnDestroy()     消息響應函數(shù),響應窗口的WM_DESTROY消息,當一個窗口將被銷毀時,發(fā)送此消息

3.OnNcDestroy()   消息響應函數(shù),響應窗口的WM_NCDESTROY消息,當一個窗口銷毀后發(fā)送此消息

4.PostNcDestroy() 重載函數(shù),作為處理OnNcDestroy()函數(shù)的最后動作,被CWnd調(diào)用

對于非模態(tài)窗口,必須重載OnCancel函數(shù),在函數(shù)中調(diào)用DestroyWindows()方法,且不能調(diào)用基類的函數(shù)。因為基類函數(shù)中調(diào)用的是 EndDialog()方法。(因為EndDialog是關閉模態(tài)對話框時調(diào)用的)而OnClose()也會調(diào)用OnCancel()方法。另外想通過OnOK關閉對話框,也必須同樣處理,不能直接用默認方法。

所以對于非模態(tài)窗口,其關閉過程為:

OnClose()->OnCancel()->DestroyWindow()->OnDestroy()->OnNcDestroy() ,->僅表示時間先后而已

而OnNcDestroy()最后又調(diào)用了PostNcDestroy()

說明:OnOK是對ID_OK的響應, OnCancel是對IDCANCEL的響應. 前者對應鍵盤的Enter, 后者對應Esc。

OnOK()和OnCancel()都調(diào)用了EndDialog().OnOK調(diào)用了UpdateData(TRUE)而OnCacel()沒有調(diào)用。
  在OnOK()結束剛進入DestroyWindow時,其實窗口并未關閉,依然可以用ShowWindow顯示出來

模態(tài)的對話框可以用EndDialog來銷毀, 非模態(tài)的對話框要用DestroyWindow來銷毀

MFC應用程序中創(chuàng)建模態(tài)對話框的函數(shù)調(diào)用順序:

1.DoModal()             重載函數(shù),重載DoModal()成員函數(shù)

2.PreSubclassWindow()   重載函數(shù),允許首先子分類一個窗口

3.OnCreate()            消息響應函數(shù),響應WM_CREATE消息,發(fā)送此消息以告訴一個窗口已經(jīng)被創(chuàng)建

4.OnSize()              消息響應函數(shù),響應WM_SIZE消息,發(fā)送此消息以告訴窗口大小發(fā)生變化

5.OnMove()              消息響應函數(shù),響應WM_MOVE消息,發(fā)送此消息,以告訴窗口正在移動

6.OnSetFont()           消息響應函數(shù),響應WM_SETFONT消息,發(fā)送此消息,以允許改變對話框中控件的字體

7.OnInitDialog()        消息響應函數(shù),響應WM_INITDIALOG消息,發(fā)送此消息以允許初始化對話框中的控件, 或者是創(chuàng)建新控件

8.OnShowWindow()        消息響應函數(shù),響應WM_SHOWWINDOW消息,該函數(shù)被ShowWindow()函數(shù)調(diào)用

9.OnCtlColor()          消息響應函數(shù),響應WM_CTLCOLOR消息,被父窗口發(fā)送已改變對話框或對話框上面控件的顏色

10. OnChildNotify()     重載函數(shù),作為WM_CTLCOLOR消息的結果發(fā)送

MFC應用程序中關閉模式對話框的順序

1.OnClose()        消息響應函數(shù),響應WM_CLOSE消息,當'關閉'按鈕被單擊的時候,該函數(shù)被調(diào)用

2.OnKillFocus()    消息響應函數(shù),響應WM_KILLFOCUS消息,當一個窗口即將失去鍵盤輸入焦點以前被發(fā)送

3.OnDestroy()      消息響應函數(shù),響應WM_DESTROY消息,當一個窗口即將被銷毀時,被發(fā)送

4.OnNcDestroy()    消息響應函數(shù),響應WM_NCDESTROY消息,當一個窗口銷毀以后被發(fā)送

5.PostNcDestroy()  重載函數(shù),作為處理OnNcDestroy()函數(shù)的最后動作被CWnd調(diào)用

對于DoModal出來的窗口,可以使用默認的OnOk()和OnCancel()來處理。其基類方法中會調(diào)用EndDialog()方法。


 最后注意一個問題,通常我們創(chuàng)建一個非模態(tài)窗口時,可能會這樣寫

{

   CDialog * pWnd = new CMyDialog();

   pWnd->Create(……);

   pWnd->ShowWindow(SW_SHOW);

}

   一般是在一個模塊或者一個函數(shù)中創(chuàng)建窗口,但是卻無法知道什么時候關閉窗口。而pWnd也只是作為一個局部變量。那么如何對它進行析構呢?

通常這樣是重載虛函數(shù)PostNcDestroy()來實現(xiàn)

void CMyDialog::PostNcDestroy()
{
       CDialog::PostNcDestroy();
       delete this;
}

 為什么把對話框類的delete this放在PostNcDestroy中而不是OnNcDestroy?

   這是因為OnNcDestroy只被已建立的窗口調(diào)用。如果建立窗口失敗(如PreCreateWindow), 則沒有窗口處來發(fā)送







本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
關于模式與非模式對話框
【轉】MFC 窗口關閉過程
VC++中MFC窗口對象的清除
VC++模態(tài)對話框和非模態(tài)對話框 | 求索閣
vc中關閉對話框dialog
MFC窗口銷毀過程
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服