学习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; 
      }