任何非對話框窗口都是來自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;
}