前幾天發現自己的程式中使用非模態對話方塊,Debug版本有警告提示如下:
Warning: calling DestroyWindow in CWnd::~CWnd OnDestroy or PostNcDestroy in derived class will not be called
由於是Warnning,就沒有太在意,後來隨意上網一找發現,這個問題還是很嚴重的問題。
最後,發現有些基本問題我還沒有搞清楚。同時在這個過程中,也學習了不少新東西,網上關於這個問題的資料很多,感覺真正把問題講清楚的不多。今天我就來個總結,同時,也把網上有些人的疑問給解答下,更重要的是自己以後忘記了,可以回來參考。
先說下模式對話方塊呼叫的原則。(就是一定要先關了這個對話方塊才能操作後面視窗的對話方塊)
在模式對話方塊下,用CDialog::OnOK()或CDialog::OnCancel()以及CDialog::OnClose()關閉對話方塊。
一定要注意之前的CDialog::(當然,你可以過載你自己對話方塊的這個虛擬函式,但是,後面必須呼叫基類的CDialog::)
具體我們再參照深入淺出的風格,來個解刨。
CDialog::Close()預設呼叫CDialog::OnCancel() , CDialog::OnCancel()呼叫CDialog::EndDialog(IDCANCEL);
CDialog::EndDialog呼叫CDialog::DestroyWindows(),CDialog::DestroyWindows呼叫CDialog::OnDestroy() ;
CDialog::OnOK()預設先CDialog::UpdateData(),然後再呼叫CDialog::EndDialog(IDOK).
CDialog::EndDialog呼叫CDialog::DestroyWindows(), CDialog::DestroyWindows呼叫CDialog::OnDestroy()
看來上面你可能就知道了如下的等式
CDialog::Close() == CDialog::OnCancel() == CDialog::EndDialog(IDCANCEL)一樣。
CDialog::OnOK() == CDialog::EndDialog(IDOK).
而CDialog::EndDialog(IDOK)跟CDialog::EndDialog(IDCANCEL)的區別就是,少了一個CDialog::UpdateData(),也就是CDialog::EndDialog(IDOK),在關閉對話方塊後,會把對話方塊上控制元件關聯的變數的值更新為使用者最後輸入的值。而CDialog::EndDialog(IDCANCEL)就不會更新這個值。
希望自己把模式對話方塊的關閉講清楚了。
下面說說非模態對話方塊。
呼叫原則是:
在無模式對話方塊,過載你自己的OnOK(),就是CMyDialog::OnOK()呼叫CDialog::DestroyWindows()。注意:不是預設的CDialog::OnOK()來關閉對話方塊。
過載CMyDialog::OnCancel()呼叫CDialog::DestroyWindows()。注意:不是呼叫預設的CDialog::OnCancel(),來關閉對話方塊。
聽起來很簡單,但是下面提到一個很具體的程式設計問題。
一般,我們用非模態對話方塊都是全域性的,也就是通過new來建立,是在heap上的,而不是在stack上的。
這樣我們當然還要通過delete 來銷燬物件,不然可是有記憶體洩漏的。那麼我們什麼時候delete這個物件呢?
在msdn上面我們可以看到微軟提供的方法是,
我們要過載PostNcDestroy(),即我們要實現CMyDialog::PostNcDestroy(),內容如下
CMyDialog::PostNcDestroy()
{
CDialog::PostNcDestroy();
delete this;
}
這樣的話,我們的類就會Auto-Cleanup了。
msdn的建議,英文的,當初我看了2遍沒看懂。現在在回頭去看,才發現比較簡單。但讓現在你看了這篇blog後就不用看這個了。