1. 程式人生 > >非模態對話方塊的建立和銷燬過程

非模態對話方塊的建立和銷燬過程

一個非模態的MFC 視窗的銷燬過程:

假設自己通過new建立了一個視窗物件pWnd,然後pWnd->Create。則銷燬視窗的呼叫次序:

1.      手工呼叫pWnd->DestroyWindow() // 一般在對話方塊類中的OnCancle函式中postMessage(WM_DESTORY)或者直接呼叫

2.       DestroyWindow會發送WM_DESTROY

3.       WM_DESTROY對應的訊息處理函式是OnDestroy()

4.       DestroyWindow會發送WM_NCDESTROY

5.       WM_NCDESTROY

對應的訊息處理函式是OnNcDestroy

6.       OnNcDestroy最後會呼叫PostNcDestroy

7.       PostNcDestroy經常被使用者過載以提供釋放記憶體操作。例如可以使用delete this

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

對於非模態視窗,必須過載OnCancel函式,在函式中呼叫DestroyWindows()方法,且不能呼叫基類的函式。因為基類函式中呼叫的是EndDialog()方法。(因為EndDialog是關閉模態對話方塊時呼叫的)而OnClose()也會呼叫OnCancel()方法。另外想通過OnOK

關閉對話方塊,也必須同樣處理,不能直接用預設方法。

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

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

OnNcDestroy()最後又呼叫了PostNcDestroy()

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

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

{

   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)則沒有窗口出來發送