学习WTL可以有多种方式,当然如果有COM和ATL的知识背景最好不过,如果你有MFC编程背景却最为糟糕,除非你对MFC无所不知、无所不能: -)(如果你不是MFC的ORACLE,那么最好忘却它)
参照3.1.1 Win32基础构造块和主要流程,来初步的了解ATL Windows编程模型(有关ATL Windows编程的文档极为“罕见“, 甚至与WTL相比 : -)) ;ATL Windows编程是WTL的基石,当然有必要在此费一番力气。
4.1 RegisterClass在哪?
在 1.2.1 Register windows class 中,MyRegisterClass函数要完成的工作:1. 初始化WNDCLASSEX;2. RegisterClassEx 。 而在ATL中,由CWellcomeWindow之由宏定义的成员函数(member function by macro defined)DECLARE_WND_CLASS(NULL)完成,其由wnd.Create(NULL, 0, appTitle) 调用(例如,在win32.cpp中)。
4.1.1 DECLARE_WND_CLASS(NULL)宏定义
/////////////////////////////////////////////////////////////////////////////
// CWndClassInfo - Manages Windows class information
#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; \
}
CWndClassInfo为ATL内使用WNDCLASSEX结构的结构(C++),看看代码就应该有所了解了,关键在于 4.1.2 CWndClassInfo结构(_ATL_WNDCLASSINFOW)定义 的黑体部分(Bold)。
4.1.2 CWndClassInfo结构(_ATL_WNDCLASSINFOW)定义
struct _ATL_WNDCLASSINFOW
{
WNDCLASSEXW m_wc;
LPCWSTR m_lpszOrigName;
WNDPROC pWndProc;
LPCWSTR m_lpszCursorID;
BOOL m_bSystemCursor;
ATOM m_atom;
WCHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT];
ATOM Register(WNDPROC* p)
{
return AtlWinModuleRegisterWndClassInfoW(&_AtlWinModule, &_AtlBaseModule, this, p);
}
};
4.1.3 ATL::CWindowImpl::Create定义
HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
{
if (T::GetWndClassInfo().m_lpszOrigName == NULL)
T::GetWndClassInfo().m_lpszOrigName = GetWndClassName();
ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
dwStyle = T::GetWndStyle(dwStyle);
dwExStyle = T::GetWndExStyle(dwExStyle);
// set caption
if (szWindowName == NULL)
szWindowName = T::GetWndCaption();
return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rect, szWindowName,
dwStyle, dwExStyle, MenuOrID, atom, lpCreateParam);
}
真正完成CreateWindow。
4.2 WndProc在哪?
Main message loop在ATL予以了保留(例如,在win32.cpp中)。
WndProc由宏定义成员函数完成,参看 2.2 添加CWellcomeWindow.h可以看到如下代码:
BEGIN_MSG_MAP(CWellcomeWindow)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
END_MSG_MAP()
4.2.1 Message-Map
#define BEGIN_MSG_MAP(theClass) \
public: \
BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
{ \
BOOL bHandled = TRUE; \
(hWnd); \
(uMsg); \
(wParam); \
(lParam); \
(lResult); \
(bHandled); \
switch(dwMsgMapID) \
{ \
case 0:
#define END_MSG_MAP() \
break; \
default: \
ATLTRACE(ATL::atlTraceWindowing, 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID); \
ATLASSERT(FALSE); \
break; \
} \
return FALSE; \
}
你所定义的特定的消息处理将会置于case 0 和defaul之间,例如 2.2 添加CWellcomeWindow.h将会产生如下代码:
BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0)
{
BOOL bHandled = TRUE;
(hWnd);
(uMsg);
(wParam);
(lParam);
(lResult);
(bHandled);
switch(dwMsgMapID)
{
case 0:
if(uMsg == msg)
{
bHandled = TRUE;
lResult = OnCreate(uMsg, wParam, lParam, bHandled);
if(bHandled)
return TRUE;
}
……
break;
default:
break;
}
return FALSE;
}