程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> ATL的GUI程序設計(4)ATL的窗口類

ATL的GUI程序設計(4)ATL的窗口類

編輯:vc教程

  第三章 ATL的窗口類

  CWindowImpl、CWindow、CWinTraits,ATL窗口類的奧秘盡在此三者之中。在本章裡,李馬將為你詳細解說它們的使用方法。另外,本章的內容也可以算是本書的核心部分——如果你要進行ATL的GUI程序設計的話,就必須將ATL的窗口類設計理念了然於心。

  窗口的組成

  把ATL的窗口類撇開不談先。我在上一章中提到:窗口類並非任何一種OOP語言中的類——它所包括的並不是通稱的屬性和方法(在C++中稱作成員變量和成員函數),而是屬性和響應。現在是解釋這句話的時候了。

  所謂窗口的屬性,無非是窗口的樣式(style)、背景畫刷(brush)、圖標(icon)、光標(cursor)……等元素。你可以從WNDCLASS及WNDCLASSEX中找到它們。需要特別指出的是,窗口的樣式事實上包括窗口類的樣式和窗口實例的樣式,窗口類的樣式在注冊窗口類之前經由WNDCLASS::style或WNDCLASSEX::style指定,而窗口實例的樣式則是在創建窗口(CreateWindow/CreateWindowEx)的時候指定的。

  對於窗口的響應,即是指窗口收到某消息後的處理。(在VB、Delphi等RAD環境中,處理窗口的響應亦稱作窗口的事件處理。)對於SDK而言,為窗口提供響應也就是為窗口類提供一個回調函數,在回調函數中對我們感興趣的窗口消息進行特殊處理,譬如上一章中針對WM_DESTROY和WM_PAINT的處理。

  另外,我們在進行Win32程序設計的時候,往往還需要對窗口進行操作,譬如ShowWindow和UpdateWindow——姑且讓我稱之為“方法”。

  屬性、方法、事件,這回這哥仨算齊了。我們在對窗口進行C++封裝時,需要考慮的也正是這三者。自然,依據OO的理念,我們可以很簡單地將句柄作為成員變量,將方法作為成員函數,然後將事件經由某種特定的消息分流手段移交給各個成員函數進行響應處理,加之對不同種類的窗口使用繼承進行區分——這就是MFC的封裝做法。大家如果有興趣的話,可以打開MFC的afxwin.h看一看CWnd類的代碼。

  ATL窗口類的活版封裝

  MFC的CWnd是一個冗長得有些過分的類。究其原因,窗口類的封裝理念決定了窗口類的消息分流,而消息分流則決定了類的代碼篇幅。如果你已經打開了afxwin.h文件,就可以發現CWnd花了很大的篇幅在“On”開頭的事件響應函數上。其實在我們進行Win32程序設計的時候,真正感興趣的事件沒有幾個,所以說“萬能”勢必造就冗長。

  另外,考慮MFC的誕生年代,所以對於窗口的封裝只是采用了C++的低端特性——例如薄層的封裝和單向繼承。(題外話:而且MFC中還存在著一些諸如CString、CArray、CList之類的工具,蓋因其時STL還未標准化之故。)隨著MFC的發展,任憑它做出任何優化,也無法避免當初架構理念帶來的效率陰影和偏差。

  ATL的誕生年代晚於MFC,使之能夠有機會使用C++的高端特性,也就是模板和多重繼承。於是,它使用了一種全新的封裝理念:將屬性、方法、事件分別獨立出來,然後利用模板和多重繼承的特性將這三者根據需要而組合在一起——打個比方來說,如果MFC的窗口封裝是雕版印刷術,那麼ATL的窗口封裝就是活版印刷術。以上一章的CHelloATLWnd類為例,它的繼承層次如下圖:

  這是一個稍顯冗長的繼承鏈,不過我並不打算對它進行詳細的解說。在此,我只請你看這個繼承層次的最底層和最上層。從最底層來看,CHelloATLWnd繼承自CWindowImpl,CWindowImpl有三個模板參數:T、TBase、TWinTraits。再看最上層,CWindowImplRoot繼承自TBase和CMessageMap。T參數即是你所繼承下來的子類名,通常用於編譯期的虛函數機制(後邊我會對這一機制進行介紹);TBase參數為對窗口方法和句柄的封裝;TWinTraits是窗口樣式的類封裝;CMessageMap是對窗口事件響應的封裝。

  下面,就讓李馬來逐一將這些組成部分介紹給你吧。

  窗口樣式的封裝

  窗口樣式通常由CWinTraits類封裝,這個類很簡單,如下:

  

/////////////////////////////////////////////////////////////////////////////
// CWinTraits - Defines various default values for a window
template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
class CWinTraits
{
public:
  static DWORD GetWndStyle(DWORD dwStyle)
  {
    return dwStyle == 0 ? t_dwStyle : dwStyle;
  }
  static DWORD GetWndExStyle(DWORD dwExStyle)
  {
    return dwExStyle == 0 ? t_dwExStyle : dwExStyle;
  }
};

  • 首頁
  • 上一頁
  • 1
  • 2
  • 3
  • 下一頁
  • 尾頁
  • 共3頁
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved