窗口类封装之窗口对象消息处理的映射方法(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

点击这里给我发消息
原文地址:https://www.cnblogs.com/charm/p/2020188.html