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


你可能感兴趣的:(对象)