WTL下载
WTL 基础概念
定位与优势
- 基于
ATL
的扩展库,专注于高效Win32 GUI
开发,无MFC
的臃肿 - 优势
- 模板驱动:零成本抽象,代码体积小
- 兼容
Win32 API
:直接操作窗口句柄,灵活性高。 - 现代
C++
风格:支持RAII
、模板元编程
WTL 与 ATL 的关系
- 依赖关系:
WTL
依赖ATL
的窗口类(如CWindow
)和COM
支持
- 扩展功能:
WTL
在ATL
基础上添加了高级控件(如CListViewCtrl
)、UI
布局工具(如CSplitterWindow
)
窗口与消息处理
窗口模板类
CWindowImpl
:窗口基类,支持消息映射CDialogImpl
:对话框封装CFrameWindowImpl
:主框架窗口
CWindow
- 轻量级句柄封装
CWindow
是对窗口句柄(HWND
)的薄封装,提供对窗口操作API
的直接映射,如ShowWindow
、MoveWindow
等- 仅包含
m_hWnd
作为窗口句柄,无额外冗余数据,确保对象占用最小内存 - 通过重载
operator HWND()
,允许将CWindow
对象隐式转换为HWND
,实现与原生API的无缝兼容
- 方法封装策略
- 将
SendMessage
等函数封装为成员方法,例如SendMessage
变为CWindow::SendMessage
,并利用模板参数校验消息参数类型 - 提供
Attach
和Detach
方法,显式控制句柄所有权,避免MFC
中隐含的资源管理开销
- 将
- 与
CWindowImpl
的协作CWindowImpl
通常以CWindow
作为模板基类(TBase
参数),继承其窗口操作方法,同时扩展窗口创建和消息处理功能CWindow
仅负责窗口操作,而窗口的生命周期管理(如注册窗口类、创建窗口)由CWindowImpl
处理
CWindowImpl
- 用途
- 用于创建自定义窗口,处理窗口消息(如
WM_PAINT
、WM_CREATE
等)
- 用于创建自定义窗口,处理窗口消息(如
- 继承关系
- 继承自
CWindowImpl
→CWindowImplBaseT
→CWindowImplRoot
→CMessageMap
- 继承自
CWindow
(ATL 的窗口句柄封装类),通过模板实现消息映射
- 继承自
- 特性
- 消息映射宏:通过
BEGIN_MSG_MAP
和END_MSG_MAP
定义消息处理逻辑 - 窗口类注册:支持动态注册窗口类(通过
DECLARE_WND_CLASS
) - 灵活性:可以自定义窗口样式、扩展样式和窗口过程
- 消息映射宏:通过
- 场景
- 需要完全自定义的窗口(如游戏界面、绘图工具)
- 实现非标准控件(如自定义按钮、图表控件)
- 示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include <atlbase.h> #include <atlapp.h> #include <atlwin.h> class CMyWindow : public CWindowImpl<CMyWindow> { public: // 1. 声明窗口类(自动注册) DECLARE_WND_CLASS(L"MyWindowClass") // 2. 消息映射表 BEGIN_MSG_MAP(CMyWindow) MESSAGE_HANDLER(WM_PAINT, OnPaint) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) END_MSG_MAP() // 3. 消息处理函数 LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { PAINTSTRUCT ps; HDC hdc = BeginPaint(&ps); TextOut(hdc, 10, 10, L"Hello WTL!", 10); EndPaint(&ps); bHandled = TRUE; // 标记消息已处理 return 0; } LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { PostQuitMessage(0); // 退出消息循环 bHandled = TRUE; return 0; } }; // 创建并显示窗口 CMyWindow wnd; wnd.Create(NULL, CWindow::rcDefault, L"WTL Window", WS_OVERLAPPEDWINDOW); wnd.ShowWindow(SW_SHOW); |
CDialogImpl
- 功能
- 用于创建模态或非模态对话框,支持对话框资源模板和控件消息处理
- 继承关系
CDialogImpl<T, TBase>
→CDialogImplBaseT<TBase>
→CWindowImplRoot<TBase>
CDialogImplBaseT<TBase>
为对话框提供基础的消息处理框架和窗口过程(DialogProc
),并通过模板参数TBase
支持基类扩展(默认基类为CWindow
)CWindowImplRoot<TBase>
作为继承链的根类,确保窗口对象销毁时关联的窗口句柄(HWND
)已被正确销毁
- 特性
- 对话框资源绑定:通过
enum { IDD = IDD_MYDIALOG }
关联资源文件中的对话框模板 - 控件消息处理:使用
COMMAND_HANDLER
或NOTIFY_HANDLER
响应按钮点击、列表项选择等事件 - 数据交换(
DDX
):通过BEGIN_DDX_MAP
和END_DDX_MAP
简化控件与变量的数据同步
- 对话框资源绑定:通过
- 场景
- 配置窗口(如设置选项、用户登录)
- 数据输入表单(如新建文件、编辑属性)
- 示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#include <atlbase.h> #include <atlapp.h> #include <atlwin.h> #include "resource.h" // 对话框资源头文件 class CMyDialog : public CDialogImpl<CMyDialog> { public: // 1. 关联对话框资源 enum { IDD = IDD_MYDIALOG }; // 2. 消息映射表 BEGIN_MSG_MAP(CMyDialog) COMMAND_ID_HANDLER(IDOK, OnOK) COMMAND_ID_HANDLER(IDCANCEL, OnCancel) END_MSG_MAP() // 3. 消息处理函数 LRESULT OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { EndDialog(IDOK); // 关闭对话框并返回 IDOK return 0; } LRESULT OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { EndDialog(IDCANCEL); // 关闭对话框并返回 IDCANCEL return 0; } }; // 显示模态对话框 CMyDialog dlg; INT_PTR nResult = dlg.DoModal(); |
CFrameWindowImpl
- 用途
- 用于创建应用程序的主窗口,支持菜单、工具栏、状态栏等复杂
UI
元素
- 用于创建应用程序的主窗口,支持菜单、工具栏、状态栏等复杂
- 继承关系
CFrameWindowImpl
→CFrameWindowImplBase
→CWindowImplBaseT<TBase>
- 特性
- 框架布局:支持嵌入子窗口(如视图、工具栏)
- 消息链(
Message Chaining
):通过CHAIN_MSG_MAP
将消息路由到子控件 UI
更新机制:通过CUpdateUI
自动启用/禁用菜单项和工具栏按钮
- 场景
- 应用程序主窗口(如文本编辑器、资源管理器)
- 多文档界面(
MDI
)的框架窗口
- 示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#include <atlbase.h> #include <atlapp.h> #include <atlwin.h> #include <atlframe.h> #include <atlctrls.h> class CMyFrame : public CFrameWindowImpl<CMyFrame> { public: // 1. 声明框架窗口类 DECLARE_FRAME_WND_CLASS(L"MyFrameClass", IDR_MAINMENU) // 2. 消息映射表 BEGIN_MSG_MAP(CMyFrame) MESSAGE_HANDLER(WM_CREATE, OnCreate) COMMAND_ID_HANDLER(ID_FILE_EXIT, OnFileExit) CHAIN_MSG_MAP(CFrameWindowImpl<CMyFrame>) // 继承基类消息处理 END_MSG_MAP() // 3. 消息处理函数 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // 创建工具栏和状态栏 m_toolbar.Create(m_hWnd, NULL, L"工具栏", ATL_SIMPLE_TOOLBAR_STYLE); m_statusbar.Create(m_hWnd); // 初始化 UI UIAddToolBar(m_toolbar); UISetCheck(ID_VIEW_TOOLBAR, TRUE); return 0; } LRESULT OnFileExit(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { PostMessage(WM_CLOSE); // 关闭窗口 return 0; } private: CToolBarCtrl m_toolbar; CStatusBarCtrl m_statusbar; }; // 创建并显示主窗口 CMyFrame frame; frame.Create(NULL, CWindow::rcDefault, L"WTL 主窗口"); frame.ShowWindow(SW_SHOW); |
消息映射机制
1 2 3 4 5 |
BEGIN_MSG_MAP(CMyWindow) MESSAGE_HANDLER(WM_PAINT, OnPaint) COMMAND_ID_HANDLER(ID_BUTTON_OK, OnOK) CHAIN_MSG_MAP(CMyParentWindow) // 消息链 END_MSG_MAP() |
消息链
- 将消息路由到父窗口或子控件
1 2 3 4 |
BEGIN_MSG_MAP(CMyWindow) MESSAGE_HANDLER(WM_PAINT, OnPaint) CHAIN_MSG_MAP_MEMBER(m_childControl) // 将消息传递给子控件 END_MSG_MAP() |
消息处理函数
1 2 3 4 5 |
LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // 处理 WM_PAINT bHandled = TRUE; return 0; } |
动态 UI 更新
CUpdateUI
机制:自动更新菜单项和工具栏状态
1 2 3 4 |
BEGIN_MSG_MAP(CMyFrame) CHAIN_MSG_MAP(CUpdateUI<CMyFrame>) CHAIN_MSG_MAP(CFrameWindowImpl<CMyFrame>) END_MSG_MAP() |
自定义窗口样式
- 修改窗口样式:在
PreCreateWindow
中调整CREATESTRUCT
。
1 2 3 4 |
BOOL PreCreateWindow(CREATESTRUCT& cs) { cs.style |= WS_CLIPCHILDREN; // 添加样式 return TRUE; } |
控件封装
常用控件
CButton
、CEdit
、CListBox
、CComboBox
。
高级控件
CListViewCtrl
、CTreeViewCtrl
、CStatusBarCtrl
控件操作
1 2 3 |
CEdit m_edit; m_edit.Create(m_hWnd, rcDefault, L"输入框", WS_VISIBLE | WS_CHILD); m_edit.SetWindowText(L"Hello WTL!"); |
资源管理
- 资源文件
.rc
- 定义对话框、菜单、图标等资源
- 对话框数据交换(
DDX
):
1 2 3 4 |
BEGIN_DDX_MAP(CMyDialog) DDX_TEXT(IDC_EDIT_NAME, m_strName) DDX_CHECK(IDC_CHECK_ENABLE, m_bEnable) END_DDX_MAP() |
高级 UI 功能
多文档界面(MDI):
CMDIFrameWindowImpl
:MDI 主框架CMDIChildWindowImpl
:MDI 子窗口
分割窗口
1 2 3 4 |
CSplitterWindow m_splitter; m_splitter.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE); m_splitter.SetSplitterPane(0, m_leftPane); m_splitter.SetSplitterPane(1, m_rightPane); |
工具栏与状态栏
CToolBarCtrl
、CStatusBarCtrl
GDI与绘图
- 封装类
CDC
(设备上下文)、CPen
、CBrush
- 双缓冲绘图
1 2 3 4 5 6 7 |
CDC memDC; CBitmap bitmap; memDC.CreateCompatibleDC(dc); bitmap.CreateCompatibleBitmap(dc, width, height); memDC.SelectBitmap(bitmap); // 在 memDC 上绘制 dc.BitBlt(0, 0, width, height, memDC, 0, 0, SRCCOPY); |
多线程与UI
UI线程安全
- 通过
PostMessage
或SendMessage
跨线程更新UI
1 2 3 4 |
std::thread([this]() { // 执行耗时操作 ::PostMessage(m_hWnd, WM_USER_UPDATE, 0, (LPARAM)result); }).detach(); |
现代 C++ 特性集成
Lambda
表达式:简化消息处理
1 2 3 4 |
MESSAGE_HANDLER(WM_TIMER, [](UINT, WPARAM, LPARAM, BOOL&) { // 处理 WM_TIMER return 0; }) |
- 智能指针:结合
std::unique_ptr
管理资源
自定义控件与 Owner-Draw
- 自定义绘制
- 重写
OnPaint
或响应WM_DRAWITEM
- 重写
1 2 3 4 5 6 7 |
BEGIN_MSG_MAP(CMyButton) MSG_WM_DRAWITEM(OnDrawItem) END_MSG_MAP() void OnDrawItem(LPDRAWITEMSTRUCT lpDrawItem) { // 自定义按钮绘制 } |
国际化与本地化
- 多语言资源:通过资源 DLL 切换语言。
- 动态字符串加载:
1 2 |
CString strTitle; strTitle.LoadStringW(IDS_TITLE); |
示例程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#include <atlbase.h> #include <atlapp.h> #include <atlwin.h> class CMyWindow : public CWindowImpl<CMyWindow> { public: DECLARE_WND_CLASS(L"MyWTLWindow") BEGIN_MSG_MAP(CMyWindow) MESSAGE_HANDLER(WM_PAINT, OnPaint) MESSAGE_HANDLER(WM_DESTROY, OnDestroy) END_MSG_MAP() LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { CPaintDC dc(m_hWnd); CRect rc; GetClientRect(&rc); dc.DrawText(L"Hello WTL!", -1, &rc, DT_CENTER | DT_VCENTER); bHandled = TRUE; return 0; } LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { PostQuitMessage(0); bHandled = TRUE; return 0; } }; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) { CMyWindow wnd; wnd.Create(NULL, CWindow::rcDefault, L"WTL Demo"); wnd.ShowWindow(nCmdShow); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } |
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ C++并发编程 _ 共享数据05/16
- ♥ STL_了解05/02
- ♥ Spdlog记述:二07/09
- ♥ 51CTO:C++网络通信引擎架构与实现一09/09
- ♥ Effective C++_第一篇01/10
- ♥ 预处理指令记录:一07/09