首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

ATL GUI 程式設計(四):視窗類別核心——CWindowImpl、CWindow、CWinTraits 深度解析

     編輯:VC 教學

視窗的三要素:屬性、方法、事件

  • 屬性:視窗類別樣式(`WNDCLASS.style`)、背景筆刷、圖示、游標等;視窗實例樣式(`CreateWindow` 的 `dwStyle`/`dwExStyle`)。
  • 方法:`ShowWindow`、`UpdateWindow`、`SetWindowPos` 等操作 API。
  • 事件:訊息回呼函數處理 `WM_PAINT`、`WM_DESTROY` 等。

ATL 活版封裝架構

// 繼承鏈示意
class CHelloATLWnd : public CWindowImpl> { ... };

// CWindowImpl 三個模板參數
template 
class CWindowImpl : public CWindowImplRoot, public CMessageMap { ... };

// CWindowImplRoot 繼承 TBase (CWindow) 與 CMessageMap
// T 用於 CRTP(編譯期多型),TBase 封裝 HWND 與視窗 API,TWinTraits 封裝樣式常數

核心類別詳解

1. CWinTraits — 樣式常數封裝

template 
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; }
};

使用:`CWinTraits` 即可在建立視窗時自動套用預設樣式。

2. CWindow — HWND 薄封裝與 API 包裝

  • 成員 `m_hWnd` 保存視窗句柄。
  • 提供 `Create`、`DestroyWindow`、`ShowWindow`、`SetWindowPos`、`GetDC` 等數百個內聯包裝函數,幾乎零開銷。
  • 支援 `operator HWND()` 隱含轉換,可直接傳遞給 SDK API。

3. CMessageMap — 訊息映射核心

  • 使用 `BEGIN_MSG_MAP` / `END_MSG_MAP` 巨集建立靜態訊息映射表。
  • 支援鏈式映射:`CHAIN_MSG_MAP(BaseClass)` 繼承基類訊息處理。
  • 支援 `ALT_MSG_MAP(id)` 實現同一類別處理多個視窗(如子類別化)。

4. CWindowImpl — 整合入口

  • 提供 `Create` 方法:內部呼叫 `TWinTraits::GetWndStyle/ExStyle`、註冊視窗類別(`CWindowImpl::GetWndClassInfo`)、`CreateWindowEx`。
  • 實作 `WindowProc` 靜態函數,透過 `CMessageMap` 分派訊息到衍生類別的處理函數。
  • CRTP 模式:`T` 為衍生類別,編譯期解析虛擬函數呼叫,無虛函數表開銷。

實戰:最小 ATL 視窗類別

class CMainWnd : public CWindowImpl> {
public:
    DECLARE_WND_CLASS(_T("MyMainWnd"))
    BEGIN_MSG_MAP(CMainWnd)
        MESSAGE_HANDLER(WM_PAINT, OnPaint)
        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
    END_MSG_MAP()

    LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&) {
        PAINTSTRUCT ps; HDC hdc = BeginPaint(m_hWnd, &ps);
        DrawText(hdc, _T("Hello, ATL!"), -1, &ps.rcPaint, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
        EndPaint(m_hWnd, &ps); return 0;
    }
    LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL&) { PostQuitMessage(0); return 0; }
};
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved