[atlnew]
[reactos.git] / reactos / lib / atl / atlwin.h
diff --git a/reactos/lib/atl/atlwin.h b/reactos/lib/atl/atlwin.h
new file mode 100644 (file)
index 0000000..e85f8b7
--- /dev/null
@@ -0,0 +1,751 @@
+/*
+ * ReactOS ATL
+ *
+ * Copyright 2009 Andrew Hill <ash77@reactos.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _atlin_h
+#define _atlwin_h
+
+#ifdef __GNUC__
+#define GCCU(x)        x __attribute__((unused))
+#define Unused(x)
+#else
+#define GCCU(x)
+#define Unused(x)      (x);
+#endif // __GNUC__
+
+#ifdef SetWindowLongPtr
+#undef SetWindowLongPtr
+inline LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong)
+{
+       return SetWindowLong(hWnd, nIndex, (LONG)dwNewLong);
+}
+#endif
+
+#ifdef GetWindowLongPtr
+#undef GetWindowLongPtr
+inline LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex)
+{
+       return (LONG_PTR)GetWindowLong(hWnd, nIndex);
+}
+#endif
+
+namespace ATL
+{
+
+struct _ATL_WNDCLASSINFOW;
+typedef _ATL_WNDCLASSINFOW CWndClassInfo;
+
+template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
+class CWinTraits
+{
+public:
+       static DWORD GetWndStyle(DWORD dwStyle)
+       {
+               if (dwStyle == 0)
+                       return t_dwStyle;
+               return dwStyle;
+       }
+
+       static DWORD GetWndExStyle(DWORD dwExStyle)
+       {
+               if (dwExStyle == 0)
+                       return t_dwExStyle;
+               return dwExStyle;
+       }
+};
+
+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;
+
+template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0, class TWinTraits = CControlWinTraits>
+class CWinTraitsOR
+{
+public:
+       static DWORD GetWndStyle(DWORD dwStyle)
+       {
+               return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle);
+       }
+
+       static DWORD GetWndExStyle(DWORD dwExStyle)
+       {
+               return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle);
+       }
+};
+
+class _U_MENUorID
+{
+public:
+       HMENU                                                                   m_hMenu;
+public:
+       _U_MENUorID(HMENU hMenu)
+       {
+               m_hMenu = hMenu;
+       }
+
+       _U_MENUorID(UINT nID)
+       {
+               m_hMenu = (HMENU)(UINT_PTR)nID;
+       }
+};
+
+class _U_RECT
+{
+public:
+       LPRECT                                                                  m_lpRect;
+public:
+       _U_RECT(LPRECT lpRect)
+       {
+               m_lpRect = lpRect;
+       }
+
+       _U_RECT(RECT &rc)
+       {
+               m_lpRect = &rc;
+       }
+};
+
+struct _ATL_MSG : public MSG
+{
+public:
+       BOOL                                                                    bHandled;
+public:
+       _ATL_MSG(HWND hWnd, UINT uMsg, WPARAM wParamIn, LPARAM lParamIn, BOOL bHandledIn = TRUE)
+       {
+               hwnd = hWnd;
+               message = uMsg;
+               wParam = wParamIn;
+               lParam = lParamIn;
+               time = 0;
+               pt.x = 0;
+               pt.y = 0;
+               bHandled = bHandledIn;
+       }
+};
+
+#if defined(_M_IX86)
+
+#pragma pack(push,1)
+struct thunkCode
+{
+       DWORD                                                                   m_mov;
+       DWORD                                                                   m_this;
+       BYTE                                                                    m_jmp;
+       DWORD                                                                   m_relproc;
+};
+#pragma pack(pop)
+
+class CWndProcThunk
+{
+public:
+       thunkCode                                                               m_thunk;
+       _AtlCreateWndData                                               cd;
+public:
+       BOOL Init(WNDPROC proc, void *pThis)
+       {
+               m_thunk.m_mov = 0x042444C7;
+               m_thunk.m_this = PtrToUlong(pThis);
+               m_thunk.m_jmp = 0xe9;
+               m_thunk.m_relproc = DWORD(reinterpret_cast<char *>(proc) - (reinterpret_cast<char *>(this) + sizeof(thunkCode)));
+               return TRUE;
+       }
+
+       WNDPROC GetWNDPROC()
+       {
+               return reinterpret_cast<WNDPROC>(&m_thunk);
+       }
+};
+
+#else
+#error Only X86 supported
+#endif
+
+class CMessageMap
+{
+public:
+       virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID) = 0;
+};
+
+class CWindow
+{
+public:
+       HWND                                                                    m_hWnd;
+       static RECT                                                             rcDefault;
+public:
+       CWindow(HWND hWnd = NULL)
+       {
+               m_hWnd = hWnd;
+       }
+
+       operator HWND() const
+       {
+               return m_hWnd;
+       }
+
+       static LPCTSTR GetWndClassName()
+       {
+               return NULL;
+       }
+
+       HDC BeginPaint(LPPAINTSTRUCT lpPaint)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::BeginPaint(m_hWnd, lpPaint);
+       }
+
+       BOOL DestroyWindow()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+
+               if (!::DestroyWindow(m_hWnd))
+                       return FALSE;
+
+               m_hWnd = NULL;
+               return TRUE;
+       }
+
+       void EndPaint(LPPAINTSTRUCT lpPaint)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               ::EndPaint(m_hWnd, lpPaint);
+       }
+
+       BOOL GetClientRect(LPRECT lpRect) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::GetClientRect(m_hWnd, lpRect);
+       }
+
+       CWindow GetParent() const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return CWindow(::GetParent(m_hWnd));
+       }
+
+       BOOL Invalidate(BOOL bErase = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::InvalidateRect(m_hWnd, NULL, bErase);
+       }
+
+       BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::InvalidateRect(m_hWnd, lpRect, bErase);
+       }
+
+       BOOL IsWindow() const
+       {
+               return ::IsWindow(m_hWnd);
+       }
+
+       BOOL KillTimer(UINT_PTR nIDEvent)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::KillTimer(m_hWnd, nIDEvent);
+       }
+
+       BOOL LockWindowUpdate(BOOL bLock = TRUE)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               if (bLock)
+                       return ::LockWindowUpdate(m_hWnd);
+               return ::LockWindowUpdate(NULL);
+       }
+
+       BOOL ScreenToClient(LPPOINT lpPoint) const
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::ScreenToClient(m_hWnd, lpPoint);
+       }
+
+       LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::SendMessage(m_hWnd, message, wParam, lParam);
+       }
+
+       static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+       {
+               ATLASSERT(::IsWindow(hWnd));
+               return ::SendMessage(hWnd, message, wParam, lParam);
+       }
+
+       HWND SetCapture()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::SetCapture(m_hWnd);
+       }
+
+       HWND SetFocus()
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::SetFocus(m_hWnd);
+       }
+
+       UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void (CALLBACK *lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) = NULL)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::SetTimer(m_hWnd, nIDEvent, nElapse, reinterpret_cast<TIMERPROC>(lpfnTimer));
+       }
+
+       BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags);
+       }
+
+       BOOL SetWindowText(LPCTSTR lpszString)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::SetWindowText(m_hWnd, lpszString);
+       }
+
+       BOOL ShowWindow(int nCmdShow)
+       {
+               ATLASSERT(::IsWindow(m_hWnd));
+               return ::ShowWindow(m_hWnd, nCmdShow);
+       }
+
+};
+
+_declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
+
+template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
+class CWindowImplBaseT : public TBase, public CMessageMap
+{
+public:
+       enum { WINSTATE_DESTROYED = 0x00000001 };
+       DWORD                                                                   m_dwState;
+       const _ATL_MSG                                                  *m_pCurrentMsg;
+       CWndProcThunk                                                   m_thunk;
+       WNDPROC                                                                 m_pfnSuperWindowProc;
+public:
+       CWindowImplBaseT()
+       {
+               m_dwState = 0;
+               m_pCurrentMsg = NULL;
+               m_pfnSuperWindowProc = ::DefWindowProc;
+       }
+
+       virtual void OnFinalMessage(HWND /* hWnd */)
+       {
+       }
+
+       BOOL SubclassWindow(HWND hWnd)
+       {
+               CWindowImplBaseT<TBase, TWinTraits>     *pThis;
+               WNDPROC                                                         newWindowProc;
+               WNDPROC                                                         oldWindowProc;
+               BOOL                                                            result;
+
+               ATLASSERT(m_hWnd == NULL);
+               ATLASSERT(::IsWindow(hWnd));
+
+               pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
+
+               result = m_thunk.Init(GetWindowProc(), this);
+               if (result == FALSE)
+                       return FALSE;
+               newWindowProc = m_thunk.GetWNDPROC();
+               oldWindowProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
+               if (oldWindowProc == NULL)
+                       return FALSE;
+               m_pfnSuperWindowProc = oldWindowProc;
+               pThis->m_hWnd = hWnd;
+               return TRUE;
+       }
+
+       virtual WNDPROC GetWindowProc()
+       {
+               return WindowProc;
+       }
+
+       static DWORD GetWndStyle(DWORD dwStyle)
+       {
+               return TWinTraits::GetWndStyle(dwStyle);
+       }
+
+       static DWORD GetWndExStyle(DWORD dwExStyle)
+       {
+               return TWinTraits::GetWndExStyle(dwExStyle);
+       }
+
+       LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               CWindowImplBaseT<TBase, TWinTraits>     *pThis;
+
+               pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(this);
+               return ::CallWindowProc(m_pfnSuperWindowProc, pThis->m_hWnd, uMsg, wParam, lParam);
+       }
+
+       static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               CWindowImplBaseT<TBase, TWinTraits>     *pThis;
+               WNDPROC                                                         newWindowProc;
+               WNDPROC                                                         GCCU(pOldProc);
+
+               pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(_AtlWinModule.ExtractCreateWndData());
+               ATLASSERT(pThis != NULL);
+               if (pThis == NULL)
+                       return 0;
+               pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);
+               newWindowProc = pThis->m_thunk.GetWNDPROC();
+               pOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
+               Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
+               pThis->m_hWnd = hWnd;
+               return newWindowProc(hWnd, uMsg, wParam, lParam);
+       }
+
+       static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               CWindowImplBaseT<TBase, TWinTraits>     *pThis = reinterpret_cast<CWindowImplBaseT< TBase, TWinTraits> *>(hWnd);
+               _ATL_MSG                                                        msg(pThis->m_hWnd, uMsg, wParam, lParam);
+               LRESULT                                                         lResult;
+               const _ATL_MSG                                          *previousMessage;
+               BOOL                                                            handled;
+               LONG_PTR                                                        saveWindowProc;
+
+               ATLASSERT(pThis != NULL && (pThis->m_dwState & WINSTATE_DESTROYED) == 0 && pThis->m_hWnd != NULL);
+               if (pThis == NULL || (pThis->m_dwState & WINSTATE_DESTROYED) != 0 || pThis->m_hWnd == NULL)
+                       return 0;
+
+               hWnd = pThis->m_hWnd;
+               previousMessage = pThis->m_pCurrentMsg;
+               pThis->m_pCurrentMsg = &msg;
+
+               handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0);
+               ATLASSERT(pThis->m_pCurrentMsg == &msg);
+
+               if (handled == FALSE)
+               {
+                       if (uMsg == WM_NCDESTROY)
+                       {
+                               saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
+                               lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
+                               if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC))
+                                       ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pThis->m_pfnSuperWindowProc));
+                               pThis->m_dwState |= WINSTATE_DESTROYED;
+                       }
+                       else
+                               lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
+               }
+               ATLASSERT(pThis->m_pCurrentMsg == &msg);
+               pThis->m_pCurrentMsg = previousMessage;
+               if (previousMessage == NULL && (pThis->m_dwState & WINSTATE_DESTROYED) != 0)
+               {
+                       pThis->m_dwState &= ~WINSTATE_DESTROYED;
+                       pThis->m_hWnd = NULL;
+                       pThis->OnFinalMessage(hWnd);
+               }
+               return lResult;
+       }
+
+       HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle,
+                                       _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
+       {
+               HWND                                                            hWnd;
+
+               ATLASSERT(m_hWnd == NULL);
+               ATLASSERT(atom != 0);
+               if (atom == 0)
+                       return NULL;
+               if (m_thunk.Init(NULL, NULL) == FALSE)
+               {
+                       SetLastError(ERROR_OUTOFMEMORY);
+                       return NULL;
+               }
+
+               _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
+               if (MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD) != 0)
+                       MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
+               if (rect.m_lpRect == NULL)
+                       rect.m_lpRect = &TBase::rcDefault;
+               hWnd = ::CreateWindowEx(dwExStyle, reinterpret_cast<LPCWSTR>(MAKEINTATOM(atom)), szWindowName, dwStyle, rect.m_lpRect->left,
+                                       rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, rect.m_lpRect->bottom - rect.m_lpRect->top,
+                                       hWndParent, MenuOrID.m_hMenu, _AtlBaseModule.GetModuleInstance(), lpCreateParam);
+
+               ATLASSERT(m_hWnd == hWnd);
+
+               return hWnd;
+       }
+};
+
+template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
+class CWindowImpl : public CWindowImplBaseT<TBase, TWinTraits>
+{
+public:
+       static LPCTSTR GetWndCaption()
+       {
+               return NULL;
+       }
+
+       HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0,
+                                       DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
+       {
+               CWindowImplBaseT<TBase, TWinTraits>     *pThis;
+               ATOM                                                            atom;
+
+               ATLASSERT(m_hWnd == NULL);
+               pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits>*>(this);
+
+               if (T::GetWndClassInfo().m_lpszOrigName == NULL)
+                       T::GetWndClassInfo().m_lpszOrigName = pThis->GetWndClassName();
+               atom = T::GetWndClassInfo().Register(&pThis->m_pfnSuperWindowProc);
+
+               if (szWindowName == NULL)
+                       szWindowName = T::GetWndCaption();
+               dwStyle = T::GetWndStyle(dwStyle);
+               dwExStyle = T::GetWndExStyle(dwExStyle);
+
+               return CWindowImplBaseT<TBase, TWinTraits>::Create(hWndParent, rect, szWindowName, dwStyle,
+                                               dwExStyle, MenuOrID, atom, lpCreateParam);
+       }
+};
+
+template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
+class CContainedWindowT : public TBase
+{
+public:
+       CWndProcThunk                                                   m_thunk;
+       LPCTSTR                                                                 m_lpszClassName;
+       WNDPROC                                                                 m_pfnSuperWindowProc;
+       CMessageMap                                                             *m_pObject;
+       DWORD                                                                   m_dwMsgMapID;
+       const _ATL_MSG                                                  *m_pCurrentMsg;
+public:
+       CContainedWindowT(CMessageMap *pObject, DWORD dwMsgMapID = 0)
+       {
+               m_lpszClassName = TBase::GetWndClassName();
+               m_pfnSuperWindowProc = ::DefWindowProc;
+               m_pObject = pObject;
+               m_dwMsgMapID = dwMsgMapID;
+               m_pCurrentMsg = NULL;
+       }
+
+       CContainedWindowT(LPTSTR lpszClassName, CMessageMap *pObject, DWORD dwMsgMapID = 0)
+       {
+               m_lpszClassName = lpszClassName;
+               m_pfnSuperWindowProc = ::DefWindowProc;
+               m_pObject = pObject;
+               m_dwMsgMapID = dwMsgMapID;
+               m_pCurrentMsg = NULL;
+       }
+
+       LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               CWindowImplBaseT<TBase, TWinTraits>     *pThis;
+
+               pThis = reinterpret_cast<CWindowImplBaseT<TBase, TWinTraits> *>(this);
+               return ::CallWindowProc(m_pfnSuperWindowProc, pThis->m_hWnd, uMsg, wParam, lParam);
+       }
+
+       BOOL SubclassWindow(HWND hWnd)
+       {
+               CContainedWindowT<TBase>                        *pThis;
+               WNDPROC                                                         newWindowProc;
+               WNDPROC                                                         oldWindowProc;
+               BOOL                                                            result;
+
+               ATLASSERT(m_hWnd == NULL);
+               ATLASSERT(::IsWindow(hWnd));
+
+               pThis = reinterpret_cast<CContainedWindowT<TBase> *>(this);
+
+               result = m_thunk.Init(WindowProc, pThis);
+               if (result == FALSE)
+                       return FALSE;
+               newWindowProc = m_thunk.GetWNDPROC();
+               oldWindowProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
+               if (oldWindowProc == NULL)
+                       return FALSE;
+               m_pfnSuperWindowProc = oldWindowProc;
+               pThis->m_hWnd = hWnd;
+               return TRUE;
+       }
+
+       static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               CContainedWindowT<TBase>                        *pThis;
+               WNDPROC                                                         newWindowProc;
+               WNDPROC                                                         GCCU(pOldProc);
+
+               pThis = reinterpret_cast<CContainedWindowT<TBase> *>(_AtlWinModule.ExtractCreateWndData());
+               ATLASSERT(pThis != NULL);
+               if (pThis == NULL)
+                       return 0;
+               pThis->m_thunk.Init(WindowProc, pThis);
+               newWindowProc = pThis->m_thunk.GetWNDPROC();
+               pOldProc = reinterpret_cast<WNDPROC>(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(newWindowProc)));
+               Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass
+               pThis->m_hWnd = hWnd;
+               return newWindowProc(hWnd, uMsg, wParam, lParam);
+       }
+
+       static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+       {
+               CContainedWindowT<TBase>                        *pThis = reinterpret_cast<CContainedWindowT<TBase> *>(hWnd);
+               _ATL_MSG                                                        msg(pThis->m_hWnd, uMsg, wParam, lParam);
+               LRESULT                                                         lResult;
+               const _ATL_MSG                                          *previousMessage;
+               BOOL                                                            handled;
+               LONG_PTR                                                        saveWindowProc;
+
+               ATLASSERT(pThis != NULL && pThis->m_hWnd != NULL && pThis->m_pObject != NULL);
+               if (pThis == NULL || pThis->m_hWnd == NULL || pThis->m_pObject == NULL)
+                       return 0;
+
+               hWnd = pThis->m_hWnd;
+               previousMessage = pThis->m_pCurrentMsg;
+               pThis->m_pCurrentMsg = &msg;
+
+               handled = pThis->m_pObject->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, pThis->m_dwMsgMapID);
+               ATLASSERT(pThis->m_pCurrentMsg == &msg);
+
+               pThis->m_pCurrentMsg = previousMessage;
+               if (handled == FALSE)
+               {
+                       if (uMsg == WM_NCDESTROY)
+                       {
+                               saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
+                               lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
+                               if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC))
+                                       ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(pThis->m_pfnSuperWindowProc));
+                               pThis->m_hWnd = NULL;
+                       }
+                       else
+                               lResult = pThis->DefWindowProc(uMsg, wParam, lParam);
+               }
+               return lResult;
+       }
+
+};
+typedef CContainedWindowT<CWindow>     CContainedWindow;
+
+#define BEGIN_MSG_MAP(theClass)                                                                                                                                                                                                \
+public:                                                                                                                                                                                                                                                \
+       BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0)     \
+       {                                                                                                                                                                                                                                               \
+               BOOL GCCU(bHandled) = TRUE;                                                                                                                                                                                     \
+               Unused(hWnd);                                                                                                                                                                                                           \
+               Unused(uMsg);                                                                                                                                                                                                           \
+               Unused(wParam);                                                                                                                                                                                                         \
+               Unused(lParam);                                                                                                                                                                                                         \
+               Unused(lResult);                                                                                                                                                                                                        \
+               Unused(bHandled);                                                                                                                                                                                                       \
+               switch(dwMsgMapID)                                                                                                                                                                                                      \
+               {                                                                                                                                                                                                                                       \
+               case 0:
+
+#define END_MSG_MAP()                                                                                                                                                  \
+                       break;                                                                                                                                                          \
+               default:                                                                                                                                                                \
+                       ATLASSERT(FALSE);                                                                                                                                       \
+                       break;                                                                                                                                                          \
+               }                                                                                                                                                                               \
+               return FALSE;                                                                                                                                                   \
+       }
+
+#define MESSAGE_HANDLER(msg, func)                                                                                                                             \
+       if (uMsg == msg)                                                                                                                                                        \
+       {                                                                                                                                                                                       \
+               bHandled = TRUE;                                                                                                                                                \
+               lResult = func(uMsg, wParam, lParam, bHandled);                                                                                 \
+               if (bHandled)                                                                                                                                                   \
+                       return TRUE;                                                                                                                                            \
+       }
+
+#define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func)                                                                                 \
+       if (uMsg >= msgFirst && uMsg <= msgLast)                                                                                                        \
+       {                                                                                                                                                                                       \
+               bHandled = TRUE;                                                                                                                                                \
+               lResult = func(uMsg, wParam, lParam, bHandled);                                                                                 \
+               if (bHandled)                                                                                                                                                   \
+                       return TRUE;                                                                                                                                            \
+       }
+
+#define COMMAND_ID_HANDLER(id, func)                                                                                                                   \
+       if (uMsg == WM_COMMAND && id == LOWORD(wParam))                                                                                         \
+       {                                                                                                                                                                                       \
+               bHandled = TRUE;                                                                                                                                                \
+               lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled);                                 \
+               if (bHandled)                                                                                                                                                   \
+                       return TRUE;                                                                                                                                            \
+       }
+
+#define COMMAND_RANGE_HANDLER(idFirst, idLast, func)                                                                                   \
+       if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst  && LOWORD(wParam) <= idLast)                       \
+       {                                                                                                                                                                                       \
+               bHandled = TRUE;                                                                                                                                                \
+               lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled);                                 \
+               if (bHandled)                                                                                                                                                   \
+                       return TRUE;                                                                                                                                            \
+       }
+
+#define NOTIFY_CODE_HANDLER(cd, func)                                                                                                                  \
+       if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code)                                                                          \
+       {                                                                                                                                                                                       \
+               bHandled = TRUE;                                                                                                                                                \
+               lResult = func((int)wParam, (LPNMHDR)lParam, bHandled);                                                                 \
+               if (bHandled)                                                                                                                                                   \
+                       return TRUE;                                                                                                                                            \
+       }
+
+#define NOTIFY_HANDLER(id, cd, func)                                                                                                                   \
+       if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code)       \
+       {                                                                                                                                                                                       \
+               bHandled = TRUE;                                                                                                                                                \
+               lResult = func((int)wParam, (LPNMHDR)lParam, bHandled);                                                                 \
+               if (bHandled)                                                                                                                                                   \
+                       return TRUE;                                                                                                                                            \
+       }
+
+#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd)                                                                               \
+static ATL::CWndClassInfo& GetWndClassInfo()                                                                                                   \
+{                                                                                                                                                                                              \
+       static ATL::CWndClassInfo wc =                                                                                                                          \
+       {                                                                                                                                                                                       \
+               { sizeof(WNDCLASSEX), style, StartWindowProc,                                                                                   \
+                 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL },                              \
+               NULL, NULL, IDC_ARROW, TRUE, 0, _T("")                                                                                                  \
+       };                                                                                                                                                                                      \
+       return wc;                                                                                                                                                                      \
+}
+
+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 *)];
+
+       ATOM Register(WNDPROC *p)
+       {
+               if (m_atom == 0)
+                       m_atom = RegisterClassEx(&m_wc);
+               return m_atom;
+       }
+};
+
+}; // namespace ATL
+
+#endif // _atlwin_h