程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> VC++深入詳解:在窗口中顯示按鈕(2)

VC++深入詳解:在窗口中顯示按鈕(2)

編輯:vc教程

  根據運行結果,我們可以看到該按鈕顯示在工具欄上了,這是因為按鈕當前的父窗口是CMainFrame類窗口,即主框架窗口。該窗口中,標題欄和菜單都位於非客戶區,而工具欄位於它的客戶區(關於窗口的客戶區和非客戶區的內容將在下一章講解)。我們程序中的按鈕是在主框架窗口的客戶區出現的,並且其位置由CRect(0,0,100,100)參數指定,說明其左上角就是其父窗口客戶區的(0,0)點,因此,該按鈕就在程序的菜單下、工具欄上顯示出來了。

  讀者可以設想一下,如果我們改在CTestView類中創建這個按鈕,會是什麼樣的結果呢?首先,我們把CMainFrame中創建按鈕的代碼(即上述例3-25所示代碼中第1行和第2行代碼)注釋起來,然後為CTestView類定義一個CButton類型的成員變量m_btn。但是接下來,我們發現CTestView類中沒有OnCreate函數。我們知道,Windows下的程序都是基於消息的,無論MFC程序,還是SDK程序都是這樣的。既然窗口在創建時都會產生一個WM_CREATE消息,那麼就可以讓CTestVIEw響應這個消息,也就是為這個類添加WM_CREATE消息的處理函數。

  在VC++中,為一個類添加某個消息的處理函數的方法是:在ClassVIEw標簽頁上,在該類名上單擊右鍵,從彈出的快捷菜單上選擇【Add Windows Message Handler…】菜單命令,這時將彈出如圖3.27所示的添加消息處理函數的窗口。

圖3.27 添加消息處理函數的窗口

  在該窗口左邊的Windows消息列表中找到並選中WM_CREATE消息,然後單擊Add Handler按鈕,接著再單擊Edit Existing按鈕,或者在選中需要處理的消息之後,直接單擊Add and Edit按鈕。這時,就為CTestVIEw類添加了WM_CREATE消息的處理函數OnCreate,並且光標將定位於該函數的定義處。我們就在該函數的尾部添加顯示按鈕的代碼,與CMainFrame中的代碼相同,可以直接復制過來,結果如例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程序,結果如圖3.28所示。

圖3.28 在視窗口中顯示按鈕

  我們可以看到按鈕顯示出來了,但位置發生了變化。因為這時給按鈕的Create函數傳遞的this指針指向的是CTestView類的對象,因此,這時按鈕的父窗口就是視類窗口,所以按鈕在視窗口的客戶區中顯示。如果這時仍想讓按鈕的父窗口為CMainFrame類窗口,即視類窗口的父窗口,可以調用GetParent函數來獲得視類的父窗口對象的指針,並將該指針傳遞給按鈕的Create函數。這時的CTestVIEw類OnCreate函數定義代碼如例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程序,讀者會發現按鈕的位置與在CMainFrame中創建按鈕的位置一樣,可見按鈕的位置與其父窗口有關,而不是與創建它的代碼所在的類有關。

  另外,如果想在創建按鈕之後立即顯示,可以將其窗口風格指定為WS_VISIBLE,這時,就不需要再調用ShowWindow函數了。即此時按鈕的創建和顯示只需要下面這一條代碼即可:

  m_btn.Create("按鈕",WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON, CRect(0,0, 100,100), GetParent(),123);  

  小技巧:Windows中很多函數名都是一些有意義的單詞的組合,並且每個單詞的首字母大寫。例如,如果想要得到某個類的父窗口,我們可以猜想這個函數名應該是Get再加上ParentWindow這樣的。打開MSDN的索引標簽頁,鍵入GetParentWindow,發現沒有這個函數,但有一個GetParent函數。打開這個函數,發現就是我們所要的函數。在編程時,通過這種方法,可以快速找到所需要的函數。

  本例中,我們選擇的是BS_DEFPUSHBUTTON按鈕風格類型,讀者可以試著使用其他類型的風格,例如BS_AUTORADIOBUTTON、BS_CHECKBOX等,看看結果如何。

  通過這個CButton對象的創建,希望讀者能更好地理解C++窗口類對象和窗口之間的關系。當我們將按鈕窗口銷毀,它所對應的m_btn這個C++對象並沒有銷毀,因為它是CTestView類的一個成員變量,它的生命周期與CTestView對象是一致的。只要CTestVIEw對象沒有銷毀,該按鈕對象就一直存在,在程序中仍可以訪問這個對象。

  另外,我們發現在調用CButton的ShowWindow函數時,也沒有傳遞一個窗口句柄,因為CButton類是CWnd類的子類,因此,它已有一個用於保存窗口句柄的成員變量m_hwnd。這樣,CButton的成員函數可以直接使用這個變量,並不需要再傳遞窗口句柄了。

  另一點需要注意的是,按鈕的父窗口不同,其顯示位置也會有所差異。

  最後,我們在寫程序時,如果不知道某個函數的名稱,可以憑感覺利用單詞的組合來拼寫,通過這種方法一般都能在MSDN中找到需要的函數。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved