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.

686 lines
17 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1997 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. #error atlwin.cpp requires atlwin.h to be included first
  12. #endif
  13. #ifndef ATL_NO_NAMESPACE
  14. namespace ATL
  15. {
  16. #endif
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CWindow
  19. HWND CWindow::GetDescendantWindow(int nID) const
  20. {
  21. _ASSERTE(::IsWindow(m_hWnd));
  22. // GetDlgItem recursive (return first found)
  23. // breadth-first for 1 level, then depth-first for next level
  24. // use GetDlgItem since it is a fast USER function
  25. HWND hWndChild, hWndTmp;
  26. CWindow wnd;
  27. if((hWndChild = ::GetDlgItem(m_hWnd, nID)) != NULL)
  28. {
  29. if(::GetTopWindow(hWndChild) != NULL)
  30. {
  31. // children with the same ID as their parent have priority
  32. wnd.Attach(hWndChild);
  33. hWndTmp = wnd.GetDescendantWindow(nID);
  34. if(hWndTmp != NULL)
  35. return hWndTmp;
  36. }
  37. return hWndChild;
  38. }
  39. // walk each child
  40. for(hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  41. hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  42. {
  43. wnd.Attach(hWndChild);
  44. hWndTmp = wnd.GetDescendantWindow(nID);
  45. if(hWndTmp != NULL)
  46. return hWndTmp;
  47. }
  48. return NULL; // not found
  49. }
  50. void CWindow::SendMessageToDescendants(UINT message, WPARAM wParam/*= 0*/, LPARAM lParam/*= 0*/, BOOL bDeep/* = TRUE*/)
  51. {
  52. CWindow wnd;
  53. for(HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;
  54. hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))
  55. {
  56. ::SendMessage(hWndChild, message, wParam, lParam);
  57. if(bDeep && ::GetTopWindow(hWndChild) != NULL)
  58. {
  59. // send to child windows after parent
  60. wnd.Attach(hWndChild);
  61. wnd.SendMessageToDescendants(message, wParam, lParam, bDeep);
  62. }
  63. }
  64. }
  65. BOOL CWindow::CenterWindow(HWND hWndCenter/* = NULL*/)
  66. {
  67. _ASSERTE(::IsWindow(m_hWnd));
  68. // determine owner window to center against
  69. DWORD dwStyle = GetStyle();
  70. if(hWndCenter == NULL)
  71. {
  72. if(dwStyle & WS_CHILD)
  73. hWndCenter = ::GetParent(m_hWnd);
  74. else
  75. hWndCenter = ::GetWindow(m_hWnd, GW_OWNER);
  76. }
  77. // get coordinates of the window relative to its parent
  78. RECT rcDlg;
  79. ::GetWindowRect(m_hWnd, &rcDlg);
  80. RECT rcArea;
  81. RECT rcCenter;
  82. HWND hWndParent;
  83. if(!(dwStyle & WS_CHILD))
  84. {
  85. // don't center against invisible or minimized windows
  86. if(hWndCenter != NULL)
  87. {
  88. DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE);
  89. if(!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE))
  90. hWndCenter = NULL;
  91. }
  92. // center within screen coordinates
  93. ::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL);
  94. if(hWndCenter == NULL)
  95. rcCenter = rcArea;
  96. else
  97. ::GetWindowRect(hWndCenter, &rcCenter);
  98. }
  99. else
  100. {
  101. // center within parent client coordinates
  102. hWndParent = ::GetParent(m_hWnd);
  103. _ASSERTE(::IsWindow(hWndParent));
  104. ::GetClientRect(hWndParent, &rcArea);
  105. _ASSERTE(::IsWindow(hWndCenter));
  106. ::GetClientRect(hWndCenter, &rcCenter);
  107. ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2);
  108. }
  109. int DlgWidth = rcDlg.right - rcDlg.left;
  110. int DlgHeight = rcDlg.bottom - rcDlg.top;
  111. // find dialog's upper left based on rcCenter
  112. int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2;
  113. int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;
  114. // if the dialog is outside the screen, move it inside
  115. if(xLeft < rcArea.left)
  116. xLeft = rcArea.left;
  117. else if(xLeft + DlgWidth > rcArea.right)
  118. xLeft = rcArea.right - DlgWidth;
  119. if(yTop < rcArea.top)
  120. yTop = rcArea.top;
  121. else if(yTop + DlgHeight > rcArea.bottom)
  122. yTop = rcArea.bottom - DlgHeight;
  123. // map screen coordinates to child coordinates
  124. return ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1,
  125. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  126. }
  127. BOOL CWindow::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  128. {
  129. _ASSERTE(::IsWindow(m_hWnd));
  130. DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
  131. DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  132. if(dwStyle == dwNewStyle)
  133. return FALSE;
  134. ::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle);
  135. if(nFlags != 0)
  136. {
  137. ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
  138. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  139. }
  140. return TRUE;
  141. }
  142. BOOL CWindow::ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  143. {
  144. _ASSERTE(::IsWindow(m_hWnd));
  145. DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
  146. DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
  147. if(dwStyle == dwNewStyle)
  148. return FALSE;
  149. ::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwNewStyle);
  150. if(nFlags != 0)
  151. {
  152. ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
  153. SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
  154. }
  155. return TRUE;
  156. }
  157. BOOL CWindow::GetWindowText(BSTR& bstrText)
  158. {
  159. USES_CONVERSION;
  160. _ASSERTE(::IsWindow(m_hWnd));
  161. int nLen = ::GetWindowTextLength(m_hWnd);
  162. if(nLen == 0)
  163. return FALSE;
  164. LPTSTR lpszText = (LPTSTR)_alloca((nLen+1)*sizeof(TCHAR));
  165. if(!::GetWindowText(m_hWnd, lpszText, nLen+1))
  166. return FALSE;
  167. bstrText = ::SysAllocString(T2OLE(lpszText));
  168. return (bstrText != NULL) ? TRUE : FALSE;
  169. }
  170. HWND CWindow::GetTopLevelParent() const
  171. {
  172. _ASSERTE(::IsWindow(m_hWnd));
  173. HWND hWndParent = m_hWnd;
  174. HWND hWndTmp;
  175. while((hWndTmp = ::GetParent(hWndParent)) != NULL)
  176. hWndParent = hWndTmp;
  177. return hWndParent;
  178. }
  179. HWND CWindow::GetTopLevelWindow() const
  180. {
  181. _ASSERTE(::IsWindow(m_hWnd));
  182. HWND hWndParent = m_hWnd;
  183. HWND hWndTmp = hWndParent;
  184. while(hWndTmp != NULL)
  185. {
  186. hWndTmp = (::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) ? ::GetParent(hWndParent) : ::GetWindow(hWndParent, GW_OWNER);
  187. hWndParent = hWndTmp;
  188. }
  189. return hWndParent;
  190. }
  191. /////////////////////////////////////////////////////////////////////////////
  192. // CDynamicChain
  193. CDynamicChain::~CDynamicChain()
  194. {
  195. if(m_pChainEntry != NULL)
  196. {
  197. for(int i = 0; i < m_nEntries; i++)
  198. {
  199. if(m_pChainEntry[i] != NULL)
  200. delete m_pChainEntry[i];
  201. }
  202. delete [] m_pChainEntry;
  203. }
  204. }
  205. BOOL CDynamicChain::SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID /* = 0 */)
  206. {
  207. // first search for an existing entry
  208. for(int i = 0; i < m_nEntries; i++)
  209. {
  210. if(m_pChainEntry[i] != NULL && m_pChainEntry[i]->m_dwChainID == dwChainID)
  211. {
  212. m_pChainEntry[i]->m_pObject = pObject;
  213. m_pChainEntry[i]->m_dwMsgMapID = dwMsgMapID;
  214. return TRUE;
  215. }
  216. }
  217. // create a new one
  218. ATL_CHAIN_ENTRY* pEntry = NULL;
  219. ATLTRY(pEntry = new ATL_CHAIN_ENTRY);
  220. if(pEntry == NULL)
  221. return FALSE;
  222. // search for an empty one
  223. for(i = 0; i < m_nEntries; i++)
  224. {
  225. if(m_pChainEntry[i] == NULL)
  226. {
  227. m_pChainEntry[i] = pEntry;
  228. return TRUE;
  229. }
  230. }
  231. // add a new one
  232. ATL_CHAIN_ENTRY** ppNew = NULL;
  233. ATLTRY(ppNew = new ATL_CHAIN_ENTRY*[m_nEntries + 1]);
  234. if(ppNew == NULL)
  235. {
  236. delete pEntry;
  237. return FALSE;
  238. }
  239. pEntry->m_dwChainID = dwChainID;
  240. pEntry->m_pObject = pObject;
  241. pEntry->m_dwMsgMapID = dwMsgMapID;
  242. if(m_pChainEntry != NULL)
  243. {
  244. memcpy(ppNew, m_pChainEntry, m_nEntries * sizeof(ATL_CHAIN_ENTRY*));
  245. delete [] m_pChainEntry;
  246. }
  247. m_pChainEntry = ppNew;
  248. m_pChainEntry[m_nEntries] = pEntry;
  249. m_nEntries++;
  250. return TRUE;
  251. }
  252. BOOL CDynamicChain::RemoveChainEntry(DWORD dwChainID)
  253. {
  254. for(int i = 0; i < m_nEntries; i++)
  255. {
  256. if(m_pChainEntry[i] != NULL && m_pChainEntry[i]->m_dwChainID == dwChainID)
  257. {
  258. delete m_pChainEntry[i];
  259. m_pChainEntry[i] = NULL;
  260. return TRUE;
  261. }
  262. }
  263. return FALSE;
  264. }
  265. BOOL CDynamicChain::CallChain(DWORD dwChainID, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult)
  266. {
  267. for(int i = 0; i < m_nEntries; i++)
  268. {
  269. if(m_pChainEntry[i] != NULL && m_pChainEntry[i]->m_dwChainID == dwChainID)
  270. return (m_pChainEntry[i]->m_pObject)->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, m_pChainEntry[i]->m_dwMsgMapID);
  271. }
  272. return FALSE;
  273. }
  274. /////////////////////////////////////////////////////////////////////////////
  275. // CWndClassInfo
  276. ATOM CWndClassInfo::Register(WNDPROC* pProc)
  277. {
  278. if (m_atom == 0)
  279. {
  280. ::EnterCriticalSection(&_Module.m_csWindowCreate);
  281. if(m_atom == 0)
  282. {
  283. HINSTANCE hInst = _Module.GetModuleInstance();
  284. if (m_lpszOrigName != NULL)
  285. {
  286. _ASSERTE(pProc != NULL);
  287. LPCTSTR lpsz = m_wc.lpszClassName;
  288. WNDPROC proc = m_wc.lpfnWndProc;
  289. WNDCLASSEX wc;
  290. wc.cbSize = sizeof(WNDCLASSEX);
  291. if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
  292. {
  293. ::LeaveCriticalSection(&_Module.m_csWindowCreate);
  294. return 0;
  295. }
  296. memcpy(&m_wc, &wc, sizeof(WNDCLASSEX));
  297. pWndProc = m_wc.lpfnWndProc;
  298. m_wc.lpszClassName = lpsz;
  299. m_wc.lpfnWndProc = proc;
  300. }
  301. else
  302. {
  303. m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst,
  304. m_lpszCursorID);
  305. }
  306. m_wc.hInstance = hInst;
  307. m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
  308. if (m_wc.lpszClassName == NULL)
  309. {
  310. #ifdef _WIN64 // %p isn't available on Win2k/Win9x
  311. wsprintf(m_szAutoName, _T("ATL:%p"), &m_wc);
  312. #else
  313. wsprintf(m_szAutoName, _T("ATL:%8.8X"), PtrToUlong(&m_wc));
  314. #endif
  315. m_wc.lpszClassName = m_szAutoName;
  316. }
  317. WNDCLASSEX wcTemp;
  318. memcpy(&wcTemp, &m_wc, sizeof(WNDCLASSEX));
  319. m_atom = (ATOM) ::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
  320. if (m_atom == 0)
  321. m_atom = ::RegisterClassEx(&m_wc);
  322. }
  323. ::LeaveCriticalSection(&_Module.m_csWindowCreate);
  324. }
  325. if (m_lpszOrigName != NULL)
  326. {
  327. _ASSERTE(pProc != NULL);
  328. _ASSERTE(pWndProc != NULL);
  329. *pProc = pWndProc;
  330. }
  331. return m_atom;
  332. }
  333. /////////////////////////////////////////////////////////////////////////////
  334. // CWindowImpl
  335. LRESULT CALLBACK CWindowImplBase::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  336. {
  337. CWindowImplBase* pT = (CWindowImplBase*)_Module.ExtractCreateWndData();
  338. _ASSERTE(pT != NULL);
  339. pT->m_hWnd = hWnd;
  340. pT->m_thunk.Init(WindowProc, pT);
  341. WNDPROC pProc = (WNDPROC)(pT->m_thunk.thunk.pThunk);
  342. ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  343. // if somebody has subclassed us already we can't do anything,
  344. // so discard return value from SetWindowLong
  345. return pProc(hWnd, uMsg, wParam, lParam);
  346. }
  347. LRESULT CALLBACK CWindowImplBase::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  348. {
  349. CWindowImplBase* pT = (CWindowImplBase*)hWnd;
  350. LRESULT lRes;
  351. BOOL bRet = pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0);
  352. if(uMsg == WM_NCDESTROY)
  353. {
  354. pT->m_hWnd = NULL;
  355. return 0;
  356. }
  357. if(bRet)
  358. return lRes;
  359. return pT->DefWindowProc(uMsg, wParam, lParam);
  360. }
  361. #ifdef _WIN64
  362. static LONG g_nNextWindowID; // Intentionally left uninitialized.
  363. #endif
  364. HWND CWindowImplBase::Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName,
  365. DWORD dwStyle, DWORD dwExStyle, UINT_PTR nID, ATOM atom)
  366. {
  367. _ASSERTE(m_hWnd == NULL);
  368. if(atom == 0)
  369. return NULL;
  370. _Module.AddCreateWndData(&m_thunk.cd, this);
  371. if(nID == 0 && (dwStyle & WS_CHILD))
  372. {
  373. #ifdef _WIN64
  374. nID = InterlockedIncrement( &g_nNextWindowID );
  375. nID |= 0x80000000; // Make sure the ID isn't zero
  376. #else
  377. nID = (UINT)this;
  378. #endif
  379. }
  380. HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)(LONG_PTR)MAKELONG(atom, 0), szWindowName,
  381. dwStyle, rcPos.left, rcPos.top, rcPos.right - rcPos.left,
  382. rcPos.bottom - rcPos.top, hWndParent, (HMENU)nID,
  383. _Module.GetModuleInstance(), NULL);
  384. _ASSERTE(m_hWnd == hWnd);
  385. return hWnd;
  386. }
  387. BOOL CWindowImplBase::SubclassWindow(HWND hWnd)
  388. {
  389. _ASSERTE(m_hWnd == NULL);
  390. _ASSERTE(::IsWindow(hWnd));
  391. m_thunk.Init(WindowProc, this);
  392. WNDPROC pProc = (WNDPROC)(m_thunk.thunk.pThunk);
  393. WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  394. if(pfnWndProc == NULL)
  395. return FALSE;
  396. m_pfnSuperWindowProc = pfnWndProc;
  397. m_hWnd = hWnd;
  398. return TRUE;
  399. }
  400. HWND CWindowImplBase::UnsubclassWindow()
  401. {
  402. _ASSERTE(m_hWnd != NULL);
  403. if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc))
  404. return NULL;
  405. m_pfnSuperWindowProc = ::DefWindowProc;
  406. HWND hWnd = m_hWnd;
  407. m_hWnd = NULL;
  408. return hWnd;
  409. }
  410. /////////////////////////////////////////////////////////////////////////////
  411. // CDialogImplBase
  412. LRESULT CALLBACK CDialogImplBase::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  413. {
  414. CDialogImplBase* pT = (CDialogImplBase*)_Module.ExtractCreateWndData();
  415. _ASSERTE(pT != NULL);
  416. pT->m_hWnd = hWnd;
  417. pT->m_thunk.Init(DialogProc, pT);
  418. WNDPROC pProc = (WNDPROC)(pT->m_thunk.thunk.pThunk);
  419. ::SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)pProc);
  420. // check if somebody has subclassed us already since we don't hold onto it
  421. ATLTRACE(_T("Subclassing through a hook discarded.\n"));
  422. return pProc(hWnd, uMsg, wParam, lParam);
  423. }
  424. LRESULT CALLBACK CDialogImplBase::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  425. {
  426. CDialogImplBase* pT = (CDialogImplBase*)hWnd;
  427. LRESULT lRes;
  428. if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0))
  429. {
  430. switch (uMsg)
  431. {
  432. case WM_COMPAREITEM:
  433. case WM_VKEYTOITEM:
  434. case WM_CHARTOITEM:
  435. case WM_INITDIALOG:
  436. case WM_QUERYDRAGICON:
  437. case WM_CTLCOLORMSGBOX:
  438. case WM_CTLCOLOREDIT:
  439. case WM_CTLCOLORLISTBOX:
  440. case WM_CTLCOLORBTN:
  441. case WM_CTLCOLORDLG:
  442. case WM_CTLCOLORSCROLLBAR:
  443. case WM_CTLCOLORSTATIC:
  444. return lRes;
  445. break;
  446. }
  447. if (lRes != 0)
  448. ::SetWindowLongPtr(pT->m_hWnd, DWLP_MSGRESULT, lRes);
  449. return TRUE;
  450. }
  451. return FALSE;
  452. }
  453. BOOL CDialogImplBase::EndDialog(int nRetCode)
  454. {
  455. _ASSERTE(m_hWnd);
  456. return ::EndDialog(m_hWnd, nRetCode);
  457. }
  458. /////////////////////////////////////////////////////////////////////////////
  459. // CContainedWindow
  460. LRESULT CALLBACK CContainedWindow::StartWindowProc(HWND hWnd, UINT uMsg,
  461. WPARAM wParam, LPARAM lParam)
  462. {
  463. CContainedWindow* pThis = (CContainedWindow*)_Module.ExtractCreateWndData();
  464. _ASSERTE(pThis != NULL);
  465. pThis->m_hWnd = hWnd;
  466. pThis->m_thunk.Init(pThis->WindowProc, pThis);
  467. WNDPROC pProc = (WNDPROC)(pThis->m_thunk.thunk.pThunk);
  468. ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  469. // check if somebody has subclassed us already since we don't hold onto it
  470. ATLTRACE(_T("Subclassing through a hook discarded.\n"));
  471. return pProc(hWnd, uMsg, wParam, lParam);
  472. }
  473. LRESULT CALLBACK CContainedWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam,
  474. LPARAM lParam)
  475. {
  476. CContainedWindow* pT = (CContainedWindow*)hWnd;
  477. _ASSERTE(pT->m_hWnd != NULL);
  478. _ASSERTE(pT->m_pObject != NULL);
  479. LRESULT lRes;
  480. BOOL bRet = pT->m_pObject->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, pT->m_dwMsgMapID);
  481. if(uMsg == WM_NCDESTROY)
  482. {
  483. pT->m_hWnd = NULL;
  484. return 0;
  485. }
  486. if(bRet)
  487. return lRes;
  488. return pT->DefWindowProc(uMsg, wParam, lParam);
  489. }
  490. ATOM CContainedWindow::RegisterWndSuperclass()
  491. {
  492. ATOM atom = 0;
  493. LPTSTR szBuff = (LPTSTR)_alloca((lstrlen(m_lpszClassName) + 14) * sizeof(TCHAR));
  494. WNDCLASSEX wc;
  495. wc.cbSize = sizeof(WNDCLASSEX);
  496. if(::GetClassInfoEx(NULL, m_lpszClassName, &wc))
  497. {
  498. m_pfnSuperWindowProc = wc.lpfnWndProc;
  499. wsprintf(szBuff, _T("ATL:%s"), m_lpszClassName);
  500. WNDCLASSEX wc1;
  501. wc1.cbSize = sizeof(WNDCLASSEX);
  502. atom = (ATOM)::GetClassInfoEx(_Module.GetModuleInstance(), szBuff, &wc1);
  503. if(atom == 0) // register class
  504. {
  505. wc.lpszClassName = szBuff;
  506. wc.lpfnWndProc = StartWindowProc;
  507. wc.hInstance = _Module.GetModuleInstance();
  508. wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
  509. atom = ::RegisterClassEx(&wc);
  510. }
  511. }
  512. return atom;
  513. }
  514. HWND CContainedWindow::Create(HWND hWndParent, RECT& rcPos,
  515. LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, UINT nID)
  516. {
  517. _ASSERTE(m_hWnd == NULL);
  518. ATOM atom = RegisterWndSuperclass();
  519. if(atom == 0)
  520. return NULL;
  521. _Module.AddCreateWndData(&m_thunk.cd, this);
  522. if(nID == 0 && (dwStyle & WS_CHILD))
  523. {
  524. #ifdef _WIN64
  525. nID = InterlockedIncrement( &g_nNextWindowID );
  526. nID |= 0x80000000; // Make sure the ID isn't zero
  527. #else
  528. nID = (UINT)this;
  529. #endif
  530. }
  531. HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)(LONG_PTR)MAKELONG(atom, 0), szWindowName,
  532. dwStyle,
  533. rcPos.left, rcPos.top,
  534. rcPos.right - rcPos.left,
  535. rcPos.bottom - rcPos.top,
  536. hWndParent, (HMENU)(DWORD_PTR)nID,
  537. _Module.GetModuleInstance(), this);
  538. _ASSERTE(m_hWnd == hWnd);
  539. return hWnd;
  540. }
  541. BOOL CContainedWindow::SubclassWindow(HWND hWnd)
  542. {
  543. _ASSERTE(m_hWnd == NULL);
  544. _ASSERTE(::IsWindow(hWnd));
  545. m_thunk.Init(WindowProc, this);
  546. WNDPROC pProc = (WNDPROC)m_thunk.thunk.pThunk;
  547. WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  548. if(pfnWndProc == NULL)
  549. return FALSE;
  550. m_pfnSuperWindowProc = pfnWndProc;
  551. m_hWnd = hWnd;
  552. return TRUE;
  553. }
  554. HWND CContainedWindow::UnsubclassWindow()
  555. {
  556. _ASSERTE(m_hWnd != NULL);
  557. if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc))
  558. return NULL;
  559. m_pfnSuperWindowProc = ::DefWindowProc;
  560. HWND hWnd = m_hWnd;
  561. m_hWnd = NULL;
  562. return hWnd;
  563. }
  564. #ifndef ATL_NO_NAMESPACE
  565. }; //namespace ATL
  566. #endif
  567. ///////////////////////////////////////////////////////////////////////////////
  568. //All Global stuff goes below this line
  569. ///////////////////////////////////////////////////////////////////////////////