?? 03.3.2 在窗口中顯示按鈕(2).txt
字號:
根據(jù)運行結(jié)果,我們可以看到該按鈕顯示在工具欄上了,這是因為按鈕當(dāng)前的父窗口是CMainFrame類窗口,即主框架窗口。該窗口中,標(biāo)題欄和菜單都位于非客戶區(qū),而工具欄位于它的客戶區(qū)(關(guān)于窗口的客戶區(qū)和非客戶區(qū)的內(nèi)容將在下一章講解)。我們程序中的按鈕是在主框架窗口的客戶區(qū)出現(xiàn)的,并且其位置由CRect(0,0,100,100)參數(shù)指定,說明其左上角就是其父窗口客戶區(qū)的(0,0)點,因此,該按鈕就在程序的菜單下、工具欄上顯示出來了。
讀者可以設(shè)想一下,如果我們改在CTestView類中創(chuàng)建這個按鈕,會是什么樣的結(jié)果呢?首先,我們把CMainFrame中創(chuàng)建按鈕的代碼(即上述例3-25所示代碼中第1行和第2行代碼)注釋起來,然后為CTestView類定義一個CButton類型的成員變量m_btn。但是接下來,我們發(fā)現(xiàn)CTestView類中沒有OnCreate函數(shù)。我們知道,Windows下的程序都是基于消息的,無論MFC程序,還是SDK程序都是這樣的。既然窗口在創(chuàng)建時都會產(chǎn)生一個WM_CREATE消息,那么就可以讓CTestView響應(yīng)這個消息,也就是為這個類添加WM_CREATE消息的處理函數(shù)。
在VC++中,為一個類添加某個消息的處理函數(shù)的方法是:在ClassView標(biāo)簽頁上,在該類名上單擊右鍵,從彈出的快捷菜單上選擇【Add Windows Message Handler…】菜單命令,這時將彈出如圖3.27所示的添加消息處理函數(shù)的窗口。
圖3.27 添加消息處理函數(shù)的窗口
在該窗口左邊的Windows消息列表中找到并選中WM_CREATE消息,然后單擊Add Handler按鈕,接著再單擊Edit Existing按鈕,或者在選中需要處理的消息之后,直接單擊Add and Edit按鈕。這時,就為CTestView類添加了WM_CREATE消息的處理函數(shù)OnCreate,并且光標(biāo)將定位于該函數(shù)的定義處。我們就在該函數(shù)的尾部添加顯示按鈕的代碼,與CMainFrame中的代碼相同,可以直接復(fù)制過來,結(jié)果如例3-26所示。
例3-26
int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
m_btn.Create("按鈕",WS_CHILD | BS_DEFPUSHBUTTON,CRect(0,0,100,100), this,123);
m_btn.ShowWindow(SW_SHOWNORMAL);
return 0;
}
編譯并運行Test程序,結(jié)果如圖3.28所示。
圖3.28 在視窗口中顯示按鈕
我們可以看到按鈕顯示出來了,但位置發(fā)生了變化。因為這時給按鈕的Create函數(shù)傳遞的this指針指向的是CTestView類的對象,因此,這時按鈕的父窗口就是視類窗口,所以按鈕在視窗口的客戶區(qū)中顯示。如果這時仍想讓按鈕的父窗口為CMainFrame類窗口,即視類窗口的父窗口,可以調(diào)用GetParent函數(shù)來獲得視類的父窗口對象的指針,并將該指針傳遞給按鈕的Create函數(shù)。這時的CTestView類OnCreate函數(shù)定義代碼如例3-27所示。
例3-27
int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
m_btn.Create("按鈕",WS_CHILD | BS_DEFPUSHBUTTON, CRect(0,0,100,100), GetParent(), 123);
m_btn.ShowWindow(SW_SHOWNORMAL);
return 0;
}
運行Test程序,讀者會發(fā)現(xiàn)按鈕的位置與在CMainFrame中創(chuàng)建按鈕的位置一樣,可見按鈕的位置與其父窗口有關(guān),而不是與創(chuàng)建它的代碼所在的類有關(guān)。
另外,如果想在創(chuàng)建按鈕之后立即顯示,可以將其窗口風(fēng)格指定為WS_VISIBLE,這時,就不需要再調(diào)用ShowWindow函數(shù)了。即此時按鈕的創(chuàng)建和顯示只需要下面這一條代碼即可:
m_btn.Create("按鈕",WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, CRect(0,0, 100,100), GetParent(),123);
小技巧:Windows中很多函數(shù)名都是一些有意義的單詞的組合,并且每個單詞的首字母大寫。例如,如果想要得到某個類的父窗口,我們可以猜想這個函數(shù)名應(yīng)該是Get再加上ParentWindow這樣的。打開MSDN的索引標(biāo)簽頁,鍵入GetParentWindow,發(fā)現(xiàn)沒有這個函數(shù),但有一個GetParent函數(shù)。打開這個函數(shù),發(fā)現(xiàn)就是我們所要的函數(shù)。在編程時,通過這種方法,可以快速找到所需要的函數(shù)。
本例中,我們選擇的是BS_DEFPUSHBUTTON按鈕風(fēng)格類型,讀者可以試著使用其他類型的風(fēng)格,例如BS_AUTORADIOBUTTON、BS_CHECKBOX等,看看結(jié)果如何。
通過這個CButton對象的創(chuàng)建,希望讀者能更好地理解C++窗口類對象和窗口之間的關(guān)系。當(dāng)我們將按鈕窗口銷毀,它所對應(yīng)的m_btn這個C++對象并沒有銷毀,因為它是CTestView類的一個成員變量,它的生命周期與CTestView對象是一致的。只要CTestView對象沒有銷毀,該按鈕對象就一直存在,在程序中仍可以訪問這個對象。
另外,我們發(fā)現(xiàn)在調(diào)用CButton的ShowWindow函數(shù)時,也沒有傳遞一個窗口句柄,因為CButton類是CWnd類的子類,因此,它已有一個用于保存窗口句柄的成員變量m_hwnd。這樣,CButton的成員函數(shù)可以直接使用這個變量,并不需要再傳遞窗口句柄了。
另一點需要注意的是,按鈕的父窗口不同,其顯示位置也會有所差異。
最后,我們在寫程序時,如果不知道某個函數(shù)的名稱,可以憑感覺利用單詞的組合來拼寫,通過這種方法一般都能在MSDN中找到需要的函數(shù)。
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -