采用模板的手法服用CWnd类
时间:2010-11-14 来源:方外之士
.h文件:
代码
class CAuxWindowT : public CWnd
{
DECLARE_DYNAMIC(CAuxWindowT)
public:
CAuxWindowT(); // 标准构造函数
virtual ~CAuxWindowT();
public:
BOOL CreateWnd(DWORD dwExStyle, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam = NULL);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
DECLARE_MESSAGE_MAP()
int OnCreate(LPCREATESTRUCT lpCreateStruct);
void OnPaint();
BOOL OnEraseBkgnd(CDC* pDC);
};
#include "AuxWindow.inl"
文件AuxWindow.inl的代码如下:

type* var = static_cast<type*>(this); \
ATLASSERT(var != NULL);
//IMPLEMENT_DYNAMIC_T(CAuxWindowT, T, CWnd)
template<typename T>
CAuxWindowT<T>::CAuxWindowT()
{
}
template<typename T>
CAuxWindowT<T>::~CAuxWindowT()
{
}
template<typename T>
BOOL CAuxWindowT<T>::CreateWnd(DWORD dwExStyle, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam)
{
DECLARE_TEMPLATE_THIS_POINTER(T, pThis);
CAuxInitWinStruct<WNDCLASSEX> wndClass;
wndClass.lpfnWndProc = ::DefWindowProc;
wndClass.hInstance = AfxGetInstanceHandle();
wndClass.lpszClassName = pThis->GetRegisterClassName();
AUX_ASSERT_FAILED_RETURN_VALUE(AuxRegisterWindowClass(&wndClass), FALSE);
AUX_ASSERT_FAILED_RETURN_VALUE(this->CreateEx(dwExStyle, pThis->GetRegisterClassName(), lpszWindowName, dwStyle, rect, pParentWnd, nID, lpParam), FALSE);
return TRUE;
}
template<typename T>
void CAuxWindowT<T>::DoDataExchange(CDataExchange* pDX)
{
CWnd::DoDataExchange(pDX);
}
BEGIN_TEMPLATE_MESSAGE_MAP(CAuxWindowT, T, CWnd)
ON_WM_CREATE()
ON_WM_PAINT()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
template<typename T>
int CAuxWindowT<T>::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
int nRet = 1;
__if_exists(T::InsideCreate)
{
DECLARE_TEMPLATE_THIS_POINTER(T, pThis);
nRet = pThis->InsideCreate(lpCreateStruct);
}
return nRet;
}
template<typename T>
void CAuxWindowT<T>::OnPaint()
{
__if_exists(T::InsidePaint)
{
DECLARE_TEMPLATE_THIS_POINTER(T, pThis);
pThis->InsidePaint();
}
__if_not_exists(T::InsidePaint)
{
CPaintDC dc(this);
}
}
template<typename T>
BOOL CAuxWindowT<T>::OnEraseBkgnd(CDC* pDC)
{
__if_not_exists(T::InsideEraseBkgnd)
{
return CWnd::OnEraseBkgnd(pDC);
}
DECLARE_TEMPLATE_THIS_POINTER(T, pThis);
return pThis->InsideEraseBkgnd(pDC);
}
这种封装很大的问题在于CWnd的消息映射宏只能映射到自己类中的某个方法,故而我只有在封装中加了一层转发接口,在这里调用派生类的相应的方法(如果有的话).如果完全定制BEGIN_MESSAGE_MAP/ END_MESSAGE_MAP宏使其保存指向派生类的方法,可以实现,但改动实在较大(不亚于自己重头开始写一个窗口类了),而且代码复用的优点也削弱了不少。
派生类的定义:代码
{
DECLARE_DYNAMIC(CFadeWindow)
public:
CFadeWindow(); // 标准构造函数
virtual ~CFadeWindow();
public:
LPCTSTR GetRegisterClassName()
{
return _T("SinaShowFadeWindow");
}
int InsideCreate(LPCREATESTRUCT lpCreateStruct);
void InsidePaint();
BOOL InsideEraseBkgnd(CDC* pDC);
};
// .cpp
IMPLEMENT_DYNAMIC(CFadeWindow, CAuxWindowT<CFadeWindow>)
代码注解:__if_exists和__if_not_exists用于判断某个标识符是否存在,其不能与else共用,所以提供2个相反的关键字。
CAuxInitWinStruct:用于初始化Windows结构体的封装
定义如下:
代码
// 封装Windows常用的结构体
// 自动进行清零操作和设置Windows结构体的cbSize字段
//
template<typename TBase>
class CAuxInitWinStruct : public TBase
{
public:
CAuxInitWinStruct()
{
::ZeroMemory(this, sizeof(TBase));
this->cbSize = sizeof(TBase);
}
CAuxInitWinStruct(const TBase& var)
{
memcpy(this, &var, sizeof(TBase));
}
};
AuxRegisterWindowClass:窗口类注册实现, 代码如下:
代码
inline BOOL AuxRegisterWindowClass(const WNDCLASSEX* pWndClass)
{
ATLASSERT(pWndClass != NULL);
BOOL bSuccess = TRUE;
// 先检测窗口是否注册过
WNDCLASSEX wndClassDummy;
BOOL bRegistered = ::GetClassInfoEx(pWndClass->hInstance, pWndClass->lpszClassName, &wndClassDummy);
if (!bRegistered || (wndClassDummy.lpfnWndProc != pWndClass->lpfnWndProc))
{
// 如果未注册或者注册的窗口过程不是本地的函数地址, 则重新注册
if (bRegistered)
{
// 如果已注册 则先取消注册
::UnregisterClass(wndClassDummy.lpszClassName, pWndClass->hInstance);
}
// 注册窗口
bSuccess = (::RegisterClassEx(pWndClass) != 0) ? TRUE : FALSE;
}
return bSuccess;
}
相关阅读 更多 +
排行榜 更多 +