home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Internet 2000 May / MICD_2000_05.iso / CBuilder5 / INSTALL / DATA1.CAB / Program_Built_Files / Include / Atl / atlwin.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-01  |  82.7 KB  |  3,125 lines

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10.  
  11. #ifndef __ATLWIN_H__
  12. #define __ATLWIN_H__
  13.  
  14. #ifdef __BORLANDC__
  15. #ifdef _BCB_ATL_DEBUG
  16. #define _DEBUG
  17. #endif
  18. #endif
  19.  
  20. #ifndef __cplusplus
  21.     #error ATL requires C++ compilation (use a .cpp suffix)
  22. #endif
  23.  
  24. #ifndef __ATLBASE_H__
  25.     #error atlwin.h requires atlbase.h to be included first
  26. #endif
  27.  
  28. struct _ATL_WNDCLASSINFOA;
  29. struct _ATL_WNDCLASSINFOW;
  30.  
  31.  
  32. #ifndef _ATL_DLL_IMPL
  33. namespace ATL
  34. {
  35. #endif
  36.  
  37. ATLAPI_(ATOM) AtlModuleRegisterWndClassInfoA(_ATL_MODULE* pM, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc);
  38. ATLAPI_(ATOM) AtlModuleRegisterWndClassInfoW(_ATL_MODULE* pM, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc);
  39.  
  40. #ifdef UNICODE
  41. #define AtlModuleRegisterWndClassInfo AtlModuleRegisterWndClassInfoW
  42. #else
  43. #define AtlModuleRegisterWndClassInfo AtlModuleRegisterWndClassInfoA
  44. #endif
  45.  
  46.  
  47. #define HIMETRIC_PER_INCH   2540
  48. #define MAP_PIX_TO_LOGHIM(x,ppli)   ( (HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli) )
  49. #define MAP_LOGHIM_TO_PIX(x,ppli)   ( ((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH )
  50.  
  51. ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd);
  52. ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix);
  53. ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric);
  54.  
  55.  
  56. #ifndef _ATL_DLL_IMPL
  57. }; //namespace ATL
  58. #endif
  59.  
  60. struct _ATL_WNDCLASSINFOA
  61. {
  62.     WNDCLASSEXA m_wc;
  63.     LPCSTR m_lpszOrigName;
  64.     WNDPROC pWndProc;
  65.     LPCSTR m_lpszCursorID;
  66.     BOOL m_bSystemCursor;
  67.     ATOM m_atom;
  68.     CHAR m_szAutoName[13];
  69.     ATOM Register(WNDPROC* p)
  70.     {
  71.         return AtlModuleRegisterWndClassInfoA(&_Module, this, p);
  72.     }
  73. };
  74. struct _ATL_WNDCLASSINFOW
  75. {
  76.     WNDCLASSEXW m_wc;
  77.     LPCWSTR m_lpszOrigName;
  78.     WNDPROC pWndProc;
  79.     LPCWSTR m_lpszCursorID;
  80.     BOOL m_bSystemCursor;
  81.     ATOM m_atom;
  82.     WCHAR m_szAutoName[13];
  83.     ATOM Register(WNDPROC* p)
  84.     {
  85.         return AtlModuleRegisterWndClassInfoW(&_Module, this, p);
  86.     }
  87. };
  88.  
  89. namespace ATL
  90. {
  91.  
  92. /////////////////////////////////////////////////////////////////////////////
  93. // Forward declarations
  94.  
  95. class CWindow;
  96. #ifndef _ATL_NO_HOSTING
  97. #ifndef __BORLANDC__
  98. template <class TBase = CWindow> class CAxWindowT;
  99. #else
  100. template <class TBase> class CAxWindowT;
  101. // BCC32 doesn't like redeclaring default arguments.
  102. #endif
  103. #endif //!_ATL_NO_HOSTING
  104. class CMessageMap;
  105. class CDynamicChain;
  106. typedef _ATL_WNDCLASSINFOA CWndClassInfoA;
  107. typedef _ATL_WNDCLASSINFOW CWndClassInfoW;
  108.  
  109. #ifdef UNICODE
  110. #define CWndClassInfo CWndClassInfoW
  111. #else
  112. #define CWndClassInfo CWndClassInfoA
  113. #endif
  114.  
  115. #ifndef __BORLANDC__
  116. template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits> class CWindowImpl;
  117. template <class T, class TBase = CWindow> class CDialogImpl;
  118. #ifndef _ATL_NO_HOSTING
  119. template <class T, class TBase = CWindow> class CAxDialogImpl;
  120. #endif //!_ATL_NO_HOSTING
  121. template <WORD t_wDlgTemplateID, BOOL t_bCenter = TRUE> class CSimpleDialog;
  122. template <class TBase = CWindow, class TWinTraits = CControlWinTraits> class CContainedWindowT;
  123.  
  124. #else
  125. template <class T, class TBase, class TWinTraits> class CWindowImpl;
  126. template <class T, class TBase> class CDialogImpl;
  127. #ifndef _ATL_NO_HOSTING
  128. template <class T, class TBase> class CAxDialogImpl;
  129. #endif //!_ATL_NO_HOSTING
  130. template <WORD t_wDlgTemplateID, BOOL t_bCenter> class CSimpleDialog;
  131. template <class TBase, class TWinTraits> class CContainedWindowT;
  132.  
  133. // BCC32 doesn't like to redeclare default parameters.
  134. #endif
  135.  
  136.  
  137. /////////////////////////////////////////////////////////////////////////////
  138. // CWindow - client side for a Windows window
  139.  
  140. class CWindow
  141. {
  142. public:
  143.     static RECT rcDefault;
  144.     HWND m_hWnd;
  145.  
  146.     CWindow(HWND hWnd = NULL)
  147.     {
  148.         m_hWnd = hWnd;
  149.     }
  150.  
  151.     CWindow& operator=(HWND hWnd)
  152.     {
  153.         m_hWnd = hWnd;
  154.         return *this;
  155.     }
  156.  
  157.     static LPCTSTR GetWndClassName()
  158.     {
  159.         return NULL;
  160.     }
  161.  
  162.     void Attach(HWND hWndNew)
  163.     {
  164.         ATLASSERT(::IsWindow(hWndNew));
  165.         m_hWnd = hWndNew;
  166.     }
  167.  
  168.     HWND Detach()
  169.     {
  170.         HWND hWnd = m_hWnd;
  171.         m_hWnd = NULL;
  172.         return hWnd;
  173.     }
  174.  
  175.     HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
  176.             DWORD dwStyle = 0, DWORD dwExStyle = 0,
  177.             UINT nID = 0, LPVOID lpCreateParam = NULL)
  178.     {
  179.         m_hWnd = ::CreateWindowEx(dwExStyle, lpstrWndClass, szWindowName,
  180.             dwStyle, rcPos.left, rcPos.top, rcPos.right - rcPos.left,
  181.             rcPos.bottom - rcPos.top, hWndParent, (HMENU)nID,
  182.             _Module.GetModuleInstance(), lpCreateParam);
  183.         return m_hWnd;
  184.     }
  185.  
  186.     HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, LPRECT lpRect = NULL, LPCTSTR szWindowName = NULL,
  187.             DWORD dwStyle = 0, DWORD dwExStyle = 0,
  188.             HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
  189.     {
  190.         if(lpRect == NULL)
  191.             lpRect = &rcDefault;
  192.         m_hWnd = ::CreateWindowEx(dwExStyle, lpstrWndClass, szWindowName,
  193.             dwStyle, lpRect->left, lpRect->top, lpRect->right - lpRect->left,
  194.             lpRect->bottom - lpRect->top, hWndParent, hMenu,
  195.             _Module.GetModuleInstance(), lpCreateParam);
  196.         return m_hWnd;
  197.     }
  198.  
  199.     BOOL DestroyWindow()
  200.     {
  201.         ATLASSERT(::IsWindow(m_hWnd));
  202.  
  203.         if(!::DestroyWindow(m_hWnd))
  204.             return FALSE;
  205.  
  206.         m_hWnd = NULL;
  207.         return TRUE;
  208.     }
  209.  
  210. // Attributes
  211.  
  212.     operator HWND() const { return m_hWnd; }
  213.  
  214.     DWORD GetStyle() const
  215.     {
  216.         ATLASSERT(::IsWindow(m_hWnd));
  217.         return (DWORD)::GetWindowLong(m_hWnd, GWL_STYLE);
  218.     }
  219.  
  220.     DWORD GetExStyle() const
  221.     {
  222.         ATLASSERT(::IsWindow(m_hWnd));
  223.         return (DWORD)::GetWindowLong(m_hWnd, GWL_EXSTYLE);
  224.     }
  225.  
  226.     LONG GetWindowLong(int nIndex) const
  227.     {
  228.         ATLASSERT(::IsWindow(m_hWnd));
  229.         return ::GetWindowLong(m_hWnd, nIndex);
  230.     }
  231.  
  232.     LONG SetWindowLong(int nIndex, LONG dwNewLong)
  233.     {
  234.         ATLASSERT(::IsWindow(m_hWnd));
  235.         return ::SetWindowLong(m_hWnd, nIndex, dwNewLong);
  236.     }
  237.  
  238.     WORD GetWindowWord(int nIndex) const
  239.     {
  240.         ATLASSERT(::IsWindow(m_hWnd));
  241.         return ::GetWindowWord(m_hWnd, nIndex);
  242.     }
  243.  
  244.     WORD SetWindowWord(int nIndex, WORD wNewWord)
  245.     {
  246.         ATLASSERT(::IsWindow(m_hWnd));
  247.         return ::SetWindowWord(m_hWnd, nIndex, wNewWord);
  248.     }
  249.  
  250. // Message Functions
  251.  
  252.     LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
  253.     {
  254.         ATLASSERT(::IsWindow(m_hWnd));
  255.         return ::SendMessage(m_hWnd,message,wParam,lParam);
  256.     }
  257.  
  258.     BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
  259.     {
  260.         ATLASSERT(::IsWindow(m_hWnd));
  261.         return ::PostMessage(m_hWnd,message,wParam,lParam);
  262.     }
  263.  
  264.     BOOL SendNotifyMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
  265.     {
  266.         ATLASSERT(::IsWindow(m_hWnd));
  267.         return ::SendNotifyMessage(m_hWnd, message, wParam, lParam);
  268.     }
  269.  
  270.     // support for C style macros
  271.     static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  272.     {
  273.         ATLASSERT(::IsWindow(hWnd));
  274.         return ::SendMessage(hWnd, message, wParam, lParam);
  275.     }
  276.  
  277. // Window Text Functions
  278.  
  279.     BOOL SetWindowText(LPCTSTR lpszString)
  280.     {
  281.         ATLASSERT(::IsWindow(m_hWnd));
  282.         return ::SetWindowText(m_hWnd, lpszString);
  283.     }
  284.  
  285.     int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const
  286.     {
  287.         ATLASSERT(::IsWindow(m_hWnd));
  288.         return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount);
  289.     }
  290.  
  291.     int GetWindowTextLength() const
  292.     {
  293.         ATLASSERT(::IsWindow(m_hWnd));
  294.         return ::GetWindowTextLength(m_hWnd);
  295.     }
  296.  
  297. // Font Functions
  298.  
  299.     void SetFont(HFONT hFont, BOOL bRedraw = TRUE)
  300.     {
  301.         ATLASSERT(::IsWindow(m_hWnd));
  302.         ::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0));
  303.     }
  304.  
  305.     HFONT GetFont() const
  306.     {
  307.         ATLASSERT(::IsWindow(m_hWnd));
  308.         return (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0);
  309.     }
  310.  
  311. // Menu Functions (non-child windows only)
  312.  
  313.     HMENU GetMenu() const
  314.     {
  315.         ATLASSERT(::IsWindow(m_hWnd));
  316.         return ::GetMenu(m_hWnd);
  317.     }
  318.  
  319.     BOOL SetMenu(HMENU hMenu)
  320.     {
  321.         ATLASSERT(::IsWindow(m_hWnd));
  322.         return ::SetMenu(m_hWnd, hMenu);
  323.     }
  324.  
  325.     BOOL DrawMenuBar()
  326.     {
  327.         ATLASSERT(::IsWindow(m_hWnd));
  328.         return ::DrawMenuBar(m_hWnd);
  329.     }
  330.  
  331.     HMENU GetSystemMenu(BOOL bRevert) const
  332.     {
  333.         ATLASSERT(::IsWindow(m_hWnd));
  334.         return ::GetSystemMenu(m_hWnd, bRevert);
  335.     }
  336.  
  337.     BOOL HiliteMenuItem(HMENU hMenu, UINT uItemHilite, UINT uHilite)
  338.     {
  339.         ATLASSERT(::IsWindow(m_hWnd));
  340.         return ::HiliteMenuItem(m_hWnd, hMenu, uItemHilite, uHilite);
  341.     }
  342.  
  343. // Window Size and Position Functions
  344.  
  345.     BOOL IsIconic() const
  346.     {
  347.         ATLASSERT(::IsWindow(m_hWnd));
  348.         return ::IsIconic(m_hWnd);
  349.     }
  350.  
  351.     BOOL IsZoomed() const
  352.     {
  353.         ATLASSERT(::IsWindow(m_hWnd));
  354.         return ::IsZoomed(m_hWnd);
  355.     }
  356.  
  357.     BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE)
  358.     {
  359.         ATLASSERT(::IsWindow(m_hWnd));
  360.         return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint);
  361.     }
  362.  
  363.     BOOL MoveWindow(LPCRECT lpRect, BOOL bRepaint = TRUE)
  364.     {
  365.         ATLASSERT(::IsWindow(m_hWnd));
  366.         return ::MoveWindow(m_hWnd, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, bRepaint);
  367.     }
  368.  
  369.     BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags)
  370.     {
  371.         ATLASSERT(::IsWindow(m_hWnd));
  372.         return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags);
  373.     }
  374.  
  375.     BOOL SetWindowPos(HWND hWndInsertAfter, LPCRECT lpRect, UINT nFlags)
  376.     {
  377.         ATLASSERT(::IsWindow(m_hWnd));
  378.         return ::SetWindowPos(m_hWnd, hWndInsertAfter, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, nFlags);
  379.     }
  380.  
  381.     UINT ArrangeIconicWindows()
  382.     {
  383.         ATLASSERT(::IsWindow(m_hWnd));
  384.         return ::ArrangeIconicWindows(m_hWnd);
  385.     }
  386.  
  387.     BOOL BringWindowToTop()
  388.     {
  389.         ATLASSERT(::IsWindow(m_hWnd));
  390.         return ::BringWindowToTop(m_hWnd);
  391.     }
  392.  
  393.     BOOL GetWindowRect(LPRECT lpRect) const
  394.     {
  395.         ATLASSERT(::IsWindow(m_hWnd));
  396.         return ::GetWindowRect(m_hWnd, lpRect);
  397.     }
  398.  
  399.     BOOL GetClientRect(LPRECT lpRect) const
  400.     {
  401.         ATLASSERT(::IsWindow(m_hWnd));
  402.         return ::GetClientRect(m_hWnd, lpRect);
  403.     }
  404.  
  405.     BOOL GetWindowPlacement(WINDOWPLACEMENT FAR* lpwndpl) const
  406.     {
  407.         ATLASSERT(::IsWindow(m_hWnd));
  408.         return ::GetWindowPlacement(m_hWnd, lpwndpl);
  409.     }
  410.  
  411.     BOOL SetWindowPlacement(const WINDOWPLACEMENT FAR* lpwndpl)
  412.     {
  413.         ATLASSERT(::IsWindow(m_hWnd));
  414.         return ::SetWindowPlacement(m_hWnd, lpwndpl);
  415.     }
  416.  
  417. // Coordinate Mapping Functions
  418.  
  419.     BOOL ClientToScreen(LPPOINT lpPoint) const
  420.     {
  421.         ATLASSERT(::IsWindow(m_hWnd));
  422.         return ::ClientToScreen(m_hWnd, lpPoint);
  423.     }
  424.  
  425.     BOOL ClientToScreen(LPRECT lpRect) const
  426.     {
  427.         ATLASSERT(::IsWindow(m_hWnd));
  428.         if(!::ClientToScreen(m_hWnd, (LPPOINT)lpRect))
  429.             return FALSE;
  430.         return ::ClientToScreen(m_hWnd, ((LPPOINT)lpRect)+1);
  431.     }
  432.  
  433.     BOOL ScreenToClient(LPPOINT lpPoint) const
  434.     {
  435.         ATLASSERT(::IsWindow(m_hWnd));
  436.         return ::ScreenToClient(m_hWnd, lpPoint);
  437.     }
  438.  
  439.     BOOL ScreenToClient(LPRECT lpRect) const
  440.     {
  441.         ATLASSERT(::IsWindow(m_hWnd));
  442.         if(!::ScreenToClient(m_hWnd, (LPPOINT)lpRect))
  443.             return FALSE;
  444.         return ::ScreenToClient(m_hWnd, ((LPPOINT)lpRect)+1);
  445.     }
  446.  
  447.     int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const
  448.     {
  449.         ATLASSERT(::IsWindow(m_hWnd));
  450.         return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount);
  451.     }
  452.  
  453.     int MapWindowPoints(HWND hWndTo, LPRECT lpRect) const
  454.     {
  455.         ATLASSERT(::IsWindow(m_hWnd));
  456.         return ::MapWindowPoints(m_hWnd, hWndTo, (LPPOINT)lpRect, 2);
  457.     }
  458.  
  459. // Update and Painting Functions
  460.  
  461.     HDC BeginPaint(LPPAINTSTRUCT lpPaint)
  462.     {
  463.         ATLASSERT(::IsWindow(m_hWnd));
  464.         return ::BeginPaint(m_hWnd, lpPaint);
  465.     }
  466.  
  467.     void EndPaint(LPPAINTSTRUCT lpPaint)
  468.     {
  469.         ATLASSERT(::IsWindow(m_hWnd));
  470.         ::EndPaint(m_hWnd, lpPaint);
  471.     }
  472.  
  473.     HDC GetDC()
  474.     {
  475.         ATLASSERT(::IsWindow(m_hWnd));
  476.         return ::GetDC(m_hWnd);
  477.     }
  478.  
  479.     HDC GetWindowDC()
  480.     {
  481.         ATLASSERT(::IsWindow(m_hWnd));
  482.         return ::GetWindowDC(m_hWnd);
  483.     }
  484.  
  485.     int ReleaseDC(HDC hDC)
  486.     {
  487.         ATLASSERT(::IsWindow(m_hWnd));
  488.         return ::ReleaseDC(m_hWnd, hDC);
  489.     }
  490.  
  491.     void Print(HDC hDC, DWORD dwFlags) const
  492.     {
  493.         ATLASSERT(::IsWindow(m_hWnd));
  494.         ::SendMessage(m_hWnd, WM_PRINT, (WPARAM)hDC, dwFlags);
  495.     }
  496.  
  497.     void PrintClient(HDC hDC, DWORD dwFlags) const
  498.     {
  499.         ATLASSERT(::IsWindow(m_hWnd));
  500.         ::SendMessage(m_hWnd, WM_PRINTCLIENT, (WPARAM)hDC, dwFlags);
  501.     }
  502.  
  503.     BOOL UpdateWindow()
  504.     {
  505.         ATLASSERT(::IsWindow(m_hWnd));
  506.         return ::UpdateWindow(m_hWnd);
  507.     }
  508.  
  509.     void SetRedraw(BOOL bRedraw = TRUE)
  510.     {
  511.         ATLASSERT(::IsWindow(m_hWnd));
  512.         ::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0);
  513.     }
  514.  
  515.     BOOL GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE)
  516.     {
  517.         ATLASSERT(::IsWindow(m_hWnd));
  518.         return ::GetUpdateRect(m_hWnd, lpRect, bErase);
  519.     }
  520.  
  521.     int GetUpdateRgn(HRGN hRgn, BOOL bErase = FALSE)
  522.     {
  523.         ATLASSERT(::IsWindow(m_hWnd));
  524.         return ::GetUpdateRgn(m_hWnd, hRgn, bErase);
  525.     }
  526.  
  527.     BOOL Invalidate(BOOL bErase = TRUE)
  528.     {
  529.         ATLASSERT(::IsWindow(m_hWnd));
  530.         return ::InvalidateRect(m_hWnd, NULL, bErase);
  531.     }
  532.  
  533.     BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE)
  534.     {
  535.         ATLASSERT(::IsWindow(m_hWnd));
  536.         return ::InvalidateRect(m_hWnd, lpRect, bErase);
  537.     }
  538.  
  539.     BOOL ValidateRect(LPCRECT lpRect)
  540.     {
  541.         ATLASSERT(::IsWindow(m_hWnd));
  542.         return ::ValidateRect(m_hWnd, lpRect);
  543.     }
  544.  
  545.     void InvalidateRgn(HRGN hRgn, BOOL bErase = TRUE)
  546.     {
  547.         ATLASSERT(::IsWindow(m_hWnd));
  548.         ::InvalidateRgn(m_hWnd, hRgn, bErase);
  549.     }
  550.  
  551.     BOOL ValidateRgn(HRGN hRgn)
  552.     {
  553.         ATLASSERT(::IsWindow(m_hWnd));
  554.         return ::ValidateRgn(m_hWnd, hRgn);
  555.     }
  556.  
  557.     BOOL ShowWindow(int nCmdShow)
  558.     {
  559.         ATLASSERT(::IsWindow(m_hWnd));
  560.         return ::ShowWindow(m_hWnd, nCmdShow);
  561.     }
  562.  
  563.     BOOL IsWindowVisible() const
  564.     {
  565.         ATLASSERT(::IsWindow(m_hWnd));
  566.         return ::IsWindowVisible(m_hWnd);
  567.     }
  568.  
  569.     BOOL ShowOwnedPopups(BOOL bShow = TRUE)
  570.     {
  571.         ATLASSERT(::IsWindow(m_hWnd));
  572.         return ::ShowOwnedPopups(m_hWnd, bShow);
  573.     }
  574.  
  575.     HDC GetDCEx(HRGN hRgnClip, DWORD flags)
  576.     {
  577.         ATLASSERT(::IsWindow(m_hWnd));
  578.         return ::GetDCEx(m_hWnd, hRgnClip, flags);
  579.     }
  580.  
  581.     BOOL LockWindowUpdate(BOOL bLock = TRUE)
  582.     {
  583.         ATLASSERT(::IsWindow(m_hWnd));
  584.         return ::LockWindowUpdate(bLock ? m_hWnd : NULL);
  585.     }
  586.  
  587.     BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, HRGN hRgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE)
  588.     {
  589.         ATLASSERT(::IsWindow(m_hWnd));
  590.         return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgnUpdate, flags);
  591.     }
  592.  
  593. // Timer Functions
  594.  
  595.     UINT SetTimer(UINT nIDEvent, UINT nElapse)
  596.     {
  597.         ATLASSERT(::IsWindow(m_hWnd));
  598.         return ::SetTimer(m_hWnd, nIDEvent, nElapse, NULL);
  599.     }
  600.  
  601.     BOOL KillTimer(UINT nIDEvent)
  602.     {
  603.         ATLASSERT(::IsWindow(m_hWnd));
  604.         return ::KillTimer(m_hWnd, nIDEvent);
  605.     }
  606.  
  607. // Window State Functions
  608.  
  609.     BOOL IsWindowEnabled() const
  610.     {
  611.         ATLASSERT(::IsWindow(m_hWnd));
  612.         return ::IsWindowEnabled(m_hWnd);
  613.     }
  614.  
  615.     BOOL EnableWindow(BOOL bEnable = TRUE)
  616.     {
  617.         ATLASSERT(::IsWindow(m_hWnd));
  618.         return ::EnableWindow(m_hWnd, bEnable);
  619.     }
  620.  
  621.     HWND SetActiveWindow()
  622.     {
  623.         ATLASSERT(::IsWindow(m_hWnd));
  624.         return ::SetActiveWindow(m_hWnd);
  625.     }
  626.  
  627.     HWND SetCapture()
  628.     {
  629.         ATLASSERT(::IsWindow(m_hWnd));
  630.         return ::SetCapture(m_hWnd);
  631.     }
  632.  
  633.     HWND SetFocus()
  634.     {
  635.         ATLASSERT(::IsWindow(m_hWnd));
  636.         return ::SetFocus(m_hWnd);
  637.     }
  638.  
  639. // Dialog-Box Item Functions
  640.  
  641.     BOOL CheckDlgButton(int nIDButton, UINT nCheck)
  642.     {
  643.         ATLASSERT(::IsWindow(m_hWnd));
  644.         return ::CheckDlgButton(m_hWnd, nIDButton, nCheck);
  645.     }
  646.  
  647.     BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton)
  648.     {
  649.         ATLASSERT(::IsWindow(m_hWnd));
  650.         return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton);
  651.     }
  652.  
  653.     int DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT nFileType)
  654.     {
  655.         ATLASSERT(::IsWindow(m_hWnd));
  656.         return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, nFileType);
  657.     }
  658.  
  659.     int DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT nFileType)
  660.     {
  661.         ATLASSERT(::IsWindow(m_hWnd));
  662.         return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, nFileType);
  663.     }
  664.  
  665.     BOOL DlgDirSelect(LPTSTR lpString, int nCount, int nIDListBox)
  666.     {
  667.         ATLASSERT(::IsWindow(m_hWnd));
  668.         return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox);
  669.     }
  670.  
  671.     BOOL DlgDirSelectComboBox(LPTSTR lpString, int nCount, int nIDComboBox)
  672.     {
  673.         ATLASSERT(::IsWindow(m_hWnd));
  674.         return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox);
  675.     }
  676.  
  677.     UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE) const
  678.     {
  679.         ATLASSERT(::IsWindow(m_hWnd));
  680.         return ::GetDlgItemInt(m_hWnd, nID, lpTrans, bSigned);
  681.     }
  682.  
  683.     UINT GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const
  684.     {
  685.         ATLASSERT(::IsWindow(m_hWnd));
  686.         return ::GetDlgItemText(m_hWnd, nID, lpStr, nMaxCount);
  687.     }
  688.     BOOL GetDlgItemText(int nID, BSTR& bstrText) const
  689.     {
  690.         ATLASSERT(::IsWindow(m_hWnd));
  691.  
  692.         HWND hWndCtl = GetDlgItem(nID);
  693.         if(hWndCtl == NULL)
  694.             return FALSE;
  695.  
  696.         return CWindow(hWndCtl).GetWindowText(bstrText);
  697.     }
  698.     HWND GetNextDlgGroupItem(HWND hWndCtl, BOOL bPrevious = FALSE) const
  699.     {
  700.         ATLASSERT(::IsWindow(m_hWnd));
  701.         return ::GetNextDlgGroupItem(m_hWnd, hWndCtl, bPrevious);
  702.     }
  703.  
  704.     HWND GetNextDlgTabItem(HWND hWndCtl, BOOL bPrevious = FALSE) const
  705.     {
  706.         ATLASSERT(::IsWindow(m_hWnd));
  707.         return ::GetNextDlgTabItem(m_hWnd, hWndCtl, bPrevious);
  708.     }
  709.  
  710.     UINT IsDlgButtonChecked(int nIDButton) const
  711.     {
  712.         ATLASSERT(::IsWindow(m_hWnd));
  713.         return ::IsDlgButtonChecked(m_hWnd, nIDButton);
  714.     }
  715.  
  716.     LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
  717.     {
  718.         ATLASSERT(::IsWindow(m_hWnd));
  719.         return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam);
  720.     }
  721.  
  722.     BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE)
  723.     {
  724.         ATLASSERT(::IsWindow(m_hWnd));
  725.         return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned);
  726.     }
  727.  
  728.     BOOL SetDlgItemText(int nID, LPCTSTR lpszString)
  729.     {
  730.         ATLASSERT(::IsWindow(m_hWnd));
  731.         return ::SetDlgItemText(m_hWnd, nID, lpszString);
  732.     }
  733.  
  734. #ifndef _ATL_NO_HOSTING
  735.     HRESULT GetDlgControl(int nID, REFIID iid, void** ppUnk)
  736.     {
  737.         ATLASSERT(::IsWindow(m_hWnd));
  738.         ATLASSERT(ppUnk != NULL);
  739.         HRESULT hr = E_FAIL;
  740.         HWND hWndCtrl = GetDlgItem(nID);
  741.         if (hWndCtrl != NULL)
  742.         {
  743.             *ppUnk = NULL;
  744.             CComPtr<IUnknown> spUnk;
  745.             hr = AtlAxGetControl(hWndCtrl, &spUnk);
  746.             if (SUCCEEDED(hr))
  747.                 hr = spUnk->QueryInterface(iid, ppUnk);
  748.         }
  749.         return hr;
  750.     }
  751. #endif //!_ATL_NO_HOSTING
  752.  
  753. // Scrolling Functions
  754.  
  755.     int GetScrollPos(int nBar) const
  756.     {
  757.         ATLASSERT(::IsWindow(m_hWnd));
  758.         return ::GetScrollPos(m_hWnd, nBar);
  759.     }
  760.  
  761.     BOOL GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const
  762.     {
  763.         ATLASSERT(::IsWindow(m_hWnd));
  764.         return ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos);
  765.     }
  766.  
  767.     BOOL ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL)
  768.     {
  769.         ATLASSERT(::IsWindow(m_hWnd));
  770.         return ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect);
  771.     }
  772.  
  773.     int ScrollWindowEx(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate, UINT uFlags)
  774.     {
  775.         ATLASSERT(::IsWindow(m_hWnd));
  776.         return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, uFlags);
  777.     }
  778.  
  779.     int ScrollWindowEx(int dx, int dy, UINT uFlags, LPCRECT lpRectScroll = NULL, LPCRECT lpRectClip = NULL, HRGN hRgnUpdate = NULL, LPRECT lpRectUpdate = NULL)
  780.     {
  781.         ATLASSERT(::IsWindow(m_hWnd));
  782.         return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, uFlags);
  783.     }
  784.  
  785.     int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE)
  786.     {
  787.         ATLASSERT(::IsWindow(m_hWnd));
  788.         return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw);
  789.     }
  790.  
  791.     BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE)
  792.     {
  793.         ATLASSERT(::IsWindow(m_hWnd));
  794.         return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
  795.     }
  796.  
  797.     BOOL ShowScrollBar(UINT nBar, BOOL bShow = TRUE)
  798.     {
  799.         ATLASSERT(::IsWindow(m_hWnd));
  800.         return ::ShowScrollBar(m_hWnd, nBar, bShow);
  801.     }
  802.  
  803.     BOOL EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH)
  804.     {
  805.         ATLASSERT(::IsWindow(m_hWnd));
  806.         return ::EnableScrollBar(m_hWnd, uSBFlags, uArrowFlags);
  807.     }
  808.  
  809. // Window Access Functions
  810.  
  811.     HWND ChildWindowFromPoint(POINT point) const
  812.     {
  813.         ATLASSERT(::IsWindow(m_hWnd));
  814.         return ::ChildWindowFromPoint(m_hWnd, point);
  815.     }
  816.  
  817.     HWND ChildWindowFromPointEx(POINT point, UINT uFlags) const
  818.     {
  819.         ATLASSERT(::IsWindow(m_hWnd));
  820.         return ::ChildWindowFromPointEx(m_hWnd, point, uFlags);
  821.     }
  822.  
  823.     HWND GetTopWindow() const
  824.     {
  825.         ATLASSERT(::IsWindow(m_hWnd));
  826.         return ::GetTopWindow(m_hWnd);
  827.     }
  828.  
  829.     HWND GetWindow(UINT nCmd) const
  830.     {
  831.         ATLASSERT(::IsWindow(m_hWnd));
  832.         return ::GetWindow(m_hWnd, nCmd);
  833.     }
  834.  
  835.     HWND GetLastActivePopup() const
  836.     {
  837.         ATLASSERT(::IsWindow(m_hWnd));
  838.         return ::GetLastActivePopup(m_hWnd);
  839.     }
  840.  
  841.     BOOL IsChild(HWND hWnd) const
  842.     {
  843.         ATLASSERT(::IsWindow(m_hWnd));
  844.         return ::IsChild(m_hWnd, hWnd);
  845.     }
  846.  
  847.     HWND GetParent() const
  848.     {
  849.         ATLASSERT(::IsWindow(m_hWnd));
  850.         return ::GetParent(m_hWnd);
  851.     }
  852.  
  853.     HWND SetParent(HWND hWndNewParent)
  854.     {
  855.         ATLASSERT(::IsWindow(m_hWnd));
  856.         return ::SetParent(m_hWnd, hWndNewParent);
  857.     }
  858.  
  859. // Window Tree Access
  860.  
  861.     int GetDlgCtrlID() const
  862.     {
  863.         ATLASSERT(::IsWindow(m_hWnd));
  864.         return ::GetDlgCtrlID(m_hWnd);
  865.     }
  866.  
  867.     int SetDlgCtrlID(int nID)
  868.     {
  869.         ATLASSERT(::IsWindow(m_hWnd));
  870.         return (int)::SetWindowLong(m_hWnd, GWL_ID, nID);
  871.     }
  872.  
  873.     HWND GetDlgItem(int nID) const
  874.     {
  875.         ATLASSERT(::IsWindow(m_hWnd));
  876.         return ::GetDlgItem(m_hWnd, nID);
  877.     }
  878.  
  879. // Alert Functions
  880.  
  881.     BOOL FlashWindow(BOOL bInvert)
  882.     {
  883.         ATLASSERT(::IsWindow(m_hWnd));
  884.         return ::FlashWindow(m_hWnd, bInvert);
  885.     }
  886.  
  887.     int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption = _T(""), UINT nType = MB_OK)
  888.     {
  889.         ATLASSERT(::IsWindow(m_hWnd));
  890.         return ::MessageBox(m_hWnd, lpszText, lpszCaption, nType);
  891.     }
  892.  
  893. // Clipboard Functions
  894.  
  895.     BOOL ChangeClipboardChain(HWND hWndNewNext)
  896.     {
  897.         ATLASSERT(::IsWindow(m_hWnd));
  898.         return ::ChangeClipboardChain(m_hWnd, hWndNewNext);
  899.     }
  900.  
  901.     HWND SetClipboardViewer()
  902.     {
  903.         ATLASSERT(::IsWindow(m_hWnd));
  904.         return ::SetClipboardViewer(m_hWnd);
  905.     }
  906.  
  907.     BOOL OpenClipboard()
  908.     {
  909.         ATLASSERT(::IsWindow(m_hWnd));
  910.         return ::OpenClipboard(m_hWnd);
  911.     }
  912.  
  913. // Caret Functions
  914.  
  915.     BOOL CreateCaret(HBITMAP hBitmap)
  916.     {
  917.         ATLASSERT(::IsWindow(m_hWnd));
  918.         return ::CreateCaret(m_hWnd, hBitmap, 0, 0);
  919.     }
  920.  
  921.     BOOL CreateSolidCaret(int nWidth, int nHeight)
  922.     {
  923.         ATLASSERT(::IsWindow(m_hWnd));
  924.         return ::CreateCaret(m_hWnd, (HBITMAP)0, nWidth, nHeight);
  925.     }
  926.  
  927.     BOOL CreateGrayCaret(int nWidth, int nHeight)
  928.     {
  929.         ATLASSERT(::IsWindow(m_hWnd));
  930.         return ::CreateCaret(m_hWnd, (HBITMAP)1, nWidth, nHeight);
  931.     }
  932.  
  933.     BOOL HideCaret()
  934.     {
  935.         ATLASSERT(::IsWindow(m_hWnd));
  936.         return ::HideCaret(m_hWnd);
  937.     }
  938.  
  939.     BOOL ShowCaret()
  940.     {
  941.         ATLASSERT(::IsWindow(m_hWnd));
  942.         return ::ShowCaret(m_hWnd);
  943.     }
  944.  
  945. #ifdef _INC_SHELLAPI
  946. // Drag-Drop Functions
  947.     void DragAcceptFiles(BOOL bAccept = TRUE)
  948.     {
  949.         ATLASSERT(::IsWindow(m_hWnd)); ::DragAcceptFiles(m_hWnd, bAccept);
  950.     }
  951. #endif
  952.  
  953. // Icon Functions
  954.  
  955.     HICON SetIcon(HICON hIcon, BOOL bBigIcon = TRUE)
  956.     {
  957.         ATLASSERT(::IsWindow(m_hWnd));
  958.         return (HICON)::SendMessage(m_hWnd, WM_SETICON, bBigIcon, (LPARAM)hIcon);
  959.     }
  960.  
  961.     HICON GetIcon(BOOL bBigIcon = TRUE) const
  962.     {
  963.         ATLASSERT(::IsWindow(m_hWnd));
  964.         return (HICON)::SendMessage(m_hWnd, WM_GETICON, bBigIcon, 0);
  965.     }
  966.  
  967. // Help Functions
  968.  
  969.     BOOL WinHelp(LPCTSTR lpszHelp, UINT nCmd = HELP_CONTEXT, DWORD dwData = 0)
  970.     {
  971.         ATLASSERT(::IsWindow(m_hWnd));
  972.         return ::WinHelp(m_hWnd, lpszHelp, nCmd, dwData);
  973.     }
  974.  
  975.     BOOL SetWindowContextHelpId(DWORD dwContextHelpId)
  976.     {
  977.         ATLASSERT(::IsWindow(m_hWnd));
  978.         return ::SetWindowContextHelpId(m_hWnd, dwContextHelpId);
  979.     }
  980.  
  981.     DWORD GetWindowContextHelpId() const
  982.     {
  983.         ATLASSERT(::IsWindow(m_hWnd));
  984.         return ::GetWindowContextHelpId(m_hWnd);
  985.     }
  986.  
  987. // Hot Key Functions
  988.  
  989.     int SetHotKey(WORD wVirtualKeyCode, WORD wModifiers)
  990.     {
  991.         ATLASSERT(::IsWindow(m_hWnd));
  992.         return (int)::SendMessage(m_hWnd, WM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0);
  993.     }
  994.  
  995.     DWORD GetHotKey() const
  996.     {
  997.         ATLASSERT(::IsWindow(m_hWnd));
  998.         return ::SendMessage(m_hWnd, WM_GETHOTKEY, 0, 0);
  999.     }
  1000.  
  1001. // Misc. Operations
  1002.  
  1003. //N new
  1004.     BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo)
  1005.     {
  1006.         ATLASSERT(::IsWindow(m_hWnd));
  1007.         return ::GetScrollInfo(m_hWnd, nBar, lpScrollInfo);
  1008.     }
  1009.     BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
  1010.     {
  1011.         ATLASSERT(::IsWindow(m_hWnd));
  1012.         return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw);
  1013.     }
  1014.     BOOL IsDialogMessage(LPMSG lpMsg)
  1015.     {
  1016.         ATLASSERT(::IsWindow(m_hWnd));
  1017.         return ::IsDialogMessage(m_hWnd, lpMsg);
  1018.     }
  1019.  
  1020.     void NextDlgCtrl() const
  1021.         {
  1022.         ATLASSERT(::IsWindow(m_hWnd));
  1023.         ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0L);
  1024.     }
  1025.     void PrevDlgCtrl() const
  1026.         {
  1027.         ATLASSERT(::IsWindow(m_hWnd));
  1028.         ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 1, 0L);
  1029.     }
  1030.     void GotoDlgCtrl(HWND hWndCtrl) const
  1031.         {
  1032.         ATLASSERT(::IsWindow(m_hWnd));
  1033.         ::SendMessage(m_hWnd, WM_NEXTDLGCTL, (WPARAM)hWndCtrl, 1L);
  1034.     }
  1035.  
  1036.     BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw = TRUE)
  1037.     {
  1038.         ATLASSERT(::IsWindow(m_hWnd));
  1039.  
  1040.         RECT rcWnd;
  1041.         if(!GetClientRect(&rcWnd))
  1042.             return FALSE;
  1043.  
  1044.         if(nWidth != -1)
  1045.             rcWnd.right = nWidth;
  1046.         if(nHeight != -1)
  1047.             rcWnd.bottom = nHeight;
  1048.  
  1049.         if(!::AdjustWindowRectEx(&rcWnd, GetStyle(), (!(GetStyle() & WS_CHILD) && (GetMenu() != NULL)), GetExStyle()))
  1050.             return FALSE;
  1051.  
  1052.         UINT uFlags = SWP_NOZORDER | SWP_NOMOVE;
  1053.         if(!bRedraw)
  1054.             uFlags |= SWP_NOREDRAW;
  1055.  
  1056.         return SetWindowPos(NULL, 0, 0, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, uFlags);
  1057.     }
  1058.  
  1059.     int GetWindowRgn(HRGN hRgn)
  1060.     {
  1061.         ATLASSERT(::IsWindow(m_hWnd));
  1062.         return ::GetWindowRgn(m_hWnd, hRgn);
  1063.     }
  1064.     int SetWindowRgn(HRGN hRgn, BOOL bRedraw = FALSE)
  1065.     {
  1066.         ATLASSERT(::IsWindow(m_hWnd));
  1067.         return ::SetWindowRgn(m_hWnd, hRgn, bRedraw);
  1068.     }
  1069.     HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags)
  1070.     {
  1071.         ATLASSERT(::IsWindow(m_hWnd));
  1072.         return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
  1073.     }
  1074.     DWORD GetWindowThreadID()
  1075.     {
  1076.         ATLASSERT(::IsWindow(m_hWnd));
  1077.         return ::GetWindowThreadProcessId(m_hWnd, NULL);
  1078.     }
  1079.     DWORD GetWindowProcessID()
  1080.     {
  1081.         ATLASSERT(::IsWindow(m_hWnd));
  1082.         DWORD dwProcessID;
  1083.         ::GetWindowThreadProcessId(m_hWnd, &dwProcessID);
  1084.         return dwProcessID;
  1085.     }
  1086.     BOOL IsWindow()
  1087.     {
  1088.         return ::IsWindow(m_hWnd);
  1089.     }
  1090.     BOOL IsWindowUnicode()
  1091.     {
  1092.         ATLASSERT(::IsWindow(m_hWnd));
  1093.         return ::IsWindowUnicode(m_hWnd);
  1094.     }
  1095.     BOOL IsParentDialog()
  1096.     {
  1097.         ATLASSERT(::IsWindow(m_hWnd));
  1098.         TCHAR szBuf[8]; // "#32770" + NUL character
  1099.         GetClassName(GetParent(), szBuf, sizeof(szBuf)/sizeof(TCHAR));
  1100.         return lstrcmp(szBuf, _T("#32770")) == 0;
  1101.     }
  1102.     BOOL ShowWindowAsync(int nCmdShow)
  1103.     {
  1104.         ATLASSERT(::IsWindow(m_hWnd));
  1105.         return ::ShowWindowAsync(m_hWnd, nCmdShow);
  1106.     }
  1107.  
  1108.     HWND GetDescendantWindow(int nID) const
  1109.     {
  1110.         ATLASSERT(::IsWindow(m_hWnd));
  1111.  
  1112.         // GetDlgItem recursive (return first found)
  1113.         // breadth-first for 1 level, then depth-first for next level
  1114.  
  1115.         // use GetDlgItem since it is a fast USER function
  1116.         HWND hWndChild, hWndTmp;
  1117.         CWindow wnd;
  1118.         if((hWndChild = ::GetDlgItem(m_hWnd, nID)) != NULL)
  1119.         {
  1120.             if(::GetTopWindow(hWndChild) != NULL)
  1121.             {
  1122.                 // children with the same ID as their parent have priority
  1123.                 wnd.Attach(hWndChild);
  1124.                 hWndTmp = wnd.GetDescendantWindow(nID);
  1125.                 if(hWndTmp != NULL)
  1126.                     return hWndTmp;
  1127.             }
  1128.             return hWndChild;
  1129.         }
  1130.  
  1131.         // walk each child
  1132.         for(hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  1133.             hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  1134.         {
  1135.             wnd.Attach(hWndChild);
  1136.             hWndTmp = wnd.GetDescendantWindow(nID);
  1137.             if(hWndTmp != NULL)
  1138.                 return hWndTmp;
  1139.         }
  1140.  
  1141.         return NULL;    // not found
  1142.     }
  1143.  
  1144.     void SendMessageToDescendants(UINT message, WPARAM wParam = 0, LPARAM lParam = 0, BOOL bDeep = TRUE)
  1145.     {
  1146.         CWindow wnd;
  1147.         for(HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  1148.             hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  1149.         {
  1150.             ::SendMessage(hWndChild, message, wParam, lParam);
  1151.  
  1152.             if(bDeep && ::GetTopWindow(hWndChild) != NULL)
  1153.             {
  1154.                 // send to child windows after parent
  1155.                 wnd.Attach(hWndChild);
  1156.                 wnd.SendMessageToDescendants(message, wParam, lParam, bDeep);
  1157.             }
  1158.         }
  1159.     }
  1160.  
  1161.     BOOL CenterWindow(HWND hWndCenter = NULL)
  1162.     {
  1163.         ATLASSERT(::IsWindow(m_hWnd));
  1164.  
  1165.         // determine owner window to center against
  1166.         DWORD dwStyle = GetStyle();
  1167.         if(hWndCenter == NULL)
  1168.         {
  1169.             if(dwStyle & WS_CHILD)
  1170.                 hWndCenter = ::GetParent(m_hWnd);
  1171.             else
  1172.                 hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
  1173.         }
  1174.  
  1175.         // get coordinates of the window relative to its parent
  1176.         RECT rcDlg;
  1177.         ::GetWindowRect(m_hWnd, &rcDlg);
  1178.         RECT rcArea;
  1179.         RECT rcCenter;
  1180.         HWND hWndParent;
  1181.         if(!(dwStyle & WS_CHILD))
  1182.         {
  1183.             // don't center against invisible or minimized windows
  1184.             if(hWndCenter != NULL)
  1185.             {
  1186.                 DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE);
  1187.                 if(!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE))
  1188.                     hWndCenter = NULL;
  1189.             }
  1190.  
  1191.             // center within screen coordinates
  1192.             ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);
  1193.             if(hWndCenter == NULL)
  1194.                 rcCenter = rcArea;
  1195.             else
  1196.                 ::GetWindowRect(hWndCenter, &rcCenter);
  1197.         }
  1198.         else
  1199.         {
  1200.             // center within parent client coordinates
  1201.             hWndParent = ::GetParent(m_hWnd);
  1202.             ATLASSERT(::IsWindow(hWndParent));
  1203.  
  1204.             ::GetClientRect(hWndParent, &rcArea);
  1205.             ATLASSERT(::IsWindow(hWndCenter));
  1206.             ::GetClientRect(hWndCenter, &rcCenter);
  1207.             ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
  1208.         }
  1209.  
  1210.         int DlgWidth = rcDlg.right - rcDlg.left;
  1211.         int DlgHeight = rcDlg.bottom - rcDlg.top;
  1212.  
  1213.         // find dialog's upper left based on rcCenter
  1214.         int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2;
  1215.         int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;
  1216.  
  1217.         // if the dialog is outside the screen, move it inside
  1218.         if(xLeft < rcArea.left)
  1219.             xLeft = rcArea.left;
  1220.         else if(xLeft + DlgWidth > rcArea.right)
  1221.             xLeft = rcArea.right - DlgWidth;
  1222.  
  1223.         if(yTop < rcArea.top)
  1224.             yTop = rcArea.top;
  1225.         else if(yTop + DlgHeight > rcArea.bottom)
  1226.             yTop = rcArea.bottom - DlgHeight;
  1227.  
  1228.         // map screen coordinates to child coordinates
  1229.         return ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1,
  1230.             SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  1231.     }
  1232.  
  1233.     BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0)
  1234.     {
  1235.         ATLASSERT(::IsWindow(m_hWnd));
  1236.  
  1237.         DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
  1238.         DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  1239.         if(dwStyle == dwNewStyle)
  1240.             return FALSE;
  1241.  
  1242.         ::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle);
  1243.         if(nFlags != 0)
  1244.         {
  1245.             ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
  1246.                 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  1247.         }
  1248.  
  1249.         return TRUE;
  1250.     }
  1251.  
  1252.     BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0)
  1253.     {
  1254.         ATLASSERT(::IsWindow(m_hWnd));
  1255.  
  1256.         DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
  1257.         DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  1258.         if(dwStyle == dwNewStyle)
  1259.             return FALSE;
  1260.  
  1261.         ::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwNewStyle);
  1262.         if(nFlags != 0)
  1263.         {
  1264.             ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
  1265.                 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  1266.         }
  1267.  
  1268.         return TRUE;
  1269.     }
  1270.  
  1271.     BOOL GetWindowText(BSTR* pbstrText)
  1272.     {
  1273.         return GetWindowText(*pbstrText);
  1274.     }
  1275.     BOOL GetWindowText(BSTR& bstrText)
  1276.     {
  1277.         USES_CONVERSION;
  1278.         ATLASSERT(::IsWindow(m_hWnd));
  1279.         if (bstrText != NULL)
  1280.         {
  1281.             SysFreeString(bstrText);
  1282.             bstrText = NULL;
  1283.         }
  1284.  
  1285.         int nLen = ::GetWindowTextLength(m_hWnd);
  1286.         if(nLen == 0)
  1287.         {
  1288.             bstrText = ::SysAllocString(OLESTR(""));
  1289.             return (bstrText != NULL) ? TRUE : FALSE;
  1290.         }
  1291.  
  1292.         LPTSTR lpszText = (LPTSTR)_alloca((nLen+1)*sizeof(TCHAR));
  1293.  
  1294.         if(!::GetWindowText(m_hWnd, lpszText, nLen+1))
  1295.             return FALSE;
  1296.  
  1297.         bstrText = ::SysAllocString(T2OLE(lpszText));
  1298.         return (bstrText != NULL) ? TRUE : FALSE;
  1299.     }
  1300.     HWND GetTopLevelParent() const
  1301.     {
  1302.         ATLASSERT(::IsWindow(m_hWnd));
  1303.  
  1304.         HWND hWndParent = m_hWnd;
  1305.         HWND hWndTmp;
  1306.         while((hWndTmp = ::GetParent(hWndParent)) != NULL)
  1307.             hWndParent = hWndTmp;
  1308.  
  1309.         return hWndParent;
  1310.     }
  1311.  
  1312.     HWND GetTopLevelWindow() const
  1313.     {
  1314.         ATLASSERT(::IsWindow(m_hWnd));
  1315.  
  1316.         HWND hWndParent;
  1317.         HWND hWndTmp = m_hWnd;
  1318.  
  1319.         do
  1320.         {
  1321.             hWndParent = hWndTmp;
  1322.             hWndTmp = (::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) ? ::GetParent(hWndParent) : ::GetWindow(hWndParent, GW_OWNER);
  1323.         }
  1324.         while(hWndTmp != NULL);
  1325.  
  1326.         return hWndParent;
  1327.     }
  1328. };
  1329.  
  1330. #ifndef __BORLANDC__
  1331. _declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
  1332. #endif
  1333.  
  1334. /////////////////////////////////////////////////////////////////////////////
  1335. // CAxWindow - client side for an ActiveX host window
  1336.  
  1337. #ifndef _ATL_NO_HOSTING
  1338.  
  1339. template <class TBase = CWindow>
  1340. class CAxWindowT : public TBase
  1341. {
  1342. public:
  1343. // Constructors
  1344.     CAxWindowT(HWND hWnd = NULL) : TBase(hWnd)
  1345.     { }
  1346.  
  1347.     CAxWindowT< TBase >& operator=(HWND hWnd)
  1348.     {
  1349.         m_hWnd = hWnd;
  1350.         return *this;
  1351.     }
  1352.  
  1353. // Attributes
  1354.     static LPCTSTR GetWndClassName()
  1355.     {
  1356.         return _T("AtlAxWin");
  1357.     }
  1358.  
  1359. // Operations
  1360.     HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
  1361.             DWORD dwStyle = 0, DWORD dwExStyle = 0,
  1362.             UINT nID = 0, LPVOID lpCreateParam = NULL)
  1363.     {
  1364.         return CWindow::Create(GetWndClassName(), hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam);
  1365.     }
  1366.     HWND Create(HWND hWndParent, LPRECT lpRect = NULL, LPCTSTR szWindowName = NULL,
  1367.             DWORD dwStyle = 0, DWORD dwExStyle = 0,
  1368.             HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
  1369.     {
  1370.         return CWindow::Create(GetWndClassName(), hWndParent, lpRect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
  1371.     }
  1372.  
  1373.     HRESULT CreateControl(LPCOLESTR lpszName, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL)
  1374.     {
  1375.         ATLASSERT(::IsWindow(m_hWnd));
  1376.         return AtlAxCreateControl(lpszName, m_hWnd, pStream, ppUnkContainer);
  1377.     }
  1378.  
  1379.     HRESULT CreateControl(DWORD dwResID, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL)
  1380.     {
  1381.         TCHAR szModule[_MAX_PATH];
  1382.         GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  1383.  
  1384.         CComBSTR bstrURL(OLESTR("res://"));
  1385.         bstrURL.Append(szModule);
  1386.         bstrURL.Append(OLESTR("/"));
  1387.         TCHAR szResID[11];
  1388.         wsprintf(szResID, _T("%0d"), dwResID);
  1389.         bstrURL.Append(szResID);
  1390.  
  1391.         ATLASSERT(::IsWindow(m_hWnd));
  1392.         return AtlAxCreateControl(bstrURL, m_hWnd, pStream, ppUnkContainer);
  1393.     }
  1394.  
  1395.     HRESULT CreateControlEx(LPCOLESTR lpszName, IStream* pStream = NULL, 
  1396.             IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL,
  1397.             REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL)
  1398.     {
  1399.         ATLASSERT(::IsWindow(m_hWnd));
  1400.         return AtlAxCreateControlEx(lpszName, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink);
  1401.     }
  1402.  
  1403.     HRESULT CreateControlEx(DWORD dwResID,  IStream* pStream = NULL, 
  1404.             IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL,
  1405.             REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL)
  1406.     {
  1407.         TCHAR szModule[_MAX_PATH];
  1408.         GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
  1409.  
  1410.         CComBSTR bstrURL(OLESTR("res://"));
  1411.         bstrURL.Append(szModule);
  1412.         bstrURL.Append(OLESTR("/"));
  1413.         TCHAR szResID[11];
  1414.         wsprintf(szResID, _T("%0d"), dwResID);
  1415.         bstrURL.Append(szResID);
  1416.  
  1417.         ATLASSERT(::IsWindow(m_hWnd));
  1418.         return AtlAxCreateControlEx(bstrURL, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink);
  1419.     }
  1420.  
  1421.     HRESULT AttachControl(IUnknown* pControl, IUnknown** ppUnkContainer)
  1422.     {
  1423.         ATLASSERT(::IsWindow(m_hWnd));
  1424.         return AtlAxAttachControl(pControl, m_hWnd, ppUnkContainer);
  1425.     }
  1426.     HRESULT QueryHost(REFIID iid, void** ppUnk)
  1427.     {
  1428.         ATLASSERT(ppUnk != NULL);
  1429.         HRESULT hr;
  1430.         *ppUnk = NULL;
  1431.         CComPtr<IUnknown> spUnk;
  1432.         hr = AtlAxGetHost(m_hWnd, &spUnk);
  1433.         if (SUCCEEDED(hr))
  1434.             hr = spUnk->QueryInterface(iid, ppUnk);
  1435.         return hr;
  1436.     }
  1437.     template <class Q>
  1438.     HRESULT QueryHost(Q** ppUnk)
  1439.     {
  1440.         return QueryHost(__uuidof(Q), (void**)ppUnk);
  1441.     }
  1442.     HRESULT QueryControl(REFIID iid, void** ppUnk)
  1443.     {
  1444.         ATLASSERT(ppUnk != NULL);
  1445.         HRESULT hr;
  1446.         *ppUnk = NULL;
  1447.         CComPtr<IUnknown> spUnk;
  1448.         hr = AtlAxGetControl(m_hWnd, &spUnk);
  1449.         if (SUCCEEDED(hr))
  1450.             hr = spUnk->QueryInterface(iid, ppUnk);
  1451.         return hr;
  1452.     }
  1453.     template <class Q>
  1454.     HRESULT QueryControl(Q** ppUnk)
  1455.     {
  1456.         return QueryControl(__uuidof(Q), (void**)ppUnk);
  1457.     }
  1458.     HRESULT SetExternalDispatch(IDispatch* pDisp)
  1459.     {
  1460.         HRESULT hr;
  1461.         CComPtr<IAxWinHostWindow> spHost;
  1462.         hr = QueryHost(IID_IAxWinHostWindow, (void**)&spHost);
  1463.         if (SUCCEEDED(hr))
  1464.             hr = spHost->SetExternalDispatch(pDisp);
  1465.         return hr;
  1466.     }
  1467.     HRESULT SetExternalUIHandler(IDocHostUIHandlerDispatch* pUIHandler)
  1468.     {
  1469.         HRESULT hr;
  1470.         CComPtr<IAxWinHostWindow> spHost;
  1471.         hr = QueryHost(IID_IAxWinHostWindow, (void**)&spHost);
  1472.         if (SUCCEEDED(hr))
  1473.             hr = spHost->SetExternalUIHandler(pUIHandler);
  1474.         return hr;
  1475.     }
  1476. };
  1477.  
  1478. typedef CAxWindowT<CWindow> CAxWindow;
  1479.  
  1480. #endif //_ATL_NO_HOSTING
  1481.  
  1482. /////////////////////////////////////////////////////////////////////////////
  1483. // WindowProc thunks
  1484.  
  1485. #if defined(_M_IX86)
  1486. #pragma pack(push,1)
  1487. struct _WndProcThunk
  1488. {
  1489.     DWORD   m_mov;          // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
  1490.     DWORD   m_this;         //
  1491.     BYTE    m_jmp;          // jmp WndProc
  1492.     DWORD   m_relproc;      // relative jmp
  1493. };
  1494. #pragma pack(pop)
  1495. #elif defined (_M_ALPHA)
  1496. // For ALPHA we will stick the this pointer into a0, which is where
  1497. // the HWND is.  However, we don't actually need the HWND so this is OK.
  1498. #pragma pack(push,4)
  1499. struct _WndProcThunk //this should come out to 20 bytes
  1500. {
  1501.     DWORD ldah_at;      //  ldah    at, HIWORD(func)
  1502.     DWORD ldah_a0;      //  ldah    a0, HIWORD(this)
  1503.     DWORD lda_at;       //  lda     at, LOWORD(func)(at)
  1504.     DWORD lda_a0;       //  lda     a0, LOWORD(this)(a0)
  1505.     DWORD jmp;          //  jmp     zero,(at),0
  1506. };
  1507. #pragma pack(pop)
  1508. #else
  1509. #error Only Alpha and X86 supported
  1510. #endif
  1511.  
  1512. class CWndProcThunk
  1513. {
  1514. public:
  1515.     union
  1516.     {
  1517.         _AtlCreateWndData cd;
  1518.         _WndProcThunk thunk;
  1519.     };
  1520.     void Init(WNDPROC proc, void* pThis)
  1521.     {
  1522. #if defined (_M_IX86)
  1523.         thunk.m_mov = 0x042444C7;  //C7 44 24 0C
  1524.         thunk.m_this = (DWORD)pThis;
  1525.         thunk.m_jmp = 0xe9;
  1526.         thunk.m_relproc = (int)proc - ((int)this+sizeof(_WndProcThunk));
  1527. #elif defined (_M_ALPHA)
  1528.         thunk.ldah_at = (0x279f0000 | HIWORD(proc)) + (LOWORD(proc)>>15);
  1529.         thunk.ldah_a0 = (0x261f0000 | HIWORD(pThis)) + (LOWORD(pThis)>>15);
  1530.         thunk.lda_at = 0x239c0000 | LOWORD(proc);
  1531.         thunk.lda_a0 = 0x22100000 | LOWORD(pThis);
  1532.         thunk.jmp = 0x6bfc0000;
  1533. #endif
  1534.         // write block from data cache and
  1535.         //  flush from instruction cache
  1536.         FlushInstructionCache(GetCurrentProcess(), &thunk, sizeof(thunk));
  1537.     }
  1538. };
  1539.  
  1540. /////////////////////////////////////////////////////////////////////////////
  1541. // CMessageMap - abstract class that provides an interface for message maps
  1542.  
  1543. class ATL_NO_VTABLE CMessageMap
  1544. {
  1545. public:
  1546.     virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
  1547.         LRESULT& lResult, DWORD dwMsgMapID) = 0;
  1548. };
  1549.  
  1550. /////////////////////////////////////////////////////////////////////////////
  1551. // Message map
  1552.  
  1553. #define BEGIN_MSG_MAP(theClass) \
  1554. public: \
  1555.     BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
  1556.     { \
  1557.         BOOL bHandled = TRUE; \
  1558.         hWnd; \
  1559.         uMsg; \
  1560.         wParam; \
  1561.         lParam; \
  1562.         lResult; \
  1563.         bHandled; \
  1564.         switch(dwMsgMapID) \
  1565.         { \
  1566.         case 0:
  1567.  
  1568. #define ALT_MSG_MAP(msgMapID) \
  1569.         break; \
  1570.         case msgMapID:
  1571.  
  1572. #define MESSAGE_HANDLER(msg, func) \
  1573.     if(uMsg == msg) \
  1574.     { \
  1575.         bHandled = TRUE; \
  1576.         lResult = func(uMsg, wParam, lParam, bHandled); \
  1577.         if(bHandled) \
  1578.             return TRUE; \
  1579.     }
  1580.  
  1581. #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
  1582.     if(uMsg >= msgFirst && uMsg <= msgLast) \
  1583.     { \
  1584.         bHandled = TRUE; \
  1585.         lResult = func(uMsg, wParam, lParam, bHandled); \
  1586.         if(bHandled) \
  1587.             return TRUE; \
  1588.     }
  1589.  
  1590. #define COMMAND_HANDLER(id, code, func) \
  1591.     if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
  1592.     { \
  1593.         bHandled = TRUE; \
  1594.         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  1595.         if(bHandled) \
  1596.             return TRUE; \
  1597.     }
  1598.  
  1599. #define COMMAND_ID_HANDLER(id, func) \
  1600.     if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
  1601.     { \
  1602.         bHandled = TRUE; \
  1603.         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  1604.         if(bHandled) \
  1605.             return TRUE; \
  1606.     }
  1607.  
  1608. #define COMMAND_CODE_HANDLER(code, func) \
  1609.     if(uMsg == WM_COMMAND && code == HIWORD(wParam)) \
  1610.     { \
  1611.         bHandled = TRUE; \
  1612.         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  1613.         if(bHandled) \
  1614.             return TRUE; \
  1615.     }
  1616.  
  1617. #define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
  1618.     if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst  && LOWORD(wParam) <= idLast) \
  1619.     { \
  1620.         bHandled = TRUE; \
  1621.         lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  1622.         if(bHandled) \
  1623.             return TRUE; \
  1624.     }
  1625.  
  1626. #define NOTIFY_HANDLER(id, cd, func) \
  1627.     if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
  1628.     { \
  1629.         bHandled = TRUE; \
  1630.         lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  1631.         if(bHandled) \
  1632.             return TRUE; \
  1633.     }
  1634.  
  1635. #define NOTIFY_ID_HANDLER(id, func) \
  1636.     if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
  1637.     { \
  1638.         bHandled = TRUE; \
  1639.         lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  1640.         if(bHandled) \
  1641.             return TRUE; \
  1642.     }
  1643.  
  1644. #define NOTIFY_CODE_HANDLER(cd, func) \
  1645.     if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
  1646.     { \
  1647.         bHandled = TRUE; \
  1648.         lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  1649.         if(bHandled) \
  1650.             return TRUE; \
  1651.     }
  1652.  
  1653. #define NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \
  1654.     if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
  1655.     { \
  1656.         bHandled = TRUE; \
  1657.         lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  1658.         if(bHandled) \
  1659.             return TRUE; \
  1660.     }
  1661.  
  1662. #define CHAIN_MSG_MAP(theChainClass) \
  1663.     { \
  1664.         if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
  1665.             return TRUE; \
  1666.     }
  1667.  
  1668. #define CHAIN_MSG_MAP_MEMBER(theChainMember) \
  1669.     { \
  1670.         if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
  1671.             return TRUE; \
  1672.     }
  1673.  
  1674. #define CHAIN_MSG_MAP_ALT(theChainClass, msgMapID) \
  1675.     { \
  1676.         if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
  1677.             return TRUE; \
  1678.     }
  1679.  
  1680. #define CHAIN_MSG_MAP_ALT_MEMBER(theChainMember, msgMapID) \
  1681.     { \
  1682.         if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
  1683.             return TRUE; \
  1684.     }
  1685.  
  1686. #define CHAIN_MSG_MAP_DYNAMIC(dynaChainID) \
  1687.     { \
  1688.         if(CDynamicChain::CallChain(dynaChainID, hWnd, uMsg, wParam, lParam, lResult)) \
  1689.             return TRUE; \
  1690.     }
  1691.  
  1692. #define END_MSG_MAP() \
  1693.             break; \
  1694.         default: \
  1695.             ATLTRACE2(atlTraceWindowing, 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID); \
  1696.             ATLASSERT(FALSE); \
  1697.             break; \
  1698.         } \
  1699.         return FALSE; \
  1700.     }
  1701.  
  1702.  
  1703. // Handler prototypes:
  1704. //  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  1705. //  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
  1706. //  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
  1707.  
  1708.  
  1709. // Empty message map macro
  1710.  
  1711. #define DECLARE_EMPTY_MSG_MAP() \
  1712. public: \
  1713.     BOOL ProcessWindowMessage(HWND, UINT, WPARAM, LPARAM, LRESULT&, DWORD) \
  1714.     { \
  1715.         return FALSE; \
  1716.     }
  1717.  
  1718. // Message reflection macros
  1719.  
  1720. #define REFLECT_NOTIFICATIONS() \
  1721.     { \
  1722.         bHandled = TRUE; \
  1723.         lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
  1724.         if(bHandled) \
  1725.             return TRUE; \
  1726.     }
  1727.  
  1728. #define DEFAULT_REFLECTION_HANDLER() \
  1729.     if(DefaultReflectionHandler(hWnd, uMsg, wParam, lParam, lResult)) \
  1730.         return TRUE;
  1731.  
  1732. /////////////////////////////////////////////////////////////////////////////
  1733. // CDynamicChain - provides support for dynamic chaining
  1734.  
  1735. class CDynamicChain
  1736. {
  1737. public:
  1738.     struct ATL_CHAIN_ENTRY
  1739.     {
  1740.         DWORD m_dwChainID;
  1741.         CMessageMap* m_pObject;
  1742.         DWORD m_dwMsgMapID;
  1743.     };
  1744.  
  1745.     CSimpleArray<ATL_CHAIN_ENTRY*> m_aChainEntry;
  1746.  
  1747.     CDynamicChain()
  1748.     { }
  1749.  
  1750.     ~CDynamicChain()
  1751.     {
  1752.         for(int i = 0; i < m_aChainEntry.GetSize(); i++)
  1753.         {
  1754.             if(m_aChainEntry[i] != NULL)
  1755.                 delete m_aChainEntry[i];
  1756.         }
  1757.     }
  1758.  
  1759.     BOOL SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID = 0)
  1760.     {
  1761.     // first search for an existing entry
  1762.     #ifdef __BORLANDC__
  1763.     int i;
  1764.         for(i = 0; i < m_aChainEntry.GetSize(); i++)
  1765.     #else
  1766.         for(int i = 0; i < m_aChainEntry.GetSize(); i++)
  1767.     #endif
  1768.         {
  1769.             if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID)
  1770.             {
  1771.                 m_aChainEntry[i]->m_pObject = pObject;
  1772.                 m_aChainEntry[i]->m_dwMsgMapID = dwMsgMapID;
  1773.                 return TRUE;
  1774.             }
  1775.         }
  1776.  
  1777.     // create a new one
  1778.  
  1779.         ATL_CHAIN_ENTRY* pEntry = NULL;
  1780.         ATLTRY(pEntry = new ATL_CHAIN_ENTRY);
  1781.  
  1782.         if(pEntry == NULL)
  1783.             return FALSE;
  1784.  
  1785.         pEntry->m_dwChainID = dwChainID;
  1786.         pEntry->m_pObject = pObject;
  1787.         pEntry->m_dwMsgMapID = dwMsgMapID;
  1788.  
  1789.     // search for an empty one
  1790.  
  1791.         for(i = 0; i < m_aChainEntry.GetSize(); i++)
  1792.         {
  1793.             if(m_aChainEntry[i] == NULL)
  1794.             {
  1795.                 m_aChainEntry[i] = pEntry;
  1796.                 return TRUE;
  1797.             }
  1798.         }
  1799.  
  1800.     // add a new one
  1801.  
  1802.         BOOL bRet = m_aChainEntry.Add(pEntry);
  1803.  
  1804.         if(!bRet)
  1805.         {
  1806.             delete pEntry;
  1807.             return FALSE;
  1808.         }
  1809.  
  1810.         return TRUE;
  1811.     }
  1812.  
  1813.     BOOL RemoveChainEntry(DWORD dwChainID)
  1814.     {
  1815.         for(int i = 0; i < m_aChainEntry.GetSize(); i++)
  1816.         {
  1817.             if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID)
  1818.             {
  1819.                 delete m_aChainEntry[i];
  1820.                 m_aChainEntry[i] = NULL;
  1821.                 return TRUE;
  1822.             }
  1823.         }
  1824.  
  1825.         return FALSE;
  1826.     }
  1827.  
  1828.     BOOL CallChain(DWORD dwChainID, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  1829.     {
  1830.         for(int i = 0; i < m_aChainEntry.GetSize(); i++)
  1831.         {
  1832.             if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID)
  1833.                 return (m_aChainEntry[i]->m_pObject)->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, m_aChainEntry[i]->m_dwMsgMapID);
  1834.         }
  1835.  
  1836.         return FALSE;
  1837.     }
  1838. };
  1839.  
  1840. /////////////////////////////////////////////////////////////////////////////
  1841. // CWndClassInfo - Manages Windows class information
  1842.  
  1843. #define DECLARE_WND_CLASS(WndClassName) \
  1844. static CWndClassInfo& GetWndClassInfo() \
  1845. { \
  1846.     static CWndClassInfo wc = \
  1847.     { \
  1848.         { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, \
  1849.           0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
  1850.         NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
  1851.     }; \
  1852.     return wc; \
  1853. }
  1854.  
  1855. #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
  1856. static CWndClassInfo& GetWndClassInfo() \
  1857. { \
  1858.     static CWndClassInfo wc = \
  1859.     { \
  1860.         { sizeof(WNDCLASSEX), style, StartWindowProc, \
  1861.           0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
  1862.         NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
  1863.     }; \
  1864.     return wc; \
  1865. }
  1866.  
  1867. #define DECLARE_WND_SUPERCLASS(WndClassName, OrigWndClassName) \
  1868. static CWndClassInfo& GetWndClassInfo() \
  1869. { \
  1870.     static CWndClassInfo wc = \
  1871.     { \
  1872.         { sizeof(WNDCLASSEX), 0, StartWindowProc, \
  1873.           0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
  1874.         OrigWndClassName, NULL, NULL, TRUE, 0, _T("") \
  1875.     }; \
  1876.     return wc; \
  1877. }
  1878.  
  1879. /////////////////////////////////////////////////////////////////////////////
  1880. // CWinTraits - Defines various default values for a window
  1881.  
  1882. template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
  1883. class CWinTraits
  1884. {
  1885. public:
  1886.     static DWORD GetWndStyle(DWORD dwStyle)
  1887.     {
  1888.         return dwStyle == 0 ? t_dwStyle : dwStyle;
  1889.     }
  1890.     static DWORD GetWndExStyle(DWORD dwExStyle)
  1891.     {
  1892.         return dwExStyle == 0 ? t_dwExStyle : dwExStyle;
  1893.     }
  1894. };
  1895.  
  1896. typedef CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0>                    CControlWinTraits;
  1897. typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE>        CFrameWinTraits;
  1898. typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD>    CMDIChildWinTraits;
  1899.  
  1900. typedef CWinTraits<0, 0> CNullTraits;
  1901.  
  1902. template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0, class TWinTraits = CControlWinTraits>
  1903. class CWinTraitsOR
  1904. {
  1905. public:
  1906.     static DWORD GetWndStyle(DWORD dwStyle)
  1907.     {
  1908.         return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle);
  1909.     }
  1910.     static DWORD GetWndExStyle(DWORD dwExStyle)
  1911.     {
  1912.         return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle);
  1913.     }
  1914. };
  1915.  
  1916. /////////////////////////////////////////////////////////////////////////////
  1917. // CWindowImpl - Implements a window
  1918.  
  1919. template <class TBase = CWindow>
  1920. class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap
  1921. {
  1922. public:
  1923.     CWndProcThunk m_thunk;
  1924.     const MSG* m_pCurrentMsg;
  1925.  
  1926. // Constructor/destructor
  1927.     CWindowImplRoot() : m_pCurrentMsg(NULL)
  1928.     { }
  1929.  
  1930.     ~CWindowImplRoot()
  1931.     {
  1932. #ifdef _DEBUG
  1933.         if(m_hWnd != NULL)    // should be cleared in WindowProc
  1934.         {
  1935.             ATLTRACE2(atlTraceWindowing, 0, _T("ERROR - Object deleted before window was destroyed\n"));
  1936.             ATLASSERT(FALSE);
  1937.         }
  1938. #endif //_DEBUG
  1939.     }
  1940.  
  1941. // Current message
  1942.     const MSG* GetCurrentMessage() const
  1943.     {
  1944.         return m_pCurrentMsg;
  1945.     }
  1946.  
  1947. // Message reflection support
  1948.     LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  1949.     static BOOL DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult);
  1950. };
  1951.  
  1952. template <class TBase>
  1953. LRESULT CWindowImplRoot< TBase >::ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  1954. {
  1955.     HWND hWndChild = NULL;
  1956.  
  1957.     switch(uMsg)
  1958.     {
  1959.     case WM_COMMAND:
  1960.         if(lParam != NULL)    // not from a menu
  1961.             hWndChild = (HWND)lParam;
  1962.         break;
  1963.     case WM_NOTIFY:
  1964.         hWndChild = ((LPNMHDR)lParam)->hwndFrom;
  1965.         break;
  1966.     case WM_PARENTNOTIFY:
  1967.         switch(LOWORD(wParam))
  1968.         {
  1969.         case WM_CREATE:
  1970.         case WM_DESTROY:
  1971.             hWndChild = (HWND)lParam;
  1972.             break;
  1973.         default:
  1974.             hWndChild = GetDlgItem(HIWORD(wParam));
  1975.             break;
  1976.         }
  1977.         break;
  1978.     case WM_DRAWITEM:
  1979.         if(wParam)    // not from a menu
  1980.             hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
  1981.         break;
  1982.     case WM_MEASUREITEM:
  1983.         if(wParam)    // not from a menu
  1984.             hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID);
  1985.         break;
  1986.     case WM_COMPAREITEM:
  1987.         if(wParam)    // not from a menu
  1988.             hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID);
  1989.         break;
  1990.     case WM_DELETEITEM:
  1991.         if(wParam)    // not from a menu
  1992.             hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID);
  1993.         break;
  1994.     case WM_VKEYTOITEM:
  1995.     case WM_CHARTOITEM:
  1996.     case WM_HSCROLL:
  1997.     case WM_VSCROLL:
  1998.         hWndChild = (HWND)lParam;
  1999.         break;
  2000.     case WM_CTLCOLORBTN:
  2001.     case WM_CTLCOLORDLG:
  2002.     case WM_CTLCOLOREDIT:
  2003.     case WM_CTLCOLORLISTBOX:
  2004.     case WM_CTLCOLORMSGBOX:
  2005.     case WM_CTLCOLORSCROLLBAR:
  2006.     case WM_CTLCOLORSTATIC:
  2007.         hWndChild = (HWND)lParam;
  2008.         break;
  2009.     default:
  2010.         break;
  2011.     }
  2012.  
  2013.     if(hWndChild == NULL)
  2014.     {
  2015.         bHandled = FALSE;
  2016.         return 1;
  2017.     }
  2018.  
  2019.     ATLASSERT(::IsWindow(hWndChild));
  2020.     return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
  2021. }
  2022.  
  2023. template <class TBase>
  2024. BOOL CWindowImplRoot< TBase >::DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  2025. {
  2026.     switch(uMsg)
  2027.     {
  2028.     case OCM_COMMAND:
  2029.     case OCM_NOTIFY:
  2030.     case OCM_PARENTNOTIFY:
  2031.     case OCM_DRAWITEM:
  2032.     case OCM_MEASUREITEM:
  2033.     case OCM_COMPAREITEM:
  2034.     case OCM_DELETEITEM:
  2035.     case OCM_VKEYTOITEM:
  2036.     case OCM_CHARTOITEM:
  2037.     case OCM_HSCROLL:
  2038.     case OCM_VSCROLL:
  2039.     case OCM_CTLCOLORBTN:
  2040.     case OCM_CTLCOLORDLG:
  2041.     case OCM_CTLCOLOREDIT:
  2042.     case OCM_CTLCOLORLISTBOX:
  2043.     case OCM_CTLCOLORMSGBOX:
  2044.     case OCM_CTLCOLORSCROLLBAR:
  2045.     case OCM_CTLCOLORSTATIC:
  2046.         lResult = ::DefWindowProc(hWnd, uMsg - OCM__BASE, wParam, lParam);
  2047.         return TRUE;
  2048.     default:
  2049.         break;
  2050.     }
  2051.     return FALSE;
  2052. }
  2053.  
  2054. template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
  2055. class ATL_NO_VTABLE CWindowImplBaseT : public CWindowImplRoot< TBase >
  2056. {
  2057. public:
  2058.     WNDPROC m_pfnSuperWindowProc;
  2059.  
  2060.     CWindowImplBaseT() : m_pfnSuperWindowProc(::DefWindowProc)
  2061.     {}
  2062.  
  2063.     static DWORD GetWndStyle(DWORD dwStyle)
  2064.     {
  2065.         return TWinTraits::GetWndStyle(dwStyle);
  2066.     }
  2067.     static DWORD GetWndExStyle(DWORD dwExStyle)
  2068.     {
  2069.         return TWinTraits::GetWndExStyle(dwExStyle);
  2070.     }
  2071.  
  2072.     virtual WNDPROC GetWindowProc()
  2073.     {
  2074.         return WindowProc;
  2075.     }
  2076.     static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  2077.     static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  2078.     HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName,
  2079.             DWORD dwStyle, DWORD dwExStyle, UINT nID, ATOM atom, LPVOID lpCreateParam = NULL);
  2080.     BOOL DestroyWindow()
  2081.     {
  2082.         ATLASSERT(::IsWindow(m_hWnd));
  2083.         return ::DestroyWindow(m_hWnd);
  2084.     }
  2085.     BOOL SubclassWindow(HWND hWnd);
  2086.     HWND UnsubclassWindow(BOOL bForce = FALSE);
  2087.  
  2088.     LRESULT DefWindowProc()
  2089.     {
  2090.         const MSG* pMsg = m_pCurrentMsg;
  2091.         LRESULT lRes = 0;
  2092.         if (pMsg != NULL)
  2093.             lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
  2094.         return lRes;
  2095.     }
  2096.  
  2097.     LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  2098.     {
  2099. #ifdef STRICT
  2100.         return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
  2101. #else
  2102.         return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
  2103. #endif
  2104.     }
  2105.  
  2106.     virtual void OnFinalMessage(HWND /*hWnd*/)
  2107.     {
  2108.         // override to do something, if needed
  2109.     }
  2110. };
  2111.  
  2112. typedef CWindowImplBaseT<CWindow>    CWindowImplBase;
  2113.  
  2114. template <class TBase, class TWinTraits>
  2115. LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2116. {
  2117.     CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)_Module.ExtractCreateWndData();
  2118.     ATLASSERT(pThis != NULL);
  2119.     pThis->m_hWnd = hWnd;
  2120.     pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);
  2121.     WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);
  2122.     WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  2123. #ifdef _DEBUG
  2124.     // check if somebody has subclassed us already since we discard it
  2125.     if(pOldProc != StartWindowProc)
  2126.         ATLTRACE2(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n"));
  2127. #else
  2128.     pOldProc;    // avoid unused warning
  2129. #endif
  2130.     return pProc(hWnd, uMsg, wParam, lParam);
  2131. }
  2132.  
  2133. template <class TBase, class TWinTraits>
  2134. LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2135. {
  2136.     CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)hWnd;
  2137.     // set a ptr to this message and save the old value
  2138.     MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };
  2139.     const MSG* pOldMsg = pThis->m_pCurrentMsg;
  2140.     pThis->m_pCurrentMsg = &msg;
  2141.     // pass to the message map to process
  2142.     LRESULT lRes;
  2143.     BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
  2144.     // restore saved value for the current message
  2145.     ATLASSERT(pThis->m_pCurrentMsg == &msg);
  2146.     pThis->m_pCurrentMsg = pOldMsg;
  2147.     // do the default processing if message was not handled
  2148.     if(!bRet)
  2149.     {
  2150.         if(uMsg != WM_NCDESTROY)
  2151.             lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  2152.         else
  2153.         {
  2154.             // unsubclass, if needed
  2155.             LONG pfnWndProc = ::GetWindowLong(pThis->m_hWnd, GWL_WNDPROC);
  2156.             lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  2157.             if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLong(pThis->m_hWnd, GWL_WNDPROC) == pfnWndProc)
  2158.                 ::SetWindowLong(pThis->m_hWnd, GWL_WNDPROC, (LONG)pThis->m_pfnSuperWindowProc);
  2159.             // clear out window handle
  2160.             HWND hWnd = pThis->m_hWnd;
  2161.             pThis->m_hWnd = NULL;
  2162.             // clean up after window is destroyed
  2163.             pThis->OnFinalMessage(hWnd);
  2164.         }
  2165.     }
  2166.     return lRes;
  2167. }
  2168.  
  2169. template <class TBase, class TWinTraits>
  2170. HWND CWindowImplBaseT< TBase, TWinTraits >::Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName,
  2171.         DWORD dwStyle, DWORD dwExStyle, UINT nID, ATOM atom, LPVOID lpCreateParam)
  2172. {
  2173.     ATLASSERT(m_hWnd == NULL);
  2174.  
  2175.     if(atom == 0)
  2176.         return NULL;
  2177.  
  2178.     _Module.AddCreateWndData(&m_thunk.cd, this);
  2179.  
  2180.     if(nID == 0 && (dwStyle & WS_CHILD))
  2181.         nID = (UINT)this;
  2182.  
  2183.     HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)MAKELONG(atom, 0), szWindowName,
  2184.         dwStyle, rcPos.left, rcPos.top, rcPos.right - rcPos.left,
  2185.         rcPos.bottom - rcPos.top, hWndParent, (HMENU)nID,
  2186.         _Module.GetModuleInstance(), lpCreateParam);
  2187.  
  2188.     ATLASSERT(m_hWnd == hWnd);
  2189.  
  2190.     return hWnd;
  2191. }
  2192.  
  2193. template <class TBase, class TWinTraits>
  2194. BOOL CWindowImplBaseT< TBase, TWinTraits >::SubclassWindow(HWND hWnd)
  2195. {
  2196.     ATLASSERT(m_hWnd == NULL);
  2197.     ATLASSERT(::IsWindow(hWnd));
  2198.     m_thunk.Init(GetWindowProc(), this);
  2199.     WNDPROC pProc = (WNDPROC)&(m_thunk.thunk);
  2200.     WNDPROC pfnWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  2201.     if(pfnWndProc == NULL)
  2202.         return FALSE;
  2203.     m_pfnSuperWindowProc = pfnWndProc;
  2204.     m_hWnd = hWnd;
  2205.     return TRUE;
  2206. }
  2207.  
  2208. // Use only if you want to subclass before window is destroyed,
  2209. // WindowProc will automatically subclass when  window goes away
  2210. template <class TBase, class TWinTraits>
  2211. HWND CWindowImplBaseT< TBase, TWinTraits >::UnsubclassWindow(BOOL bForce /*= FALSE*/)
  2212. {
  2213.     ATLASSERT(m_hWnd != NULL);
  2214.  
  2215.     WNDPROC pOurProc = (WNDPROC)&(m_thunk.thunk);
  2216.     WNDPROC pActiveProc = (WNDPROC)::GetWindowLong(m_hWnd, GWL_WNDPROC);
  2217.  
  2218.     HWND hWnd = NULL;
  2219.     if (bForce || pOurProc == pActiveProc)
  2220.     {
  2221.         if(!::SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_pfnSuperWindowProc))
  2222.             return NULL;
  2223.  
  2224.         m_pfnSuperWindowProc = ::DefWindowProc;
  2225.         hWnd = m_hWnd;
  2226.         m_hWnd = NULL;
  2227.     }
  2228.     return hWnd;
  2229. }
  2230.  
  2231. template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
  2232. class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits >
  2233. {
  2234. public:
  2235.     DECLARE_WND_CLASS(NULL)
  2236.  
  2237.     HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
  2238.             DWORD dwStyle = 0, DWORD dwExStyle = 0,
  2239.             UINT nID = 0, LPVOID lpCreateParam = NULL)
  2240.     {
  2241.         if (T::GetWndClassInfo().m_lpszOrigName == NULL)
  2242.             T::GetWndClassInfo().m_lpszOrigName = GetWndClassName();
  2243.         ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
  2244.  
  2245.         dwStyle = T::GetWndStyle(dwStyle);
  2246.         dwExStyle = T::GetWndExStyle(dwExStyle);
  2247.  
  2248.         return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rcPos, szWindowName,
  2249.             dwStyle, dwExStyle, nID, atom, lpCreateParam);
  2250.     }
  2251. };
  2252.  
  2253. /////////////////////////////////////////////////////////////////////////////
  2254. // CDialogImpl - Implements a dialog box
  2255.  
  2256. template <class TBase = CWindow>
  2257. class ATL_NO_VTABLE CDialogImplBaseT : public CWindowImplRoot< TBase >
  2258. {
  2259. public:
  2260.     virtual WNDPROC GetDialogProc()
  2261.     {
  2262.         return DialogProc;
  2263.     }
  2264.     static LRESULT CALLBACK StartDialogProc(HWND hWnd, UINT uMsg,
  2265.         WPARAM wParam, LPARAM lParam);
  2266.     static LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  2267.     BOOL MapDialogRect(LPRECT lpRect)
  2268.     {
  2269.         ATLASSERT(::IsWindow(m_hWnd));
  2270.         return ::MapDialogRect(m_hWnd, lpRect);
  2271.     }
  2272.     virtual void OnFinalMessage(HWND /*hWnd*/)
  2273.     {
  2274.         // override to do something, if needed
  2275.     }
  2276.     // has no meaning for a dialog, but needed for handlers that use it
  2277.     LRESULT DefWindowProc()
  2278.     {
  2279.         return 0;
  2280.     }
  2281. };
  2282.  
  2283. template <class TBase>
  2284. LRESULT CALLBACK CDialogImplBaseT< TBase >::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2285. {
  2286.     CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)_Module.ExtractCreateWndData();
  2287.     ATLASSERT(pThis != NULL);
  2288.     pThis->m_hWnd = hWnd;
  2289.     pThis->m_thunk.Init(pThis->GetDialogProc(), pThis);
  2290.     WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);
  2291.     WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, DWL_DLGPROC, (LONG)pProc);
  2292. #ifdef _DEBUG
  2293.     // check if somebody has subclassed us already since we discard it
  2294.     if(pOldProc != StartDialogProc)
  2295.         ATLTRACE2(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n"));
  2296. #else
  2297.     pOldProc;    // avoid unused warning
  2298. #endif
  2299.     return pProc(hWnd, uMsg, wParam, lParam);
  2300. }
  2301.  
  2302. template <class TBase>
  2303. LRESULT CALLBACK CDialogImplBaseT< TBase >::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2304. {
  2305.     CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)hWnd;
  2306.     // set a ptr to this message and save the old value
  2307.     MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };
  2308.     const MSG* pOldMsg = pThis->m_pCurrentMsg;
  2309.     pThis->m_pCurrentMsg = &msg;
  2310.     // pass to the message map to process
  2311.     LRESULT lRes;
  2312.     BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
  2313.     // restore saved value for the current message
  2314.     ATLASSERT(pThis->m_pCurrentMsg == &msg);
  2315.     pThis->m_pCurrentMsg = pOldMsg;
  2316.     // set result if message was handled
  2317.     if(bRet)
  2318.     {
  2319.         switch (uMsg)
  2320.         {
  2321.         case WM_COMPAREITEM:
  2322.         case WM_VKEYTOITEM:
  2323.         case WM_CHARTOITEM:
  2324.         case WM_INITDIALOG:
  2325.         case WM_QUERYDRAGICON:
  2326.         case WM_CTLCOLORMSGBOX:
  2327.         case WM_CTLCOLOREDIT:
  2328.         case WM_CTLCOLORLISTBOX:
  2329.         case WM_CTLCOLORBTN:
  2330.         case WM_CTLCOLORDLG:
  2331.         case WM_CTLCOLORSCROLLBAR:
  2332.         case WM_CTLCOLORSTATIC:
  2333.             return lRes;
  2334.             break;
  2335.         }
  2336.         ::SetWindowLong(pThis->m_hWnd, DWL_MSGRESULT, lRes);
  2337.         return TRUE;
  2338.     }
  2339.     if(uMsg == WM_NCDESTROY)
  2340.     {
  2341.         // clear out window handle
  2342.         HWND hWnd = pThis->m_hWnd;
  2343.         pThis->m_hWnd = NULL;
  2344.         // clean up after dialog is destroyed
  2345.         pThis->OnFinalMessage(hWnd);
  2346.     }
  2347.     return FALSE;
  2348. }
  2349.  
  2350. typedef CDialogImplBaseT<CWindow>    CDialogImplBase;
  2351.  
  2352. template <class T, class TBase = CWindow>
  2353. class ATL_NO_VTABLE CDialogImpl : public CDialogImplBaseT< TBase >
  2354. {
  2355. public:
  2356. #ifdef _DEBUG
  2357.     bool m_bModal;
  2358.     CDialogImpl() : m_bModal(false) { }
  2359. #endif //_DEBUG
  2360.     // modal dialogs
  2361.     int DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
  2362.     {
  2363.         ATLASSERT(m_hWnd == NULL);
  2364.         _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this);
  2365. #ifdef _DEBUG
  2366.         m_bModal = true;
  2367. #endif //_DEBUG
  2368.         return ::DialogBoxParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),
  2369.                     hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
  2370.     }
  2371.     BOOL EndDialog(int nRetCode)
  2372.     {
  2373.         ATLASSERT(::IsWindow(m_hWnd));
  2374.         ATLASSERT(m_bModal);    // must be a modal dialog
  2375.         return ::EndDialog(m_hWnd, nRetCode);
  2376.     }
  2377.     // modeless dialogs
  2378.     HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
  2379.     {
  2380.         ATLASSERT(m_hWnd == NULL);
  2381.         _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this);
  2382. #ifdef _DEBUG
  2383.         m_bModal = false;
  2384. #endif //_DEBUG
  2385.         HWND hWnd = ::CreateDialogParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),
  2386.                     hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
  2387.         ATLASSERT(m_hWnd == hWnd);
  2388.         return hWnd;
  2389.     }
  2390.     // for CComControl
  2391.     HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL)
  2392.     {
  2393.         return Create(hWndParent, dwInitParam);
  2394.     }
  2395.     BOOL DestroyWindow()
  2396.     {
  2397.         ATLASSERT(::IsWindow(m_hWnd));
  2398.         ATLASSERT(!m_bModal);    // must not be a modal dialog
  2399.         return ::DestroyWindow(m_hWnd);
  2400.     }
  2401. };
  2402.  
  2403. /////////////////////////////////////////////////////////////////////////////
  2404. // CAxDialogImpl - Implements a dialog box that hosts ActiveX controls
  2405.  
  2406. #ifndef _ATL_NO_HOSTING
  2407.  
  2408. template <class T, class TBase = CWindow>
  2409. class ATL_NO_VTABLE CAxDialogImpl : public CDialogImplBaseT< TBase >
  2410. {
  2411. public:
  2412. #ifdef _DEBUG
  2413.     bool m_bModal;
  2414.     CAxDialogImpl() : m_bModal(false) { }
  2415. #endif //_DEBUG
  2416.     // modal dialogs
  2417.     int DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
  2418.     {
  2419.         ATLASSERT(m_hWnd == NULL);
  2420.         _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this);
  2421. #ifdef _DEBUG
  2422.         m_bModal = true;
  2423. #endif //_DEBUG
  2424.         return AtlAxDialogBox(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),
  2425.                     hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
  2426.     }
  2427.     BOOL EndDialog(int nRetCode)
  2428.     {
  2429.         ATLASSERT(::IsWindow(m_hWnd));
  2430.         ATLASSERT(m_bModal);    // must be a modal dialog
  2431.         return ::EndDialog(m_hWnd, nRetCode);
  2432.     }
  2433.     // modeless dialogs
  2434.     HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
  2435.     {
  2436.         ATLASSERT(m_hWnd == NULL);
  2437.         _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this);
  2438. #ifdef _DEBUG
  2439.         m_bModal = false;
  2440. #endif //_DEBUG
  2441.         HWND hWnd = AtlAxCreateDialog(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),
  2442.                     hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
  2443.         ATLASSERT(m_hWnd == hWnd);
  2444.         return hWnd;
  2445.     }
  2446.     // for CComControl
  2447.     HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL)
  2448.     {
  2449.         return Create(hWndParent, dwInitParam);
  2450.     }
  2451.     BOOL DestroyWindow()
  2452.     {
  2453.         ATLASSERT(::IsWindow(m_hWnd));
  2454.         ATLASSERT(!m_bModal);    // must not be a modal dialog
  2455.         return ::DestroyWindow(m_hWnd);
  2456.     }
  2457. };
  2458.  
  2459. #endif //_ATL_NO_HOSTING
  2460.  
  2461. /////////////////////////////////////////////////////////////////////////////
  2462. // CSimpleDialog - Prebuilt modal dialog that uses standard buttons
  2463.  
  2464. template <WORD t_wDlgTemplateID, BOOL t_bCenter = TRUE>
  2465. class CSimpleDialog : public CDialogImplBase
  2466. {
  2467. public:
  2468.     int DoModal(HWND hWndParent = ::GetActiveWindow())
  2469.     {
  2470.         ATLASSERT(m_hWnd == NULL);
  2471.         _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBase*)this);
  2472.         int nRet = ::DialogBox(_Module.GetResourceInstance(),
  2473.             MAKEINTRESOURCE(t_wDlgTemplateID), hWndParent, (DLGPROC)StartDialogProc);
  2474.         m_hWnd = NULL;
  2475.         return nRet;
  2476.     }
  2477.  
  2478.     typedef CSimpleDialog<t_wDlgTemplateID, t_bCenter>    thisClass;
  2479.     BEGIN_MSG_MAP(thisClass)
  2480.         MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
  2481.         COMMAND_RANGE_HANDLER(IDOK, IDNO, OnCloseCmd)
  2482.     END_MSG_MAP()
  2483.  
  2484.     LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  2485.     {
  2486.         if(t_bCenter)
  2487.             CenterWindow(GetParent());
  2488.         return TRUE;
  2489.     }
  2490.  
  2491.     LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  2492.     {
  2493.         ::EndDialog(m_hWnd, wID);
  2494.         return 0;
  2495.     }
  2496. };
  2497.  
  2498. /////////////////////////////////////////////////////////////////////////////
  2499. // CContainedWindow - Implements a contained window
  2500.  
  2501. template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
  2502. class CContainedWindowT : public TBase
  2503. {
  2504. public:
  2505.     CWndProcThunk m_thunk;
  2506.     LPCTSTR m_lpszClassName;
  2507.     WNDPROC m_pfnSuperWindowProc;
  2508.     CMessageMap* m_pObject;
  2509.     DWORD m_dwMsgMapID;
  2510.     const MSG* m_pCurrentMsg;
  2511.  
  2512.     // If you use this constructor you must supply
  2513.     // the Window Class Name, Object* and Message Map ID
  2514.     // Later to the Create call
  2515.     CContainedWindowT() : m_pCurrentMsg(NULL)
  2516.     { }
  2517.  
  2518.     CContainedWindowT(LPTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID = 0)
  2519.         : m_lpszClassName(lpszClassName),
  2520.         m_pfnSuperWindowProc(::DefWindowProc),
  2521.         m_pObject(pObject), m_dwMsgMapID(dwMsgMapID),
  2522.         m_pCurrentMsg(NULL)
  2523.     { }
  2524.  
  2525.     CContainedWindowT(CMessageMap* pObject, DWORD dwMsgMapID = 0)
  2526.         : m_lpszClassName(TBase::GetWndClassName()),
  2527.         m_pfnSuperWindowProc(::DefWindowProc),
  2528.         m_pObject(pObject), m_dwMsgMapID(dwMsgMapID),
  2529.         m_pCurrentMsg(NULL)
  2530.     { }
  2531.  
  2532.     void SwitchMessageMap(DWORD dwMsgMapID)
  2533.     {
  2534.         m_dwMsgMapID = dwMsgMapID;
  2535.     }
  2536.  
  2537.     const MSG* GetCurrentMessage() const
  2538.     {
  2539.         return m_pCurrentMsg;
  2540.     }
  2541.  
  2542.     LRESULT DefWindowProc()
  2543.     {
  2544.         const MSG* pMsg = m_pCurrentMsg;
  2545.         LRESULT lRes = 0;
  2546.         if (pMsg != NULL)
  2547.             lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
  2548.         return lRes;
  2549.     }
  2550.  
  2551.     LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  2552.     {
  2553. #ifdef STRICT
  2554.         return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
  2555. #else
  2556.         return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
  2557. #endif
  2558.     }
  2559.     static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg,
  2560.         WPARAM wParam, LPARAM lParam)
  2561.     {
  2562.         CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)_Module.ExtractCreateWndData();
  2563.         ATLASSERT(pThis != NULL);
  2564.         pThis->m_hWnd = hWnd;
  2565.         pThis->m_thunk.Init(WindowProc, pThis);
  2566.         WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);
  2567.         WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  2568. #ifdef _DEBUG
  2569.         // check if somebody has subclassed us already since we discard it
  2570.         if(pOldProc != StartWindowProc)
  2571.             ATLTRACE2(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n"));
  2572. #else
  2573.         pOldProc;    // avoid unused warning
  2574. #endif
  2575.         return pProc(hWnd, uMsg, wParam, lParam);
  2576.     }
  2577.  
  2578.     static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2579.     {
  2580.         CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)hWnd;
  2581.         ATLASSERT(pThis->m_hWnd != NULL);
  2582.         ATLASSERT(pThis->m_pObject != NULL);
  2583.         // set a ptr to this message and save the old value
  2584.         MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };
  2585.         const MSG* pOldMsg = pThis->m_pCurrentMsg;
  2586.         pThis->m_pCurrentMsg = &msg;
  2587.         // pass to the message map to process
  2588.         LRESULT lRes;
  2589.         BOOL bRet = pThis->m_pObject->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, pThis->m_dwMsgMapID);
  2590.         // restore saved value for the current message
  2591.         ATLASSERT(pThis->m_pCurrentMsg == &msg);
  2592.         pThis->m_pCurrentMsg = pOldMsg;
  2593.         // do the default processing if message was not handled
  2594.         if(!bRet)
  2595.         {
  2596.             if(uMsg != WM_NCDESTROY)
  2597.                 lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  2598.             else
  2599.             {
  2600.                 // unsubclass, if needed
  2601.                 LONG pfnWndProc = ::GetWindowLong(pThis->m_hWnd, GWL_WNDPROC);
  2602.                 lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  2603.                 if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLong(pThis->m_hWnd, GWL_WNDPROC) == pfnWndProc)
  2604.                     ::SetWindowLong(pThis->m_hWnd, GWL_WNDPROC, (LONG)pThis->m_pfnSuperWindowProc);
  2605.                 // clear out window handle
  2606.                 pThis->m_hWnd = NULL;
  2607.             }
  2608.         }
  2609.         return lRes;
  2610.     }
  2611.  
  2612.     ATOM RegisterWndSuperclass()
  2613.     {
  2614.         ATOM atom = 0;
  2615.         LPTSTR szBuff = (LPTSTR)_alloca((lstrlen(m_lpszClassName) + 14) * sizeof(TCHAR));
  2616.  
  2617.         WNDCLASSEX wc;
  2618.         wc.cbSize = sizeof(WNDCLASSEX);
  2619.  
  2620.         // Try global class
  2621.         if(!::GetClassInfoEx(NULL, m_lpszClassName, &wc))
  2622.         {
  2623.             // try local class
  2624.             if(!::GetClassInfoEx(_Module.GetModuleInstance(), m_lpszClassName, &wc))
  2625.                 return atom;
  2626.         }
  2627.  
  2628.         m_pfnSuperWindowProc = wc.lpfnWndProc;
  2629.         lstrcpy(szBuff, _T("ATL:"));
  2630.         lstrcat(szBuff, m_lpszClassName);
  2631.  
  2632.         WNDCLASSEX wc1;
  2633.         wc1.cbSize = sizeof(WNDCLASSEX);
  2634.         atom = (ATOM)::GetClassInfoEx(_Module.GetModuleInstance(), szBuff, &wc1);
  2635.  
  2636.         if(atom == 0)   // register class
  2637.         {
  2638.             wc.lpszClassName = szBuff;
  2639.             wc.lpfnWndProc = StartWindowProc;
  2640.             wc.hInstance = _Module.GetModuleInstance();
  2641.             wc.style &= ~CS_GLOBALCLASS;    // we don't register global classes
  2642.  
  2643.             atom = ::RegisterClassEx(&wc);
  2644.         }
  2645.  
  2646.         return atom;
  2647.     }
  2648.     HWND Create(CMessageMap* pObject, DWORD dwMsgMapID, HWND hWndParent, RECT* prcPos,
  2649.         LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0,
  2650.         UINT nID = 0, LPVOID lpCreateParam = NULL)
  2651.     {
  2652.         m_lpszClassName = TBase::GetWndClassName();
  2653.         m_pfnSuperWindowProc = ::DefWindowProc;
  2654.         m_pObject = pObject;
  2655.         m_dwMsgMapID = dwMsgMapID;
  2656.         return Create(hWndParent, prcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam);
  2657.     }
  2658.  
  2659.     HWND Create(LPCTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID, HWND hWndParent, RECT* prcPos, LPCTSTR szWindowName = NULL,
  2660.         DWORD dwStyle = 0, DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL)
  2661.     {
  2662.         m_lpszClassName = lpszClassName;
  2663.         m_pfnSuperWindowProc = ::DefWindowProc;
  2664.         m_pObject = pObject;
  2665.         m_dwMsgMapID = dwMsgMapID;
  2666.         return Create(hWndParent, prcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam);
  2667.     }
  2668.  
  2669.  
  2670.     // This function is Deprecated, use the version
  2671.     // which takes a RECT* instead
  2672.     HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
  2673.         DWORD dwStyle = 0, DWORD dwExStyle = 0,
  2674.         UINT nID = 0, LPVOID lpCreateParam = NULL)
  2675.     {
  2676.         return Create(hWndParent, &rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam);
  2677.     }
  2678.  
  2679.     HWND Create(HWND hWndParent, RECT* prcPos, LPCTSTR szWindowName = NULL,
  2680.         DWORD dwStyle = 0, DWORD dwExStyle = 0,
  2681.         UINT nID = 0, LPVOID lpCreateParam = NULL)
  2682.     {
  2683.         ATLASSERT(m_hWnd == NULL);
  2684.  
  2685.         ATOM atom = RegisterWndSuperclass();
  2686.         if(atom == 0)
  2687.             return NULL;
  2688.  
  2689.         _Module.AddCreateWndData(&m_thunk.cd, this);
  2690.  
  2691.         if(nID == 0 && (dwStyle & WS_CHILD))
  2692.             nID = (UINT)this;
  2693.  
  2694.         dwStyle = TWinTraits::GetWndStyle(dwStyle);
  2695.         dwExStyle = TWinTraits::GetWndExStyle(dwExStyle);
  2696.  
  2697.         HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)MAKELONG(atom, 0), szWindowName,
  2698.                                 dwStyle,
  2699.                                 prcPos->left, prcPos->top,
  2700.                                 prcPos->right - prcPos->left,
  2701.                                 prcPos->bottom - prcPos->top,
  2702.                                 hWndParent, (HMENU)nID,
  2703.                                 _Module.GetModuleInstance(), lpCreateParam);
  2704.         ATLASSERT(m_hWnd == hWnd);
  2705.         return hWnd;
  2706.     }
  2707.  
  2708.     BOOL SubclassWindow(HWND hWnd)
  2709.     {
  2710.         ATLASSERT(m_hWnd == NULL);
  2711.         ATLASSERT(::IsWindow(hWnd));
  2712.  
  2713.         m_thunk.Init(WindowProc, this);
  2714.         WNDPROC pProc = (WNDPROC)&m_thunk.thunk;
  2715.         WNDPROC pfnWndProc = (WNDPROC)::SetWindowLong(hWnd, GWL_WNDPROC, (LONG)pProc);
  2716.         if(pfnWndProc == NULL)
  2717.             return FALSE;
  2718.         m_pfnSuperWindowProc = pfnWndProc;
  2719.         m_hWnd = hWnd;
  2720.         return TRUE;
  2721.     }
  2722.  
  2723.     // Use only if you want to subclass before window is destroyed,
  2724.     // WindowProc will automatically subclass when  window goes away
  2725.     HWND UnsubclassWindow(BOOL bForce = FALSE)
  2726.     {
  2727.         ATLASSERT(m_hWnd != NULL);
  2728.  
  2729.         WNDPROC pOurProc = (WNDPROC)&(m_thunk.thunk);
  2730.         WNDPROC pActiveProc = (WNDPROC)::GetWindowLong(m_hWnd, GWL_WNDPROC);
  2731.  
  2732.         HWND hWnd = NULL;
  2733.         if (bForce || pOurProc == pActiveProc)
  2734.         {
  2735.             if(!::SetWindowLong(m_hWnd, GWL_WNDPROC, (LONG)m_pfnSuperWindowProc))
  2736.                 return NULL;
  2737.  
  2738.             m_pfnSuperWindowProc = ::DefWindowProc;
  2739.             hWnd = m_hWnd;
  2740.             m_hWnd = NULL;
  2741.         }
  2742.         return hWnd;
  2743.     }
  2744. };
  2745.  
  2746. typedef CContainedWindowT<CWindow>    CContainedWindow;
  2747.  
  2748. /////////////////////////////////////////////////////////////////////////////
  2749. // _DialogSizeHelper - helpers for calculating the size of a dialog template
  2750.  
  2751. class _DialogSizeHelper
  2752. {
  2753. public:
  2754. //local struct used for implementation
  2755. #pragma pack(push, 1)
  2756.     struct _ATL_DLGTEMPLATEEX
  2757.     {
  2758.         WORD dlgVer;
  2759.         WORD signature;
  2760.         DWORD helpID;
  2761.         DWORD exStyle;
  2762.         DWORD style;
  2763.         WORD cDlgItems;
  2764.         short x;
  2765.         short y;
  2766.         short cx;
  2767.         short cy;
  2768.     };
  2769. #pragma pack(pop)
  2770.  
  2771.     static void GetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize)
  2772.     {
  2773.         // If the dialog has a font we use it otherwise we default
  2774.         // to the system font.
  2775.         if (HasFont(pTemplate))
  2776.         {
  2777.             TCHAR szFace[LF_FACESIZE];
  2778.             WORD  wFontSize = 0;
  2779.             GetFont(pTemplate, szFace, &wFontSize);
  2780.             GetSizeInDialogUnits(pTemplate, pSize);
  2781.             ConvertDialogUnitsToPixels(szFace, wFontSize, pSize);
  2782.         }
  2783.         else
  2784.         {
  2785.             GetSizeInDialogUnits(pTemplate, pSize);
  2786.             LONG nDlgBaseUnits = GetDialogBaseUnits();
  2787.             pSize->cx = MulDiv(pSize->cx, LOWORD(nDlgBaseUnits), 4);
  2788.             pSize->cy = MulDiv(pSize->cy, HIWORD(nDlgBaseUnits), 8);
  2789.         }
  2790.     }
  2791.  
  2792.     static void ConvertDialogUnitsToPixels(LPCTSTR pszFontFace, WORD wFontSize, SIZE* pSizePixel)
  2793.     {
  2794.         // Attempt to create the font to be used in the dialog box
  2795.         UINT cxSysChar, cySysChar;
  2796.         LOGFONT lf;
  2797.         HDC hDC = ::GetDC(NULL);
  2798.         int cxDlg = pSizePixel->cx;
  2799.         int cyDlg = pSizePixel->cy;
  2800.  
  2801.         ZeroMemory(&lf, sizeof(LOGFONT));
  2802.         lf.lfHeight = -MulDiv(wFontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
  2803.         lf.lfWeight = FW_NORMAL;
  2804.         lf.lfCharSet = DEFAULT_CHARSET;
  2805.         lstrcpy(lf.lfFaceName, pszFontFace);
  2806.  
  2807.         HFONT hNewFont = CreateFontIndirect(&lf);
  2808.         if (hNewFont != NULL)
  2809.         {
  2810.             TEXTMETRIC  tm;
  2811.             SIZE        size;
  2812.             HFONT       hFontOld = (HFONT)SelectObject(hDC, hNewFont);
  2813.             GetTextMetrics(hDC, &tm);
  2814.             cySysChar = tm.tmHeight + tm.tmExternalLeading;
  2815.             ::GetTextExtentPoint(hDC,
  2816.                 _T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52,
  2817.                 &size);
  2818.             cxSysChar = (size.cx + 26) / 52;
  2819.             SelectObject(hDC, hFontOld);
  2820.             DeleteObject(hNewFont);
  2821.         }
  2822.         else
  2823.         {
  2824.             // Could not create the font so just use the system's values
  2825.             cxSysChar = LOWORD(GetDialogBaseUnits());
  2826.             cySysChar = HIWORD(GetDialogBaseUnits());
  2827.         }
  2828.         ::ReleaseDC(NULL, hDC);
  2829.  
  2830.         // Translate dialog units to pixels
  2831.         pSizePixel->cx = MulDiv(cxDlg, cxSysChar, 4);
  2832.         pSizePixel->cy = MulDiv(cyDlg, cySysChar, 8);
  2833.     }
  2834.  
  2835.     static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate)
  2836.     {
  2837.         return ((_ATL_DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF;
  2838.     }
  2839.  
  2840.     static BOOL HasFont(const DLGTEMPLATE* pTemplate)
  2841.     {
  2842.         return (DS_SETFONT &
  2843.             (IsDialogEx(pTemplate) ?
  2844.                 ((_ATL_DLGTEMPLATEEX*)pTemplate)->style : pTemplate->style));
  2845.     }
  2846.  
  2847.     static BYTE* GetFontSizeField(const DLGTEMPLATE* pTemplate)
  2848.     {
  2849.         BOOL bDialogEx = IsDialogEx(pTemplate);
  2850.         WORD* pw;
  2851.  
  2852.         if (bDialogEx)
  2853.             pw = (WORD*)((_ATL_DLGTEMPLATEEX*)pTemplate + 1);
  2854.         else
  2855.             pw = (WORD*)(pTemplate + 1);
  2856.  
  2857.         if (*pw == (WORD)-1)        // Skip menu name string or ordinal
  2858.             pw += 2; // WORDs
  2859.         else
  2860.             while(*pw++);
  2861.  
  2862.         if (*pw == (WORD)-1)        // Skip class name string or ordinal
  2863.             pw += 2; // WORDs
  2864.         else
  2865.             while(*pw++);
  2866.  
  2867.         while (*pw++);          // Skip caption string
  2868.  
  2869.         return (BYTE*)pw;
  2870.     }
  2871.  
  2872.     static BOOL GetFont(const DLGTEMPLATE* pTemplate, TCHAR* pszFace, WORD* pFontSize)
  2873.     {
  2874.         USES_CONVERSION;
  2875.         if (!HasFont(pTemplate))
  2876.             return FALSE;
  2877.  
  2878.         BYTE* pb = GetFontSizeField(pTemplate);
  2879.         *pFontSize = *(WORD*)pb;
  2880.         // Skip over font attributes to get to the font name
  2881.         pb += sizeof(WORD) * (IsDialogEx(pTemplate) ? 3 : 1);
  2882.  
  2883.         _tcscpy(pszFace, W2T((WCHAR*)pb));
  2884.         return TRUE;
  2885.     }
  2886.  
  2887.     static void GetSizeInDialogUnits(const DLGTEMPLATE* pTemplate, SIZE* pSize)
  2888.     {
  2889.         if (IsDialogEx(pTemplate))
  2890.         {
  2891.             pSize->cx = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cx;
  2892.             pSize->cy = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cy;
  2893.         }
  2894.         else
  2895.         {
  2896.             pSize->cx = pTemplate->cx;
  2897.             pSize->cy = pTemplate->cy;
  2898.         }
  2899.     }
  2900. };
  2901.  
  2902. inline void AtlGetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize)
  2903. {
  2904.     _DialogSizeHelper::GetDialogSize(pTemplate, pSize);
  2905. }
  2906.  
  2907. }; //namespace ATL
  2908.  
  2909. #ifndef _ATL_DLL_IMPL
  2910. #ifndef _ATL_DLL
  2911. #define _ATLWIN_IMPL
  2912. #endif
  2913. #endif
  2914.  
  2915. #endif // __ATLWIN_H__
  2916.  
  2917. //All exports go here
  2918. #ifdef _ATLWIN_IMPL
  2919.  
  2920. #ifndef _ATL_DLL_IMPL
  2921. namespace ATL
  2922. {
  2923. #endif
  2924.  
  2925. ATLINLINE ATLAPI_(ATOM) AtlModuleRegisterWndClassInfoA(_ATL_MODULE* pM, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc)
  2926. {
  2927.     if (p->m_atom == 0)
  2928.     {
  2929.         ::EnterCriticalSection(&pM->m_csWindowCreate);
  2930.         if(p->m_atom == 0)
  2931.         {
  2932.             HINSTANCE hInst = pM->m_hInst;
  2933.             if (p->m_lpszOrigName != NULL)
  2934.             {
  2935.                 ATLASSERT(pProc != NULL);
  2936.                 LPCSTR lpsz = p->m_wc.lpszClassName;
  2937.                 WNDPROC proc = p->m_wc.lpfnWndProc;
  2938.  
  2939.                 WNDCLASSEXA wc;
  2940.                 wc.cbSize = sizeof(WNDCLASSEX);
  2941.                 // Try global class
  2942.                 if(!::GetClassInfoExA(NULL, p->m_lpszOrigName, &wc))
  2943.                 {
  2944.                     // try process local
  2945.                     if(!::GetClassInfoExA(_Module.GetModuleInstance(), p->m_lpszOrigName, &wc))
  2946.                     {
  2947.                         ::LeaveCriticalSection(&pM->m_csWindowCreate);
  2948.                         return 0;
  2949.                     }
  2950.                 }
  2951.                 memcpy(&p->m_wc, &wc, sizeof(WNDCLASSEX));
  2952.                 p->pWndProc = p->m_wc.lpfnWndProc;
  2953.                 p->m_wc.lpszClassName = lpsz;
  2954.                 p->m_wc.lpfnWndProc = proc;
  2955.             }
  2956.             else
  2957.             {
  2958.                 p->m_wc.hCursor = ::LoadCursorA(p->m_bSystemCursor ? NULL : hInst,
  2959.                     p->m_lpszCursorID);
  2960.             }
  2961.  
  2962.             p->m_wc.hInstance = hInst;
  2963.             p->m_wc.style &= ~CS_GLOBALCLASS;    // we don't register global classes
  2964.             if (p->m_wc.lpszClassName == NULL)
  2965.             {
  2966.                 wsprintfA(p->m_szAutoName, "ATL:%8.8X", (DWORD)&p->m_wc);
  2967.                 p->m_wc.lpszClassName = p->m_szAutoName;
  2968.             }
  2969.             WNDCLASSEXA wcTemp;
  2970.             memcpy(&wcTemp, &p->m_wc, sizeof(WNDCLASSEXW));
  2971.             p->m_atom = (ATOM)::GetClassInfoExA(p->m_wc.hInstance, p->m_wc.lpszClassName, &wcTemp);
  2972.             if (p->m_atom == 0)
  2973.                 p->m_atom = ::RegisterClassExA(&p->m_wc);
  2974.         }
  2975.         ::LeaveCriticalSection(&pM->m_csWindowCreate);
  2976.     }
  2977.  
  2978.     if (p->m_lpszOrigName != NULL)
  2979.     {
  2980.         ATLASSERT(pProc != NULL);
  2981.         ATLASSERT(p->pWndProc != NULL);
  2982.         *pProc = p->pWndProc;
  2983.     }
  2984.     return p->m_atom;
  2985. }
  2986.  
  2987. ATLINLINE ATLAPI_(ATOM) AtlModuleRegisterWndClassInfoW(_ATL_MODULE* pM, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc)
  2988. {
  2989.     if (p->m_atom == 0)
  2990.     {
  2991.         ::EnterCriticalSection(&pM->m_csWindowCreate);
  2992.         if(p->m_atom == 0)
  2993.         {
  2994.             HINSTANCE hInst = pM->m_hInst;
  2995.             if (p->m_lpszOrigName != NULL)
  2996.             {
  2997.                 ATLASSERT(pProc != NULL);
  2998.                 LPCWSTR lpsz = p->m_wc.lpszClassName;
  2999.                 WNDPROC proc = p->m_wc.lpfnWndProc;
  3000.  
  3001.                 WNDCLASSEXW wc;
  3002.                 wc.cbSize = sizeof(WNDCLASSEX);
  3003.                 // Try global class
  3004.                 if(!::GetClassInfoExW(NULL, p->m_lpszOrigName, &wc))
  3005.                 {
  3006.                     // try process local
  3007.                     if(!::GetClassInfoExW(_Module.GetModuleInstance(), p->m_lpszOrigName, &wc))
  3008.                     {
  3009.                         ::LeaveCriticalSection(&pM->m_csWindowCreate);
  3010.                         return 0;
  3011.                     }
  3012.                 }
  3013.                 memcpy(&p->m_wc, &wc, sizeof(WNDCLASSEX));
  3014.                 p->pWndProc = p->m_wc.lpfnWndProc;
  3015.                 p->m_wc.lpszClassName = lpsz;
  3016.                 p->m_wc.lpfnWndProc = proc;
  3017.             }
  3018.             else
  3019.             {
  3020.                 p->m_wc.hCursor = ::LoadCursorW(p->m_bSystemCursor ? NULL : hInst,
  3021.                     p->m_lpszCursorID);
  3022.             }
  3023.  
  3024.             p->m_wc.hInstance = hInst;
  3025.             p->m_wc.style &= ~CS_GLOBALCLASS;    // we don't register global classes
  3026.             if (p->m_wc.lpszClassName == NULL)
  3027.             {
  3028.                 wsprintfW(p->m_szAutoName, L"ATL:%8.8X", (DWORD)&p->m_wc);
  3029.                 p->m_wc.lpszClassName = p->m_szAutoName;
  3030.             }
  3031.             WNDCLASSEXW wcTemp;
  3032.             memcpy(&wcTemp, &p->m_wc, sizeof(WNDCLASSEXW));
  3033.             p->m_atom = (ATOM)::GetClassInfoExW(p->m_wc.hInstance, p->m_wc.lpszClassName, &wcTemp);
  3034.             if (p->m_atom == 0)
  3035.                 p->m_atom = ::RegisterClassExW(&p->m_wc);
  3036.         }
  3037.         ::LeaveCriticalSection(&pM->m_csWindowCreate);
  3038.     }
  3039.  
  3040.     if (p->m_lpszOrigName != NULL)
  3041.     {
  3042.         ATLASSERT(pProc != NULL);
  3043.         ATLASSERT(p->pWndProc != NULL);
  3044.         *pProc = p->pWndProc;
  3045.     }
  3046.     return p->m_atom;
  3047. }
  3048.  
  3049. ATLINLINE ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd)
  3050. {
  3051.     USES_CONVERSION;
  3052.  
  3053.     // cases  hdc, ptd, hdc is metafile, hic
  3054. //  NULL,    NULL,  n/a,    Display
  3055. //  NULL,   !NULL,  n/a,    ptd
  3056. //  !NULL,   NULL,  FALSE,  hdc
  3057. //  !NULL,   NULL,  TRUE,   display
  3058. //  !NULL,  !NULL,  FALSE,  ptd
  3059. //  !NULL,  !NULL,  TRUE,   ptd
  3060.  
  3061.     if (ptd != NULL)
  3062.     {
  3063.         LPDEVMODEOLE lpDevMode;
  3064.         LPOLESTR lpszDriverName;
  3065.         LPOLESTR lpszDeviceName;
  3066.         LPOLESTR lpszPortName;
  3067.  
  3068.         if (ptd->tdExtDevmodeOffset == 0)
  3069.             lpDevMode = NULL;
  3070.         else
  3071.             lpDevMode  = (LPDEVMODEOLE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
  3072.  
  3073.         lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
  3074.         lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
  3075.         lpszPortName   = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
  3076.  
  3077.         return ::CreateDC(OLE2CT(lpszDriverName), OLE2CT(lpszDeviceName),
  3078.             OLE2CT(lpszPortName), DEVMODEOLE2T(lpDevMode));
  3079.     }
  3080.     else if (hdc == NULL || GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE)
  3081.         return ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  3082.     else
  3083.         return hdc;
  3084. }
  3085.  
  3086. ATLINLINE ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix)
  3087. {
  3088.     int nPixelsPerInchX;    // Pixels per logical inch along width
  3089.     int nPixelsPerInchY;    // Pixels per logical inch along height
  3090.  
  3091.     HDC hDCScreen = GetDC(NULL);
  3092.     ATLASSERT(hDCScreen != NULL);
  3093.     nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  3094.     nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  3095.     ReleaseDC(NULL, hDCScreen);
  3096.  
  3097.     lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, nPixelsPerInchX);
  3098.     lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, nPixelsPerInchY);
  3099. }
  3100.  
  3101. ATLINLINE ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric)
  3102. {
  3103.     int nPixelsPerInchX;    // Pixels per logical inch along width
  3104.     int nPixelsPerInchY;    // Pixels per logical inch along height
  3105.  
  3106.     HDC hDCScreen = GetDC(NULL);
  3107.     ATLASSERT(hDCScreen != NULL);
  3108.     nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  3109.     nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  3110.     ReleaseDC(NULL, hDCScreen);
  3111.  
  3112.     lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, nPixelsPerInchX);
  3113.     lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, nPixelsPerInchY);
  3114. }
  3115.  
  3116.  
  3117. #ifndef _ATL_DLL_IMPL
  3118. }; //namespace ATL
  3119. #endif
  3120.  
  3121. //Prevent pulling in second time 
  3122. #undef _ATLWIN_IMPL
  3123.  
  3124. #endif // _ATLWIN_IMPL
  3125.