Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

893 lines
27 KiB

  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. #ifndef __ATLWIN21_H__
  11. #define __ATLWIN21_H__
  12. #ifndef __cplusplus
  13. #error ATL requires C++ compilation (use a .cpp suffix)
  14. #endif
  15. #ifdef __ATLWIN_H__
  16. #error atlwin21.h should be included instead of atlwin.h
  17. #endif
  18. #if (_ATL_VER < 0x0200) && (_ATL_VER >= 0x0300)
  19. #error atlwin21.h should be used only with ATL 2.0/2.1
  20. #endif //(_ATL_VER < 0x0200) && (_ATL_VER >= 0x0300)
  21. // Redefine class names and include old atlwin.h
  22. #define CWindow CWindowOld
  23. #define _WndProcThunk _WndProcThunkOld
  24. #define _FuncDesc _FuncDescOld
  25. #define CWndProcThunk CWndProcThunkOld
  26. #define _stdcallthunk _stdcallthunkOld
  27. #define CDynamicStdCallThunk CDynamicStdCallThunkOld
  28. #define CStdCallThunk CStdCallThunkOld
  29. #define CWindowImplBase CWindowImplBaseOld
  30. #define CWindowImpl CWindowImplOld
  31. #define CDialogImplBase CDialogImplBaseOld
  32. #define CDialogImpl CDialogImplOld
  33. #include <atlwin.h>
  34. #undef CWindow
  35. #undef _FuncDesc
  36. #undef _WndProcThunk
  37. #undef CWndProcThunk
  38. #undef _stdcallthunk
  39. #undef CDynamicStdCallThunk
  40. #undef CStdCallThunk
  41. #undef CWindowImplBase
  42. #undef CWindowImpl
  43. #undef CDialogImplBase
  44. #undef CDialogImpl
  45. #ifndef ATLASSERT
  46. #define ATLASSERT(expr) _ASSERTE(expr)
  47. #endif
  48. #ifndef ATLTRACE2
  49. #define ATLTRACE2(cat, lev, msg) ATLTRACE(msg)
  50. #endif
  51. namespace ATL
  52. {
  53. #pragma pack(push, _ATL_PACKING)
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CWindow - client side for a Windows window
  56. class CWindow : public CWindowOld
  57. {
  58. public:
  59. static RECT rcDefault;
  60. // Construction and creation
  61. CWindow(HWND hWnd = NULL)
  62. {
  63. m_hWnd = hWnd;
  64. }
  65. CWindow& operator=(HWND hWnd)
  66. {
  67. m_hWnd = hWnd;
  68. return *this;
  69. }
  70. HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
  71. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  72. UINT nID = 0, LPVOID lpCreateParam = NULL)
  73. {
  74. m_hWnd = ::CreateWindowEx(dwExStyle, lpstrWndClass, szWindowName,
  75. dwStyle, rcPos.left, rcPos.top, rcPos.right - rcPos.left,
  76. rcPos.bottom - rcPos.top, hWndParent, (HMENU)(UINT_PTR)nID,
  77. _Module.GetModuleInstance(), lpCreateParam);
  78. return m_hWnd;
  79. }
  80. HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, LPRECT lpRect = NULL, LPCTSTR szWindowName = NULL,
  81. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  82. HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
  83. {
  84. if(lpRect == NULL)
  85. lpRect = &rcDefault;
  86. m_hWnd = ::CreateWindowEx(dwExStyle, lpstrWndClass, szWindowName,
  87. dwStyle, lpRect->left, lpRect->top, lpRect->right - lpRect->left,
  88. lpRect->bottom - lpRect->top, hWndParent, hMenu,
  89. _Module.GetModuleInstance(), lpCreateParam);
  90. return m_hWnd;
  91. }
  92. // Attributes
  93. operator HWND() const { return m_hWnd; }
  94. static LPCTSTR GetWndClassName()
  95. {
  96. return NULL;
  97. }
  98. // Operations
  99. // support for C style macros
  100. static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  101. {
  102. ATLASSERT(::IsWindow(hWnd));
  103. return ::SendMessage(hWnd, message, wParam, lParam);
  104. }
  105. // this one is here just so it's not hidden
  106. LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0)
  107. {
  108. ATLASSERT(::IsWindow(m_hWnd));
  109. return ::SendMessage(m_hWnd, message, wParam, lParam);
  110. }
  111. BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo)
  112. {
  113. ATLASSERT(::IsWindow(m_hWnd));
  114. return ::GetScrollInfo(m_hWnd, nBar, lpScrollInfo);
  115. }
  116. BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE)
  117. {
  118. ATLASSERT(::IsWindow(m_hWnd));
  119. return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw);
  120. }
  121. BOOL IsDialogMessage(LPMSG lpMsg)
  122. {
  123. ATLASSERT(::IsWindow(m_hWnd));
  124. return ::IsDialogMessage(m_hWnd, lpMsg);
  125. }
  126. void NextDlgCtrl() const
  127. {
  128. ATLASSERT(::IsWindow(m_hWnd));
  129. ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0L);
  130. }
  131. void PrevDlgCtrl() const
  132. {
  133. ATLASSERT(::IsWindow(m_hWnd));
  134. ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 1, 0L);
  135. }
  136. void GotoDlgCtrl(HWND hWndCtrl) const
  137. {
  138. ATLASSERT(::IsWindow(m_hWnd));
  139. ::SendMessage(m_hWnd, WM_NEXTDLGCTL, (WPARAM)hWndCtrl, 1L);
  140. }
  141. BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw = TRUE)
  142. {
  143. ATLASSERT(::IsWindow(m_hWnd));
  144. RECT rcWnd;
  145. if(!GetClientRect(&rcWnd))
  146. return FALSE;
  147. if(nWidth != -1)
  148. rcWnd.right = nWidth;
  149. if(nHeight != -1)
  150. rcWnd.bottom = nHeight;
  151. if(!::AdjustWindowRectEx(&rcWnd, GetStyle(), (!(GetStyle() & WS_CHILD) && (GetMenu() != NULL)), GetExStyle()))
  152. return FALSE;
  153. UINT uFlags = SWP_NOZORDER | SWP_NOMOVE;
  154. if(!bRedraw)
  155. uFlags |= SWP_NOREDRAW;
  156. return SetWindowPos(NULL, 0, 0, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, uFlags);
  157. }
  158. #ifndef UNDER_CE
  159. int GetWindowRgn(HRGN hRgn)
  160. {
  161. ATLASSERT(::IsWindow(m_hWnd));
  162. return ::GetWindowRgn(m_hWnd, hRgn);
  163. }
  164. int SetWindowRgn(HRGN hRgn, BOOL bRedraw = FALSE)
  165. {
  166. ATLASSERT(::IsWindow(m_hWnd));
  167. return ::SetWindowRgn(m_hWnd, hRgn, bRedraw);
  168. }
  169. HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags)
  170. {
  171. ATLASSERT(::IsWindow(m_hWnd));
  172. return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
  173. }
  174. #endif //!UNDER_CE
  175. DWORD GetWindowThreadID()
  176. {
  177. ATLASSERT(::IsWindow(m_hWnd));
  178. return ::GetWindowThreadProcessId(m_hWnd, NULL);
  179. }
  180. DWORD GetWindowProcessID()
  181. {
  182. ATLASSERT(::IsWindow(m_hWnd));
  183. DWORD dwProcessID;
  184. ::GetWindowThreadProcessId(m_hWnd, &dwProcessID);
  185. return dwProcessID;
  186. }
  187. BOOL IsWindow()
  188. {
  189. return ::IsWindow(m_hWnd);
  190. }
  191. #ifndef UNDER_CE
  192. BOOL IsWindowUnicode()
  193. {
  194. ATLASSERT(::IsWindow(m_hWnd));
  195. return ::IsWindowUnicode(m_hWnd);
  196. }
  197. BOOL ShowWindowAsync(int nCmdShow)
  198. {
  199. ATLASSERT(::IsWindow(m_hWnd));
  200. return ::ShowWindowAsync(m_hWnd, nCmdShow);
  201. }
  202. #endif //!UNDER_CE
  203. };
  204. _declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
  205. /////////////////////////////////////////////////////////////////////////////
  206. // Thunks for __stdcall member functions
  207. #if defined(_M_IX86)
  208. #pragma pack(push,1)
  209. struct _stdcallthunk
  210. {
  211. DWORD m_mov; // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
  212. DWORD m_this; //
  213. BYTE m_jmp; // jmp WndProc
  214. DWORD m_relproc; // relative jmp
  215. void Init(DWORD_PTR proc, void* pThis)
  216. {
  217. m_mov = 0x042444C7; //C7 44 24 0C
  218. m_this = PtrToUlong(pThis);
  219. m_jmp = 0xe9;
  220. m_relproc = DWORD((INT_PTR)proc - ((INT_PTR)this+sizeof(_stdcallthunk)));
  221. // write block from data cache and
  222. // flush from instruction cache
  223. FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
  224. }
  225. };
  226. #pragma pack(pop)
  227. #elif defined (_M_AMD64)
  228. #pragma pack(push,2)
  229. struct _stdcallthunk
  230. {
  231. USHORT RcxMov; // mov rcx, pThis
  232. ULONG64 RcxImm; //
  233. USHORT RaxMov; // mov rax, target
  234. ULONG64 RaxImm; //
  235. USHORT RaxJmp; // jmp target
  236. void Init(DWORD_PTR proc, void *pThis)
  237. {
  238. RcxMov = 0xb948; // mov rcx, pThis
  239. RcxImm = (ULONG64)pThis; //
  240. RaxMov = 0xb848; // mov rax, target
  241. RaxImm = (ULONG64)proc; //
  242. RaxJmp = 0xe0ff; // jmp rax
  243. FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk));
  244. }
  245. };
  246. #pragma pack(pop)
  247. #elif defined(_M_IA64)
  248. #pragma pack(push,8)
  249. extern "C" LRESULT CALLBACK _WndProcThunkProc( HWND, UINT, WPARAM, LPARAM );
  250. struct _FuncDesc
  251. {
  252. void* pfn;
  253. void* gp;
  254. };
  255. struct _stdcallthunk
  256. {
  257. _FuncDesc m_funcdesc;
  258. void* m_pFunc;
  259. void* m_pThis;
  260. void Init(DWORD_PTR proc, void* pThis)
  261. {
  262. const _FuncDesc* pThunkProc;
  263. pThunkProc = reinterpret_cast< const _FuncDesc* >( _WndProcThunkProc );
  264. m_funcdesc.pfn = pThunkProc->pfn;
  265. m_funcdesc.gp = &m_pFunc;
  266. m_pFunc = reinterpret_cast< void* >( proc );
  267. m_pThis = pThis;
  268. ::FlushInstructionCache( GetCurrentProcess(), this, sizeof( _stdcallthunk ) );
  269. }
  270. };
  271. #pragma pack(pop)
  272. #else
  273. #error Only AMD64, IA64, and X86 supported
  274. #endif
  275. class CDynamicStdCallThunk
  276. {
  277. public:
  278. _stdcallthunk *pThunk;
  279. CDynamicStdCallThunk()
  280. {
  281. pThunk = NULL;
  282. }
  283. ~CDynamicStdCallThunk()
  284. {
  285. if (pThunk)
  286. HeapFree(GetProcessHeap(), 0, pThunk);
  287. }
  288. void Init(DWORD_PTR proc, void *pThis)
  289. {
  290. if (!pThunk) {
  291. pThunk = static_cast<_stdcallthunk *>(HeapAlloc(GetProcessHeap(),
  292. HEAP_GENERATE_EXCEPTIONS, sizeof(_stdcallthunk)));
  293. }
  294. ATLASSERT(pThunk);
  295. pThunk->Init(proc, pThis);
  296. }
  297. };
  298. typedef CDynamicStdCallThunk CStdCallThunk;
  299. /////////////////////////////////////////////////////////////////////////////
  300. // WindowProc thunks
  301. class CWndProcThunk
  302. {
  303. public:
  304. _AtlCreateWndData cd;
  305. CStdCallThunk thunk;
  306. void Init(WNDPROC proc, void* pThis)
  307. {
  308. thunk.Init((DWORD_PTR)proc, pThis);
  309. }
  310. };
  311. /////////////////////////////////////////////////////////////////////////////
  312. // New message map macros
  313. // Empty message map macro
  314. #define DECLARE_EMPTY_MSG_MAP() \
  315. public: \
  316. BOOL ProcessWindowMessage(HWND, UINT, WPARAM, LPARAM, LRESULT&, DWORD) \
  317. { \
  318. return FALSE; \
  319. }
  320. // Message reflection macros
  321. #define REFLECT_NOTIFICATIONS() \
  322. { \
  323. bHandled = TRUE; \
  324. lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
  325. if(bHandled) \
  326. return TRUE; \
  327. }
  328. #define DEFAULT_REFLECTION_HANDLER() \
  329. if(DefaultReflectionHandler(hWnd, uMsg, wParam, lParam, lResult)) \
  330. return TRUE;
  331. /////////////////////////////////////////////////////////////////////////////
  332. // CWinTraits - Defines various default values for a window
  333. template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
  334. class CWinTraits
  335. {
  336. public:
  337. static DWORD GetWndStyle(DWORD dwStyle)
  338. {
  339. return dwStyle == 0 ? t_dwStyle : dwStyle;
  340. }
  341. static DWORD GetWndExStyle(DWORD dwExStyle)
  342. {
  343. return dwExStyle == 0 ? t_dwExStyle : dwExStyle;
  344. }
  345. };
  346. typedef CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0> CControlWinTraits;
  347. #ifndef UNDER_CE
  348. typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> CFrameWinTraits;
  349. #else
  350. typedef CWinTraits<WS_OVERLAPPED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_BORDER, WS_EX_WINDOWEDGE> CFrameWinTraits;
  351. #endif //!UNDER_CE
  352. typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD> CMDIChildWinTraits;
  353. typedef CWinTraits<0, 0> CNullTraits;
  354. template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0, class TWinTraits = CControlWinTraits>
  355. class CWinTraitsOR
  356. {
  357. public:
  358. static DWORD GetWndStyle(DWORD dwStyle)
  359. {
  360. return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle);
  361. }
  362. static DWORD GetWndExStyle(DWORD dwExStyle)
  363. {
  364. return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle);
  365. }
  366. };
  367. /////////////////////////////////////////////////////////////////////////////
  368. // CWindowImpl - Implements a window
  369. template <class TBase = CWindow>
  370. class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap
  371. {
  372. public:
  373. CWndProcThunk m_thunk;
  374. // Destructor
  375. ~CWindowImplRoot()
  376. {
  377. ATLASSERT(m_hWnd == NULL); // should be cleared in WindowProc
  378. }
  379. // Message reflection support
  380. LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  381. static BOOL DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult);
  382. };
  383. template <class TBase>
  384. LRESULT CWindowImplRoot< TBase >::ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  385. {
  386. HWND hWndChild = NULL;
  387. switch(uMsg)
  388. {
  389. case WM_COMMAND:
  390. if(lParam != NULL) // not from a menu
  391. hWndChild = (HWND)lParam;
  392. break;
  393. case WM_NOTIFY:
  394. hWndChild = ((LPNMHDR)lParam)->hwndFrom;
  395. break;
  396. #ifndef UNDER_CE
  397. case WM_PARENTNOTIFY:
  398. switch(LOWORD(wParam))
  399. {
  400. case WM_CREATE:
  401. case WM_DESTROY:
  402. hWndChild = (HWND)lParam;
  403. break;
  404. default:
  405. hWndChild = GetDlgItem(HIWORD(wParam));
  406. break;
  407. }
  408. break;
  409. #endif //!UNDER_CE
  410. case WM_DRAWITEM:
  411. if(wParam) // not from a menu
  412. hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
  413. break;
  414. case WM_MEASUREITEM:
  415. if(wParam) // not from a menu
  416. hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID);
  417. break;
  418. case WM_COMPAREITEM:
  419. if(wParam) // not from a menu
  420. hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID);
  421. break;
  422. case WM_DELETEITEM:
  423. if(wParam) // not from a menu
  424. hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID);
  425. break;
  426. case WM_VKEYTOITEM:
  427. case WM_CHARTOITEM:
  428. case WM_HSCROLL:
  429. case WM_VSCROLL:
  430. hWndChild = (HWND)lParam;
  431. break;
  432. case WM_CTLCOLORBTN:
  433. case WM_CTLCOLORDLG:
  434. case WM_CTLCOLOREDIT:
  435. case WM_CTLCOLORLISTBOX:
  436. case WM_CTLCOLORMSGBOX:
  437. case WM_CTLCOLORSCROLLBAR:
  438. case WM_CTLCOLORSTATIC:
  439. hWndChild = (HWND)lParam;
  440. break;
  441. default:
  442. break;
  443. }
  444. if(hWndChild == NULL)
  445. {
  446. bHandled = FALSE;
  447. return 1;
  448. }
  449. ATLASSERT(::IsWindow(hWndChild));
  450. return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
  451. }
  452. template <class TBase>
  453. BOOL CWindowImplRoot< TBase >::DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  454. {
  455. switch(uMsg)
  456. {
  457. case OCM_COMMAND:
  458. case OCM_NOTIFY:
  459. #ifndef UNDER_CE
  460. case OCM_PARENTNOTIFY:
  461. #endif //!UNDER_CE
  462. case OCM_DRAWITEM:
  463. case OCM_MEASUREITEM:
  464. case OCM_COMPAREITEM:
  465. case OCM_DELETEITEM:
  466. case OCM_VKEYTOITEM:
  467. case OCM_CHARTOITEM:
  468. case OCM_HSCROLL:
  469. case OCM_VSCROLL:
  470. case OCM_CTLCOLORBTN:
  471. case OCM_CTLCOLORDLG:
  472. case OCM_CTLCOLOREDIT:
  473. case OCM_CTLCOLORLISTBOX:
  474. case OCM_CTLCOLORMSGBOX:
  475. case OCM_CTLCOLORSCROLLBAR:
  476. case OCM_CTLCOLORSTATIC:
  477. lResult = ::DefWindowProc(hWnd, uMsg - OCM__BASE, wParam, lParam);
  478. return TRUE;
  479. default:
  480. break;
  481. }
  482. return FALSE;
  483. }
  484. template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
  485. class ATL_NO_VTABLE CWindowImplBaseT : public CWindowImplRoot< TBase >
  486. {
  487. public:
  488. WNDPROC m_pfnSuperWindowProc;
  489. CWindowImplBaseT() : m_pfnSuperWindowProc(::DefWindowProc)
  490. {}
  491. static DWORD GetWndStyle(DWORD dwStyle)
  492. {
  493. return TWinTraits::GetWndStyle(dwStyle);
  494. }
  495. static DWORD GetWndExStyle(DWORD dwExStyle)
  496. {
  497. return TWinTraits::GetWndExStyle(dwExStyle);
  498. }
  499. virtual WNDPROC GetWindowProc()
  500. {
  501. return WindowProc;
  502. }
  503. static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  504. static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  505. HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName,
  506. DWORD dwStyle, DWORD dwExStyle, UINT nID, ATOM atom, LPVOID lpCreateParam = NULL);
  507. BOOL DestroyWindow()
  508. {
  509. ATLASSERT(::IsWindow(m_hWnd));
  510. return ::DestroyWindow(m_hWnd);
  511. }
  512. BOOL SubclassWindow(HWND hWnd);
  513. HWND UnsubclassWindow(BOOL bForce = FALSE);
  514. LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  515. {
  516. #ifdef STRICT
  517. return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
  518. #else
  519. return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
  520. #endif
  521. }
  522. virtual void OnFinalMessage(HWND /*hWnd*/)
  523. {
  524. // override to do something, if needed
  525. }
  526. };
  527. typedef CWindowImplBaseT<CWindow> CWindowImplBase;
  528. template <class TBase, class TWinTraits>
  529. LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  530. {
  531. CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)_Module.ExtractCreateWndData();
  532. ATLASSERT(pThis != NULL);
  533. pThis->m_hWnd = hWnd;
  534. pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);
  535. WNDPROC pProc = (WNDPROC)(pThis->m_thunk.thunk.pThunk);
  536. WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  537. #ifdef _DEBUG
  538. // check if somebody has subclassed us already since we discard it
  539. if(pOldProc != StartWindowProc)
  540. ATLTRACE(_T("ATL: Subclassing through a hook discarded.\n"));
  541. #else
  542. pOldProc; // avoid unused warning
  543. #endif
  544. return pProc(hWnd, uMsg, wParam, lParam);
  545. }
  546. template <class TBase, class TWinTraits>
  547. LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  548. {
  549. CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)hWnd;
  550. LRESULT lRes;
  551. if(pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0) == FALSE)
  552. {
  553. #ifndef UNDER_CE
  554. if(uMsg != WM_NCDESTROY)
  555. #else // CE specific
  556. if(uMsg != WM_DESTROY)
  557. #endif //!UNDER_CE
  558. lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  559. else
  560. {
  561. // unsubclass, if needed
  562. LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
  563. lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  564. if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
  565. ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
  566. // clear out window handle
  567. HWND hWnd = pThis->m_hWnd;
  568. pThis->m_hWnd = NULL;
  569. // clean up after window is destroyed
  570. pThis->OnFinalMessage(hWnd);
  571. }
  572. }
  573. return lRes;
  574. }
  575. template <class TBase, class TWinTraits>
  576. HWND CWindowImplBaseT< TBase, TWinTraits >::Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName,
  577. DWORD dwStyle, DWORD dwExStyle, UINT nID, ATOM atom, LPVOID lpCreateParam)
  578. {
  579. static LONG s_nNextChildID = 1;
  580. ATLASSERT(m_hWnd == NULL);
  581. if(atom == 0)
  582. return NULL;
  583. _Module.AddCreateWndData(&m_thunk.cd, this);
  584. if(nID == 0 && (dwStyle & WS_CHILD))
  585. {
  586. #ifdef _WIN64
  587. nID = InterlockedIncrement( &s_nNextChildID );
  588. nID |= 0x80000000;
  589. #else
  590. nID = (UINT)this;
  591. #endif
  592. }
  593. HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)MAKELONG(atom, 0), szWindowName,
  594. dwStyle, rcPos.left, rcPos.top, rcPos.right - rcPos.left,
  595. rcPos.bottom - rcPos.top, hWndParent, (HMENU)nID,
  596. _Module.GetModuleInstance(), lpCreateParam);
  597. ATLASSERT(m_hWnd == hWnd);
  598. return hWnd;
  599. }
  600. template <class TBase, class TWinTraits>
  601. BOOL CWindowImplBaseT< TBase, TWinTraits >::SubclassWindow(HWND hWnd)
  602. {
  603. ATLASSERT(m_hWnd == NULL);
  604. ATLASSERT(::IsWindow(hWnd));
  605. m_thunk.Init(GetWindowProc(), this);
  606. WNDPROC pProc = (WNDPROC)(m_thunk.thunk.pThunk);
  607. WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  608. if(pfnWndProc == NULL)
  609. return FALSE;
  610. m_pfnSuperWindowProc = pfnWndProc;
  611. m_hWnd = hWnd;
  612. return TRUE;
  613. }
  614. // Use only if you want to subclass before window is destroyed,
  615. // WindowProc will automatically subclass when window goes away
  616. template <class TBase, class TWinTraits>
  617. HWND CWindowImplBaseT< TBase, TWinTraits >::UnsubclassWindow(BOOL bForce /*= FALSE*/)
  618. {
  619. ATLASSERT(m_hWnd != NULL);
  620. WNDPROC pOurProc = (WNDPROC)(m_thunk.thunk.pThunk);
  621. WNDPROC pActiveProc = (WNDPROC)::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC);
  622. HWND hWnd = NULL;
  623. if (bForce || pOurProc == pActiveProc)
  624. {
  625. if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc))
  626. return NULL;
  627. m_pfnSuperWindowProc = ::DefWindowProc;
  628. hWnd = m_hWnd;
  629. m_hWnd = NULL;
  630. }
  631. return hWnd;
  632. }
  633. template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
  634. class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits >
  635. {
  636. public:
  637. DECLARE_WND_CLASS(NULL)
  638. HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL,
  639. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  640. UINT nID = 0, LPVOID lpCreateParam = NULL)
  641. {
  642. if (T::GetWndClassInfo().m_lpszOrigName == NULL)
  643. T::GetWndClassInfo().m_lpszOrigName = GetWndClassName();
  644. ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
  645. dwStyle = T::GetWndStyle(dwStyle);
  646. dwExStyle = T::GetWndExStyle(dwExStyle);
  647. return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rcPos, szWindowName,
  648. dwStyle, dwExStyle, nID, atom, lpCreateParam);
  649. }
  650. };
  651. /////////////////////////////////////////////////////////////////////////////
  652. // CDialogImpl - Implements a dialog box
  653. template <class TBase = CWindow>
  654. class ATL_NO_VTABLE CDialogImplBaseT : public CWindowImplRoot< TBase >
  655. {
  656. public:
  657. virtual DLGPROC GetDialogProc()
  658. {
  659. return DialogProc;
  660. }
  661. static INT_PTR CALLBACK StartDialogProc(HWND hWnd, UINT uMsg,
  662. WPARAM wParam, LPARAM lParam);
  663. static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  664. BOOL MapDialogRect(LPRECT lpRect)
  665. {
  666. ATLASSERT(::IsWindow(m_hWnd));
  667. return ::MapDialogRect(m_hWnd, lpRect);
  668. }
  669. virtual void OnFinalMessage(HWND /*hWnd*/)
  670. {
  671. // override to do something, if needed
  672. }
  673. // has no meaning for a dialog, but needed for handlers that use it
  674. LRESULT DefWindowProc()
  675. {
  676. return 0;
  677. }
  678. };
  679. template <class TBase>
  680. INT_PTR CALLBACK CDialogImplBaseT< TBase >::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  681. {
  682. CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)_Module.ExtractCreateWndData();
  683. ATLASSERT(pThis != NULL);
  684. pThis->m_hWnd = hWnd;
  685. pThis->m_thunk.Init((WNDPROC)pThis->GetDialogProc(), pThis);
  686. WNDPROC pProc = (WNDPROC)(pThis->m_thunk.thunk.pThunk);
  687. WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)pProc);
  688. #ifdef _DEBUG
  689. // check if somebody has subclassed us already since we discard it
  690. if(pOldProc != StartDialogProc)
  691. ATLTRACE(_T("ATL: Subclassing through a hook discarded.\n"));
  692. #endif
  693. return pProc(hWnd, uMsg, wParam, lParam);
  694. }
  695. template <class TBase>
  696. INT_PTR CALLBACK CDialogImplBaseT< TBase >::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  697. {
  698. CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)hWnd;
  699. LRESULT lRes;
  700. if(pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0))
  701. {
  702. switch (uMsg)
  703. {
  704. case WM_COMPAREITEM:
  705. case WM_VKEYTOITEM:
  706. case WM_CHARTOITEM:
  707. case WM_INITDIALOG:
  708. case WM_QUERYDRAGICON:
  709. case WM_CTLCOLORMSGBOX:
  710. case WM_CTLCOLOREDIT:
  711. case WM_CTLCOLORLISTBOX:
  712. case WM_CTLCOLORBTN:
  713. case WM_CTLCOLORDLG:
  714. case WM_CTLCOLORSCROLLBAR:
  715. case WM_CTLCOLORSTATIC:
  716. return lRes;
  717. break;
  718. }
  719. ::SetWindowLongPtr(pThis->m_hWnd, DWLP_MSGRESULT, lRes);
  720. return TRUE;
  721. }
  722. #ifndef UNDER_CE
  723. if(uMsg == WM_NCDESTROY)
  724. #else // CE specific
  725. if(uMsg == WM_DESTROY)
  726. #endif //!UNDER_CE
  727. {
  728. // clear out window handle
  729. HWND hWnd = pThis->m_hWnd;
  730. pThis->m_hWnd = NULL;
  731. // clean up after dialog is destroyed
  732. pThis->OnFinalMessage(hWnd);
  733. }
  734. return FALSE;
  735. }
  736. typedef CDialogImplBaseT<CWindow> CDialogImplBase;
  737. template <class T, class TBase = CWindow>
  738. class ATL_NO_VTABLE CDialogImpl : public CDialogImplBaseT< TBase >
  739. {
  740. public:
  741. #ifdef _DEBUG
  742. bool m_bModal;
  743. CDialogImpl() : m_bModal(false) { }
  744. #endif //_DEBUG
  745. // modal dialogs
  746. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
  747. {
  748. ATLASSERT(m_hWnd == NULL);
  749. _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this);
  750. #ifdef _DEBUG
  751. m_bModal = true; // set to true for _DEBUG only
  752. #endif // _DEBUG
  753. return ::DialogBoxParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),
  754. hWndParent, T::StartDialogProc, dwInitParam);
  755. }
  756. BOOL EndDialog(int nRetCode)
  757. {
  758. ATLASSERT(::IsWindow(m_hWnd));
  759. #ifdef _DEBUG
  760. ATLASSERT(m_bModal); // must be a modal dialog
  761. #endif // _DEBUG
  762. return ::EndDialog(m_hWnd, nRetCode);
  763. }
  764. // modeless dialogs
  765. HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
  766. {
  767. ATLASSERT(m_hWnd == NULL);
  768. _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this);
  769. #ifdef _DEBUG
  770. m_bModal = false; // set to false for _DEBUG only
  771. #endif // _DEBUG
  772. HWND hWnd = ::CreateDialogParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),
  773. hWndParent, T::StartDialogProc, dwInitParam);
  774. ATLASSERT(m_hWnd == hWnd);
  775. return hWnd;
  776. }
  777. // for CComControl
  778. HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL)
  779. {
  780. return Create(hWndParent, dwInitParam);
  781. }
  782. BOOL DestroyWindow()
  783. {
  784. ATLASSERT(::IsWindow(m_hWnd));
  785. #ifdef _DEBUG
  786. ATLASSERT(!m_bModal); // must not be a modal dialog
  787. #endif // _DEBUG
  788. return ::DestroyWindow(m_hWnd);
  789. }
  790. };
  791. }; //namespace ATL
  792. #endif // __ATLWIN21_H__