窗口类封装之--窗口对象消息处理的映射方法(1)
对界面进行封装,一般都是一个窗口一个类,比如实现一个最基本的窗口类CMyWnd,你一定会把窗口过程作为这个类的成员函数,但是使用WINAPI创建窗口时必须注册类WNDCLASS,里面有个成员数据lpfnWndProc需要WNDPROC的函数指针,一般想法就是把窗口类的消息处理函数指针传过去,使用静态类成员函数,或者全局的消息处理函数,否则无法转换到WNDPROC。
静态消息处理函数:缺点,消息处理函数无法获取到窗口对象的窗口句柄。
全局消息处理函数:无法得到窗口类对象指针。
一种解决方法是用窗口列表,开一个结构数组,窗口类对象创建窗口的时候把窗口HWND和this指针放入数组,全局消息处理函数遍历数组,利用HWND找出this指针,然后定位到对象内部的消息处理函数。这种方法查找对象的时间会随着窗口个数的增多而增长。代码如下:
#ifndef _WINDOW_H_ #define _WINDOW_H_ #include "stdafx.h" #include "Resource.h" #include <map> class window{ public : window():_hwnd(NULL){} ~window(){} bool Create( HINSTANCE hInstance, const LPCTSTR lpszClassName); protected : HWND _hwnd; private : LRESULT CALLBACK WndProc( UINT message, WPARAM wParam, LPARAM lParam); void RemoveHwndFormMap(); protected : static LRESULT CALLBACK StaticWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); static std::map< HWND ,window*>* _sWindowMap; }; std::map< HWND ,window*>* window::_sWindowMap = new std::map< HWND ,window*>; bool window::Create( HINSTANCE hInstance, LPCTSTR lpszClassName) { WNDCLASSEX wcex; wcex.cbSize = sizeof (WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = StaticWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = ( HBRUSH )(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TEST); wcex.lpszClassName = lpszClassName; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); RegisterClassEx(&wcex); _hwnd = CreateWindow(lpszClassName, NULL, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (_hwnd == NULL) { MessageBox(NULL,TEXT( "Error" ),NULL,NULL); return FALSE; } //_sWindowMap[_hwnd] = this; (*_sWindowMap).insert(std::make_pair(_hwnd, this )); ShowWindow(_hwnd, SW_SHOW); UpdateWindow(_hwnd); return TRUE; } LRESULT CALLBACK window::StaticWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { if ((*_sWindowMap).empty()) { return ::DefWindowProcW(hWnd, message, wParam, lParam); } else return (*_sWindowMap)[hWnd]->WndProc( message, wParam, lParam); } LRESULT CALLBACK window::WndProc( UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: //DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); MessageBox(NULL,TEXT( "AboutDlg" ),TEXT( "关于" ),NULL); break ; case IDM_EXIT: DestroyWindow(_hwnd); RemoveHwndFormMap(); break ; default : return DefWindowProc(_hwnd, message, wParam, lParam); } break ; case WM_PAINT: hdc = BeginPaint(_hwnd, &ps); // TODO: 在此添加任意绘图代码... EndPaint(_hwnd, &ps); break ; case WM_DESTROY: PostQuitMessage(0); RemoveHwndFormMap(); break ; default : return ::DefWindowProc(_hwnd, message, wParam, lParam); } return 0; } void window::RemoveHwndFormMap() { std::map< HWND ,window*>::iterator it; it = (*_sWindowMap).find(_hwnd); (*_sWindowMap).erase(it); } #endif |
posted on 2011-04-18 20:44 Pro.Charm 阅读(1069) 评论(0) 编辑 收藏 举报
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 从零开始开发一个 MCP Server!
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档