【作者按】本文主要針對初學者在使用對話框賦值時的一些問題而寫。如果你對對話框的使用已經很熟練,請跳過本文。
【針對現象】許多初學者,常常寫出這樣的程序來修改對話框中某個按鈕的標題:
CMyDialog dlg;
dlg.m_Btn.SetWindowText("MyButton");
其中m_Btn的定義為CButton m_Btn;
這段程序運行後會抱錯,debug一下,錯誤會指向一個斷言語句ASSERT(::IsWindow(m_hWnd));
報告窗口指針為空。看一下m_hWnd,等於0x00000000.其實就是m_Btn這個CButton對象的句柄為空。
【原因分析】出現這種錯誤的原因,顯然是m_Btn這個窗口對象還沒有創建造成的。
我們看一下CMyDialog dlg這個構造函數,看一看MSDN對CDialog構造函數的說明。其實它只是簡單的創建了一個對話框實例。這裡我這樣理解,就是對話框是一個容器,而對話框上的各個控件是容器中包含的對象。對話框的構造函數只是構造了一個容器,而並沒有創建容器中的各個對象。我想這裡大家就應該明白為什麼m_Btn的句柄為空了。那對話框中的控件在什麼時候被創建的呢?我個人沒有仔細的研究過,但從個人使用的經驗看,應該在DoModal函數和對話框的Create函數中創建的。因為使用一個模式對話框時,m_Btn.SetWindowText("MyButton")語句在OnInitDialog函數中執行沒有問題。所以應該在DoModal中創建的。至於DoModal中是如何創建的,歡迎各位高手給與講解。而對於非模式對話框,以下的程序運行沒有問題:
CMyDialog dlg;
dlg.Create(IDD_MYDIALOG,this);
dlg.m_Btn.SetWindowText("MyButton");
可見控件的創建應該在Create函數中。
[解決辦法]那麼,如果非要實現這樣的功能怎麼辦呢?筆者的解決辦法是在對話框類中增加成員變量,比如m_sBtnTitle。數據的傳遞有以下三種方法:
1。增加Set函數,比如SetBtnTitle(CString str);
CMyDialog::SetBtnTitle(CString str)
{
m_sBtnTitle = str;
}
調用程序如下:
CMyDialog dlg;
dlg.SetBtnTitle("MyButton");
2。將m_sBtnTitle定義成公有類型。
那麼dlg.m_sBtnTitle = "MyButton";就可以了。
3。修改或者重載一個新的構造函數,比如:
CMyDialog::CMyDialog(CString str)
{
m_sBtnTitle = str;
}
最後,在對話框類的初始化函數增加m_Btn.SetWindowText(m_sBtnTitle);即可。
還有一些網友提供的方法是定義全局變量。當然,首先肯定全局變量是可以完成此功能的。不過筆者並不贊同用全局變量的方法。對於面向對象的編程和設計來說,全局變量應該盡量少使用,因為全局變量將增加模塊之間的耦合度,與面向對象的思想是有違背的。正如goto語句,好用但盡量少用。在這裡筆者並不是反對用全局變量,而是要看情況而用。筆者曾經開發過一個日本項目,粗略計算一下,全局變量不下於1000個,這樣的程序的維護難度可想而知。
希望此文能夠幫助初學者在VC之路上少走一些歪路,盡快融入VC開發大軍。