c++窗口过程封装的一些实现
如何封装窗口过程是所有UI库最核心的设计之一,像MFC/WTL/VCL都各有自己的实现代码,最终的目标却是一样的:将窗口过程转化为对象的方法,从而把面向过程的Windows转化为面向对象的方式。这里要介绍我自己想到两种实现方式,这些实现都很简单,但都可以达到同样的目的。
一、利用窗口的属性表
基本原理是将窗口句柄和窗口类实例绑定在一起,每个窗口都有自己的属性表,通过GetProp和SetProp等API操作之,属性表本质上就是哈希表,通过一个Key快速查找到Value,在这里Key就是窗口句柄,Value就是窗口类。
另外,我们需要一个自己的标准窗口过程,用来找到与句柄关联的窗口类,然后再调用窗口类的窗口过程。
先看看实现的代码:
view plaincopy to clipboardprint?
#ifndef WndHandler_h__
#define WndHandler_h__
#include <crtdbg.h>
#define _WINDOW_CLSATOM "wndatom"
class WndHandler
{
public:
WndHandler(): mDefWndProc(NULL), mHwnd(NULL)
{
}
virtual ~WndHandler()
{
Unsubclass();
}
bool Subclass(HWND hwnd)
{
Unsubclass();
_ASSERT(::IsWindow(hwnd));
_ASSERT(::GetPropA(hwnd, _WINDOW_CLSATOM) == NULL);
mDefWndProc = (WNDPROC)::GetWindowLongW(hwnd, GWL_WNDPROC);
if (mDefWndProc == WndHandler::StdWndProc)
mDefWndProc = DefWindowProcW;
::SetWindowLongW(hwnd, GWL_WNDPROC, (long)StdWndProc);
::SetPropA(hwnd, _WINDOW_CLSATOM, (HANDLE)this);
mHwnd = hwnd;
return true;
}
void Unsubclass()
{
if (!::IsWindow(mHwnd) || !mDefWndProc)
return;
::SetWindowLongW(mHwnd, (LONG)mDefWndProc, GWL_WNDPROC);
::RemovePropA(mHwnd, _WINDOW_CLSATOM);
mDefWndProc = NULL;
mHwnd = NULL;
}
protected:
static LRESULT CALLBACK StdWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
WndHandler* handler = (WndHandler*)GetPropA(hwnd, _WINDOW_CLSATOM);
_ASSERT(handler);
LRESULT ret = 0;
BOOL done = handler->WndProc(hwnd, msg, wparam, lparam, ret);
if (done)
return ret;
else
return CallWindowProcW(handler->mDefWndProc, hwnd, msg, wparam, lparam);
}
virtual BOOL WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, LRESULT& ret)
{
switch (msg)
{
case WM_NCDESTROY:
{
mHwnd = NULL;
break;
}
}
return FALSE;
}
protected:
WNDPROC mDefWndProc;
HWND mHwnd;
};
#endif // WndHandler_h__
#ifndef WndHandler_h__
#define WndHandler_h__
#include <crtdbg.h>
#define _WINDOW_CLSATOM "wndatom"
class WndHandler
{
public:
WndHandler(): mDefWndProc(NULL), mHwnd(NULL)
{
}
virtual ~WndHandler()
{
Unsubclass();
}
bool Subclass(HWND hwnd)
{
Unsubclass();
_ASSERT(::IsWindow(hwnd));
_ASSERT(::GetPropA(hwnd, _WINDOW_CLSATOM) == NULL);
mDefWndProc = (WNDPROC)::GetWindowLongW(hwnd, GWL_WNDPROC);
if (mDefWndProc == WndHandler::StdWndProc)
mDefWndProc = DefWindowProcW;
::SetWindowLongW(hwnd, GWL_WNDPROC, (long)StdWndProc);
::SetPropA(hwnd, _WINDOW_CLSATOM, (HANDLE)this);
mHwnd = hwnd;
return true;
}
void Unsubclass()
{
if (!::IsWindow(mHwnd) || !mDefWndProc)
return;
::SetWindowLongW(mHwnd, (LONG)mDefWndProc, GWL_WNDPROC);
::RemovePropA(mHwnd, _WINDOW_CLSATOM);
mDefWndProc = NULL;
mHwnd = NULL;
}
protected:
static LRESULT CALLBACK StdWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
WndHandler* handler = (WndHandler*)GetPropA(hwnd, _WINDOW_CLSATOM);
_ASSERT(handler);
LRESULT ret = 0;
BOOL done = handler->WndProc(hwnd, msg, wparam, lparam, ret);
if (done)
return ret;
else
return CallWindowProcW(handler->mDefWndProc, hwnd, msg, wpa
补充:软件开发 , C++ ,