WPARAM/LPARAM、視窗程序、訊息迴圈。| MFC 優勢 | WTL 優勢 |
|---|---|
| 成熟完整的 GUI 類別庫 | 無需複雜 Document/View 架構 |
| ClassWizard 強大支援 | 保有 DDX/DDV、命令 UI 自動更新 |
| 官方文件與技術支援 | 分隔視窗等部分功能優於 MFC |
| 動態連結執行檔較小 | 靜態連結執行檔極小 (無 MFC DLL 依賴) |
| 穩定性經大規模驗證 | 原始碼可自行修正 Bug 不影響他程式 |
WTL 與 MFC 視窗可「和平共處」,例如在 MFC CFrameWnd 中嵌入 WTL CSplitterWindow 再包含 MFC CDialog。
ATL (Active Template Library) 最初為簡化 COM 元件/ActiveX 控件開發而生,僅提供輕量視窗封裝 (CWindow, CWindowImpl, CDialogImpl),WTL 在此基礎上建構完整 UI 框架。
template <class T> class B1 {
void SayHi() {
T* pT = static_cast<T*>(this);
pT->PrintClassName();
}
void PrintClassName() { cout << "This is B1"; }
};
class D1 : public B1<D1> {}; // 未覆寫
class D2 : public B1<D2> {
void PrintClassName() { cout << "This is D2"; }
};
// D1.SayHi() → "This is B1", D2.SayHi() → "This is D2"
static_cast<T*>(this) 為核心關鍵,將基類指標安全轉為衍生類別指標。HWND 為首參數的 API (SetWindowText, DestroyWindow 等)。m_hWnd 與 operator HWND(),方便互操作。CWnd)。WindowProc 等完整實作。CWinTraits)。CDialogImpl:一般對話框。CAxDialogImpl:支援 ActiveX 控件的對話框。class CMyWindow : public CWindowImpl<CMyWindow>
{
public:
DECLARE_WND_CLASS(_T("My Window Class"))
// 或 DECLARE_WND_CLASS_EX(類別名, 樣式, 背景筆刷)
};
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_ID_HANDLER(IDC_ABOUT, OnAbout)
END_MSG_MAP()
LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&) { DestroyWindow(); return 0; }
LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL&) { PostQuitMessage(0); return 0; }
LRESULT OnAbout(WORD, WORD, HWND, BOOL&) { MessageBox(...); return 0; }
LRESULT Func(UINT, WPARAM, LPARAM, BOOL& bHandled)。bHandled=TRUE 表示已處理,設 FALSE 則呼叫預設 DefWindowProc。COMMAND_ID_HANDLER/NOTIFY_HANDLER 已自動解碼參數。typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, WS_EX_APPWINDOW> CMyWindowTraits;
class CMyWindow : public CWindowImpl<CMyWindow, CWindow, CMyWindowTraits> { ... }
預設特徵 CFrameWinTraits:WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS + WS_EX_APPWINDOW | WS_EX_WINDOWEDGE。
class CMyWindow : public CWindowImpl<...>, public CPaintBkgnd<CMyWindow, RGB(0,0,255)>
{
typedef CPaintBkgnd<CMyWindow, RGB(0,0,255)> CPaintBkgndBase;
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
CHAIN_MSG_MAP(CPaintBkgndBase)
END_MSG_MAP()
};
CPaintBkgnd 處理 WM_ERASEBKGND 繪製背景)。typedef 避免巨集參數逗號誤判。template <class T, COLORREF t_crBrushColor>
class CPaintBkgnd : public CMessageMap
{
public:
CPaintBkgnd() { m_hbrBkgnd = CreateSolidBrush(t_crBrushColor); }
~CPaintBkgnd() { DeleteObject(m_hbrBkgnd); }
BEGIN_MSG_MAP(CPaintBkgnd)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
END_MSG_MAP()
LRESULT OnEraseBkgnd(UINT, WPARAM wParam, LPARAM, BOOL&)
{
T* pT = static_cast<T*>(this);
HDC dc = (HDC)wParam; RECT rc; pT->GetClientRect(&rc);
FillRect(dc, &rc, m_hbrBkgnd); return 1;
}
protected:
HBRUSH m_hbrBkgnd;
};
// stdafx.h
#define STRICT; #define VC_EXTRALEAN
#include <atlbase.h>
extern CComModule _Module;
#include <atlwin.h>
// main.cpp
CComModule _Module;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
{
_Module.Init(NULL, hInst);
CMyWindow wndMain;
if (NULL == wndMain.Create(NULL, CWindow::rcDefault, _T("My First ATL Window"))) return 1;
wndMain.ShowWindow(nCmdShow); wndMain.UpdateWindow();
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); }
_Module.Term(); return msg.wParam;
}
CComModule _Module 對應 MFC CWinApp theApp,名稱固定為 _Module。CWindow::rcDefault 相當於 CW_USEDEFAULT。HWND 與 C++ 物件,支援跨執行緒傳遞 CWindow 物件。class CAboutDlg : public CDialogImpl<CAboutDlg>
{
public:
enum { IDD = IDD_ABOUT };
BEGIN_MSG_MAP(CAboutDlg)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
COMMAND_ID_HANDLER(IDOK, OnOKCancel)
COMMAND_ID_HANDLER(IDCANCEL, OnOKCancel)
END_MSG_MAP()
LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { CenterWindow(); return TRUE; }
LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL&) { EndDialog(IDCANCEL); return 0; }
LRESULT OnOKCancel(WORD, WORD, HWND, BOOL& bHandled) { EndDialog(wID); return 0; }
};
IDOK/IDCANCEL、WM_CLOSE、WM_INITDIALOG。DoModal() 第一個參數為父視窗 HWND (MFC 為建構式傳遞指標)。_Module.GetResourceInstance() 相當於 AfxGetResourceHandle()。

將介紹 WTL 基礎視窗類別與更好用的訊息映射巨集 (BEGIN_MSG_MAP_EX),正式進入 WTL 核心開發領域。