視窗關閉過程

來源:互聯網
上載者:User

視窗關閉過程

——OnOK(),OnCancel(),OnClose(),EndDialog(),DestroyWindow(),OnDestroy(),OnNcDestroy()

 

  發現我誤導人了,說的不準確,修改一下。

 

   一、對於非模態視窗,必須重載OnCancel函數,在函數中調用DestroyWindows()方法,且不能調用基類的函數。因為基類函數中調用的是EndDialog()方法。而OnClose()也會調用OnCancel()方法。另外想通過OnOK關閉對話方塊,也必須同樣處理,不能直接用預設方法。

 

   1 、只有點擊標題列的叉號表徵圖、在案頭工作列右鍵-關閉、Alt+F4、標題列最左邊表徵圖上單擊-關閉,發送WM_CLOSE訊息,觸發OnClose()。

 所以對於非模態視窗,其關閉過程

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

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

 

  2、斷行符號、ESC、點擊“確定”或“取消”,都不會調用OnClose()

  一般來說,OnOK是對ID_OK的響應, OnCancel是對IDCANCEL的響應. 前者對應鍵盤的Enter, 後者對應Esc。

  OnCancel()->DestroyWindow()->OnDestroy()->OnNcDestroy()

  OnOK()->DestroyWindow()->OnDestroy()->OnNcDestroy()

  OnNcDestroy()最後又調用了PostNcDestroy()

 

  OnOK()與OnCancel()
       如前面所述,OnOK是對ID_OK的響應, OnCancel是對IDCANCEL的響應. 前者對應鍵盤的Enter, 後者對應Esc。

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

  模態的對話方塊可以用EndDialog來銷毀, 非模態的對話方塊要用DestroyWindow來銷毀
  見《OnOK與OnCancel》http://ponymaggie.blog.sohu.com/135823530.html

 

  EndDialog()
  該函數清除一個模態對話方塊,並使系統中止對對話方塊的任何處理

 

  對於DoModal出來的視窗,可以使用預設的OnOk()和OnCancel()來處理。其基類方法中會調用EndDialog()方法。

  它只能在對話方塊的訊息處理函數裡使用,並且這個函數調用之後,沒有立即就刪除對話方塊的,而是設定了作業系統裡的結束標誌。當作業系統查檢到有這個標誌時,就去刪除對話方塊的訊息迴圈,同時也去解除配置框佔用的資源。其實對話方塊的生命週期是這樣的,先由函數DialogBox建立對話方塊,這樣函數DialogBox完成建立對話方塊但還沒有顯示前會發出訊息WM_INITDIALOG,讓對話方塊有機會初始化上面所有視窗或控制項的顯示,比如設定文字框的字串等。最後當使用者點出確定或者取消的按鈕,就收到兩個命令IDOK或IDCANCEL,這時就可以調用函數EndDialog來結束對話方塊的生命。
見《Windows API一日一練(18)EndDialog函數》http://blog.csdn.net/caimouse/archive/2007/07/30/1716140.aspx

 

  DestroyWindows()

  CWnd::DestroyWindow銷毀m_hWnd(必須非空),同時銷毀其菜單、定時器,以及完成其他清理工作。
  ::DestroyWindow使將被銷毀的視窗失去啟用、失去輸入焦點,並發送WM_DESTROY、WM_NCDESTROY訊息到該視窗及其各級子視窗。如果被銷毀的視窗是子視窗且沒有設定WM_NOPARENTNOTFIY風格,則給其父視窗發送WM_PARENTNOFITY訊息。

 

  CWnd::OnDestroy()  和 CWnd::OnNcDestroy() 以及 CWnd::PostNcDestroy()

  CWnd::OnDestroy()  調用預設處理函數Default()。

  CWnd::OnNcDestroy() 首先判斷當前線程的主視窗是否是該視窗,如果是且模組非DLL,則發送WM_QUIT訊息,使得程式結束;
然後,判斷當前線程的使用中視窗是否是該視窗,如果是則設定使用中視窗為NULL;
     接著,清理Tooltip視窗,調用Default由Windows預設處理WM_NCDESTROY訊息,UNSUBCLASS,把視窗控制代碼和MFC

視窗對象分離(Detach);

    最後,調用虛函數PostNcDestoy()。

    見《MFC教程_應用程式的退出》http://www.vczx.com/tutorial/mfc/mfc6.php

 

    總結一下的話,DestroyWindows可以理解成是主動的,OnDestroy是被動的.  
    使用者主動調用DestroyWindows來關閉視窗,而當視窗被關閉時OnDestroy函數被調用!  
    你調用DestroyWindow(),那麼系統就會發一個WM_DESTROY的訊息,這個訊息會調用OnDestroy()函數.

    DestroyWindow()     ------>   WM_DESTROY + WM_NCDESTROY   ------>OnDestroy()   
                                         發訊息                                                               響應訊息映射

 

   另外,如果要在退出時提示使用者,應在OnClose()或OnOK()、OnCancel()中作出處理,而不能在響應WM_DESTROY時處理

,因為那是視窗已經銷毀了(但應用程式並沒有退出)。在處理WM_DESTROY訊息時,系統會調用

 PostQuitMessage()向訊息隊裡投遞WM_QUIT訊息,結束訊息迴圈。(見《VC++深入詳解》P18)

 

   最後注意一個問題,通常我們建立一個非模態視窗時,可能會這樣寫

{

   CDialog * pWnd = new CMyDialog();

   pWnd->Create(……);

   pWnd->ShowWindow(SW_SHOW);

}

   很肯能是在一個模組或者一個函數中建立視窗,但是卻無法知道什麼時候關閉視窗。而pWnd也只是作為一個局部變數。那麼如何對它進行析構呢?

通常這樣是重載虛函數PostNcDestroy()來實現

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

 為什麼把對話方塊類的delete this放在PostNcDestroy中而不是OnNcDestroy

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

WM_NCDESTROY訊息。PostNcDestroy是在對象視窗被完全刪除, 在OnNcDestroy後,甚至在視窗建立失敗之後

調用的。

 

    以上是學習MFC視窗關閉銷毀等相關知識時的一些總結。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.