乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

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

       行走在理想邊緣 2016-12-28

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

      一個簡單的目的是創(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ù)也有顯示對話框的功能,所以也無需調用其他函數(shù)來顯示對話框。(這里就關系到DoModal中的函數(shù)調用順序,后面會有順序的說明

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

       創(chuàng)建非模態(tài)對話框,必須聲明一個指向CTestDialog類的指針變量,且需要顯示的調用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)建的對話框,如果對話框對象指針是局部的,那么離開作用域,指針就消失掉,所以當釋放對話框對象指針所指的內存時就無法在創(chuàng)建對話框的類中進行釋放,若不做處理,則會造成內存泄露。打開很多個對話框則會導致內存耗盡程序奔潰。

      可以有兩種解決辦法:

      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(); //給指針分配內存  
      3. pTD->Create(IDD_DIALOG1); //創(chuàng)建一個非模態(tài)對話框  
      4. pTD->ShowWindow(SW_SHOWNORMAL); //顯示非模態(tài)對話框  

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

      1. delete pTD;  

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

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

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

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

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

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

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

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

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

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

      6.       OnNcDestroy最后會調用PostNcDestroy;

      7.       PostNcDestroy經常被用戶重載以提供釋放內存操作。例如可以使用delete this;

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

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

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

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


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

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

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


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

      非模態(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ā)送消息告訴一個窗口已經被創(chuàng)建

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

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

      9.OnChildNotify()     該函數(shù)為重載函數(shù),作為部分消息映射被調用,告訴父窗口即將被告知一個窗口剛剛被創(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調用

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

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

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

      而OnNcDestroy()最后又調用了PostNcDestroy()

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

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

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

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

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

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

      3.OnCreate()            消息響應函數(shù),響應WM_CREATE消息,發(fā)送此消息以告訴一個窗口已經被創(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ù)調用

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

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

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

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

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

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

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

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

      對于DoModal出來的窗口,可以使用默認的OnOk()和OnCancel()來處理。其基類方法中會調用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只被已建立的窗口調用。如果建立窗口失敗(如PreCreateWindow), 則沒有窗口處來發(fā)送







        本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多