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

    点击这里给我发消息
  • 相关阅读:
    zipalign内存对齐优化
    反编译 waring...
    android.os.NetworkOnMainThreadException
    android:LayoutInflater
    Notification NotificationManager RemoteViews PendingIntent
    WebView WebViewClient WebChromeClient
    寒假1
    冻死可怕了
    一个人失眠
    军训快乐
  • 原文地址:https://www.cnblogs.com/charm/p/2020188.html
Copyright © 2020-2023  润新知