Source code of Windows XP (NT5)
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.

4435 lines
118 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-2001 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 __ATLWIN_H__
  11. #define __ATLWIN_H__
  12. #pragma once
  13. #ifndef __cplusplus
  14. #error ATL requires C++ compilation (use a .cpp suffix)
  15. #endif
  16. #ifndef __ATLBASE_H__
  17. #error atlwin.h requires atlbase.h to be included first
  18. #endif
  19. #include <atlbase.inl>
  20. #include <commctrl.h>
  21. #include <atlsimpstr.h>
  22. // protect template members from windowsx.h macros
  23. #ifdef _INC_WINDOWSX
  24. #undef SubclassWindow
  25. #endif //_INC_WINDOWSX
  26. #ifdef SetWindowLongPtrA
  27. #undef SetWindowLongPtrA
  28. inline LONG_PTR SetWindowLongPtrA( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
  29. {
  30. return( ::SetWindowLongA( hWnd, nIndex, LONG( dwNewLong ) ) );
  31. }
  32. #endif
  33. #ifdef SetWindowLongPtrW
  34. #undef SetWindowLongPtrW
  35. inline LONG_PTR SetWindowLongPtrW( HWND hWnd, int nIndex, LONG_PTR dwNewLong )
  36. {
  37. return( ::SetWindowLongW( hWnd, nIndex, LONG( dwNewLong ) ) );
  38. }
  39. #endif
  40. #ifdef GetWindowLongPtrA
  41. #undef GetWindowLongPtrA
  42. inline LONG_PTR GetWindowLongPtrA( HWND hWnd, int nIndex )
  43. {
  44. return( ::GetWindowLongA( hWnd, nIndex ) );
  45. }
  46. #endif
  47. #ifdef GetWindowLongPtrW
  48. #undef GetWindowLongPtrW
  49. inline LONG_PTR GetWindowLongPtrW( HWND hWnd, int nIndex )
  50. {
  51. return( ::GetWindowLongW( hWnd, nIndex ) );
  52. }
  53. #endif
  54. //REVIEW: Just to fix VSEE
  55. #pragma push_macro("min")
  56. #pragma push_macro("max")
  57. #undef min
  58. #undef max
  59. #define min(a,b) (((a) < (b)) ? (a) : (b))
  60. #define max(a,b) (((a) > (b)) ? (a) : (b))
  61. //#ifndef _ATL_DLL_IMPL
  62. namespace ATL
  63. {
  64. //#endif
  65. struct _ATL_WNDCLASSINFOA;
  66. struct _ATL_WNDCLASSINFOW;
  67. ATLAPI_(ATOM) AtlWinModuleRegisterWndClassInfoA(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc);
  68. inline ATOM AtlModuleRegisterWndClassInfoA(_ATL_MODULE* /*pM*/, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc)
  69. {
  70. return AtlWinModuleRegisterWndClassInfoA(&_AtlWinModule, &_AtlBaseModule, p, pProc);
  71. }
  72. ATLAPI_(ATOM) AtlWinModuleRegisterWndClassInfoW(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc);
  73. inline ATOM AtlModuleRegisterWndClassInfoW(_ATL_MODULE* /*pM*/, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc)
  74. {
  75. return AtlWinModuleRegisterWndClassInfoW(&_AtlWinModule, &_AtlBaseModule, p, pProc);
  76. }
  77. ATLINLINE ATLAPI_(ATOM) AtlWinModuleRegisterClassExA(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXA *lpwc);
  78. inline ATOM AtlModuleRegisterClassExA(_ATL_MODULE* /*pM*/, const WNDCLASSEXA *lpwc)
  79. {
  80. return AtlWinModuleRegisterClassExA(&_AtlWinModule, lpwc);
  81. }
  82. ATLAPI_(ATOM) AtlWinModuleRegisterClassExW(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXW *lpwc);
  83. inline ATOM AtlModuleRegisterClassExW(_ATL_MODULE* /*pM*/, const WNDCLASSEXW *lpwc)
  84. {
  85. return AtlWinModuleRegisterClassExW(&_AtlWinModule, lpwc);
  86. }
  87. #ifdef UNICODE
  88. #define AtlWinModuleRegisterWndClassInfo AtlWinModuleRegisterWndClassInfoW
  89. #define AtlWinModuleRegisterClassEx AtlWinModuleRegisterClassExW
  90. #define AtlModuleRegisterWndClassInfo AtlModuleRegisterWndClassInfoW
  91. #define AtlModuleRegisterClassEx AtlModuleRegisterClassExW
  92. #else
  93. #define AtlWinModuleRegisterWndClassInfo AtlWinModuleRegisterWndClassInfoA
  94. #define AtlWinModuleRegisterClassEx AtlWinModuleRegisterClassExA
  95. #define AtlModuleRegisterWndClassInfo AtlModuleRegisterWndClassInfoA
  96. #define AtlModuleRegisterClassEx AtlModuleRegisterClassExA
  97. #endif
  98. #define HIMETRIC_PER_INCH 2540
  99. #define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
  100. #define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH)
  101. ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd);
  102. ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix);
  103. ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric);
  104. #ifndef GET_X_LPARAM
  105. #define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
  106. #endif
  107. #ifndef GET_Y_LPARAM
  108. #define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
  109. #endif
  110. //#ifndef _ATL_DLL_IMPL
  111. }; //namespace ATL
  112. //#endif
  113. namespace ATL
  114. {
  115. struct _ATL_WNDCLASSINFOA
  116. {
  117. WNDCLASSEXA m_wc;
  118. LPCSTR m_lpszOrigName;
  119. WNDPROC pWndProc;
  120. LPCSTR m_lpszCursorID;
  121. BOOL m_bSystemCursor;
  122. ATOM m_atom;
  123. CHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT];
  124. ATOM Register(WNDPROC* p)
  125. {
  126. return AtlWinModuleRegisterWndClassInfoA(&_AtlWinModule, &_AtlBaseModule, this, p);
  127. }
  128. };
  129. struct _ATL_WNDCLASSINFOW
  130. {
  131. WNDCLASSEXW m_wc;
  132. LPCWSTR m_lpszOrigName;
  133. WNDPROC pWndProc;
  134. LPCWSTR m_lpszCursorID;
  135. BOOL m_bSystemCursor;
  136. ATOM m_atom;
  137. WCHAR m_szAutoName[5+sizeof(void*)*CHAR_BIT];
  138. ATOM Register(WNDPROC* p)
  139. {
  140. return AtlWinModuleRegisterWndClassInfoW(&_AtlWinModule, &_AtlBaseModule, this, p);
  141. }
  142. };
  143. }; // namespace ATL
  144. namespace ATL
  145. {
  146. /////////////////////////////////////////////////////////////////////////////
  147. // Forward declarations
  148. class CWindow;
  149. #ifndef _ATL_NO_HOSTING
  150. template <class TBase = CWindow> class CAxWindowT;
  151. template <class TBase = CWindow> class CAxWindow2T;
  152. #endif //!_ATL_NO_HOSTING
  153. class CMessageMap;
  154. class CDynamicChain;
  155. typedef _ATL_WNDCLASSINFOA CWndClassInfoA;
  156. typedef _ATL_WNDCLASSINFOW CWndClassInfoW;
  157. #ifdef UNICODE
  158. #define CWndClassInfo CWndClassInfoW
  159. #else
  160. #define CWndClassInfo CWndClassInfoA
  161. #endif
  162. template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits> class CWindowImpl;
  163. template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits> class CWindowWithReflectorImpl;
  164. template <class T, class TBase = CWindow> class CDialogImpl;
  165. #ifndef _ATL_NO_HOSTING
  166. template <class T, class TBase = CWindow> class CAxDialogImpl;
  167. #endif //!_ATL_NO_HOSTING
  168. template <WORD t_wDlgTemplateID, BOOL t_bCenter = TRUE> class CSimpleDialog;
  169. template <class TBase = CWindow, class TWinTraits = CControlWinTraits> class CContainedWindowT;
  170. /////////////////////////////////////////////////////////////////////////////
  171. // Helper functions for cracking dialog templates
  172. class _DialogSplitHelper
  173. {
  174. public:
  175. // Constants used in DLGINIT resources for OLE control containers
  176. // NOTE: These are NOT real Windows messages they are simply tags
  177. // used in the control resource and are never used as 'messages'
  178. enum
  179. {
  180. ATL_WM_OCC_LOADFROMSTREAM = 0x0376,
  181. ATL_WM_OCC_LOADFROMSTORAGE = 0x0377,
  182. ATL_WM_OCC_INITNEW = 0x0378,
  183. ATL_WM_OCC_LOADFROMSTREAM_EX = 0x037A,
  184. ATL_WM_OCC_LOADFROMSTORAGE_EX = 0x037B,
  185. ATL_DISPID_DATASOURCE = 0x80010001,
  186. ATL_DISPID_DATAFIELD = 0x80010002,
  187. };
  188. //local struct used for implementation
  189. #pragma pack(push, 1)
  190. struct DLGINITSTRUCT
  191. {
  192. WORD nIDC;
  193. WORD message;
  194. DWORD dwSize;
  195. };
  196. struct DLGTEMPLATEEX
  197. {
  198. WORD dlgVer;
  199. WORD signature;
  200. DWORD helpID;
  201. DWORD exStyle;
  202. DWORD style;
  203. WORD cDlgItems;
  204. short x;
  205. short y;
  206. short cx;
  207. short cy;
  208. // Everything else in this structure is variable length,
  209. // and therefore must be determined dynamically
  210. // sz_Or_Ord menu; // name or ordinal of a menu resource
  211. // sz_Or_Ord windowClass; // name or ordinal of a window class
  212. // WCHAR title[titleLen]; // title string of the dialog box
  213. // short pointsize; // only if DS_SETFONT is set
  214. // short weight; // only if DS_SETFONT is set
  215. // short bItalic; // only if DS_SETFONT is set
  216. // WCHAR font[fontLen]; // typeface name, if DS_SETFONT is set
  217. };
  218. struct DLGITEMTEMPLATEEX
  219. {
  220. DWORD helpID;
  221. DWORD exStyle;
  222. DWORD style;
  223. short x;
  224. short y;
  225. short cx;
  226. short cy;
  227. DWORD id;
  228. // Everything else in this structure is variable length,
  229. // and therefore must be determined dynamically
  230. // sz_Or_Ord windowClass; // name or ordinal of a window class
  231. // sz_Or_Ord title; // title string or ordinal of a resource
  232. // WORD extraCount; // bytes following creation data
  233. };
  234. #pragma pack(pop)
  235. static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate)
  236. {
  237. return ((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF;
  238. }
  239. inline static WORD& DlgTemplateItemCount(DLGTEMPLATE* pTemplate)
  240. {
  241. if (IsDialogEx(pTemplate))
  242. return reinterpret_cast<DLGTEMPLATEEX*>(pTemplate)->cDlgItems;
  243. else
  244. return pTemplate->cdit;
  245. }
  246. inline static const WORD& DlgTemplateItemCount(const DLGTEMPLATE* pTemplate)
  247. {
  248. if (IsDialogEx(pTemplate))
  249. return reinterpret_cast<const DLGTEMPLATEEX*>(pTemplate)->cDlgItems;
  250. else
  251. return pTemplate->cdit;
  252. }
  253. static DLGITEMTEMPLATE* FindFirstDlgItem(const DLGTEMPLATE* pTemplate)
  254. {
  255. BOOL bDialogEx = IsDialogEx(pTemplate);
  256. WORD* pw;
  257. DWORD dwStyle;
  258. if (bDialogEx)
  259. {
  260. pw = (WORD*)((DLGTEMPLATEEX*)pTemplate + 1);
  261. dwStyle = ((DLGTEMPLATEEX*)pTemplate)->style;
  262. }
  263. else
  264. {
  265. pw = (WORD*)(pTemplate + 1);
  266. dwStyle = pTemplate->style;
  267. }
  268. // Check for presence of menu and skip it if there is one
  269. // 0x0000 means there is no menu
  270. // 0xFFFF means there is a menu ID following
  271. // Everything else means that this is a NULL terminated Unicode string
  272. // which identifies the menu resource
  273. if (*pw == 0xFFFF)
  274. pw += 2; // Has menu ID, so skip 2 words
  275. else
  276. while (*pw++); // Either No menu, or string, skip past terminating NULL
  277. // Check for presence of class name string
  278. // 0x0000 means "Use system dialog class name"
  279. // 0xFFFF means there is a window class (atom) specified
  280. // Everything else means that this is a NULL terminated Unicode string
  281. // which identifies the menu resource
  282. if (*pw == 0xFFFF)
  283. pw += 2; // Has class atom, so skip 2 words
  284. else
  285. while (*pw++); // Either No class, or string, skip past terminating NULL
  286. // Skip caption string
  287. while (*pw++);
  288. // If we have DS_SETFONT, there is extra font information which we must now skip
  289. if (dwStyle & DS_SETFONT)
  290. {
  291. // If it is a regular DLGTEMPLATE there is only a short for the point size
  292. // and a string specifying the font (typefacename). If this is a DLGTEMPLATEEX
  293. // then there is also the font weight, and bItalic which must be skipped
  294. if (bDialogEx)
  295. pw += 3; // Skip font size, weight, (italic, charset)
  296. else
  297. pw += 1; // Skip font size
  298. while (*pw++); // Skip typeface name
  299. }
  300. // Dword-align and return
  301. return (DLGITEMTEMPLATE*)(((DWORD_PTR)pw + 3) & ~3);
  302. }
  303. // Given the current dialog item and whether this is an extended dialog
  304. // return a pointer to the next DLGITEMTEMPLATE*
  305. static DLGITEMTEMPLATE* FindNextDlgItem(DLGITEMTEMPLATE* pItem, BOOL bDialogEx)
  306. {
  307. WORD* pw;
  308. // First skip fixed size header information, size of which depends
  309. // if this is a DLGITEMTEMPLATE or DLGITEMTEMPLATEEX
  310. if (bDialogEx)
  311. pw = (WORD*)((DLGITEMTEMPLATEEX*)pItem + 1);
  312. else
  313. pw = (WORD*)(pItem + 1);
  314. if (*pw == 0xFFFF) // Skip class name ordinal or string
  315. pw += 2; // (WORDs)
  316. else
  317. while (*pw++);
  318. if (*pw == 0xFFFF) // Skip title ordinal or string
  319. pw += 2; // (WORDs)
  320. else
  321. while (*pw++);
  322. WORD cbExtra = *pw++; // Skip extra data
  323. // cbExtra includes the size WORD in DIALOG resource.
  324. if (cbExtra != 0 && !bDialogEx)
  325. cbExtra -= 2;
  326. // Dword-align and return
  327. return (DLGITEMTEMPLATE*)(((DWORD_PTR)pw + cbExtra + 3) & ~3);
  328. }
  329. // Find the initialization data (Stream) for the control specified by the ID
  330. // If found, return the pointer into the data and the length of the data
  331. static DWORD FindCreateData(DWORD dwID, BYTE* pInitData, BYTE** pData)
  332. {
  333. while (pInitData)
  334. {
  335. // Read the DLGINIT header
  336. WORD nIDC = *((UNALIGNED WORD*)pInitData);
  337. pInitData += sizeof(WORD);
  338. BYTE* pTemp = pInitData;
  339. WORD nMsg = *((UNALIGNED WORD*)pInitData);
  340. pInitData += sizeof(WORD);
  341. DWORD dwLen = *((UNALIGNED DWORD*)pInitData);
  342. pInitData += sizeof(DWORD);
  343. // If the header is for the control specified get the other info
  344. if (nIDC == dwID)
  345. {
  346. if (nMsg == (WORD)ATL_WM_OCC_INITNEW)
  347. {
  348. ATLASSERT(dwLen == 0);
  349. return 0;
  350. }
  351. *pData = pTemp;
  352. return dwLen + sizeof(WORD) + sizeof(DWORD);
  353. }
  354. // It's not the right control, skip past data
  355. pInitData += dwLen;
  356. }
  357. return 0;
  358. }
  359. static bool IsActiveXControl(DLGITEMTEMPLATE* pItem, BOOL bDialogEx)
  360. {
  361. LPWSTR pszClassName;
  362. pszClassName = bDialogEx ?
  363. (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
  364. (LPWSTR)(pItem + 1);
  365. if (pszClassName[0] == L'{')
  366. return true;
  367. return false;
  368. }
  369. // Convert MSDEV (MFC) style DLGTEMPLATE with controls to regular DLGTEMPLATE
  370. // Changing all ActiveX Controls to use ATL AxWin hosting code
  371. static DLGTEMPLATE* SplitDialogTemplate(DLGTEMPLATE* pTemplate, BYTE* /*pInitData*/)
  372. {
  373. // Calculate the size of the DLGTEMPLATE for allocating the new one
  374. DLGITEMTEMPLATE* pFirstItem = FindFirstDlgItem(pTemplate);
  375. ULONG_PTR cbHeader = (BYTE*)pFirstItem - (BYTE*)pTemplate;
  376. ULONG_PTR cbNewTemplate = cbHeader;
  377. BOOL bDialogEx = IsDialogEx(pTemplate);
  378. int iItem;
  379. int nItems = (int)DlgTemplateItemCount(pTemplate);
  380. LPWSTR pszClassName;
  381. BOOL bHasOleControls = FALSE;
  382. // Make first pass through the dialog template. On this pass, we're
  383. // interested in determining:
  384. // 1. Does this template contain any ActiveX Controls?
  385. // 2. If so, how large a buffer is needed for a template containing
  386. // only the non-OLE controls?
  387. DLGITEMTEMPLATE* pItem = pFirstItem;
  388. DLGITEMTEMPLATE* pNextItem = pItem;
  389. for (iItem = 0; iItem < nItems; iItem++)
  390. {
  391. pNextItem = FindNextDlgItem(pItem, bDialogEx);
  392. pszClassName = bDialogEx ?
  393. (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
  394. (LPWSTR)(pItem + 1);
  395. // Check if the class name begins with a '{'
  396. // If it does, that means it is an ActiveX Control in MSDEV (MFC) format
  397. if (pszClassName[0] == L'{')
  398. {
  399. // Item is an ActiveX control.
  400. bHasOleControls = TRUE;
  401. }
  402. else
  403. {
  404. // Item is not an ActiveX Control: make room for it in new template.
  405. cbNewTemplate += (BYTE*)pNextItem - (BYTE*)pItem;
  406. }
  407. pItem = pNextItem;
  408. }
  409. // No OLE controls were found, so there's no reason to go any further.
  410. if (!bHasOleControls)
  411. return pTemplate;
  412. // Copy entire header into new template.
  413. BYTE* pNew = (BYTE*)GlobalAlloc(GMEM_FIXED, cbNewTemplate);
  414. DLGTEMPLATE* pNewTemplate = (DLGTEMPLATE*)pNew;
  415. memcpy(pNew, pTemplate, cbHeader);
  416. pNew += cbHeader;
  417. // Initialize item count in new header to zero.
  418. DlgTemplateItemCount(pNewTemplate) = 0;
  419. pItem = pFirstItem;
  420. pNextItem = pItem;
  421. // Second pass through the dialog template. On this pass, we want to:
  422. // 1. Copy all the non-OLE controls into the new template.
  423. for (iItem = 0; iItem < nItems; iItem++)
  424. {
  425. pNextItem = FindNextDlgItem(pItem, bDialogEx);
  426. pszClassName = bDialogEx ?
  427. (LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
  428. (LPWSTR)(pItem + 1);
  429. if (pszClassName[0] != L'{')
  430. {
  431. // Item is not an OLE control: copy it to the new template.
  432. ULONG_PTR cbItem = (BYTE*)pNextItem - (BYTE*)pItem;
  433. ATLASSERT(cbItem >= (bDialogEx ?
  434. sizeof(DLGITEMTEMPLATEEX) :
  435. sizeof(DLGITEMTEMPLATE)));
  436. memcpy(pNew, pItem, cbItem);
  437. pNew += cbItem;
  438. // Incrememt item count in new header.
  439. ++DlgTemplateItemCount(pNewTemplate);
  440. }
  441. pItem = pNextItem;
  442. }
  443. return pNewTemplate;
  444. }
  445. static HRESULT ParseInitData(IStream* pStream, BSTR* pLicKey)
  446. {
  447. *pLicKey = NULL;
  448. if(pStream == NULL)
  449. return S_OK; // nothing to do
  450. ULONG uRead;
  451. HRESULT hr;
  452. WORD nMsg;
  453. hr = pStream->Read(&nMsg, sizeof(WORD), &uRead);
  454. if (FAILED(hr))
  455. return hr;
  456. DWORD dwLen;
  457. hr = pStream->Read(&dwLen, sizeof(DWORD), &uRead);
  458. if (FAILED(hr))
  459. return hr;
  460. DWORD cchLicKey;
  461. hr = pStream->Read(&cchLicKey, sizeof(DWORD), &uRead);
  462. if (FAILED(hr))
  463. return hr;
  464. if (cchLicKey > 0)
  465. {
  466. CComBSTR bstr(cchLicKey);
  467. if (bstr.Length() == 0)
  468. return E_OUTOFMEMORY;
  469. memset(bstr.m_str, 0, (cchLicKey + 1) * sizeof(OLECHAR));
  470. hr = pStream->Read(bstr.m_str, cchLicKey * sizeof(OLECHAR), &uRead);
  471. if (FAILED(hr))
  472. return hr;
  473. *pLicKey = bstr.Detach();
  474. }
  475. // Extended (DATABINDING) stream format is not supported,
  476. // we reject databinding info but preserve other information
  477. if (nMsg == (WORD)ATL_WM_OCC_LOADFROMSTREAM_EX ||
  478. nMsg == (WORD)ATL_WM_OCC_LOADFROMSTORAGE_EX)
  479. {
  480. // Read the size of the section
  481. ULONG cbOffset;
  482. hr = pStream->Read(&cbOffset, sizeof(ULONG), &uRead);
  483. if (FAILED(hr))
  484. return hr;
  485. BYTE pTemp[1000];
  486. cbOffset -= sizeof(ULONG);
  487. while (cbOffset > 0)
  488. {
  489. pStream->Read(pTemp, min(cbOffset, 1000), &uRead);
  490. cbOffset -= uRead;
  491. }
  492. return S_OK;
  493. }
  494. if (nMsg == (WORD)ATL_WM_OCC_LOADFROMSTREAM)
  495. {
  496. return S_OK;
  497. }
  498. return E_FAIL;
  499. }
  500. };
  501. /////////////////////////////////////////////////////////////////////////////
  502. // CWindow - client side for a Windows window
  503. class CWindow
  504. {
  505. public:
  506. static RECT rcDefault;
  507. HWND m_hWnd;
  508. CWindow(HWND hWnd = NULL) throw() :
  509. m_hWnd(hWnd)
  510. {
  511. }
  512. CWindow& operator=(HWND hWnd) throw()
  513. {
  514. m_hWnd = hWnd;
  515. return *this;
  516. }
  517. static LPCTSTR GetWndClassName() throw()
  518. {
  519. return NULL;
  520. }
  521. void Attach(HWND hWndNew) throw()
  522. {
  523. ATLASSERT(m_hWnd == NULL);
  524. ATLASSERT((hWndNew == NULL) || ::IsWindow(hWndNew));
  525. m_hWnd = hWndNew;
  526. }
  527. HWND Detach() throw()
  528. {
  529. HWND hWnd = m_hWnd;
  530. m_hWnd = NULL;
  531. return hWnd;
  532. }
  533. HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
  534. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  535. _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) throw()
  536. {
  537. ATLASSERT(m_hWnd == NULL);
  538. if(rect.m_lpRect == NULL)
  539. rect.m_lpRect = &rcDefault;
  540. m_hWnd = ::CreateWindowEx(dwExStyle, lpstrWndClass, szWindowName,
  541. dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left,
  542. rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu,
  543. _AtlBaseModule.GetModuleInstance(), lpCreateParam);
  544. return m_hWnd;
  545. }
  546. BOOL DestroyWindow() throw()
  547. {
  548. ATLASSERT(::IsWindow(m_hWnd));
  549. if(!::DestroyWindow(m_hWnd))
  550. return FALSE;
  551. m_hWnd = NULL;
  552. return TRUE;
  553. }
  554. // Attributes
  555. operator HWND() const throw()
  556. {
  557. return m_hWnd;
  558. }
  559. DWORD GetStyle() const throw()
  560. {
  561. ATLASSERT(::IsWindow(m_hWnd));
  562. return (DWORD)::GetWindowLong(m_hWnd, GWL_STYLE);
  563. }
  564. DWORD GetExStyle() const throw()
  565. {
  566. ATLASSERT(::IsWindow(m_hWnd));
  567. return (DWORD)::GetWindowLong(m_hWnd, GWL_EXSTYLE);
  568. }
  569. LONG GetWindowLong(int nIndex) const throw()
  570. {
  571. ATLASSERT(::IsWindow(m_hWnd));
  572. return ::GetWindowLong(m_hWnd, nIndex);
  573. }
  574. LONG_PTR GetWindowLongPtr(int nIndex) const throw()
  575. {
  576. ATLASSERT(::IsWindow(m_hWnd));
  577. return ::GetWindowLongPtr(m_hWnd, nIndex);
  578. }
  579. LONG SetWindowLong(int nIndex, LONG dwNewLong) throw()
  580. {
  581. ATLASSERT(::IsWindow(m_hWnd));
  582. return ::SetWindowLong(m_hWnd, nIndex, dwNewLong);
  583. }
  584. LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) throw()
  585. {
  586. ATLASSERT(::IsWindow(m_hWnd));
  587. return ::SetWindowLongPtr(m_hWnd, nIndex, dwNewLong);
  588. }
  589. WORD GetWindowWord(int nIndex) const throw()
  590. {
  591. ATLASSERT(::IsWindow(m_hWnd));
  592. return ::GetWindowWord(m_hWnd, nIndex);
  593. }
  594. WORD SetWindowWord(int nIndex, WORD wNewWord) throw()
  595. {
  596. ATLASSERT(::IsWindow(m_hWnd));
  597. return ::SetWindowWord(m_hWnd, nIndex, wNewWord);
  598. }
  599. // Message Functions
  600. LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw()
  601. {
  602. ATLASSERT(::IsWindow(m_hWnd));
  603. return ::SendMessage(m_hWnd,message,wParam,lParam);
  604. }
  605. BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw()
  606. {
  607. ATLASSERT(::IsWindow(m_hWnd));
  608. return ::PostMessage(m_hWnd,message,wParam,lParam);
  609. }
  610. BOOL SendNotifyMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw()
  611. {
  612. ATLASSERT(::IsWindow(m_hWnd));
  613. return ::SendNotifyMessage(m_hWnd, message, wParam, lParam);
  614. }
  615. // support for C style macros
  616. static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) throw()
  617. {
  618. ATLASSERT(::IsWindow(hWnd));
  619. return ::SendMessage(hWnd, message, wParam, lParam);
  620. }
  621. // Window Text Functions
  622. BOOL SetWindowText(LPCTSTR lpszString) throw()
  623. {
  624. ATLASSERT(::IsWindow(m_hWnd));
  625. return ::SetWindowText(m_hWnd, lpszString);
  626. }
  627. int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const throw()
  628. {
  629. ATLASSERT(::IsWindow(m_hWnd));
  630. return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount);
  631. }
  632. int GetWindowText(CSimpleString& strText) const
  633. {
  634. int nLength;
  635. LPTSTR pszText;
  636. nLength = GetWindowTextLength();
  637. pszText = strText.GetBuffer(nLength+1);
  638. nLength = GetWindowText(pszText, nLength+1);
  639. strText.ReleaseBuffer(nLength);
  640. return nLength;
  641. }
  642. int GetWindowTextLength() const throw()
  643. {
  644. ATLASSERT(::IsWindow(m_hWnd));
  645. return ::GetWindowTextLength(m_hWnd);
  646. }
  647. // Font Functions
  648. void SetFont(HFONT hFont, BOOL bRedraw = TRUE) throw()
  649. {
  650. ATLASSERT(::IsWindow(m_hWnd));
  651. ::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0));
  652. }
  653. HFONT GetFont() const throw()
  654. {
  655. ATLASSERT(::IsWindow(m_hWnd));
  656. return (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0);
  657. }
  658. // Menu Functions (non-child windows only)
  659. HMENU GetMenu() const throw()
  660. {
  661. ATLASSERT(::IsWindow(m_hWnd));
  662. return (HMENU)::GetMenu(m_hWnd);
  663. }
  664. BOOL SetMenu(HMENU hMenu) throw()
  665. {
  666. ATLASSERT(::IsWindow(m_hWnd));
  667. return ::SetMenu(m_hWnd, hMenu);
  668. }
  669. BOOL DrawMenuBar() throw()
  670. {
  671. ATLASSERT(::IsWindow(m_hWnd));
  672. return ::DrawMenuBar(m_hWnd);
  673. }
  674. HMENU GetSystemMenu(BOOL bRevert) const throw()
  675. {
  676. ATLASSERT(::IsWindow(m_hWnd));
  677. return (HMENU)::GetSystemMenu(m_hWnd, bRevert);
  678. }
  679. BOOL HiliteMenuItem(HMENU hMenu, UINT uItemHilite, UINT uHilite) throw()
  680. {
  681. ATLASSERT(::IsWindow(m_hWnd));
  682. return ::HiliteMenuItem(m_hWnd, hMenu, uItemHilite, uHilite);
  683. }
  684. // Window Size and Position Functions
  685. BOOL IsIconic() const throw()
  686. {
  687. ATLASSERT(::IsWindow(m_hWnd));
  688. return ::IsIconic(m_hWnd);
  689. }
  690. BOOL IsZoomed() const throw()
  691. {
  692. ATLASSERT(::IsWindow(m_hWnd));
  693. return ::IsZoomed(m_hWnd);
  694. }
  695. BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE) throw()
  696. {
  697. ATLASSERT(::IsWindow(m_hWnd));
  698. return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint);
  699. }
  700. BOOL MoveWindow(LPCRECT lpRect, BOOL bRepaint = TRUE) throw()
  701. {
  702. ATLASSERT(::IsWindow(m_hWnd));
  703. return ::MoveWindow(m_hWnd, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, bRepaint);
  704. }
  705. BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags) throw()
  706. {
  707. ATLASSERT(::IsWindow(m_hWnd));
  708. return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags);
  709. }
  710. BOOL SetWindowPos(HWND hWndInsertAfter, LPCRECT lpRect, UINT nFlags) throw()
  711. {
  712. ATLASSERT(::IsWindow(m_hWnd));
  713. return ::SetWindowPos(m_hWnd, hWndInsertAfter, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, nFlags);
  714. }
  715. UINT ArrangeIconicWindows() throw()
  716. {
  717. ATLASSERT(::IsWindow(m_hWnd));
  718. return ::ArrangeIconicWindows(m_hWnd);
  719. }
  720. BOOL BringWindowToTop() throw()
  721. {
  722. ATLASSERT(::IsWindow(m_hWnd));
  723. return ::BringWindowToTop(m_hWnd);
  724. }
  725. BOOL GetWindowRect(LPRECT lpRect) const throw()
  726. {
  727. ATLASSERT(::IsWindow(m_hWnd));
  728. return ::GetWindowRect(m_hWnd, lpRect);
  729. }
  730. BOOL GetClientRect(LPRECT lpRect) const throw()
  731. {
  732. ATLASSERT(::IsWindow(m_hWnd));
  733. return ::GetClientRect(m_hWnd, lpRect);
  734. }
  735. BOOL GetWindowPlacement(WINDOWPLACEMENT FAR* lpwndpl) const throw()
  736. {
  737. ATLASSERT(::IsWindow(m_hWnd));
  738. return ::GetWindowPlacement(m_hWnd, lpwndpl);
  739. }
  740. BOOL SetWindowPlacement(const WINDOWPLACEMENT FAR* lpwndpl) throw()
  741. {
  742. ATLASSERT(::IsWindow(m_hWnd));
  743. return ::SetWindowPlacement(m_hWnd, lpwndpl);
  744. }
  745. // Coordinate Mapping Functions
  746. BOOL ClientToScreen(LPPOINT lpPoint) const throw()
  747. {
  748. ATLASSERT(::IsWindow(m_hWnd));
  749. return ::ClientToScreen(m_hWnd, lpPoint);
  750. }
  751. BOOL ClientToScreen(LPRECT lpRect) const throw()
  752. {
  753. ATLASSERT(::IsWindow(m_hWnd));
  754. if(!::ClientToScreen(m_hWnd, (LPPOINT)lpRect))
  755. return FALSE;
  756. return ::ClientToScreen(m_hWnd, ((LPPOINT)lpRect)+1);
  757. }
  758. BOOL ScreenToClient(LPPOINT lpPoint) const throw()
  759. {
  760. ATLASSERT(::IsWindow(m_hWnd));
  761. return ::ScreenToClient(m_hWnd, lpPoint);
  762. }
  763. BOOL ScreenToClient(LPRECT lpRect) const throw()
  764. {
  765. ATLASSERT(::IsWindow(m_hWnd));
  766. if(!::ScreenToClient(m_hWnd, (LPPOINT)lpRect))
  767. return FALSE;
  768. return ::ScreenToClient(m_hWnd, ((LPPOINT)lpRect)+1);
  769. }
  770. int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const throw()
  771. {
  772. ATLASSERT(::IsWindow(m_hWnd));
  773. return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount);
  774. }
  775. int MapWindowPoints(HWND hWndTo, LPRECT lpRect) const throw()
  776. {
  777. ATLASSERT(::IsWindow(m_hWnd));
  778. return ::MapWindowPoints(m_hWnd, hWndTo, (LPPOINT)lpRect, 2);
  779. }
  780. // Update and Painting Functions
  781. HDC BeginPaint(LPPAINTSTRUCT lpPaint) throw()
  782. {
  783. ATLASSERT(::IsWindow(m_hWnd));
  784. return ::BeginPaint(m_hWnd, lpPaint);
  785. }
  786. void EndPaint(LPPAINTSTRUCT lpPaint) throw()
  787. {
  788. ATLASSERT(::IsWindow(m_hWnd));
  789. ::EndPaint(m_hWnd, lpPaint);
  790. }
  791. HDC GetDC() throw()
  792. {
  793. ATLASSERT(::IsWindow(m_hWnd));
  794. return ::GetDC(m_hWnd);
  795. }
  796. HDC GetWindowDC() throw()
  797. {
  798. ATLASSERT(::IsWindow(m_hWnd));
  799. return ::GetWindowDC(m_hWnd);
  800. }
  801. int ReleaseDC(HDC hDC) throw()
  802. {
  803. ATLASSERT(::IsWindow(m_hWnd));
  804. return ::ReleaseDC(m_hWnd, hDC);
  805. }
  806. void Print(HDC hDC, DWORD dwFlags) const throw()
  807. {
  808. ATLASSERT(::IsWindow(m_hWnd));
  809. ::SendMessage(m_hWnd, WM_PRINT, (WPARAM)hDC, dwFlags);
  810. }
  811. void PrintClient(HDC hDC, DWORD dwFlags) const throw()
  812. {
  813. ATLASSERT(::IsWindow(m_hWnd));
  814. ::SendMessage(m_hWnd, WM_PRINTCLIENT, (WPARAM)hDC, dwFlags);
  815. }
  816. BOOL UpdateWindow() throw()
  817. {
  818. ATLASSERT(::IsWindow(m_hWnd));
  819. return ::UpdateWindow(m_hWnd);
  820. }
  821. void SetRedraw(BOOL bRedraw = TRUE) throw()
  822. {
  823. ATLASSERT(::IsWindow(m_hWnd));
  824. ::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0);
  825. }
  826. BOOL GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE) throw()
  827. {
  828. ATLASSERT(::IsWindow(m_hWnd));
  829. return ::GetUpdateRect(m_hWnd, lpRect, bErase);
  830. }
  831. int GetUpdateRgn(HRGN hRgn, BOOL bErase = FALSE) throw()
  832. {
  833. ATLASSERT(::IsWindow(m_hWnd));
  834. return ::GetUpdateRgn(m_hWnd, hRgn, bErase);
  835. }
  836. BOOL Invalidate(BOOL bErase = TRUE) throw()
  837. {
  838. ATLASSERT(::IsWindow(m_hWnd));
  839. return ::InvalidateRect(m_hWnd, NULL, bErase);
  840. }
  841. BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE) throw()
  842. {
  843. ATLASSERT(::IsWindow(m_hWnd));
  844. return ::InvalidateRect(m_hWnd, lpRect, bErase);
  845. }
  846. BOOL ValidateRect(LPCRECT lpRect) throw()
  847. {
  848. ATLASSERT(::IsWindow(m_hWnd));
  849. return ::ValidateRect(m_hWnd, lpRect);
  850. }
  851. void InvalidateRgn(HRGN hRgn, BOOL bErase = TRUE) throw()
  852. {
  853. ATLASSERT(::IsWindow(m_hWnd));
  854. ::InvalidateRgn(m_hWnd, hRgn, bErase);
  855. }
  856. BOOL ValidateRgn(HRGN hRgn) throw()
  857. {
  858. ATLASSERT(::IsWindow(m_hWnd));
  859. return ::ValidateRgn(m_hWnd, hRgn);
  860. }
  861. BOOL ShowWindow(int nCmdShow) throw()
  862. {
  863. ATLASSERT(::IsWindow(m_hWnd));
  864. return ::ShowWindow(m_hWnd, nCmdShow);
  865. }
  866. BOOL IsWindowVisible() const throw()
  867. {
  868. ATLASSERT(::IsWindow(m_hWnd));
  869. return ::IsWindowVisible(m_hWnd);
  870. }
  871. BOOL ShowOwnedPopups(BOOL bShow = TRUE) throw()
  872. {
  873. ATLASSERT(::IsWindow(m_hWnd));
  874. return ::ShowOwnedPopups(m_hWnd, bShow);
  875. }
  876. HDC GetDCEx(HRGN hRgnClip, DWORD flags) throw()
  877. {
  878. ATLASSERT(::IsWindow(m_hWnd));
  879. return ::GetDCEx(m_hWnd, hRgnClip, flags);
  880. }
  881. BOOL LockWindowUpdate(BOOL bLock = TRUE) throw()
  882. {
  883. ATLASSERT(::IsWindow(m_hWnd));
  884. return ::LockWindowUpdate(bLock ? m_hWnd : NULL);
  885. }
  886. BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, HRGN hRgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE) throw()
  887. {
  888. ATLASSERT(::IsWindow(m_hWnd));
  889. return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgnUpdate, flags);
  890. }
  891. // Timer Functions
  892. UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) = NULL) throw()
  893. {
  894. ATLASSERT(::IsWindow(m_hWnd));
  895. return ::SetTimer(m_hWnd, nIDEvent, nElapse, (TIMERPROC)lpfnTimer);
  896. }
  897. BOOL KillTimer(UINT_PTR nIDEvent) throw()
  898. {
  899. ATLASSERT(::IsWindow(m_hWnd));
  900. return ::KillTimer(m_hWnd, nIDEvent);
  901. }
  902. // Window State Functions
  903. BOOL IsWindowEnabled() const throw()
  904. {
  905. ATLASSERT(::IsWindow(m_hWnd));
  906. return ::IsWindowEnabled(m_hWnd);
  907. }
  908. BOOL EnableWindow(BOOL bEnable = TRUE) throw()
  909. {
  910. ATLASSERT(::IsWindow(m_hWnd));
  911. return ::EnableWindow(m_hWnd, bEnable);
  912. }
  913. HWND SetActiveWindow() throw()
  914. {
  915. ATLASSERT(::IsWindow(m_hWnd));
  916. return ::SetActiveWindow(m_hWnd);
  917. }
  918. HWND SetCapture() throw()
  919. {
  920. ATLASSERT(::IsWindow(m_hWnd));
  921. return ::SetCapture(m_hWnd);
  922. }
  923. HWND SetFocus() throw()
  924. {
  925. ATLASSERT(::IsWindow(m_hWnd));
  926. return ::SetFocus(m_hWnd);
  927. }
  928. // Dialog-Box Item Functions
  929. BOOL CheckDlgButton(int nIDButton, UINT nCheck) throw()
  930. {
  931. ATLASSERT(::IsWindow(m_hWnd));
  932. return ::CheckDlgButton(m_hWnd, nIDButton, nCheck);
  933. }
  934. BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) throw()
  935. {
  936. ATLASSERT(::IsWindow(m_hWnd));
  937. return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton);
  938. }
  939. int DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT nFileType) throw()
  940. {
  941. ATLASSERT(::IsWindow(m_hWnd));
  942. return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, nFileType);
  943. }
  944. int DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT nFileType) throw()
  945. {
  946. ATLASSERT(::IsWindow(m_hWnd));
  947. return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, nFileType);
  948. }
  949. BOOL DlgDirSelect(LPTSTR lpString, int nCount, int nIDListBox) throw()
  950. {
  951. ATLASSERT(::IsWindow(m_hWnd));
  952. return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox);
  953. }
  954. BOOL DlgDirSelectComboBox(LPTSTR lpString, int nCount, int nIDComboBox) throw()
  955. {
  956. ATLASSERT(::IsWindow(m_hWnd));
  957. return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox);
  958. }
  959. UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE) const throw()
  960. {
  961. ATLASSERT(::IsWindow(m_hWnd));
  962. return ::GetDlgItemInt(m_hWnd, nID, lpTrans, bSigned);
  963. }
  964. UINT GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const throw()
  965. {
  966. ATLASSERT(::IsWindow(m_hWnd));
  967. return ::GetDlgItemText(m_hWnd, nID, lpStr, nMaxCount);
  968. }
  969. UINT GetDlgItemText(int nID, CSimpleString& strText) const
  970. {
  971. HWND hItem;
  972. ATLASSERT(::IsWindow(m_hWnd));
  973. hItem = GetDlgItem(nID);
  974. if (hItem != NULL)
  975. {
  976. int nLength;
  977. LPTSTR pszText;
  978. nLength = ::GetWindowTextLength(hItem);
  979. pszText = strText.GetBuffer(nLength+1);
  980. nLength = ::GetWindowText(hItem, pszText, nLength+1);
  981. strText.ReleaseBuffer(nLength);
  982. return nLength;
  983. }
  984. else
  985. {
  986. strText.Empty();
  987. return 0;
  988. }
  989. }
  990. #ifdef _OLEAUTO_H_
  991. BOOL GetDlgItemText(int nID, BSTR& bstrText) const throw()
  992. {
  993. ATLASSERT(::IsWindow(m_hWnd));
  994. HWND hWndCtl = GetDlgItem(nID);
  995. if(hWndCtl == NULL)
  996. return FALSE;
  997. return CWindow(hWndCtl).GetWindowText(bstrText);
  998. }
  999. #endif // _OLEAUTO_H_
  1000. CWindow GetNextDlgGroupItem(HWND hWndCtl, BOOL bPrevious = FALSE) const throw()
  1001. {
  1002. ATLASSERT(::IsWindow(m_hWnd));
  1003. return CWindow(::GetNextDlgGroupItem(m_hWnd, hWndCtl, bPrevious));
  1004. }
  1005. CWindow GetNextDlgTabItem(HWND hWndCtl, BOOL bPrevious = FALSE) const throw()
  1006. {
  1007. ATLASSERT(::IsWindow(m_hWnd));
  1008. return CWindow(::GetNextDlgTabItem(m_hWnd, hWndCtl, bPrevious));
  1009. }
  1010. UINT IsDlgButtonChecked(int nIDButton) const throw()
  1011. {
  1012. ATLASSERT(::IsWindow(m_hWnd));
  1013. return ::IsDlgButtonChecked(m_hWnd, nIDButton);
  1014. }
  1015. LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0) throw()
  1016. {
  1017. ATLASSERT(::IsWindow(m_hWnd));
  1018. return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam);
  1019. }
  1020. BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE) throw()
  1021. {
  1022. ATLASSERT(::IsWindow(m_hWnd));
  1023. return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned);
  1024. }
  1025. BOOL SetDlgItemText(int nID, LPCTSTR lpszString) throw()
  1026. {
  1027. ATLASSERT(::IsWindow(m_hWnd));
  1028. return ::SetDlgItemText(m_hWnd, nID, lpszString);
  1029. }
  1030. #ifndef _ATL_NO_HOSTING
  1031. HRESULT GetDlgControl(int nID, REFIID iid, void** ppCtrl) throw()
  1032. {
  1033. ATLASSERT(::IsWindow(m_hWnd));
  1034. ATLASSERT(ppCtrl != NULL);
  1035. if (ppCtrl == NULL)
  1036. return E_POINTER;
  1037. *ppCtrl = NULL;
  1038. HRESULT hr = HRESULT_FROM_WIN32(ERROR_CONTROL_ID_NOT_FOUND);
  1039. HWND hWndCtrl = GetDlgItem(nID);
  1040. if (hWndCtrl != NULL)
  1041. {
  1042. *ppCtrl = NULL;
  1043. CComPtr<IUnknown> spUnk;
  1044. hr = AtlAxGetControl(hWndCtrl, &spUnk);
  1045. if (SUCCEEDED(hr))
  1046. hr = spUnk->QueryInterface(iid, ppCtrl);
  1047. }
  1048. return hr;
  1049. }
  1050. HRESULT GetDlgHost(int nID, REFIID iid, void** ppHost) throw()
  1051. {
  1052. ATLASSERT(::IsWindow(m_hWnd));
  1053. ATLASSERT(ppHost != NULL);
  1054. if (ppHost == NULL)
  1055. return E_POINTER;
  1056. *ppHost = NULL;
  1057. HRESULT hr = HRESULT_FROM_WIN32(ERROR_CONTROL_ID_NOT_FOUND);
  1058. HWND hWndCtrl = GetDlgItem(nID);
  1059. if (hWndCtrl != NULL)
  1060. {
  1061. CComPtr<IUnknown> spUnk;
  1062. hr = AtlAxGetHost(hWndCtrl, &spUnk);
  1063. if (SUCCEEDED(hr))
  1064. hr = spUnk->QueryInterface(iid, ppHost);
  1065. }
  1066. return hr;
  1067. }
  1068. #endif //!_ATL_NO_HOSTING
  1069. // Scrolling Functions
  1070. int GetScrollPos(int nBar) const throw()
  1071. {
  1072. ATLASSERT(::IsWindow(m_hWnd));
  1073. return ::GetScrollPos(m_hWnd, nBar);
  1074. }
  1075. BOOL GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const throw()
  1076. {
  1077. ATLASSERT(::IsWindow(m_hWnd));
  1078. return ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos);
  1079. }
  1080. BOOL ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL) throw()
  1081. {
  1082. ATLASSERT(::IsWindow(m_hWnd));
  1083. return ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect);
  1084. }
  1085. int ScrollWindowEx(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate, UINT uFlags) throw()
  1086. {
  1087. ATLASSERT(::IsWindow(m_hWnd));
  1088. return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, uFlags);
  1089. }
  1090. int ScrollWindowEx(int dx, int dy, UINT uFlags, LPCRECT lpRectScroll = NULL, LPCRECT lpRectClip = NULL, HRGN hRgnUpdate = NULL, LPRECT lpRectUpdate = NULL) throw()
  1091. {
  1092. ATLASSERT(::IsWindow(m_hWnd));
  1093. return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, uFlags);
  1094. }
  1095. int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) throw()
  1096. {
  1097. ATLASSERT(::IsWindow(m_hWnd));
  1098. return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw);
  1099. }
  1100. BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE) throw()
  1101. {
  1102. ATLASSERT(::IsWindow(m_hWnd));
  1103. return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw);
  1104. }
  1105. BOOL ShowScrollBar(UINT nBar, BOOL bShow = TRUE) throw()
  1106. {
  1107. ATLASSERT(::IsWindow(m_hWnd));
  1108. return ::ShowScrollBar(m_hWnd, nBar, bShow);
  1109. }
  1110. BOOL EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH) throw()
  1111. {
  1112. ATLASSERT(::IsWindow(m_hWnd));
  1113. return ::EnableScrollBar(m_hWnd, uSBFlags, uArrowFlags);
  1114. }
  1115. // Window Access Functions
  1116. CWindow ChildWindowFromPoint(POINT point) const throw()
  1117. {
  1118. ATLASSERT(::IsWindow(m_hWnd));
  1119. return CWindow(::ChildWindowFromPoint(m_hWnd, point));
  1120. }
  1121. CWindow ChildWindowFromPointEx(POINT point, UINT uFlags) const throw()
  1122. {
  1123. ATLASSERT(::IsWindow(m_hWnd));
  1124. return CWindow(::ChildWindowFromPointEx(m_hWnd, point, uFlags));
  1125. }
  1126. CWindow GetTopWindow() const throw()
  1127. {
  1128. ATLASSERT(::IsWindow(m_hWnd));
  1129. return CWindow(::GetTopWindow(m_hWnd));
  1130. }
  1131. CWindow GetWindow(UINT nCmd) const throw()
  1132. {
  1133. ATLASSERT(::IsWindow(m_hWnd));
  1134. return CWindow(::GetWindow(m_hWnd, nCmd));
  1135. }
  1136. CWindow GetLastActivePopup() const throw()
  1137. {
  1138. ATLASSERT(::IsWindow(m_hWnd));
  1139. return CWindow(::GetLastActivePopup(m_hWnd));
  1140. }
  1141. BOOL IsChild(HWND hWnd) const throw()
  1142. {
  1143. ATLASSERT(::IsWindow(m_hWnd));
  1144. return ::IsChild(m_hWnd, hWnd);
  1145. }
  1146. CWindow GetParent() const throw()
  1147. {
  1148. ATLASSERT(::IsWindow(m_hWnd));
  1149. return CWindow(::GetParent(m_hWnd));
  1150. }
  1151. CWindow SetParent(HWND hWndNewParent) throw()
  1152. {
  1153. ATLASSERT(::IsWindow(m_hWnd));
  1154. return CWindow(::SetParent(m_hWnd, hWndNewParent));
  1155. }
  1156. // Window Tree Access
  1157. int GetDlgCtrlID() const throw()
  1158. {
  1159. ATLASSERT(::IsWindow(m_hWnd));
  1160. return ::GetDlgCtrlID(m_hWnd);
  1161. }
  1162. int SetDlgCtrlID(int nID) throw()
  1163. {
  1164. ATLASSERT(::IsWindow(m_hWnd));
  1165. return (int)::SetWindowLong(m_hWnd, GWL_ID, nID);
  1166. }
  1167. CWindow GetDlgItem(int nID) const throw()
  1168. {
  1169. ATLASSERT(::IsWindow(m_hWnd));
  1170. return CWindow(::GetDlgItem(m_hWnd, nID));
  1171. }
  1172. // Alert Functions
  1173. BOOL FlashWindow(BOOL bInvert) throw()
  1174. {
  1175. ATLASSERT(::IsWindow(m_hWnd));
  1176. return ::FlashWindow(m_hWnd, bInvert);
  1177. }
  1178. int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption = _T(""), UINT nType = MB_OK) throw()
  1179. {
  1180. ATLASSERT(::IsWindow(m_hWnd));
  1181. return ::MessageBox(m_hWnd, lpszText, lpszCaption, nType);
  1182. }
  1183. // Clipboard Functions
  1184. BOOL ChangeClipboardChain(HWND hWndNewNext) throw()
  1185. {
  1186. ATLASSERT(::IsWindow(m_hWnd));
  1187. return ::ChangeClipboardChain(m_hWnd, hWndNewNext);
  1188. }
  1189. HWND SetClipboardViewer() throw()
  1190. {
  1191. ATLASSERT(::IsWindow(m_hWnd));
  1192. return ::SetClipboardViewer(m_hWnd);
  1193. }
  1194. BOOL OpenClipboard() throw()
  1195. {
  1196. ATLASSERT(::IsWindow(m_hWnd));
  1197. return ::OpenClipboard(m_hWnd);
  1198. }
  1199. // Caret Functions
  1200. BOOL CreateCaret(HBITMAP hBitmap) throw()
  1201. {
  1202. ATLASSERT(::IsWindow(m_hWnd));
  1203. return ::CreateCaret(m_hWnd, hBitmap, 0, 0);
  1204. }
  1205. BOOL CreateSolidCaret(int nWidth, int nHeight) throw()
  1206. {
  1207. ATLASSERT(::IsWindow(m_hWnd));
  1208. return ::CreateCaret(m_hWnd, (HBITMAP)0, nWidth, nHeight);
  1209. }
  1210. BOOL CreateGrayCaret(int nWidth, int nHeight) throw()
  1211. {
  1212. ATLASSERT(::IsWindow(m_hWnd));
  1213. return ::CreateCaret(m_hWnd, (HBITMAP)1, nWidth, nHeight);
  1214. }
  1215. BOOL HideCaret() throw()
  1216. {
  1217. ATLASSERT(::IsWindow(m_hWnd));
  1218. return ::HideCaret(m_hWnd);
  1219. }
  1220. BOOL ShowCaret() throw()
  1221. {
  1222. ATLASSERT(::IsWindow(m_hWnd));
  1223. return ::ShowCaret(m_hWnd);
  1224. }
  1225. #ifdef _INC_SHELLAPI
  1226. // Drag-Drop Functions
  1227. void DragAcceptFiles(BOOL bAccept = TRUE) throw()
  1228. {
  1229. ATLASSERT(::IsWindow(m_hWnd)); ::DragAcceptFiles(m_hWnd, bAccept);
  1230. }
  1231. #endif
  1232. // Icon Functions
  1233. HICON SetIcon(HICON hIcon, BOOL bBigIcon = TRUE) throw()
  1234. {
  1235. ATLASSERT(::IsWindow(m_hWnd));
  1236. return (HICON)::SendMessage(m_hWnd, WM_SETICON, bBigIcon, (LPARAM)hIcon);
  1237. }
  1238. HICON GetIcon(BOOL bBigIcon = TRUE) const throw()
  1239. {
  1240. ATLASSERT(::IsWindow(m_hWnd));
  1241. return (HICON)::SendMessage(m_hWnd, WM_GETICON, bBigIcon, 0);
  1242. }
  1243. // Help Functions
  1244. BOOL WinHelp(LPCTSTR lpszHelp, UINT nCmd = HELP_CONTEXT, DWORD dwData = 0) throw()
  1245. {
  1246. ATLASSERT(::IsWindow(m_hWnd));
  1247. return ::WinHelp(m_hWnd, lpszHelp, nCmd, dwData);
  1248. }
  1249. BOOL SetWindowContextHelpId(DWORD dwContextHelpId) throw()
  1250. {
  1251. ATLASSERT(::IsWindow(m_hWnd));
  1252. return ::SetWindowContextHelpId(m_hWnd, dwContextHelpId);
  1253. }
  1254. DWORD GetWindowContextHelpId() const throw()
  1255. {
  1256. ATLASSERT(::IsWindow(m_hWnd));
  1257. return ::GetWindowContextHelpId(m_hWnd);
  1258. }
  1259. // Hot Key Functions
  1260. int SetHotKey(WORD wVirtualKeyCode, WORD wModifiers) throw()
  1261. {
  1262. ATLASSERT(::IsWindow(m_hWnd));
  1263. return (int)::SendMessage(m_hWnd, WM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0);
  1264. }
  1265. DWORD GetHotKey() const throw()
  1266. {
  1267. ATLASSERT(::IsWindow(m_hWnd));
  1268. return (DWORD)::SendMessage(m_hWnd, WM_GETHOTKEY, 0, 0);
  1269. }
  1270. // Misc. Operations
  1271. //N new
  1272. BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) throw()
  1273. {
  1274. ATLASSERT(::IsWindow(m_hWnd));
  1275. return ::GetScrollInfo(m_hWnd, nBar, lpScrollInfo);
  1276. }
  1277. int SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) throw()
  1278. {
  1279. ATLASSERT(::IsWindow(m_hWnd));
  1280. return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw);
  1281. }
  1282. BOOL IsDialogMessage(LPMSG lpMsg) throw()
  1283. {
  1284. ATLASSERT(::IsWindow(m_hWnd));
  1285. return ::IsDialogMessage(m_hWnd, lpMsg);
  1286. }
  1287. void NextDlgCtrl() const throw()
  1288. {
  1289. ATLASSERT(::IsWindow(m_hWnd));
  1290. ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0L);
  1291. }
  1292. void PrevDlgCtrl() const throw()
  1293. {
  1294. ATLASSERT(::IsWindow(m_hWnd));
  1295. ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 1, 0L);
  1296. }
  1297. void GotoDlgCtrl(HWND hWndCtrl) const throw()
  1298. {
  1299. ATLASSERT(::IsWindow(m_hWnd));
  1300. ::SendMessage(m_hWnd, WM_NEXTDLGCTL, (WPARAM)hWndCtrl, 1L);
  1301. }
  1302. BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw = TRUE) throw()
  1303. {
  1304. ATLASSERT(::IsWindow(m_hWnd));
  1305. RECT rcWnd;
  1306. if(!GetClientRect(&rcWnd))
  1307. return FALSE;
  1308. if(nWidth != -1)
  1309. rcWnd.right = nWidth;
  1310. if(nHeight != -1)
  1311. rcWnd.bottom = nHeight;
  1312. if(!::AdjustWindowRectEx(&rcWnd, GetStyle(), (!(GetStyle() & WS_CHILD) && (GetMenu() != NULL)), GetExStyle()))
  1313. return FALSE;
  1314. UINT uFlags = SWP_NOZORDER | SWP_NOMOVE;
  1315. if(!bRedraw)
  1316. uFlags |= SWP_NOREDRAW;
  1317. return SetWindowPos(NULL, 0, 0, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, uFlags);
  1318. }
  1319. int GetWindowRgn(HRGN hRgn) throw()
  1320. {
  1321. ATLASSERT(::IsWindow(m_hWnd));
  1322. return ::GetWindowRgn(m_hWnd, hRgn);
  1323. }
  1324. int SetWindowRgn(HRGN hRgn, BOOL bRedraw = FALSE) throw()
  1325. {
  1326. ATLASSERT(::IsWindow(m_hWnd));
  1327. return ::SetWindowRgn(m_hWnd, hRgn, bRedraw);
  1328. }
  1329. HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) throw()
  1330. {
  1331. ATLASSERT(::IsWindow(m_hWnd));
  1332. return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
  1333. }
  1334. DWORD GetWindowThreadID() throw()
  1335. {
  1336. ATLASSERT(::IsWindow(m_hWnd));
  1337. return ::GetWindowThreadProcessId(m_hWnd, NULL);
  1338. }
  1339. DWORD GetWindowProcessID() throw()
  1340. {
  1341. ATLASSERT(::IsWindow(m_hWnd));
  1342. DWORD dwProcessID;
  1343. ::GetWindowThreadProcessId(m_hWnd, &dwProcessID);
  1344. return dwProcessID;
  1345. }
  1346. BOOL IsWindow() const throw()
  1347. {
  1348. return ::IsWindow(m_hWnd);
  1349. }
  1350. BOOL IsWindowUnicode() const throw()
  1351. {
  1352. ATLASSERT(::IsWindow(m_hWnd));
  1353. return ::IsWindowUnicode(m_hWnd);
  1354. }
  1355. BOOL IsParentDialog() throw()
  1356. {
  1357. ATLASSERT(::IsWindow(m_hWnd));
  1358. TCHAR szBuf[8]; // "#32770" + NUL character
  1359. if (GetClassName(GetParent(), szBuf, sizeof(szBuf)/sizeof(TCHAR)) == 0)
  1360. return FALSE;
  1361. return lstrcmp(szBuf, _T("#32770")) == 0;
  1362. }
  1363. BOOL ShowWindowAsync(int nCmdShow) throw()
  1364. {
  1365. ATLASSERT(::IsWindow(m_hWnd));
  1366. return ::ShowWindowAsync(m_hWnd, nCmdShow);
  1367. }
  1368. CWindow GetDescendantWindow(int nID) const throw()
  1369. {
  1370. ATLASSERT(::IsWindow(m_hWnd));
  1371. // GetDlgItem recursive (return first found)
  1372. // breadth-first for 1 level, then depth-first for next level
  1373. // use GetDlgItem since it is a fast USER function
  1374. HWND hWndChild, hWndTmp;
  1375. if((hWndChild = ::GetDlgItem(m_hWnd, nID)) != NULL)
  1376. {
  1377. if(::GetTopWindow(hWndChild) != NULL)
  1378. {
  1379. // children with the same ID as their parent have priority
  1380. CWindow wnd(hWndChild);
  1381. hWndTmp = wnd.GetDescendantWindow(nID);
  1382. if(hWndTmp != NULL)
  1383. return CWindow(hWndTmp);
  1384. }
  1385. return CWindow(hWndChild);
  1386. }
  1387. // walk each child
  1388. for(hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  1389. hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  1390. {
  1391. CWindow wnd(hWndChild);
  1392. hWndTmp = wnd.GetDescendantWindow(nID);
  1393. if(hWndTmp != NULL)
  1394. return CWindow(hWndTmp);
  1395. }
  1396. return CWindow(NULL); // not found
  1397. }
  1398. void SendMessageToDescendants(UINT message, WPARAM wParam = 0, LPARAM lParam = 0, BOOL bDeep = TRUE) throw()
  1399. {
  1400. for(HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  1401. hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  1402. {
  1403. ::SendMessage(hWndChild, message, wParam, lParam);
  1404. if(bDeep && ::GetTopWindow(hWndChild) != NULL)
  1405. {
  1406. // send to child windows after parent
  1407. CWindow wnd(hWndChild);
  1408. wnd.SendMessageToDescendants(message, wParam, lParam, bDeep);
  1409. }
  1410. }
  1411. }
  1412. BOOL CenterWindow(HWND hWndCenter = NULL) throw()
  1413. {
  1414. ATLASSERT(::IsWindow(m_hWnd));
  1415. // determine owner window to center against
  1416. DWORD dwStyle = GetStyle();
  1417. if(hWndCenter == NULL)
  1418. {
  1419. if(dwStyle & WS_CHILD)
  1420. hWndCenter = ::GetParent(m_hWnd);
  1421. else
  1422. hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
  1423. }
  1424. // get coordinates of the window relative to its parent
  1425. RECT rcDlg;
  1426. ::GetWindowRect(m_hWnd, &rcDlg);
  1427. RECT rcArea;
  1428. RECT rcCenter;
  1429. HWND hWndParent;
  1430. if(!(dwStyle & WS_CHILD))
  1431. {
  1432. // don't center against invisible or minimized windows
  1433. if(hWndCenter != NULL)
  1434. {
  1435. DWORD dwStyleCenter = ::GetWindowLong(hWndCenter, GWL_STYLE);
  1436. if(!(dwStyleCenter & WS_VISIBLE) || (dwStyleCenter & WS_MINIMIZE))
  1437. hWndCenter = NULL;
  1438. }
  1439. // center within screen coordinates
  1440. ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);
  1441. if(hWndCenter == NULL)
  1442. rcCenter = rcArea;
  1443. else
  1444. ::GetWindowRect(hWndCenter, &rcCenter);
  1445. }
  1446. else
  1447. {
  1448. // center within parent client coordinates
  1449. hWndParent = ::GetParent(m_hWnd);
  1450. ATLASSERT(::IsWindow(hWndParent));
  1451. ::GetClientRect(hWndParent, &rcArea);
  1452. ATLASSERT(::IsWindow(hWndCenter));
  1453. ::GetClientRect(hWndCenter, &rcCenter);
  1454. ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
  1455. }
  1456. int DlgWidth = rcDlg.right - rcDlg.left;
  1457. int DlgHeight = rcDlg.bottom - rcDlg.top;
  1458. // find dialog's upper left based on rcCenter
  1459. int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2;
  1460. int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;
  1461. // if the dialog is outside the screen, move it inside
  1462. if(xLeft < rcArea.left)
  1463. xLeft = rcArea.left;
  1464. else if(xLeft + DlgWidth > rcArea.right)
  1465. xLeft = rcArea.right - DlgWidth;
  1466. if(yTop < rcArea.top)
  1467. yTop = rcArea.top;
  1468. else if(yTop + DlgHeight > rcArea.bottom)
  1469. yTop = rcArea.bottom - DlgHeight;
  1470. // map screen coordinates to child coordinates
  1471. return ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1,
  1472. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  1473. }
  1474. BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0) throw()
  1475. {
  1476. ATLASSERT(::IsWindow(m_hWnd));
  1477. DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
  1478. DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  1479. if(dwStyle == dwNewStyle)
  1480. return FALSE;
  1481. ::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle);
  1482. if(nFlags != 0)
  1483. {
  1484. ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
  1485. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  1486. }
  1487. return TRUE;
  1488. }
  1489. BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0) throw()
  1490. {
  1491. ATLASSERT(::IsWindow(m_hWnd));
  1492. DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
  1493. DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  1494. if(dwStyle == dwNewStyle)
  1495. return FALSE;
  1496. ::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwNewStyle);
  1497. if(nFlags != 0)
  1498. {
  1499. ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
  1500. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  1501. }
  1502. return TRUE;
  1503. }
  1504. #ifdef _OLEAUTO_H_
  1505. BOOL GetWindowText(BSTR* pbstrText) throw()
  1506. {
  1507. return GetWindowText(*pbstrText);
  1508. }
  1509. BOOL GetWindowText(BSTR& bstrText) throw()
  1510. {
  1511. USES_CONVERSION;
  1512. ATLASSERT(::IsWindow(m_hWnd));
  1513. if (bstrText != NULL)
  1514. {
  1515. SysFreeString(bstrText);
  1516. bstrText = NULL;
  1517. }
  1518. int nLen = ::GetWindowTextLength(m_hWnd);
  1519. if(nLen == 0)
  1520. {
  1521. bstrText = ::SysAllocString(OLESTR(""));
  1522. return (bstrText != NULL) ? TRUE : FALSE;
  1523. }
  1524. LPTSTR lpszText = (LPTSTR)_alloca((nLen+1)*sizeof(TCHAR));
  1525. if(!::GetWindowText(m_hWnd, lpszText, nLen+1))
  1526. return FALSE;
  1527. bstrText = ::SysAllocString(T2OLE(lpszText));
  1528. return (bstrText != NULL) ? TRUE : FALSE;
  1529. }
  1530. #endif // _OLEAUTO_H_
  1531. CWindow GetTopLevelParent() const throw()
  1532. {
  1533. ATLASSERT(::IsWindow(m_hWnd));
  1534. HWND hWndParent = m_hWnd;
  1535. HWND hWndTmp;
  1536. while((hWndTmp = ::GetParent(hWndParent)) != NULL)
  1537. hWndParent = hWndTmp;
  1538. return CWindow(hWndParent);
  1539. }
  1540. CWindow GetTopLevelWindow() const throw()
  1541. {
  1542. ATLASSERT(::IsWindow(m_hWnd));
  1543. HWND hWndParent;
  1544. HWND hWndTmp = m_hWnd;
  1545. do
  1546. {
  1547. hWndParent = hWndTmp;
  1548. hWndTmp = (::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) ? ::GetParent(hWndParent) : ::GetWindow(hWndParent, GW_OWNER);
  1549. }
  1550. while(hWndTmp != NULL);
  1551. return CWindow(hWndParent);
  1552. }
  1553. };
  1554. _declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
  1555. /////////////////////////////////////////////////////////////////////////////
  1556. // CAxWindow - client side for an ActiveX host window
  1557. #ifndef _ATL_NO_HOSTING
  1558. template <class TBase = CWindow>
  1559. class CAxWindowT : public TBase
  1560. {
  1561. public:
  1562. // Constructors
  1563. CAxWindowT(HWND hWnd = NULL) : TBase(hWnd)
  1564. {
  1565. AtlAxWinInit();
  1566. }
  1567. CAxWindowT< TBase >& operator=(HWND hWnd)
  1568. {
  1569. m_hWnd = hWnd;
  1570. return *this;
  1571. }
  1572. // Attributes
  1573. static LPCTSTR GetWndClassName()
  1574. {
  1575. return _T(ATLAXWIN_CLASS);
  1576. }
  1577. // Operations
  1578. HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
  1579. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  1580. _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
  1581. {
  1582. return CWindow::Create(GetWndClassName(), hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam);
  1583. }
  1584. HRESULT CreateControl(LPCOLESTR lpszName, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL)
  1585. {
  1586. return CreateControlEx(lpszName, pStream, ppUnkContainer);
  1587. }
  1588. HRESULT CreateControl(DWORD dwResID, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL)
  1589. {
  1590. return CreateControlEx(dwResID, pStream, ppUnkContainer);
  1591. }
  1592. HRESULT CreateControlEx(LPCOLESTR lpszName, IStream* pStream = NULL,
  1593. IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL,
  1594. REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL)
  1595. {
  1596. ATLASSERT(::IsWindow(m_hWnd));
  1597. // We must have a valid window!
  1598. // Get a pointer to the container object connected to this window
  1599. CComPtr<IAxWinHostWindow> spWinHost;
  1600. HRESULT hr = QueryHost(&spWinHost);
  1601. // If QueryHost failed, there is no host attached to this window
  1602. // We assume that the user wants to create a new host and subclass the current window
  1603. if (FAILED(hr))
  1604. return AtlAxCreateControlEx(lpszName, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink);
  1605. // Create the control requested by the caller
  1606. CComPtr<IUnknown> pControl;
  1607. if (SUCCEEDED(hr))
  1608. hr = spWinHost->CreateControlEx(lpszName, m_hWnd, pStream, &pControl, iidSink, punkSink);
  1609. // Send back the necessary interface pointers
  1610. if (SUCCEEDED(hr))
  1611. {
  1612. if (ppUnkControl)
  1613. *ppUnkControl = pControl.Detach();
  1614. if (ppUnkContainer)
  1615. {
  1616. hr = spWinHost.QueryInterface(ppUnkContainer);
  1617. ATLASSERT(SUCCEEDED(hr)); // This should not fail!
  1618. }
  1619. }
  1620. return hr;
  1621. }
  1622. HRESULT CreateControlEx(DWORD dwResID, IStream* pStream = NULL,
  1623. IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL,
  1624. REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL)
  1625. {
  1626. TCHAR szModule[_MAX_PATH];
  1627. GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szModule, _MAX_PATH);
  1628. CComBSTR bstrURL(OLESTR("res://"));
  1629. bstrURL.Append(szModule);
  1630. bstrURL.Append(OLESTR("/"));
  1631. TCHAR szResID[11];
  1632. wsprintf(szResID, _T("%0d"), dwResID);
  1633. bstrURL.Append(szResID);
  1634. ATLASSERT(::IsWindow(m_hWnd));
  1635. return CreateControlEx(bstrURL, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink);
  1636. }
  1637. HRESULT AttachControl(IUnknown* pControl, IUnknown** ppUnkContainer)
  1638. {
  1639. ATLASSERT(::IsWindow(m_hWnd));
  1640. // We must have a valid window!
  1641. // Get a pointer to the container object connected to this window
  1642. CComPtr<IAxWinHostWindow> spWinHost;
  1643. HRESULT hr = QueryHost(&spWinHost);
  1644. // If QueryHost failed, there is no host attached to this window
  1645. // We assume that the user wants to create a new host and subclass the current window
  1646. if (FAILED(hr))
  1647. return AtlAxAttachControl(pControl, m_hWnd, ppUnkContainer);
  1648. // Attach the control specified by the caller
  1649. if (SUCCEEDED(hr))
  1650. hr = spWinHost->AttachControl(pControl, m_hWnd);
  1651. // Get the IUnknown interface of the container
  1652. if (SUCCEEDED(hr) && ppUnkContainer)
  1653. {
  1654. hr = spWinHost.QueryInterface(ppUnkContainer);
  1655. ATLASSERT(SUCCEEDED(hr)); // This should not fail!
  1656. }
  1657. return hr;
  1658. }
  1659. HRESULT QueryHost(REFIID iid, void** ppUnk)
  1660. {
  1661. ATLASSERT(ppUnk != NULL);
  1662. if (ppUnk == NULL)
  1663. return E_POINTER;
  1664. HRESULT hr;
  1665. *ppUnk = NULL;
  1666. CComPtr<IUnknown> spUnk;
  1667. hr = AtlAxGetHost(m_hWnd, &spUnk);
  1668. if (SUCCEEDED(hr))
  1669. hr = spUnk->QueryInterface(iid, ppUnk);
  1670. return hr;
  1671. }
  1672. template <class Q>
  1673. HRESULT QueryHost(Q** ppUnk)
  1674. {
  1675. return QueryHost(__uuidof(Q), (void**)ppUnk);
  1676. }
  1677. HRESULT QueryControl(REFIID iid, void** ppUnk)
  1678. {
  1679. ATLASSERT(ppUnk != NULL);
  1680. if (ppUnk == NULL)
  1681. return E_POINTER;
  1682. HRESULT hr;
  1683. *ppUnk = NULL;
  1684. CComPtr<IUnknown> spUnk;
  1685. hr = AtlAxGetControl(m_hWnd, &spUnk);
  1686. if (SUCCEEDED(hr))
  1687. hr = spUnk->QueryInterface(iid, ppUnk);
  1688. return hr;
  1689. }
  1690. template <class Q>
  1691. HRESULT QueryControl(Q** ppUnk)
  1692. {
  1693. return QueryControl(__uuidof(Q), (void**)ppUnk);
  1694. }
  1695. HRESULT SetExternalDispatch(IDispatch* pDisp)
  1696. {
  1697. HRESULT hr;
  1698. CComPtr<IAxWinHostWindow> spHost;
  1699. hr = QueryHost(__uuidof(IAxWinHostWindow), (void**)&spHost);
  1700. if (SUCCEEDED(hr))
  1701. hr = spHost->SetExternalDispatch(pDisp);
  1702. return hr;
  1703. }
  1704. HRESULT SetExternalUIHandler(IDocHostUIHandlerDispatch* pUIHandler)
  1705. {
  1706. HRESULT hr;
  1707. CComPtr<IAxWinHostWindow> spHost;
  1708. hr = QueryHost(__uuidof(IAxWinHostWindow), (void**)&spHost);
  1709. if (SUCCEEDED(hr))
  1710. hr = spHost->SetExternalUIHandler(pUIHandler);
  1711. return hr;
  1712. }
  1713. };
  1714. typedef CAxWindowT<CWindow> CAxWindow;
  1715. template <class TBase = CWindow>
  1716. class CAxWindow2T : public CAxWindowT<TBase>
  1717. {
  1718. public:
  1719. // Constructors
  1720. CAxWindow2T(HWND hWnd = NULL) : CAxWindowT<TBase>(hWnd)
  1721. {
  1722. }
  1723. CAxWindow2T< TBase >& operator=(HWND hWnd)
  1724. {
  1725. m_hWnd = hWnd;
  1726. return *this;
  1727. }
  1728. // Attributes
  1729. static LPCTSTR GetWndClassName()
  1730. {
  1731. return _T(ATLAXWINLIC_CLASS);
  1732. }
  1733. // Operations
  1734. HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
  1735. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  1736. _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
  1737. {
  1738. return CWindow::Create(GetWndClassName(), hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam);
  1739. }
  1740. HRESULT CreateControlLic(LPCOLESTR lpszName, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL, BSTR bstrLicKey = NULL)
  1741. {
  1742. return CreateControlLicEx(lpszName, pStream, ppUnkContainer, NULL, IID_NULL, NULL, bstrLicKey);
  1743. }
  1744. HRESULT CreateControlLic(DWORD dwResID, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL, BSTR bstrLicKey = NULL)
  1745. {
  1746. return CreateControlLicEx(dwResID, pStream, ppUnkContainer, NULL, IID_NULL, NULL, bstrLicKey);
  1747. }
  1748. HRESULT CreateControlLicEx(LPCOLESTR lpszName, IStream* pStream = NULL,
  1749. IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL,
  1750. REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL, BSTR bstrLicKey = NULL)
  1751. {
  1752. ATLASSERT(::IsWindow(m_hWnd));
  1753. // We must have a valid window!
  1754. // Get a pointer to the container object connected to this window
  1755. CComPtr<IAxWinHostWindowLic> spWinHost;
  1756. HRESULT hr = QueryHost(&spWinHost);
  1757. // If QueryHost failed, there is no host attached to this window
  1758. // We assume that the user wants to create a new host and subclass the current window
  1759. if (FAILED(hr))
  1760. return AtlAxCreateControlLicEx(lpszName, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink, bstrLicKey);
  1761. // Create the control requested by the caller
  1762. CComPtr<IUnknown> pControl;
  1763. if (SUCCEEDED(hr))
  1764. hr = spWinHost->CreateControlLicEx(lpszName, m_hWnd, pStream, &pControl, iidSink, punkSink, bstrLicKey);
  1765. // Send back the necessary interface pointers
  1766. if (SUCCEEDED(hr))
  1767. {
  1768. if (ppUnkControl)
  1769. *ppUnkControl = pControl.Detach();
  1770. if (ppUnkContainer)
  1771. {
  1772. hr = spWinHost.QueryInterface(ppUnkContainer);
  1773. ATLASSERT(SUCCEEDED(hr)); // This should not fail!
  1774. }
  1775. }
  1776. return hr;
  1777. }
  1778. HRESULT CreateControlLicEx(DWORD dwResID, IStream* pStream = NULL,
  1779. IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL,
  1780. REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL, BSTR bstrLickey = NULL)
  1781. {
  1782. TCHAR szModule[_MAX_PATH];
  1783. GetModuleFileName(_AtlBaseModule.GetModuleInstance(), szModule, _MAX_PATH);
  1784. CComBSTR bstrURL(OLESTR("res://"));
  1785. bstrURL.Append(szModule);
  1786. bstrURL.Append(OLESTR("/"));
  1787. TCHAR szResID[11];
  1788. wsprintf(szResID, _T("%0d"), dwResID);
  1789. bstrURL.Append(szResID);
  1790. ATLASSERT(::IsWindow(m_hWnd));
  1791. return CreateControlLicEx(bstrURL, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink, bstrLickey);
  1792. }
  1793. };
  1794. typedef CAxWindow2T<CWindow> CAxWindow2;
  1795. #endif //_ATL_NO_HOSTING
  1796. /////////////////////////////////////////////////////////////////////////////
  1797. // WindowProc thunks
  1798. class CWndProcThunk
  1799. {
  1800. public:
  1801. _AtlCreateWndData cd;
  1802. CStdCallThunk thunk;
  1803. void Init(WNDPROC proc, void* pThis)
  1804. {
  1805. thunk.Init((DWORD_PTR)proc, pThis);
  1806. }
  1807. WNDPROC GetWNDPROC()
  1808. {
  1809. return (WNDPROC)thunk.GetCodeAddress();
  1810. }
  1811. };
  1812. /////////////////////////////////////////////////////////////////////////////
  1813. // CMessageMap - abstract class that provides an interface for message maps
  1814. class ATL_NO_VTABLE CMessageMap
  1815. {
  1816. public:
  1817. virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
  1818. LRESULT& lResult, DWORD dwMsgMapID) = 0;
  1819. };
  1820. /////////////////////////////////////////////////////////////////////////////
  1821. // Message map
  1822. #define BEGIN_MSG_MAP(theClass) \
  1823. public: \
  1824. BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
  1825. { \
  1826. BOOL bHandled = TRUE; \
  1827. hWnd; \
  1828. uMsg; \
  1829. wParam; \
  1830. lParam; \
  1831. lResult; \
  1832. bHandled; \
  1833. switch(dwMsgMapID) \
  1834. { \
  1835. case 0:
  1836. #define ALT_MSG_MAP(msgMapID) \
  1837. break; \
  1838. case msgMapID:
  1839. #define MESSAGE_HANDLER(msg, func) \
  1840. if(uMsg == msg) \
  1841. { \
  1842. bHandled = TRUE; \
  1843. lResult = func(uMsg, wParam, lParam, bHandled); \
  1844. if(bHandled) \
  1845. return TRUE; \
  1846. }
  1847. #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \
  1848. if(uMsg >= msgFirst && uMsg <= msgLast) \
  1849. { \
  1850. bHandled = TRUE; \
  1851. lResult = func(uMsg, wParam, lParam, bHandled); \
  1852. if(bHandled) \
  1853. return TRUE; \
  1854. }
  1855. #define COMMAND_HANDLER(id, code, func) \
  1856. if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
  1857. { \
  1858. bHandled = TRUE; \
  1859. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  1860. if(bHandled) \
  1861. return TRUE; \
  1862. }
  1863. #define COMMAND_ID_HANDLER(id, func) \
  1864. if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \
  1865. { \
  1866. bHandled = TRUE; \
  1867. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  1868. if(bHandled) \
  1869. return TRUE; \
  1870. }
  1871. #define COMMAND_CODE_HANDLER(code, func) \
  1872. if(uMsg == WM_COMMAND && code == HIWORD(wParam)) \
  1873. { \
  1874. bHandled = TRUE; \
  1875. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  1876. if(bHandled) \
  1877. return TRUE; \
  1878. }
  1879. #define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
  1880. if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
  1881. { \
  1882. bHandled = TRUE; \
  1883. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  1884. if(bHandled) \
  1885. return TRUE; \
  1886. }
  1887. #define COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \
  1888. if(uMsg == WM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
  1889. { \
  1890. bHandled = TRUE; \
  1891. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  1892. if(bHandled) \
  1893. return TRUE; \
  1894. }
  1895. #define NOTIFY_HANDLER(id, cd, func) \
  1896. if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
  1897. { \
  1898. bHandled = TRUE; \
  1899. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  1900. if(bHandled) \
  1901. return TRUE; \
  1902. }
  1903. #define NOTIFY_ID_HANDLER(id, func) \
  1904. if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
  1905. { \
  1906. bHandled = TRUE; \
  1907. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  1908. if(bHandled) \
  1909. return TRUE; \
  1910. }
  1911. #define NOTIFY_CODE_HANDLER(cd, func) \
  1912. if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
  1913. { \
  1914. bHandled = TRUE; \
  1915. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  1916. if(bHandled) \
  1917. return TRUE; \
  1918. }
  1919. #define NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \
  1920. if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
  1921. { \
  1922. bHandled = TRUE; \
  1923. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  1924. if(bHandled) \
  1925. return TRUE; \
  1926. }
  1927. #define NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \
  1928. if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
  1929. { \
  1930. bHandled = TRUE; \
  1931. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  1932. if(bHandled) \
  1933. return TRUE; \
  1934. }
  1935. #define CHAIN_MSG_MAP(theChainClass) \
  1936. { \
  1937. if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
  1938. return TRUE; \
  1939. }
  1940. #define CHAIN_MSG_MAP_MEMBER(theChainMember) \
  1941. { \
  1942. if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
  1943. return TRUE; \
  1944. }
  1945. #define CHAIN_MSG_MAP_ALT(theChainClass, msgMapID) \
  1946. { \
  1947. if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
  1948. return TRUE; \
  1949. }
  1950. #define CHAIN_MSG_MAP_ALT_MEMBER(theChainMember, msgMapID) \
  1951. { \
  1952. if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
  1953. return TRUE; \
  1954. }
  1955. #define CHAIN_MSG_MAP_DYNAMIC(dynaChainID) \
  1956. { \
  1957. if(CDynamicChain::CallChain(dynaChainID, hWnd, uMsg, wParam, lParam, lResult)) \
  1958. return TRUE; \
  1959. }
  1960. #define END_MSG_MAP() \
  1961. break; \
  1962. default: \
  1963. ATLTRACE(ATL::atlTraceWindowing, 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID); \
  1964. ATLASSERT(FALSE); \
  1965. break; \
  1966. } \
  1967. return FALSE; \
  1968. }
  1969. // Handler prototypes:
  1970. // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  1971. // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
  1972. // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
  1973. // Empty message map macro
  1974. #define DECLARE_EMPTY_MSG_MAP() \
  1975. public: \
  1976. BOOL ProcessWindowMessage(HWND, UINT, WPARAM, LPARAM, LRESULT&, DWORD = 0) \
  1977. { \
  1978. return FALSE; \
  1979. }
  1980. // Message forwarding and reflection macros
  1981. #define FORWARD_NOTIFICATIONS() \
  1982. { \
  1983. bHandled = TRUE; \
  1984. lResult = ForwardNotifications(uMsg, wParam, lParam, bHandled); \
  1985. if(bHandled) \
  1986. return TRUE; \
  1987. }
  1988. #define REFLECT_NOTIFICATIONS() \
  1989. { \
  1990. bHandled = TRUE; \
  1991. lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \
  1992. if(bHandled) \
  1993. return TRUE; \
  1994. }
  1995. #define DEFAULT_REFLECTION_HANDLER() \
  1996. if(DefaultReflectionHandler(hWnd, uMsg, wParam, lParam, lResult)) \
  1997. return TRUE;
  1998. #define REFLECTED_COMMAND_HANDLER(id, code, func) \
  1999. if(uMsg == OCM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
  2000. { \
  2001. bHandled = TRUE; \
  2002. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  2003. if(bHandled) \
  2004. return TRUE; \
  2005. }
  2006. #define REFLECTED_COMMAND_ID_HANDLER(id, func) \
  2007. if(uMsg == OCM_COMMAND && id == LOWORD(wParam)) \
  2008. { \
  2009. bHandled = TRUE; \
  2010. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  2011. if(bHandled) \
  2012. return TRUE; \
  2013. }
  2014. #define REFLECTED_COMMAND_CODE_HANDLER(code, func) \
  2015. if(uMsg == OCM_COMMAND && code == HIWORD(wParam)) \
  2016. { \
  2017. bHandled = TRUE; \
  2018. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  2019. if(bHandled) \
  2020. return TRUE; \
  2021. }
  2022. #define REFLECTED_COMMAND_RANGE_HANDLER(idFirst, idLast, func) \
  2023. if(uMsg == OCM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
  2024. { \
  2025. bHandled = TRUE; \
  2026. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  2027. if(bHandled) \
  2028. return TRUE; \
  2029. }
  2030. #define REFLECTED_COMMAND_RANGE_CODE_HANDLER(idFirst, idLast, code, func) \
  2031. if(uMsg == OCM_COMMAND && code == HIWORD(wParam) && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \
  2032. { \
  2033. bHandled = TRUE; \
  2034. lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
  2035. if(bHandled) \
  2036. return TRUE; \
  2037. }
  2038. #define REFLECTED_NOTIFY_HANDLER(id, cd, func) \
  2039. if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
  2040. { \
  2041. bHandled = TRUE; \
  2042. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  2043. if(bHandled) \
  2044. return TRUE; \
  2045. }
  2046. #define REFLECTED_NOTIFY_ID_HANDLER(id, func) \
  2047. if(uMsg == OCM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \
  2048. { \
  2049. bHandled = TRUE; \
  2050. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  2051. if(bHandled) \
  2052. return TRUE; \
  2053. }
  2054. #define REFLECTED_NOTIFY_CODE_HANDLER(cd, func) \
  2055. if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \
  2056. { \
  2057. bHandled = TRUE; \
  2058. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  2059. if(bHandled) \
  2060. return TRUE; \
  2061. }
  2062. #define REFLECTED_NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \
  2063. if(uMsg == OCM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
  2064. { \
  2065. bHandled = TRUE; \
  2066. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  2067. if(bHandled) \
  2068. return TRUE; \
  2069. }
  2070. #define REFLECTED_NOTIFY_RANGE_CODE_HANDLER(idFirst, idLast, cd, func) \
  2071. if(uMsg == OCM_NOTIFY && cd == ((LPNMHDR)lParam)->code && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \
  2072. { \
  2073. bHandled = TRUE; \
  2074. lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
  2075. if(bHandled) \
  2076. return TRUE; \
  2077. }
  2078. /////////////////////////////////////////////////////////////////////////////
  2079. // CDynamicChain - provides support for dynamic chaining
  2080. class CDynamicChain
  2081. {
  2082. public:
  2083. struct ATL_CHAIN_ENTRY
  2084. {
  2085. DWORD m_dwChainID;
  2086. CMessageMap* m_pObject;
  2087. DWORD m_dwMsgMapID;
  2088. };
  2089. CSimpleArray<ATL_CHAIN_ENTRY*> m_aChainEntry;
  2090. CDynamicChain()
  2091. { }
  2092. ~CDynamicChain()
  2093. {
  2094. for(int i = 0; i < m_aChainEntry.GetSize(); i++)
  2095. {
  2096. if(m_aChainEntry[i] != NULL)
  2097. delete m_aChainEntry[i];
  2098. }
  2099. }
  2100. BOOL SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID = 0)
  2101. {
  2102. // first search for an existing entry
  2103. int i;
  2104. for(i = 0; i < m_aChainEntry.GetSize(); i++)
  2105. {
  2106. if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID)
  2107. {
  2108. m_aChainEntry[i]->m_pObject = pObject;
  2109. m_aChainEntry[i]->m_dwMsgMapID = dwMsgMapID;
  2110. return TRUE;
  2111. }
  2112. }
  2113. // create a new one
  2114. ATL_CHAIN_ENTRY* pEntry = NULL;
  2115. ATLTRY(pEntry = new ATL_CHAIN_ENTRY);
  2116. if(pEntry == NULL)
  2117. return FALSE;
  2118. pEntry->m_dwChainID = dwChainID;
  2119. pEntry->m_pObject = pObject;
  2120. pEntry->m_dwMsgMapID = dwMsgMapID;
  2121. // search for an empty one
  2122. for(i = 0; i < m_aChainEntry.GetSize(); i++)
  2123. {
  2124. if(m_aChainEntry[i] == NULL)
  2125. {
  2126. m_aChainEntry[i] = pEntry;
  2127. return TRUE;
  2128. }
  2129. }
  2130. // add a new one
  2131. BOOL bRet = m_aChainEntry.Add(pEntry);
  2132. if(!bRet)
  2133. {
  2134. delete pEntry;
  2135. return FALSE;
  2136. }
  2137. return TRUE;
  2138. }
  2139. BOOL RemoveChainEntry(DWORD dwChainID)
  2140. {
  2141. for(int i = 0; i < m_aChainEntry.GetSize(); i++)
  2142. {
  2143. if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID)
  2144. {
  2145. delete m_aChainEntry[i];
  2146. m_aChainEntry[i] = NULL;
  2147. return TRUE;
  2148. }
  2149. }
  2150. return FALSE;
  2151. }
  2152. BOOL CallChain(DWORD dwChainID, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  2153. {
  2154. for(int i = 0; i < m_aChainEntry.GetSize(); i++)
  2155. {
  2156. if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID)
  2157. return (m_aChainEntry[i]->m_pObject)->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, m_aChainEntry[i]->m_dwMsgMapID);
  2158. }
  2159. return FALSE;
  2160. }
  2161. };
  2162. /////////////////////////////////////////////////////////////////////////////
  2163. // CWndClassInfo - Manages Windows class information
  2164. #define DECLARE_WND_CLASS(WndClassName) \
  2165. static ATL::CWndClassInfo& GetWndClassInfo() \
  2166. { \
  2167. static ATL::CWndClassInfo wc = \
  2168. { \
  2169. { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, \
  2170. 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
  2171. NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
  2172. }; \
  2173. return wc; \
  2174. }
  2175. #define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
  2176. static ATL::CWndClassInfo& GetWndClassInfo() \
  2177. { \
  2178. static ATL::CWndClassInfo wc = \
  2179. { \
  2180. { sizeof(WNDCLASSEX), style, StartWindowProc, \
  2181. 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
  2182. NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \
  2183. }; \
  2184. return wc; \
  2185. }
  2186. #define DECLARE_WND_SUPERCLASS(WndClassName, OrigWndClassName) \
  2187. static ATL::CWndClassInfo& GetWndClassInfo() \
  2188. { \
  2189. static ATL::CWndClassInfo wc = \
  2190. { \
  2191. { sizeof(WNDCLASSEX), 0, StartWindowProc, \
  2192. 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
  2193. OrigWndClassName, NULL, NULL, TRUE, 0, _T("") \
  2194. }; \
  2195. return wc; \
  2196. }
  2197. /////////////////////////////////////////////////////////////////////////////
  2198. // CWinTraits - Defines various default values for a window
  2199. template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
  2200. class CWinTraits
  2201. {
  2202. public:
  2203. static DWORD GetWndStyle(DWORD dwStyle)
  2204. {
  2205. return dwStyle == 0 ? t_dwStyle : dwStyle;
  2206. }
  2207. static DWORD GetWndExStyle(DWORD dwExStyle)
  2208. {
  2209. return dwExStyle == 0 ? t_dwExStyle : dwExStyle;
  2210. }
  2211. };
  2212. typedef CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0> CControlWinTraits;
  2213. typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> CFrameWinTraits;
  2214. typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD> CMDIChildWinTraits;
  2215. typedef CWinTraits<0, 0> CNullTraits;
  2216. template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0, class TWinTraits = CControlWinTraits>
  2217. class CWinTraitsOR
  2218. {
  2219. public:
  2220. static DWORD GetWndStyle(DWORD dwStyle)
  2221. {
  2222. return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle);
  2223. }
  2224. static DWORD GetWndExStyle(DWORD dwExStyle)
  2225. {
  2226. return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle);
  2227. }
  2228. };
  2229. /////////////////////////////////////////////////////////////////////////////
  2230. // CWindowImpl - Implements a window
  2231. template <class TBase = CWindow>
  2232. class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap
  2233. {
  2234. public:
  2235. CWndProcThunk m_thunk;
  2236. const _ATL_MSG* m_pCurrentMsg;
  2237. DWORD m_dwState;
  2238. enum { WINSTATE_DESTROYED = 0x00000001 };
  2239. // Constructor/destructor
  2240. CWindowImplRoot() : m_pCurrentMsg(NULL), m_dwState(0)
  2241. { }
  2242. ~CWindowImplRoot()
  2243. {
  2244. #ifdef _DEBUG
  2245. if(m_hWnd != NULL) // should be cleared in WindowProc
  2246. {
  2247. ATLTRACE(atlTraceWindowing, 0, _T("ERROR - Object deleted before window was destroyed\n"));
  2248. ATLASSERT(FALSE);
  2249. }
  2250. #endif //_DEBUG
  2251. }
  2252. // Current message
  2253. const _ATL_MSG* GetCurrentMessage() const
  2254. {
  2255. return m_pCurrentMsg;
  2256. }
  2257. // "handled" management for cracked handlers
  2258. BOOL IsMsgHandled() const
  2259. {
  2260. const _ATL_MSG* pMsg = GetCurrentMessage();
  2261. ATLASSERT(pMsg != NULL);
  2262. ATLASSERT(pMsg->cbSize >= sizeof(_ATL_MSG));
  2263. return pMsg->bHandled;
  2264. }
  2265. void SetMsgHandled(BOOL bHandled)
  2266. {
  2267. _ATL_MSG* pMsg = (_ATL_MSG*)GetCurrentMessage(); // override const
  2268. ATLASSERT(pMsg != NULL);
  2269. ATLASSERT(pMsg->cbSize >= sizeof(_ATL_MSG));
  2270. pMsg->bHandled = bHandled;
  2271. }
  2272. // Message forwarding and reflection support
  2273. LRESULT ForwardNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  2274. LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  2275. static BOOL DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult);
  2276. };
  2277. template <class TBase>
  2278. LRESULT CWindowImplRoot< TBase >::ForwardNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  2279. {
  2280. LRESULT lResult = 0;
  2281. switch(uMsg)
  2282. {
  2283. case WM_COMMAND:
  2284. case WM_NOTIFY:
  2285. case WM_PARENTNOTIFY:
  2286. case WM_DRAWITEM:
  2287. case WM_MEASUREITEM:
  2288. case WM_COMPAREITEM:
  2289. case WM_DELETEITEM:
  2290. case WM_VKEYTOITEM:
  2291. case WM_CHARTOITEM:
  2292. case WM_HSCROLL:
  2293. case WM_VSCROLL:
  2294. case WM_CTLCOLORBTN:
  2295. case WM_CTLCOLORDLG:
  2296. case WM_CTLCOLOREDIT:
  2297. case WM_CTLCOLORLISTBOX:
  2298. case WM_CTLCOLORMSGBOX:
  2299. case WM_CTLCOLORSCROLLBAR:
  2300. case WM_CTLCOLORSTATIC:
  2301. lResult = GetParent().SendMessage(uMsg, wParam, lParam);
  2302. break;
  2303. default:
  2304. bHandled = FALSE;
  2305. break;
  2306. }
  2307. return lResult;
  2308. }
  2309. template <class TBase>
  2310. LRESULT CWindowImplRoot< TBase >::ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  2311. {
  2312. HWND hWndChild = NULL;
  2313. switch(uMsg)
  2314. {
  2315. case WM_COMMAND:
  2316. if(lParam != NULL) // not from a menu
  2317. hWndChild = (HWND)lParam;
  2318. break;
  2319. case WM_NOTIFY:
  2320. hWndChild = ((LPNMHDR)lParam)->hwndFrom;
  2321. break;
  2322. case WM_PARENTNOTIFY:
  2323. switch(LOWORD(wParam))
  2324. {
  2325. case WM_CREATE:
  2326. case WM_DESTROY:
  2327. hWndChild = (HWND)lParam;
  2328. break;
  2329. default:
  2330. hWndChild = GetDlgItem(HIWORD(wParam));
  2331. break;
  2332. }
  2333. break;
  2334. case WM_DRAWITEM:
  2335. if(wParam) // not from a menu
  2336. hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
  2337. break;
  2338. case WM_MEASUREITEM:
  2339. if(wParam) // not from a menu
  2340. hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID);
  2341. break;
  2342. case WM_COMPAREITEM:
  2343. if(wParam) // not from a menu
  2344. hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID);
  2345. break;
  2346. case WM_DELETEITEM:
  2347. if(wParam) // not from a menu
  2348. hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID);
  2349. break;
  2350. case WM_VKEYTOITEM:
  2351. case WM_CHARTOITEM:
  2352. case WM_HSCROLL:
  2353. case WM_VSCROLL:
  2354. hWndChild = (HWND)lParam;
  2355. break;
  2356. case WM_CTLCOLORBTN:
  2357. case WM_CTLCOLORDLG:
  2358. case WM_CTLCOLOREDIT:
  2359. case WM_CTLCOLORLISTBOX:
  2360. case WM_CTLCOLORMSGBOX:
  2361. case WM_CTLCOLORSCROLLBAR:
  2362. case WM_CTLCOLORSTATIC:
  2363. hWndChild = (HWND)lParam;
  2364. break;
  2365. default:
  2366. break;
  2367. }
  2368. if(hWndChild == NULL)
  2369. {
  2370. bHandled = FALSE;
  2371. return 1;
  2372. }
  2373. ATLASSERT(::IsWindow(hWndChild));
  2374. return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
  2375. }
  2376. template <class TBase>
  2377. BOOL CWindowImplRoot< TBase >::DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  2378. {
  2379. switch(uMsg)
  2380. {
  2381. case OCM_COMMAND:
  2382. case OCM_NOTIFY:
  2383. case OCM_PARENTNOTIFY:
  2384. case OCM_DRAWITEM:
  2385. case OCM_MEASUREITEM:
  2386. case OCM_COMPAREITEM:
  2387. case OCM_DELETEITEM:
  2388. case OCM_VKEYTOITEM:
  2389. case OCM_CHARTOITEM:
  2390. case OCM_HSCROLL:
  2391. case OCM_VSCROLL:
  2392. case OCM_CTLCOLORBTN:
  2393. case OCM_CTLCOLORDLG:
  2394. case OCM_CTLCOLOREDIT:
  2395. case OCM_CTLCOLORLISTBOX:
  2396. case OCM_CTLCOLORMSGBOX:
  2397. case OCM_CTLCOLORSCROLLBAR:
  2398. case OCM_CTLCOLORSTATIC:
  2399. lResult = ::DefWindowProc(hWnd, uMsg - OCM__BASE, wParam, lParam);
  2400. return TRUE;
  2401. default:
  2402. break;
  2403. }
  2404. return FALSE;
  2405. }
  2406. template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
  2407. class ATL_NO_VTABLE CWindowImplBaseT : public CWindowImplRoot< TBase >
  2408. {
  2409. public:
  2410. WNDPROC m_pfnSuperWindowProc;
  2411. CWindowImplBaseT() : m_pfnSuperWindowProc(::DefWindowProc)
  2412. {}
  2413. static DWORD GetWndStyle(DWORD dwStyle)
  2414. {
  2415. return TWinTraits::GetWndStyle(dwStyle);
  2416. }
  2417. static DWORD GetWndExStyle(DWORD dwExStyle)
  2418. {
  2419. return TWinTraits::GetWndExStyle(dwExStyle);
  2420. }
  2421. virtual WNDPROC GetWindowProc()
  2422. {
  2423. return WindowProc;
  2424. }
  2425. static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  2426. static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  2427. HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName,
  2428. DWORD dwStyle, DWORD dwExStyle, _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam = NULL);
  2429. BOOL DestroyWindow()
  2430. {
  2431. ATLASSERT(::IsWindow(m_hWnd));
  2432. return ::DestroyWindow(m_hWnd);
  2433. }
  2434. BOOL SubclassWindow(HWND hWnd);
  2435. HWND UnsubclassWindow(BOOL bForce = FALSE);
  2436. LRESULT DefWindowProc()
  2437. {
  2438. const _ATL_MSG* pMsg = m_pCurrentMsg;
  2439. LRESULT lRes = 0;
  2440. if (pMsg != NULL)
  2441. lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
  2442. return lRes;
  2443. }
  2444. LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  2445. {
  2446. #ifdef STRICT
  2447. return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
  2448. #else
  2449. return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
  2450. #endif
  2451. }
  2452. virtual void OnFinalMessage(HWND /*hWnd*/)
  2453. {
  2454. // override to do something, if needed
  2455. }
  2456. };
  2457. typedef CWindowImplBaseT<CWindow> CWindowImplBase;
  2458. template <class TBase, class TWinTraits>
  2459. LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2460. {
  2461. CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)_AtlWinModule.ExtractCreateWndData();
  2462. ATLASSERT(pThis != NULL);
  2463. pThis->m_hWnd = hWnd;
  2464. pThis->m_thunk.Init(pThis->GetWindowProc(), pThis);
  2465. WNDPROC pProc = pThis->m_thunk.GetWNDPROC();
  2466. WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  2467. #ifdef _DEBUG
  2468. // check if somebody has subclassed us already since we discard it
  2469. if(pOldProc != StartWindowProc)
  2470. ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n"));
  2471. #else
  2472. pOldProc; // avoid unused warning
  2473. #endif
  2474. return pProc(hWnd, uMsg, wParam, lParam);
  2475. }
  2476. template <class TBase, class TWinTraits>
  2477. LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2478. {
  2479. CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)hWnd;
  2480. // set a ptr to this message and save the old value
  2481. _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
  2482. const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
  2483. pThis->m_pCurrentMsg = &msg;
  2484. // pass to the message map to process
  2485. LRESULT lRes;
  2486. BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
  2487. // restore saved value for the current message
  2488. ATLASSERT(pThis->m_pCurrentMsg == &msg);
  2489. pThis->m_pCurrentMsg = pOldMsg;
  2490. // do the default processing if message was not handled
  2491. if(!bRet)
  2492. {
  2493. if(uMsg != WM_NCDESTROY)
  2494. lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  2495. else
  2496. {
  2497. // unsubclass, if needed
  2498. LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
  2499. lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  2500. if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
  2501. ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
  2502. // mark window as destryed
  2503. pThis->m_dwState |= WINSTATE_DESTROYED;
  2504. }
  2505. }
  2506. if((pThis->m_dwState & WINSTATE_DESTROYED) && pThis->m_pCurrentMsg == NULL)
  2507. {
  2508. // clear out window handle
  2509. HWND hWnd = pThis->m_hWnd;
  2510. pThis->m_hWnd = NULL;
  2511. pThis->m_dwState &= ~WINSTATE_DESTROYED;
  2512. // clean up after window is destroyed
  2513. pThis->OnFinalMessage(hWnd);
  2514. }
  2515. return lRes;
  2516. }
  2517. template <class TBase, class TWinTraits>
  2518. HWND CWindowImplBaseT< TBase, TWinTraits >::Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName,
  2519. DWORD dwStyle, DWORD dwExStyle, _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
  2520. {
  2521. ATLASSERT(m_hWnd == NULL);
  2522. if(atom == 0)
  2523. return NULL;
  2524. _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
  2525. if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD))
  2526. MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
  2527. if(rect.m_lpRect == NULL)
  2528. rect.m_lpRect = &TBase::rcDefault;
  2529. HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName,
  2530. dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left,
  2531. rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu,
  2532. _AtlBaseModule.GetModuleInstance(), lpCreateParam);
  2533. ATLASSERT(m_hWnd == hWnd);
  2534. return hWnd;
  2535. }
  2536. template <class TBase, class TWinTraits>
  2537. BOOL CWindowImplBaseT< TBase, TWinTraits >::SubclassWindow(HWND hWnd)
  2538. {
  2539. ATLASSERT(m_hWnd == NULL);
  2540. ATLASSERT(::IsWindow(hWnd));
  2541. m_thunk.Init(GetWindowProc(), this);
  2542. WNDPROC pProc = m_thunk.GetWNDPROC();
  2543. WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  2544. if(pfnWndProc == NULL)
  2545. return FALSE;
  2546. m_pfnSuperWindowProc = pfnWndProc;
  2547. m_hWnd = hWnd;
  2548. return TRUE;
  2549. }
  2550. // Use only if you want to subclass before window is destroyed,
  2551. // WindowProc will automatically subclass when window goes away
  2552. template <class TBase, class TWinTraits>
  2553. HWND CWindowImplBaseT< TBase, TWinTraits >::UnsubclassWindow(BOOL bForce /*= FALSE*/)
  2554. {
  2555. ATLASSERT(m_hWnd != NULL);
  2556. WNDPROC pOurProc = m_thunk.GetWNDPROC();
  2557. WNDPROC pActiveProc = (WNDPROC)::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC);
  2558. HWND hWnd = NULL;
  2559. if (bForce || pOurProc == pActiveProc)
  2560. {
  2561. if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc))
  2562. return NULL;
  2563. m_pfnSuperWindowProc = ::DefWindowProc;
  2564. hWnd = m_hWnd;
  2565. m_hWnd = NULL;
  2566. }
  2567. return hWnd;
  2568. }
  2569. template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
  2570. class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits >
  2571. {
  2572. public:
  2573. DECLARE_WND_CLASS(NULL)
  2574. static LPCTSTR GetWndCaption()
  2575. {
  2576. return NULL;
  2577. }
  2578. HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
  2579. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  2580. _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
  2581. {
  2582. if (T::GetWndClassInfo().m_lpszOrigName == NULL)
  2583. T::GetWndClassInfo().m_lpszOrigName = GetWndClassName();
  2584. ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
  2585. dwStyle = T::GetWndStyle(dwStyle);
  2586. dwExStyle = T::GetWndExStyle(dwExStyle);
  2587. // set caption
  2588. if (szWindowName == NULL)
  2589. szWindowName = T::GetWndCaption();
  2590. return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rect, szWindowName,
  2591. dwStyle, dwExStyle, MenuOrID, atom, lpCreateParam);
  2592. }
  2593. };
  2594. template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
  2595. class ATL_NO_VTABLE CWindowWithReflectorImpl : public CWindowImpl< T, TBase, TWinTraits >
  2596. {
  2597. public:
  2598. HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
  2599. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  2600. _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
  2601. {
  2602. m_wndReflector.Create(hWndParent, rect, NULL, WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, Reflector::REFLECTOR_MAP_ID);
  2603. RECT rcPos = { 0, 0, rect.m_lpRect->right, rect.m_lpRect->bottom };
  2604. return CWindowImpl< T, TBase, TWinTraits >::Create(m_wndReflector, rcPos, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam);
  2605. }
  2606. // message map and handlers
  2607. typedef CWindowWithReflectorImpl< T, TBase, TWinTraits > thisClass;
  2608. BEGIN_MSG_MAP(thisClass)
  2609. MESSAGE_HANDLER(WM_NCDESTROY, OnNcDestroy)
  2610. MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChanging)
  2611. END_MSG_MAP()
  2612. LRESULT OnNcDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  2613. {
  2614. m_wndReflector.DestroyWindow();
  2615. bHandled = FALSE;
  2616. return 1;
  2617. }
  2618. LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
  2619. {
  2620. WINDOWPOS* pWP = (WINDOWPOS*)lParam;
  2621. m_wndReflector.SetWindowPos(m_wndReflector.GetParent(), pWP->x, pWP->y, pWP->cx, pWP->cy, pWP->flags);
  2622. pWP->flags |= SWP_NOMOVE;
  2623. pWP->x = 0;
  2624. pWP->y = 0;
  2625. return DefWindowProc(uMsg, wParam, lParam);
  2626. }
  2627. // reflector window stuff
  2628. class Reflector : public CWindowImpl<Reflector>
  2629. {
  2630. public:
  2631. enum { REFLECTOR_MAP_ID = 69 };
  2632. DECLARE_WND_CLASS_EX(_T("ATLReflectorWindow"), 0, -1)
  2633. BEGIN_MSG_MAP(Reflector)
  2634. REFLECT_NOTIFICATIONS()
  2635. END_MSG_MAP()
  2636. } m_wndReflector;
  2637. };
  2638. /////////////////////////////////////////////////////////////////////////////
  2639. // CDialogImpl - Implements a dialog box
  2640. #define _ATL_RT_DLGINIT MAKEINTRESOURCE(240)
  2641. template <class TBase = CWindow>
  2642. class ATL_NO_VTABLE CDialogImplBaseT : public CWindowImplRoot< TBase >
  2643. {
  2644. public:
  2645. virtual DLGPROC GetDialogProc()
  2646. {
  2647. return DialogProc;
  2648. }
  2649. static INT_PTR CALLBACK StartDialogProc(HWND hWnd, UINT uMsg,
  2650. WPARAM wParam, LPARAM lParam);
  2651. static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  2652. BOOL MapDialogRect(LPRECT lpRect)
  2653. {
  2654. ATLASSERT(::IsWindow(m_hWnd));
  2655. return ::MapDialogRect(m_hWnd, lpRect);
  2656. }
  2657. virtual void OnFinalMessage(HWND /*hWnd*/)
  2658. {
  2659. // override to do something, if needed
  2660. }
  2661. // has no meaning for a dialog, but needed for handlers that use it
  2662. LRESULT DefWindowProc()
  2663. {
  2664. return 0;
  2665. }
  2666. // initialize combobox and comboboxex from RT_DLGINIT resource if any
  2667. BOOL ExecuteDlgInit(int iDlgID)
  2668. {
  2669. BOOL bSuccess = TRUE;
  2670. HINSTANCE hInst = _AtlBaseModule.GetResourceInstance();
  2671. HRSRC hrsrc = ::FindResource(hInst, MAKEINTRESOURCE(iDlgID), _ATL_RT_DLGINIT);
  2672. if (hrsrc)
  2673. {
  2674. HGLOBAL hResData = ::LoadResource(hInst, hrsrc);
  2675. if (hResData)
  2676. {
  2677. UNALIGNED WORD* pDlgInit = (UNALIGNED WORD*)::LockResource(hResData);
  2678. if (pDlgInit)
  2679. {
  2680. USES_CONVERSION;
  2681. while (bSuccess && NULL != *pDlgInit)
  2682. {
  2683. WORD wID = *pDlgInit++;
  2684. WORD wMsg = *pDlgInit++;
  2685. DWORD dwSize = *((UNALIGNED DWORD*&)pDlgInit)++;
  2686. // CB_ADDSTRING is stored as 0x403
  2687. if (0x403 == wMsg)
  2688. {
  2689. if (-1 == SendDlgItemMessage(wID, CB_ADDSTRING, 0, (LPARAM)(A2T((LPSTR)pDlgInit))))
  2690. bSuccess = FALSE;
  2691. }
  2692. // CBEM_INSERTITEM is stored as 0x1234
  2693. else if (0x1234 == wMsg)
  2694. {
  2695. COMBOBOXEXITEM item;
  2696. item.mask = CBEIF_TEXT;
  2697. item.iItem = -1;
  2698. item.pszText = A2T(LPSTR(pDlgInit));
  2699. if (-1 == SendDlgItemMessage(wID, CBEM_INSERTITEM, 0, (LPARAM)&item))
  2700. bSuccess = FALSE;
  2701. }
  2702. pDlgInit = (LPWORD)((LPBYTE)pDlgInit + dwSize);
  2703. }
  2704. }
  2705. }
  2706. }
  2707. return bSuccess;
  2708. }
  2709. };
  2710. template <class TBase>
  2711. INT_PTR CALLBACK CDialogImplBaseT< TBase >::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2712. {
  2713. CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)_AtlWinModule.ExtractCreateWndData();
  2714. ATLASSERT(pThis != NULL);
  2715. pThis->m_hWnd = hWnd;
  2716. pThis->m_thunk.Init((WNDPROC)pThis->GetDialogProc(), pThis);
  2717. DLGPROC pProc = (DLGPROC)pThis->m_thunk.GetWNDPROC();
  2718. DLGPROC pOldProc = (DLGPROC)::SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)pProc);
  2719. #ifdef _DEBUG
  2720. // check if somebody has subclassed us already since we discard it
  2721. if(pOldProc != StartDialogProc)
  2722. ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n"));
  2723. #else
  2724. pOldProc; // avoid unused warning
  2725. #endif
  2726. return pProc(hWnd, uMsg, wParam, lParam);
  2727. }
  2728. template <class TBase>
  2729. INT_PTR CALLBACK CDialogImplBaseT< TBase >::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2730. {
  2731. CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)hWnd;
  2732. // set a ptr to this message and save the old value
  2733. _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
  2734. const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
  2735. pThis->m_pCurrentMsg = &msg;
  2736. // pass to the message map to process
  2737. LRESULT lRes;
  2738. BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
  2739. // restore saved value for the current message
  2740. ATLASSERT(pThis->m_pCurrentMsg == &msg);
  2741. pThis->m_pCurrentMsg = pOldMsg;
  2742. // set result if message was handled
  2743. if(bRet)
  2744. {
  2745. switch (uMsg)
  2746. {
  2747. case WM_COMPAREITEM:
  2748. case WM_VKEYTOITEM:
  2749. case WM_CHARTOITEM:
  2750. case WM_INITDIALOG:
  2751. case WM_QUERYDRAGICON:
  2752. case WM_CTLCOLORMSGBOX:
  2753. case WM_CTLCOLOREDIT:
  2754. case WM_CTLCOLORLISTBOX:
  2755. case WM_CTLCOLORBTN:
  2756. case WM_CTLCOLORDLG:
  2757. case WM_CTLCOLORSCROLLBAR:
  2758. case WM_CTLCOLORSTATIC:
  2759. // return directly
  2760. bRet = (BOOL)lRes;
  2761. break;
  2762. default:
  2763. // return in DWL_MSGRESULT
  2764. ::SetWindowLongPtr(pThis->m_hWnd, DWLP_MSGRESULT, lRes);
  2765. break;
  2766. }
  2767. }
  2768. else if(uMsg == WM_NCDESTROY)
  2769. {
  2770. // mark dialog as destryed
  2771. pThis->m_dwState |= WINSTATE_DESTROYED;
  2772. }
  2773. if((pThis->m_dwState & WINSTATE_DESTROYED) && pThis->m_pCurrentMsg == NULL)
  2774. {
  2775. // clear out window handle
  2776. HWND hWnd = pThis->m_hWnd;
  2777. pThis->m_hWnd = NULL;
  2778. pThis->m_dwState &= ~WINSTATE_DESTROYED;
  2779. // clean up after dialog is destroyed
  2780. pThis->OnFinalMessage(hWnd);
  2781. }
  2782. return bRet;
  2783. }
  2784. typedef CDialogImplBaseT<CWindow> CDialogImplBase;
  2785. template <class T, class TBase = CWindow>
  2786. class ATL_NO_VTABLE CDialogImpl : public CDialogImplBaseT< TBase >
  2787. {
  2788. public:
  2789. #ifdef _DEBUG
  2790. bool m_bModal;
  2791. CDialogImpl() : m_bModal(false) { }
  2792. #endif //_DEBUG
  2793. // modal dialogs
  2794. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
  2795. {
  2796. ATLASSERT(m_hWnd == NULL);
  2797. _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this);
  2798. #ifdef _DEBUG
  2799. m_bModal = true;
  2800. #endif //_DEBUG
  2801. T* pT;
  2802. pT = static_cast<T*>(this);
  2803. return ::DialogBoxParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(pT->IDD),
  2804. hWndParent, T::StartDialogProc, dwInitParam);
  2805. }
  2806. BOOL EndDialog(int nRetCode)
  2807. {
  2808. ATLASSERT(::IsWindow(m_hWnd));
  2809. ATLASSERT(m_bModal); // must be a modal dialog
  2810. return ::EndDialog(m_hWnd, nRetCode);
  2811. }
  2812. // modeless dialogs
  2813. HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
  2814. {
  2815. ATLASSERT(m_hWnd == NULL);
  2816. _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this);
  2817. #ifdef _DEBUG
  2818. m_bModal = false;
  2819. #endif //_DEBUG
  2820. T* pT;
  2821. pT = static_cast<T*>(this);
  2822. HWND hWnd = ::CreateDialogParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(pT->IDD),
  2823. hWndParent, T::StartDialogProc, dwInitParam);
  2824. ATLASSERT(m_hWnd == hWnd);
  2825. return hWnd;
  2826. }
  2827. // for CComControl
  2828. HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL)
  2829. {
  2830. return Create(hWndParent, dwInitParam);
  2831. }
  2832. BOOL DestroyWindow()
  2833. {
  2834. ATLASSERT(::IsWindow(m_hWnd));
  2835. ATLASSERT(!m_bModal); // must not be a modal dialog
  2836. return ::DestroyWindow(m_hWnd);
  2837. }
  2838. };
  2839. /////////////////////////////////////////////////////////////////////////////
  2840. // CAxDialogImpl - Implements a dialog box that hosts ActiveX controls
  2841. #ifndef _ATL_NO_HOSTING
  2842. template <class T, class TBase = CWindow>
  2843. class ATL_NO_VTABLE CAxDialogImpl : public CDialogImplBaseT< TBase >
  2844. {
  2845. public:
  2846. #ifdef _DEBUG
  2847. bool m_bModal;
  2848. CAxDialogImpl() : m_bModal(false) { }
  2849. #endif //_DEBUG
  2850. int GetIDD()
  2851. {
  2852. return( static_cast<T*>(this)->IDD );
  2853. }
  2854. virtual DLGPROC GetDialogProc()
  2855. {
  2856. return DialogProc;
  2857. }
  2858. static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  2859. // modal dialogs
  2860. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL)
  2861. {
  2862. ATLASSERT(m_hWnd == NULL);
  2863. _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this);
  2864. #ifdef _DEBUG
  2865. m_bModal = true;
  2866. #endif //_DEBUG
  2867. T* pT;
  2868. pT = static_cast<T*>(this);
  2869. return AtlAxDialogBox(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(pT->IDD),
  2870. hWndParent, T::StartDialogProc, dwInitParam);
  2871. }
  2872. BOOL EndDialog(int nRetCode)
  2873. {
  2874. ATLASSERT(::IsWindow(m_hWnd));
  2875. #ifdef _DEBUG
  2876. ATLASSERT(m_bModal); // must be a modal dialog
  2877. #endif //_DEBUG
  2878. return ::EndDialog(m_hWnd, nRetCode);
  2879. }
  2880. // modeless dialogs
  2881. HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL)
  2882. {
  2883. ATLASSERT(m_hWnd == NULL);
  2884. _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this);
  2885. #ifdef _DEBUG
  2886. m_bModal = false;
  2887. #endif //_DEBUG
  2888. T* pT;
  2889. pT = static_cast<T*>(this);
  2890. HWND hWnd = AtlAxCreateDialog(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(pT->IDD),
  2891. hWndParent, T::StartDialogProc, dwInitParam);
  2892. ATLASSERT(m_hWnd == hWnd);
  2893. return hWnd;
  2894. }
  2895. // for CComControl
  2896. HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL)
  2897. {
  2898. return Create(hWndParent, dwInitParam);
  2899. }
  2900. BOOL DestroyWindow()
  2901. {
  2902. ATLASSERT(::IsWindow(m_hWnd));
  2903. #ifdef _DEBUG
  2904. ATLASSERT(!m_bModal); // must not be a modal dialog
  2905. #endif //_DEBUG
  2906. return ::DestroyWindow(m_hWnd);
  2907. }
  2908. // Event handling support and Message map
  2909. HRESULT AdviseSinkMap(bool bAdvise)
  2910. {
  2911. if(!bAdvise && m_hWnd == NULL)
  2912. {
  2913. // window is gone, controls are already unadvised
  2914. ATLTRACE(atlTraceControls, 1, _T("CAxDialogImpl::AdviseSinkMap called after the window was destroyed\n"));
  2915. return S_OK;
  2916. }
  2917. HRESULT hRet = E_NOTIMPL;
  2918. __if_exists(T::_GetSinkMapFinder)
  2919. {
  2920. T* pT = static_cast<T*>(this);
  2921. hRet = AtlAdviseSinkMap(pT, bAdvise);
  2922. }
  2923. return hRet;
  2924. }
  2925. typedef CAxDialogImpl< T, TBase > thisClass;
  2926. BEGIN_MSG_MAP(thisClass)
  2927. MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
  2928. MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
  2929. END_MSG_MAP()
  2930. virtual HRESULT CreateActiveXControls(UINT nID)
  2931. {
  2932. // Load dialog template and InitData
  2933. HRSRC hDlgInit = ::FindResource(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)_ATL_RT_DLGINIT);
  2934. BYTE* pInitData = NULL;
  2935. HGLOBAL hData = NULL;
  2936. HRESULT hr = S_OK;
  2937. if (hDlgInit != NULL)
  2938. {
  2939. hData = ::LoadResource(_AtlBaseModule.GetResourceInstance(), hDlgInit);
  2940. if (hData != NULL)
  2941. pInitData = (BYTE*) ::LockResource(hData);
  2942. }
  2943. HRSRC hDlg = ::FindResource(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(nID), (LPTSTR)RT_DIALOG);
  2944. if (hDlg != NULL)
  2945. {
  2946. HGLOBAL hResource = ::LoadResource(_AtlBaseModule.GetResourceInstance(), hDlg);
  2947. DLGTEMPLATE* pDlg = NULL;
  2948. if (hResource != NULL)
  2949. {
  2950. pDlg = (DLGTEMPLATE*) ::LockResource(hResource);
  2951. if (pDlg != NULL)
  2952. {
  2953. // Get first control on the template
  2954. BOOL bDialogEx = _DialogSplitHelper::IsDialogEx(pDlg);
  2955. WORD nItems = _DialogSplitHelper::DlgTemplateItemCount(pDlg);
  2956. // Get first control on the dialog
  2957. DLGITEMTEMPLATE* pItem = _DialogSplitHelper::FindFirstDlgItem(pDlg);
  2958. HWND hWndPrev = GetWindow(GW_CHILD);
  2959. // Create all ActiveX cotnrols in the dialog template and place them in the correct tab order (z-order)
  2960. for (WORD nItem = 0; nItem < nItems; nItem++)
  2961. {
  2962. DWORD wID = bDialogEx ? ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id : pItem->id;
  2963. if (_DialogSplitHelper::IsActiveXControl(pItem, bDialogEx))
  2964. {
  2965. BYTE* pData = NULL;
  2966. DWORD dwLen = _DialogSplitHelper::FindCreateData(wID, pInitData, &pData);
  2967. CComPtr<IStream> spStream;
  2968. if (dwLen != 0)
  2969. {
  2970. HGLOBAL h = GlobalAlloc(GHND, dwLen);
  2971. if (h != NULL)
  2972. {
  2973. BYTE* pBytes = (BYTE*) GlobalLock(h);
  2974. BYTE* pSource = pData;
  2975. memcpy(pBytes, pSource, dwLen);
  2976. GlobalUnlock(h);
  2977. CreateStreamOnHGlobal(h, TRUE, &spStream);
  2978. }
  2979. else
  2980. {
  2981. hr = E_OUTOFMEMORY;
  2982. break;
  2983. }
  2984. }
  2985. CComBSTR bstrLicKey;
  2986. hr = _DialogSplitHelper::ParseInitData(spStream, &bstrLicKey.m_str);
  2987. if (SUCCEEDED(hr))
  2988. {
  2989. CAxWindow2 wnd;
  2990. // Get control caption.
  2991. LPWSTR pszClassName =
  2992. bDialogEx ?
  2993. (LPWSTR)(((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem) + 1) :
  2994. (LPWSTR)(pItem + 1);
  2995. // Get control rect.
  2996. RECT rect;
  2997. rect.left =
  2998. bDialogEx ?
  2999. ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->x :
  3000. pItem->x;
  3001. rect.top =
  3002. bDialogEx ?
  3003. ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->y :
  3004. pItem->y;
  3005. rect.right = rect.left +
  3006. (bDialogEx ?
  3007. ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cx :
  3008. pItem->cx);
  3009. rect.bottom = rect.top +
  3010. (bDialogEx ?
  3011. ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->cy :
  3012. pItem->cy);
  3013. // Convert from dialog units to screen units
  3014. MapDialogRect(&rect);
  3015. // Create AxWindow with a NULL caption.
  3016. wnd.Create(m_hWnd,
  3017. &rect,
  3018. NULL,
  3019. (bDialogEx ?
  3020. ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->style :
  3021. pItem->style) | WS_TABSTOP,
  3022. bDialogEx ?
  3023. ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->exStyle :
  3024. 0,
  3025. bDialogEx ?
  3026. ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->id :
  3027. pItem->id,
  3028. NULL);
  3029. if (wnd != NULL)
  3030. {
  3031. // Set the Help ID
  3032. if (bDialogEx && ((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID != 0)
  3033. wnd.SetWindowContextHelpId(((_DialogSplitHelper::DLGITEMTEMPLATEEX*)pItem)->helpID);
  3034. // Try to create the ActiveX control.
  3035. hr = wnd.CreateControlLic(pszClassName, spStream, NULL, bstrLicKey);
  3036. if (FAILED(hr))
  3037. break;
  3038. // Set the correct tab position.
  3039. if (nItem == 0)
  3040. hWndPrev = HWND_TOP;
  3041. wnd.SetWindowPos(hWndPrev, 0,0,0,0,SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  3042. hWndPrev = wnd;
  3043. }
  3044. else
  3045. {
  3046. hr = AtlHresultFromLastError();
  3047. }
  3048. }
  3049. }
  3050. else
  3051. {
  3052. if (nItem != 0)
  3053. hWndPrev = ::GetWindow(hWndPrev, GW_HWNDNEXT);
  3054. }
  3055. pItem = _DialogSplitHelper::FindNextDlgItem(pItem, bDialogEx);
  3056. }
  3057. }
  3058. else
  3059. hr = AtlHresultFromLastError();
  3060. }
  3061. else
  3062. hr = AtlHresultFromLastError();
  3063. }
  3064. return hr;
  3065. }
  3066. LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  3067. {
  3068. // initialize controls in dialog with DLGINIT resource section
  3069. T* pT = static_cast<T*>(this);
  3070. (void)pT; // Avoid 'initialized but not referenced' warning if T::IDD is static
  3071. ExecuteDlgInit(pT->IDD);
  3072. AdviseSinkMap(true);
  3073. bHandled = FALSE;
  3074. return 1;
  3075. }
  3076. LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  3077. {
  3078. AdviseSinkMap(false);
  3079. bHandled = FALSE;
  3080. return 1;
  3081. }
  3082. // Accelerators handling - needs to be called from a message loop
  3083. BOOL IsDialogMessage(LPMSG pMsg)
  3084. {
  3085. if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
  3086. (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
  3087. return FALSE;
  3088. // find a direct child of the dialog from the window that has focus
  3089. HWND hWndCtl = ::GetFocus();
  3090. if(IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd)
  3091. {
  3092. do
  3093. {
  3094. hWndCtl = ::GetParent(hWndCtl);
  3095. }
  3096. while (::GetParent(hWndCtl) != m_hWnd);
  3097. }
  3098. // give controls a chance to translate this message
  3099. if (::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) == 1)
  3100. return TRUE;
  3101. // do the Windows default thing
  3102. return CDialogImplBaseT< TBase >::IsDialogMessage(pMsg);
  3103. }
  3104. };
  3105. template <class T, class TBase>
  3106. INT_PTR CALLBACK CAxDialogImpl< T, TBase >::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3107. {
  3108. CAxDialogImpl< T, TBase >* pThis = (CAxDialogImpl< T, TBase >*)hWnd;
  3109. if (uMsg == WM_INITDIALOG)
  3110. {
  3111. HRESULT hr;
  3112. if (FAILED(hr = pThis->CreateActiveXControls(pThis->GetIDD())))
  3113. {
  3114. pThis->DestroyWindow();
  3115. SetLastError(hr & 0x0000FFFF);
  3116. return FALSE;
  3117. }
  3118. }
  3119. return CDialogImplBaseT< TBase >::DialogProc(hWnd, uMsg, wParam, lParam);
  3120. }
  3121. #endif //_ATL_NO_HOSTING
  3122. /////////////////////////////////////////////////////////////////////////////
  3123. // CSimpleDialog - Prebuilt modal dialog that uses standard buttons
  3124. template <WORD t_wDlgTemplateID, BOOL t_bCenter = TRUE>
  3125. class CSimpleDialog : public CDialogImplBase
  3126. {
  3127. public:
  3128. INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow())
  3129. {
  3130. ATLASSERT(m_hWnd == NULL);
  3131. _AtlWinModule.AddCreateWndData(&m_thunk.cd, (CDialogImplBase*)this);
  3132. int nRet = ::DialogBox(_AtlBaseModule.GetResourceInstance(),
  3133. MAKEINTRESOURCE(t_wDlgTemplateID), hWndParent, StartDialogProc);
  3134. m_hWnd = NULL;
  3135. return nRet;
  3136. }
  3137. typedef CSimpleDialog<t_wDlgTemplateID, t_bCenter> thisClass;
  3138. BEGIN_MSG_MAP(thisClass)
  3139. MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
  3140. COMMAND_RANGE_HANDLER(IDOK, IDNO, OnCloseCmd)
  3141. END_MSG_MAP()
  3142. LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  3143. {
  3144. // initialize controls in dialog with DLGINIT resource section
  3145. ExecuteDlgInit(t_wDlgTemplateID);
  3146. if(t_bCenter)
  3147. CenterWindow(GetParent());
  3148. return TRUE;
  3149. }
  3150. LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
  3151. {
  3152. ::EndDialog(m_hWnd, wID);
  3153. return 0;
  3154. }
  3155. };
  3156. /////////////////////////////////////////////////////////////////////////////
  3157. // CContainedWindow - Implements a contained window
  3158. template <class TBase = CWindow, class TWinTraits = CControlWinTraits>
  3159. class CContainedWindowT : public TBase
  3160. {
  3161. public:
  3162. CWndProcThunk m_thunk;
  3163. LPCTSTR m_lpszClassName;
  3164. WNDPROC m_pfnSuperWindowProc;
  3165. CMessageMap* m_pObject;
  3166. DWORD m_dwMsgMapID;
  3167. const _ATL_MSG* m_pCurrentMsg;
  3168. // If you use this constructor you must supply
  3169. // the Window Class Name, Object* and Message Map ID
  3170. // Later to the Create call
  3171. CContainedWindowT() : m_pCurrentMsg(NULL)
  3172. { }
  3173. CContainedWindowT(LPTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID = 0)
  3174. : m_lpszClassName(lpszClassName),
  3175. m_pfnSuperWindowProc(::DefWindowProc),
  3176. m_pObject(pObject), m_dwMsgMapID(dwMsgMapID),
  3177. m_pCurrentMsg(NULL)
  3178. { }
  3179. CContainedWindowT(CMessageMap* pObject, DWORD dwMsgMapID = 0)
  3180. : m_lpszClassName(TBase::GetWndClassName()),
  3181. m_pfnSuperWindowProc(::DefWindowProc),
  3182. m_pObject(pObject), m_dwMsgMapID(dwMsgMapID),
  3183. m_pCurrentMsg(NULL)
  3184. { }
  3185. void SwitchMessageMap(DWORD dwMsgMapID)
  3186. {
  3187. m_dwMsgMapID = dwMsgMapID;
  3188. }
  3189. const _ATL_MSG* GetCurrentMessage() const
  3190. {
  3191. return m_pCurrentMsg;
  3192. }
  3193. LRESULT DefWindowProc()
  3194. {
  3195. const _ATL_MSG* pMsg = m_pCurrentMsg;
  3196. LRESULT lRes = 0;
  3197. if (pMsg != NULL)
  3198. lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
  3199. return lRes;
  3200. }
  3201. LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  3202. {
  3203. #ifdef STRICT
  3204. return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
  3205. #else
  3206. return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam);
  3207. #endif
  3208. }
  3209. static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg,
  3210. WPARAM wParam, LPARAM lParam)
  3211. {
  3212. CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)_AtlWinModule.ExtractCreateWndData();
  3213. ATLASSERT(pThis != NULL);
  3214. pThis->m_hWnd = hWnd;
  3215. pThis->m_thunk.Init(WindowProc, pThis);
  3216. WNDPROC pProc = pThis->m_thunk.GetWNDPROC();
  3217. WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  3218. #ifdef _DEBUG
  3219. // check if somebody has subclassed us already since we discard it
  3220. if(pOldProc != StartWindowProc)
  3221. ATLTRACE(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n"));
  3222. #else
  3223. pOldProc; // avoid unused warning
  3224. #endif
  3225. return pProc(hWnd, uMsg, wParam, lParam);
  3226. }
  3227. static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3228. {
  3229. CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)hWnd;
  3230. ATLASSERT(pThis->m_hWnd != NULL);
  3231. ATLASSERT(pThis->m_pObject != NULL);
  3232. // set a ptr to this message and save the old value
  3233. _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
  3234. const _ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
  3235. pThis->m_pCurrentMsg = &msg;
  3236. // pass to the message map to process
  3237. LRESULT lRes;
  3238. BOOL bRet = pThis->m_pObject->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, pThis->m_dwMsgMapID);
  3239. // restore saved value for the current message
  3240. ATLASSERT(pThis->m_pCurrentMsg == &msg);
  3241. pThis->m_pCurrentMsg = pOldMsg;
  3242. // do the default processing if message was not handled
  3243. if(!bRet)
  3244. {
  3245. if(uMsg != WM_NCDESTROY)
  3246. lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  3247. else
  3248. {
  3249. // unsubclass, if needed
  3250. LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
  3251. lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  3252. if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
  3253. ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
  3254. // clear out window handle
  3255. pThis->m_hWnd = NULL;
  3256. }
  3257. }
  3258. return lRes;
  3259. }
  3260. ATOM RegisterWndSuperclass()
  3261. {
  3262. ATOM atom = 0;
  3263. LPTSTR szBuff = (LPTSTR)_alloca((lstrlen(m_lpszClassName) + 14) * sizeof(TCHAR));
  3264. WNDCLASSEX wc;
  3265. wc.cbSize = sizeof(WNDCLASSEX);
  3266. // Try global class
  3267. if(!::GetClassInfoEx(NULL, m_lpszClassName, &wc))
  3268. {
  3269. // try local class
  3270. if(!::GetClassInfoEx(_AtlBaseModule.GetModuleInstance(), m_lpszClassName, &wc))
  3271. return atom;
  3272. }
  3273. m_pfnSuperWindowProc = wc.lpfnWndProc;
  3274. lstrcpy(szBuff, _T("ATL:"));
  3275. lstrcat(szBuff, m_lpszClassName);
  3276. WNDCLASSEX wc1;
  3277. wc1.cbSize = sizeof(WNDCLASSEX);
  3278. atom = (ATOM)::GetClassInfoEx(_AtlBaseModule.GetModuleInstance(), szBuff, &wc1);
  3279. if(atom == 0) // register class
  3280. {
  3281. wc.lpszClassName = szBuff;
  3282. wc.lpfnWndProc = StartWindowProc;
  3283. wc.hInstance = _AtlBaseModule.GetModuleInstance();
  3284. wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
  3285. atom = AtlWinModuleRegisterClassEx(&_AtlWinModule, &wc);
  3286. }
  3287. return atom;
  3288. }
  3289. HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName = NULL,
  3290. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  3291. _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
  3292. {
  3293. ATLASSERT(m_hWnd == NULL);
  3294. ATOM atom = RegisterWndSuperclass();
  3295. if(atom == 0)
  3296. return NULL;
  3297. _AtlWinModule.AddCreateWndData(&m_thunk.cd, this);
  3298. if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD))
  3299. MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
  3300. if(rect.m_lpRect == NULL)
  3301. rect.m_lpRect = &TBase::rcDefault;
  3302. dwStyle = TWinTraits::GetWndStyle(dwStyle);
  3303. dwExStyle = TWinTraits::GetWndExStyle(dwExStyle);
  3304. HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName,
  3305. dwStyle,
  3306. rect.m_lpRect->left, rect.m_lpRect->top,
  3307. rect.m_lpRect->right - rect.m_lpRect->left,
  3308. rect.m_lpRect->bottom - rect.m_lpRect->top,
  3309. hWndParent, MenuOrID.m_hMenu,
  3310. _AtlBaseModule.GetModuleInstance(), lpCreateParam);
  3311. ATLASSERT(m_hWnd == hWnd);
  3312. return hWnd;
  3313. }
  3314. HWND Create(CMessageMap* pObject, DWORD dwMsgMapID, HWND hWndParent, _U_RECT rect,
  3315. LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0,
  3316. _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
  3317. {
  3318. m_lpszClassName = TBase::GetWndClassName();
  3319. m_pfnSuperWindowProc = ::DefWindowProc;
  3320. m_pObject = pObject;
  3321. m_dwMsgMapID = dwMsgMapID;
  3322. return Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam);
  3323. }
  3324. HWND Create(LPCTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID, HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName = NULL,
  3325. DWORD dwStyle = 0, DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
  3326. {
  3327. m_lpszClassName = lpszClassName;
  3328. m_pfnSuperWindowProc = ::DefWindowProc;
  3329. m_pObject = pObject;
  3330. m_dwMsgMapID = dwMsgMapID;
  3331. return Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, MenuOrID, lpCreateParam);
  3332. }
  3333. BOOL SubclassWindow(HWND hWnd)
  3334. {
  3335. ATLASSERT(m_hWnd == NULL);
  3336. ATLASSERT(::IsWindow(hWnd));
  3337. m_thunk.Init(WindowProc, this);
  3338. WNDPROC pProc = m_thunk.GetWNDPROC();
  3339. WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  3340. if(pfnWndProc == NULL)
  3341. return FALSE;
  3342. m_pfnSuperWindowProc = pfnWndProc;
  3343. m_hWnd = hWnd;
  3344. return TRUE;
  3345. }
  3346. // Use only if you want to subclass before window is destroyed,
  3347. // WindowProc will automatically subclass when window goes away
  3348. HWND UnsubclassWindow(BOOL bForce = FALSE)
  3349. {
  3350. ATLASSERT(m_hWnd != NULL);
  3351. WNDPROC pOurProc = m_thunk.GetWNDPROC();
  3352. WNDPROC pActiveProc = (WNDPROC)::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC);
  3353. HWND hWnd = NULL;
  3354. if (bForce || pOurProc == pActiveProc)
  3355. {
  3356. if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc))
  3357. return NULL;
  3358. m_pfnSuperWindowProc = ::DefWindowProc;
  3359. hWnd = m_hWnd;
  3360. m_hWnd = NULL;
  3361. }
  3362. return hWnd;
  3363. }
  3364. LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  3365. {
  3366. HWND hWndChild = NULL;
  3367. switch(uMsg)
  3368. {
  3369. case WM_COMMAND:
  3370. if(lParam != NULL) // not from a menu
  3371. hWndChild = (HWND)lParam;
  3372. break;
  3373. case WM_NOTIFY:
  3374. hWndChild = ((LPNMHDR)lParam)->hwndFrom;
  3375. break;
  3376. case WM_PARENTNOTIFY:
  3377. switch(LOWORD(wParam))
  3378. {
  3379. case WM_CREATE:
  3380. case WM_DESTROY:
  3381. hWndChild = (HWND)lParam;
  3382. break;
  3383. default:
  3384. hWndChild = GetDlgItem(HIWORD(wParam));
  3385. break;
  3386. }
  3387. break;
  3388. case WM_DRAWITEM:
  3389. if(wParam) // not from a menu
  3390. hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
  3391. break;
  3392. case WM_MEASUREITEM:
  3393. if(wParam) // not from a menu
  3394. hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID);
  3395. break;
  3396. case WM_COMPAREITEM:
  3397. if(wParam) // not from a menu
  3398. hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID);
  3399. break;
  3400. case WM_DELETEITEM:
  3401. if(wParam) // not from a menu
  3402. hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID);
  3403. break;
  3404. case WM_VKEYTOITEM:
  3405. case WM_CHARTOITEM:
  3406. case WM_HSCROLL:
  3407. case WM_VSCROLL:
  3408. hWndChild = (HWND)lParam;
  3409. break;
  3410. case WM_CTLCOLORBTN:
  3411. case WM_CTLCOLORDLG:
  3412. case WM_CTLCOLOREDIT:
  3413. case WM_CTLCOLORLISTBOX:
  3414. case WM_CTLCOLORMSGBOX:
  3415. case WM_CTLCOLORSCROLLBAR:
  3416. case WM_CTLCOLORSTATIC:
  3417. hWndChild = (HWND)lParam;
  3418. break;
  3419. default:
  3420. break;
  3421. }
  3422. if(hWndChild == NULL)
  3423. {
  3424. bHandled = FALSE;
  3425. return 1;
  3426. }
  3427. ATLASSERT(::IsWindow(hWndChild));
  3428. return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
  3429. }
  3430. };
  3431. typedef CContainedWindowT<CWindow> CContainedWindow;
  3432. /////////////////////////////////////////////////////////////////////////////
  3433. // _DialogSizeHelper - helpers for calculating the size of a dialog template
  3434. class _DialogSizeHelper
  3435. {
  3436. public:
  3437. //local struct used for implementation
  3438. #pragma pack(push, 1)
  3439. struct _ATL_DLGTEMPLATEEX
  3440. {
  3441. WORD dlgVer;
  3442. WORD signature;
  3443. DWORD helpID;
  3444. DWORD exStyle;
  3445. DWORD style;
  3446. WORD cDlgItems;
  3447. short x;
  3448. short y;
  3449. short cx;
  3450. short cy;
  3451. };
  3452. #pragma pack(pop)
  3453. static void GetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize, bool bPropertyPage = false)
  3454. {
  3455. // If the dialog has a font we use it otherwise we default
  3456. // to the system font.
  3457. TCHAR szFace[LF_FACESIZE];
  3458. WORD wFontSize = 0;
  3459. GetSizeInDialogUnits(pTemplate, pSize);
  3460. BOOL bFont = GetFont(pTemplate, szFace, &wFontSize);
  3461. if (bFont)
  3462. {
  3463. ConvertDialogUnitsToPixels(szFace, wFontSize, pSize, bPropertyPage);
  3464. }
  3465. else
  3466. {
  3467. ConvertDialogUnitsToPixels(NULL, 0, pSize, bPropertyPage);
  3468. }
  3469. }
  3470. static void GetFontDimensions(LPCTSTR pszFontFace, WORD wFontSize, SIZE* pSizeChar, LONG *ptmHeight)
  3471. {
  3472. if (pszFontFace != NULL)
  3473. {
  3474. // Attempt to create the font to be used in the dialog box
  3475. HDC hDC = ::GetDC(NULL);
  3476. if (hDC != NULL)
  3477. {
  3478. LOGFONT lf;
  3479. memset(&lf, 0, sizeof(LOGFONT));
  3480. lf.lfHeight = -MulDiv(wFontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
  3481. lf.lfWeight = FW_NORMAL;
  3482. lf.lfCharSet = DEFAULT_CHARSET;
  3483. lstrcpy(lf.lfFaceName, pszFontFace);
  3484. HFONT hNewFont = CreateFontIndirect(&lf);
  3485. if (hNewFont != NULL)
  3486. {
  3487. TEXTMETRIC tm;
  3488. SIZE size;
  3489. HFONT hFontOld = (HFONT)SelectObject(hDC, hNewFont);
  3490. GetTextMetrics(hDC, &tm);
  3491. ::GetTextExtentPoint(hDC,
  3492. _T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52,
  3493. &size);
  3494. SelectObject(hDC, hFontOld);
  3495. DeleteObject(hNewFont);
  3496. *ptmHeight = tm.tmHeight;
  3497. pSizeChar->cy = tm.tmHeight + tm.tmExternalLeading;
  3498. pSizeChar->cx = (size.cx + 26) / 52;
  3499. ::ReleaseDC(NULL, hDC);
  3500. return;
  3501. }
  3502. ::ReleaseDC(NULL, hDC);
  3503. }
  3504. }
  3505. // Could not create font or no font name was not specified
  3506. LONG nDlgBaseUnits = GetDialogBaseUnits();
  3507. pSizeChar->cx = LOWORD(nDlgBaseUnits);
  3508. *ptmHeight = pSizeChar->cy = HIWORD(nDlgBaseUnits);
  3509. }
  3510. // ID of the dialog template used for property sheet in comctl32.dll
  3511. #define IDD_PROPSHEET_ID 1006
  3512. static void ConvertDialogUnitsToPixels(LPCTSTR pszFontFace, WORD wFontSize, SIZE* pSizePixel, bool bPropertyPage = false)
  3513. {
  3514. LONG tmHeight;
  3515. SIZE sizeFontChar;
  3516. GetFontDimensions(pszFontFace, wFontSize, &sizeFontChar, &tmHeight);
  3517. if (bPropertyPage)
  3518. {
  3519. // Get the font used by the property sheet
  3520. HINSTANCE hInst = LoadLibrary(_T("COMCTL32.DLL"));
  3521. if (hInst != NULL)
  3522. {
  3523. HRSRC hResource = ::FindResource(hInst,
  3524. MAKEINTRESOURCE(IDD_PROPSHEET_ID),
  3525. RT_DIALOG);
  3526. if (hResource != NULL)
  3527. {
  3528. HGLOBAL hTemplate = LoadResource(hInst, hResource);
  3529. if (hTemplate != NULL)
  3530. {
  3531. TCHAR szFace[LF_FACESIZE];
  3532. WORD wSize;
  3533. BOOL bFont;
  3534. bFont = _DialogSizeHelper::GetFont((DLGTEMPLATE*)hTemplate, szFace, &wSize);
  3535. FreeLibrary(hInst);
  3536. if (bFont)
  3537. {
  3538. SIZE sizeSheetFontChar;
  3539. LONG tmHeightSheetFont;
  3540. GetFontDimensions(szFace, wSize, &sizeSheetFontChar, &tmHeightSheetFont);
  3541. // Now translate to pixels compensating for the calculations made by OLEAUT32 and Dialog manager
  3542. // Calculate the size of pixels using property sheet font.
  3543. pSizePixel->cx = MulDiv(pSizePixel->cx, sizeFontChar.cx, 4);
  3544. pSizePixel->cy = MulDiv(pSizePixel->cy, sizeSheetFontChar.cy, 8);
  3545. // Inflate/Deflate the height to compensate for the correct font.
  3546. pSizePixel->cy = MulDiv(pSizePixel->cy, tmHeight, tmHeightSheetFont);
  3547. return ;
  3548. }
  3549. }
  3550. }
  3551. }
  3552. }
  3553. // Not property page or could not load Property sheet resource.
  3554. // Translate dialog units to pixels
  3555. pSizePixel->cx = MulDiv(pSizePixel->cx, sizeFontChar.cx, 4);
  3556. pSizePixel->cy = MulDiv(pSizePixel->cy, sizeFontChar.cy, 8);
  3557. }
  3558. static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate)
  3559. {
  3560. return ((_ATL_DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF;
  3561. }
  3562. static BOOL HasFont(const DLGTEMPLATE* pTemplate)
  3563. {
  3564. return (DS_SETFONT &
  3565. (IsDialogEx(pTemplate) ?
  3566. ((_ATL_DLGTEMPLATEEX*)pTemplate)->style : pTemplate->style));
  3567. }
  3568. static BYTE* GetFontSizeField(const DLGTEMPLATE* pTemplate)
  3569. {
  3570. BOOL bDialogEx = IsDialogEx(pTemplate);
  3571. WORD* pw;
  3572. if (bDialogEx)
  3573. pw = (WORD*)((_ATL_DLGTEMPLATEEX*)pTemplate + 1);
  3574. else
  3575. pw = (WORD*)(pTemplate + 1);
  3576. if (*pw == (WORD)-1) // Skip menu name string or ordinal
  3577. pw += 2; // WORDs
  3578. else
  3579. while(*pw++);
  3580. if (*pw == (WORD)-1) // Skip class name string or ordinal
  3581. pw += 2; // WORDs
  3582. else
  3583. while(*pw++);
  3584. while (*pw++); // Skip caption string
  3585. return (BYTE*)pw;
  3586. }
  3587. static BOOL GetFont(const DLGTEMPLATE* pTemplate, TCHAR* pszFace, WORD* pFontSize)
  3588. {
  3589. USES_CONVERSION;
  3590. if (!HasFont(pTemplate))
  3591. return FALSE;
  3592. BYTE* pb = GetFontSizeField(pTemplate);
  3593. *pFontSize = *(WORD*)pb;
  3594. // Skip over font attributes to get to the font name
  3595. pb += sizeof(WORD) * (IsDialogEx(pTemplate) ? 3 : 1);
  3596. _tcscpy(pszFace, W2T((WCHAR*)pb));
  3597. return TRUE;
  3598. }
  3599. static void GetSizeInDialogUnits(const DLGTEMPLATE* pTemplate, SIZE* pSize)
  3600. {
  3601. if (IsDialogEx(pTemplate))
  3602. {
  3603. pSize->cx = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cx;
  3604. pSize->cy = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cy;
  3605. }
  3606. else
  3607. {
  3608. pSize->cx = pTemplate->cx;
  3609. pSize->cy = pTemplate->cy;
  3610. }
  3611. }
  3612. };
  3613. inline void AtlGetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize, bool bPropertyPage = false)
  3614. {
  3615. ATLASSERT(pTemplate != NULL);
  3616. ATLASSERT(pSize != NULL);
  3617. _DialogSizeHelper::GetDialogSize(pTemplate, pSize, bPropertyPage);
  3618. }
  3619. }; //namespace ATL
  3620. #ifndef _ATL_NO_HOSTING
  3621. #include <atlhost.h>
  3622. #endif
  3623. #ifndef _ATL_DLL_IMPL
  3624. #ifndef _ATL_DLL
  3625. #define _ATLWIN_IMPL
  3626. #endif
  3627. #endif
  3628. //REVIEW: Just to fix VSEE
  3629. #pragma pop_macro("min")
  3630. #pragma pop_macro("max")
  3631. #endif // __ATLWIN_H__
  3632. //All exports go here
  3633. #ifdef _ATLWIN_IMPL
  3634. //#ifndef _ATL_DLL_IMPL
  3635. namespace ATL
  3636. {
  3637. //#endif
  3638. class AtlModuleRegisterWndClassInfoParamA
  3639. {
  3640. public:
  3641. typedef LPSTR PXSTR;
  3642. typedef LPCSTR PCXSTR;
  3643. typedef _ATL_WNDCLASSINFOA _ATL_WNDCLASSINFO;
  3644. typedef WNDCLASSEXA WNDCLASSEX;
  3645. static BOOL GetClassInfoEx(HINSTANCE hinst, PCXSTR lpszClass, WNDCLASSEX* lpwcx)
  3646. {
  3647. return ::GetClassInfoExA(hinst, lpszClass, lpwcx);
  3648. }
  3649. static void FormatWindowClassName(PXSTR szBuffer, void* unique)
  3650. {
  3651. #if defined(_WIN64) // || or Windows 2000
  3652. ::wsprintfA(szBuffer, "ATL:%p", unique);
  3653. #else
  3654. ::wsprintfA(szBuffer, "ATL:%8.8X", reinterpret_cast<DWORD_PTR>(unique));
  3655. #endif
  3656. }
  3657. static HCURSOR LoadCursor(HINSTANCE hInstance, PCXSTR lpCursorName)
  3658. {
  3659. return ::LoadCursorA(hInstance, lpCursorName);
  3660. }
  3661. static ATOM RegisterClassEx(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEX* lpwcx)
  3662. {
  3663. return AtlWinModuleRegisterClassExA(pWinModule, lpwcx);
  3664. }
  3665. };
  3666. class AtlModuleRegisterWndClassInfoParamW
  3667. {
  3668. public:
  3669. typedef LPWSTR PXSTR;
  3670. typedef LPCWSTR PCXSTR;
  3671. typedef _ATL_WNDCLASSINFOW _ATL_WNDCLASSINFO;
  3672. typedef WNDCLASSEXW WNDCLASSEX;
  3673. static BOOL GetClassInfoEx(HINSTANCE hinst, PCXSTR lpszClass, WNDCLASSEX* lpwcx)
  3674. {
  3675. return ::GetClassInfoExW(hinst, lpszClass, lpwcx);
  3676. }
  3677. static void FormatWindowClassName(PXSTR szBuffer, void* unique)
  3678. {
  3679. #if defined(_WIN64) // || or Windows 2000
  3680. ::wsprintfW(szBuffer, L"ATL:%p", unique);
  3681. #else
  3682. ::wsprintfW(szBuffer, L"ATL:%8.8X", reinterpret_cast<DWORD_PTR>(unique));
  3683. #endif
  3684. }
  3685. static HCURSOR LoadCursor(HINSTANCE hInstance, PCXSTR lpCursorName)
  3686. {
  3687. return ::LoadCursorW(hInstance, lpCursorName);
  3688. }
  3689. static ATOM RegisterClassEx(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEX* lpwcx)
  3690. {
  3691. return AtlWinModuleRegisterClassExW(pWinModule, lpwcx);
  3692. }
  3693. };
  3694. ATLINLINE ATLAPI_(ATOM) AtlWinModuleRegisterClassExA(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXA *lpwc)
  3695. {
  3696. ATOM atom = ::RegisterClassExA(lpwc);
  3697. pWinModule->m_rgWindowClassAtoms[pWinModule->m_nAtomIndex++] = atom;
  3698. return atom;
  3699. }
  3700. ATLINLINE ATLAPI_(ATOM) AtlWinModuleRegisterClassExW(_ATL_WIN_MODULE* pWinModule, const WNDCLASSEXW *lpwc)
  3701. {
  3702. ATOM atom = ::RegisterClassExW(lpwc);
  3703. pWinModule->m_rgWindowClassAtoms[pWinModule->m_nAtomIndex++] = atom;
  3704. return atom;
  3705. }
  3706. template <class T>
  3707. ATLINLINE ATOM AtlModuleRegisterWndClassInfoT(_ATL_BASE_MODULE* pBaseModule, _ATL_WIN_MODULE* pWinModule, T::_ATL_WNDCLASSINFO* p, WNDPROC* pProc, T)
  3708. {
  3709. if (p->m_atom == 0)
  3710. {
  3711. CComCritSecLock<CComCriticalSection> lock(pWinModule->m_csWindowCreate, false);
  3712. if (FAILED(lock.Lock()))
  3713. {
  3714. ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to lock critical section in AtlModuleRegisterWndClassInfoT\n"));
  3715. ATLASSERT(0);
  3716. return 0;
  3717. }
  3718. if(p->m_atom == 0)
  3719. {
  3720. if (p->m_lpszOrigName != NULL)
  3721. {
  3722. ATLASSERT(pProc != NULL);
  3723. T::PCXSTR lpsz = p->m_wc.lpszClassName;
  3724. WNDPROC proc = p->m_wc.lpfnWndProc;
  3725. T::WNDCLASSEX wc;
  3726. wc.cbSize = sizeof(T::WNDCLASSEX);
  3727. // Try global class
  3728. if(!T::GetClassInfoEx(NULL, p->m_lpszOrigName, &wc))
  3729. {
  3730. // try process local
  3731. if(!T::GetClassInfoEx(pBaseModule->m_hInst, p->m_lpszOrigName, &wc))
  3732. {
  3733. ATLTRACE(atlTraceWindowing, 0, "ERROR : Could not obtain Window Class information for %s\n", p->m_lpszOrigName);
  3734. return 0;
  3735. }
  3736. }
  3737. p->m_wc = wc;
  3738. p->pWndProc = p->m_wc.lpfnWndProc;
  3739. p->m_wc.lpszClassName = lpsz;
  3740. p->m_wc.lpfnWndProc = proc;
  3741. }
  3742. else
  3743. {
  3744. p->m_wc.hCursor = T::LoadCursor(p->m_bSystemCursor ? NULL : pBaseModule->m_hInstResource,
  3745. p->m_lpszCursorID);
  3746. }
  3747. p->m_wc.hInstance = pBaseModule->m_hInst;
  3748. p->m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
  3749. if (p->m_wc.lpszClassName == NULL)
  3750. {
  3751. T::FormatWindowClassName(p->m_szAutoName, &p->m_wc);
  3752. p->m_wc.lpszClassName = p->m_szAutoName;
  3753. }
  3754. T::WNDCLASSEX wcTemp;
  3755. wcTemp = p->m_wc;
  3756. p->m_atom = static_cast<ATOM>(T::GetClassInfoEx(p->m_wc.hInstance, p->m_wc.lpszClassName, &wcTemp));
  3757. if (p->m_atom == 0)
  3758. {
  3759. p->m_atom = T::RegisterClassEx(pWinModule, &p->m_wc);
  3760. }
  3761. }
  3762. }
  3763. if (p->m_lpszOrigName != NULL)
  3764. {
  3765. ATLASSERT(pProc != NULL);
  3766. ATLASSERT(p->pWndProc != NULL);
  3767. *pProc = p->pWndProc;
  3768. }
  3769. return p->m_atom;
  3770. }
  3771. ATLINLINE ATLAPI_(ATOM) AtlWinModuleRegisterWndClassInfoA(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc)
  3772. {
  3773. AtlModuleRegisterWndClassInfoParamA templateParameter;
  3774. return AtlModuleRegisterWndClassInfoT<AtlModuleRegisterWndClassInfoParamA>(pBaseModule, pWinModule, p, pProc, templateParameter);
  3775. }
  3776. ATLINLINE ATLAPI_(ATOM) AtlWinModuleRegisterWndClassInfoW(_ATL_WIN_MODULE* pWinModule, _ATL_BASE_MODULE* pBaseModule, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc)
  3777. {
  3778. AtlModuleRegisterWndClassInfoParamW templateParameter;
  3779. return AtlModuleRegisterWndClassInfoT<AtlModuleRegisterWndClassInfoParamW>(pBaseModule, pWinModule, p, pProc, templateParameter);
  3780. }
  3781. ATLINLINE ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd)
  3782. {
  3783. USES_CONVERSION;
  3784. // cases hdc, ptd, hdc is metafile, hic
  3785. // NULL, NULL, n/a, Display
  3786. // NULL, !NULL, n/a, ptd
  3787. // !NULL, NULL, FALSE, hdc
  3788. // !NULL, NULL, TRUE, display
  3789. // !NULL, !NULL, FALSE, ptd
  3790. // !NULL, !NULL, TRUE, ptd
  3791. if (ptd != NULL)
  3792. {
  3793. LPDEVMODEOLE lpDevMode;
  3794. LPOLESTR lpszDriverName;
  3795. LPOLESTR lpszDeviceName;
  3796. LPOLESTR lpszPortName;
  3797. if (ptd->tdExtDevmodeOffset == 0)
  3798. lpDevMode = NULL;
  3799. else
  3800. lpDevMode = (LPDEVMODEOLE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
  3801. lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
  3802. lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
  3803. lpszPortName = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
  3804. return ::CreateDC(OLE2CT(lpszDriverName), OLE2CT(lpszDeviceName),
  3805. OLE2CT(lpszPortName), DEVMODEOLE2T(lpDevMode));
  3806. }
  3807. else if (hdc == NULL || GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE)
  3808. return ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  3809. else
  3810. return hdc;
  3811. }
  3812. ATLINLINE ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix)
  3813. {
  3814. int nPixelsPerInchX; // Pixels per logical inch along width
  3815. int nPixelsPerInchY; // Pixels per logical inch along height
  3816. HDC hDCScreen = GetDC(NULL);
  3817. ATLASSERT(hDCScreen != NULL);
  3818. nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  3819. nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  3820. ReleaseDC(NULL, hDCScreen);
  3821. lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, nPixelsPerInchX);
  3822. lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, nPixelsPerInchY);
  3823. }
  3824. ATLINLINE ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric)
  3825. {
  3826. int nPixelsPerInchX; // Pixels per logical inch along width
  3827. int nPixelsPerInchY; // Pixels per logical inch along height
  3828. HDC hDCScreen = GetDC(NULL);
  3829. ATLASSERT(hDCScreen != NULL);
  3830. nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX);
  3831. nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY);
  3832. ReleaseDC(NULL, hDCScreen);
  3833. lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, nPixelsPerInchX);
  3834. lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, nPixelsPerInchY);
  3835. }
  3836. //#ifndef _ATL_DLL_IMPL
  3837. }; //namespace ATL
  3838. //#endif
  3839. //Prevent pulling in second time
  3840. #undef _ATLWIN_IMPL
  3841. #endif // _ATLWIN_IMPL