任何非对话框窗口都是来自CWindowImpl派生
对话框窗口都是来自CDialogImpl派生
定义一个窗口的实现
你的新窗口类需要包含三件事情:
一、一个窗口类的定义,如:
默认由父类CWindowImpl的DECLARE_WND_CLASS(NULL) 完成窗口WNDCLASS结构体的定义.
也可以自己通过DECLARE_WND_CLASS(_T("My Window Class")) 完成窗口WNDCLASS结构体的定义.
二、添加消息映射链
其中祖先类CWindowImplRoot继承自CMessageMap
三、窗口使用的默认窗口类型,称为称为window traits
预定义的window traits:
typedef CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0> CControlWinTraits;
typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> CFrameWinTraits;
typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD> CMDIChildWinTraits;
typedef CWinTraits<0, 0> CNullTraits;
类继承关系:
template <class T, class TBase /* = CWindow */, class TWinTraits /* = CControlWinTraits */>
class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits >
{
};
template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CWindowImplBaseT : public CWindowImplRoot< TBase >
{
public:
WNDPROC m_pfnSuperWindowProc;
CWindowImplBaseT() : m_pfnSuperWindowProc(::DefWindowProc)
{}
};
template <class TBase /* = CWindow */>
class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap
{
};
//窗口类的注册,宏:DECLARE_WND_CLASS
#define DECLARE_WND_CLASS(WndClassName) \
static ATL::CWndClassInfo& GetWndClassInfo() \
{ \
static ATL::CWndClassInfo wc = \
{ \
{ sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, \
0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
}; \
return wc; \
}
全局变量:_AtlWinModule,_AtlBaseModule
extern CAtlWinModule _AtlWinModule;
extern CAtlBaseModule _AtlBaseModule;
//窗口类WNDCLASS结构体的填充
struct _ATL_WNDCLASSINFOA
{
WNDCLASSEXA m_wc;
LPCSTR m_lpszOrigName;
WNDPROC pWndProc;
LPCSTR m_lpszCursorID;
BOOL m_bSystemCursor;
ATOM m_atom;
CHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT];
ATOM Register(WNDPROC* p)
{
return AtlWinModuleRegisterWndClassInfoA(&_AtlWinModule, &_AtlBaseModule, this, p);
}
};
typedef _ATL_WNDCLASSINFOA CWndClassInfoA;
窗口注册过程
CMainFrame wndMain;
CFrameWindowImpl::Create()
ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
//模板展开后
//ATOM atom = CMainFrame::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
//这里的T就是类 CMainFrame
//然后通过如下代码,返回一个静态变量 static WTL::CFrameWndClassInfo wc;
CFrameWndClassInfo::Register(&m_pfnSuperWindowProc);
//CWindowImplBaseT::m_pfnSuperWindowProc
//CWindowImplBaseT() : m_pfnSuperWindowProc(::DefWindowProc){}
#include <atlbase.h>
#include <atlwin.h>
//可选的消息处理类
template <typename T>
class CPaintBkgnd : public CMessageMap
{
public:
BEGIN_MSG_MAP(CPaintBkgnd)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
END_MSG_MAP()
LRESULT OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
HDC dc = (HDC)wParam;
RECT rcClient;
pT->GetClientRect ( &rcClient );
::FillRect(dc, &rcClient, CreateSolidBrush(RGB(0xff,0x66,0x99)) );
return 1;
}
};
class CMyWindow :
public CWindowImpl<CMyWindow, CWindow,CFrameWinTraits>,
public CPaintBkgnd<CMyWindow>
{
public:
//DECLARE_WND_CLASS(_T("abc"))
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_CLOSE, OnClose)
//CHAIN_MSG_MAP(CPaintBkgnd)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
END_MSG_MAP()
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
ATLTRACE("WM_CREATE==0x0001,MSG ID:0x%u\n",uMsg);
return 0;
}
LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
DestroyWindow();
PostQuitMessage(0);
return 0;
}
LRESULT OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HDC dc = (HDC) wParam;
RECT rcClient;
this->GetClientRect ( &rcClient );
::FillRect(dc, &rcClient, CreateSolidBrush(RGB(0xff,0x66,0x00)) );
return 1;
}
};
int _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
CMyWindow wndMain;
HWND hWnd = wndMain.Create(NULL,NULL,"good luck Aaron");
if (hWnd==NULL)
{
::MessageBox(NULL,"创建窗口失败","提示",MB_OK);
}
wndMain.ShowWindow(nCmdShow);
wndMain.UpdateWindow();
MSG msg;
while ( GetMessage ( &msg, NULL, 0, 0 ) > 0 )
{
TranslateMessage ( &msg );
DispatchMessage ( &msg );
}
return 0;
}