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

692 lines
18 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. __try
  282. {
  283. if(m_atom == 0)
  284. {
  285. HINSTANCE hInst = _Module.GetModuleInstance();
  286. if (m_lpszOrigName != NULL)
  287. {
  288. _ASSERTE(pProc != NULL);
  289. LPCTSTR lpsz = m_wc.lpszClassName;
  290. WNDPROC proc = m_wc.lpfnWndProc;
  291. WNDCLASSEX wc;
  292. wc.cbSize = sizeof(WNDCLASSEX);
  293. if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
  294. {
  295. ::LeaveCriticalSection(&_Module.m_csWindowCreate);
  296. return 0;
  297. }
  298. memcpy(&m_wc, &wc, sizeof(WNDCLASSEX));
  299. pWndProc = m_wc.lpfnWndProc;
  300. m_wc.lpszClassName = lpsz;
  301. m_wc.lpfnWndProc = proc;
  302. }
  303. else
  304. {
  305. m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst,
  306. m_lpszCursorID);
  307. }
  308. m_wc.hInstance = hInst;
  309. m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
  310. if (m_wc.lpszClassName == NULL)
  311. {
  312. #ifdef _WIN64 // %p isn't available on Win2k/Win9x
  313. wsprintf(m_szAutoName, _T("ATL:%p"), &m_wc);
  314. #else
  315. wsprintf(m_szAutoName, _T("ATL:%8.8X"), PtrToUlong(&m_wc));
  316. #endif
  317. m_wc.lpszClassName = m_szAutoName;
  318. }
  319. WNDCLASSEX wcTemp;
  320. memcpy(&wcTemp, &m_wc, sizeof(WNDCLASSEX));
  321. m_atom = (ATOM) ::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
  322. if (m_atom == 0)
  323. m_atom = ::RegisterClassEx(&m_wc);
  324. }
  325. }
  326. __finally
  327. {
  328. ::LeaveCriticalSection(&_Module.m_csWindowCreate);
  329. }
  330. }
  331. if (m_lpszOrigName != NULL)
  332. {
  333. _ASSERTE(pProc != NULL);
  334. _ASSERTE(pWndProc != NULL);
  335. *pProc = pWndProc;
  336. }
  337. return m_atom;
  338. }
  339. /////////////////////////////////////////////////////////////////////////////
  340. // CWindowImpl
  341. LRESULT CALLBACK CWindowImplBase::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  342. {
  343. CWindowImplBase* pT = (CWindowImplBase*)_Module.ExtractCreateWndData();
  344. _ASSERTE(pT != NULL);
  345. pT->m_hWnd = hWnd;
  346. pT->m_thunk.Init(WindowProc, pT);
  347. WNDPROC pProc = (WNDPROC)(pT->m_thunk.thunk.pThunk);
  348. ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  349. // if somebody has subclassed us already we can't do anything,
  350. // so discard return value from SetWindowLong
  351. return pProc(hWnd, uMsg, wParam, lParam);
  352. }
  353. LRESULT CALLBACK CWindowImplBase::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  354. {
  355. CWindowImplBase* pT = (CWindowImplBase*)hWnd;
  356. LRESULT lRes;
  357. BOOL bRet = pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0);
  358. if(uMsg == WM_NCDESTROY)
  359. {
  360. pT->m_hWnd = NULL;
  361. return 0;
  362. }
  363. if(bRet)
  364. return lRes;
  365. return pT->DefWindowProc(uMsg, wParam, lParam);
  366. }
  367. #ifdef _WIN64
  368. static LONG g_nNextWindowID; // Intentionally left uninitialized.
  369. #endif
  370. HWND CWindowImplBase::Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName,
  371. DWORD dwStyle, DWORD dwExStyle, UINT_PTR nID, ATOM atom)
  372. {
  373. _ASSERTE(m_hWnd == NULL);
  374. if(atom == 0)
  375. return NULL;
  376. _Module.AddCreateWndData(&m_thunk.cd, this);
  377. if(nID == 0 && (dwStyle & WS_CHILD))
  378. {
  379. #ifdef _WIN64
  380. nID = InterlockedIncrement( &g_nNextWindowID );
  381. nID |= 0x80000000; // Make sure the ID isn't zero
  382. #else
  383. nID = (UINT)this;
  384. #endif
  385. }
  386. HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)(LONG_PTR)MAKELONG(atom, 0), szWindowName,
  387. dwStyle, rcPos.left, rcPos.top, rcPos.right - rcPos.left,
  388. rcPos.bottom - rcPos.top, hWndParent, (HMENU)nID,
  389. _Module.GetModuleInstance(), NULL);
  390. _ASSERTE(m_hWnd == hWnd);
  391. return hWnd;
  392. }
  393. BOOL CWindowImplBase::SubclassWindow(HWND hWnd)
  394. {
  395. _ASSERTE(m_hWnd == NULL);
  396. _ASSERTE(::IsWindow(hWnd));
  397. m_thunk.Init(WindowProc, this);
  398. WNDPROC pProc = (WNDPROC)(m_thunk.thunk.pThunk);
  399. WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  400. if(pfnWndProc == NULL)
  401. return FALSE;
  402. m_pfnSuperWindowProc = pfnWndProc;
  403. m_hWnd = hWnd;
  404. return TRUE;
  405. }
  406. HWND CWindowImplBase::UnsubclassWindow()
  407. {
  408. _ASSERTE(m_hWnd != NULL);
  409. if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc))
  410. return NULL;
  411. m_pfnSuperWindowProc = ::DefWindowProc;
  412. HWND hWnd = m_hWnd;
  413. m_hWnd = NULL;
  414. return hWnd;
  415. }
  416. /////////////////////////////////////////////////////////////////////////////
  417. // CDialogImplBase
  418. INT_PTR CALLBACK CDialogImplBase::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  419. {
  420. CDialogImplBase* pT = (CDialogImplBase*)_Module.ExtractCreateWndData();
  421. _ASSERTE(pT != NULL);
  422. pT->m_hWnd = hWnd;
  423. pT->m_thunk.Init((WNDPROC)DialogProc, pT);
  424. WNDPROC pProc = (WNDPROC)(pT->m_thunk.thunk.pThunk);
  425. ::SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)pProc);
  426. // check if somebody has subclassed us already since we don't hold onto it
  427. ATLTRACE(_T("Subclassing through a hook discarded.\n"));
  428. return pProc(hWnd, uMsg, wParam, lParam);
  429. }
  430. INT_PTR CALLBACK CDialogImplBase::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  431. {
  432. CDialogImplBase* pT = (CDialogImplBase*)hWnd;
  433. LRESULT lRes;
  434. if(pT->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, 0))
  435. {
  436. switch (uMsg)
  437. {
  438. case WM_COMPAREITEM:
  439. case WM_VKEYTOITEM:
  440. case WM_CHARTOITEM:
  441. case WM_INITDIALOG:
  442. case WM_QUERYDRAGICON:
  443. case WM_CTLCOLORMSGBOX:
  444. case WM_CTLCOLOREDIT:
  445. case WM_CTLCOLORLISTBOX:
  446. case WM_CTLCOLORBTN:
  447. case WM_CTLCOLORDLG:
  448. case WM_CTLCOLORSCROLLBAR:
  449. case WM_CTLCOLORSTATIC:
  450. return lRes;
  451. break;
  452. }
  453. if (lRes != 0)
  454. ::SetWindowLongPtr(pT->m_hWnd, DWLP_MSGRESULT, lRes);
  455. return TRUE;
  456. }
  457. return FALSE;
  458. }
  459. BOOL CDialogImplBase::EndDialog(int nRetCode)
  460. {
  461. _ASSERTE(m_hWnd);
  462. return ::EndDialog(m_hWnd, nRetCode);
  463. }
  464. /////////////////////////////////////////////////////////////////////////////
  465. // CContainedWindow
  466. LRESULT CALLBACK CContainedWindow::StartWindowProc(HWND hWnd, UINT uMsg,
  467. WPARAM wParam, LPARAM lParam)
  468. {
  469. CContainedWindow* pThis = (CContainedWindow*)_Module.ExtractCreateWndData();
  470. _ASSERTE(pThis != NULL);
  471. pThis->m_hWnd = hWnd;
  472. pThis->m_thunk.Init(pThis->WindowProc, pThis);
  473. WNDPROC pProc = (WNDPROC)(pThis->m_thunk.thunk.pThunk);
  474. ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  475. // check if somebody has subclassed us already since we don't hold onto it
  476. ATLTRACE(_T("Subclassing through a hook discarded.\n"));
  477. return pProc(hWnd, uMsg, wParam, lParam);
  478. }
  479. LRESULT CALLBACK CContainedWindow::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam,
  480. LPARAM lParam)
  481. {
  482. CContainedWindow* pT = (CContainedWindow*)hWnd;
  483. _ASSERTE(pT->m_hWnd != NULL);
  484. _ASSERTE(pT->m_pObject != NULL);
  485. LRESULT lRes;
  486. BOOL bRet = pT->m_pObject->ProcessWindowMessage(pT->m_hWnd, uMsg, wParam, lParam, lRes, pT->m_dwMsgMapID);
  487. if(uMsg == WM_NCDESTROY)
  488. {
  489. pT->m_hWnd = NULL;
  490. return 0;
  491. }
  492. if(bRet)
  493. return lRes;
  494. return pT->DefWindowProc(uMsg, wParam, lParam);
  495. }
  496. ATOM CContainedWindow::RegisterWndSuperclass()
  497. {
  498. ATOM atom = 0;
  499. LPTSTR szBuff = (LPTSTR)_alloca((lstrlen(m_lpszClassName) + 14) * sizeof(TCHAR));
  500. WNDCLASSEX wc;
  501. wc.cbSize = sizeof(WNDCLASSEX);
  502. if(::GetClassInfoEx(NULL, m_lpszClassName, &wc))
  503. {
  504. m_pfnSuperWindowProc = wc.lpfnWndProc;
  505. wsprintf(szBuff, _T("ATL:%s"), m_lpszClassName);
  506. WNDCLASSEX wc1;
  507. wc1.cbSize = sizeof(WNDCLASSEX);
  508. atom = (ATOM)::GetClassInfoEx(_Module.GetModuleInstance(), szBuff, &wc1);
  509. if(atom == 0) // register class
  510. {
  511. wc.lpszClassName = szBuff;
  512. wc.lpfnWndProc = StartWindowProc;
  513. wc.hInstance = _Module.GetModuleInstance();
  514. wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
  515. atom = ::RegisterClassEx(&wc);
  516. }
  517. }
  518. return atom;
  519. }
  520. HWND CContainedWindow::Create(HWND hWndParent, RECT& rcPos,
  521. LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, UINT nID)
  522. {
  523. _ASSERTE(m_hWnd == NULL);
  524. ATOM atom = RegisterWndSuperclass();
  525. if(atom == 0)
  526. return NULL;
  527. _Module.AddCreateWndData(&m_thunk.cd, this);
  528. if(nID == 0 && (dwStyle & WS_CHILD))
  529. {
  530. #ifdef _WIN64
  531. nID = InterlockedIncrement( &g_nNextWindowID );
  532. nID |= 0x80000000; // Make sure the ID isn't zero
  533. #else
  534. nID = (UINT)this;
  535. #endif
  536. }
  537. HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)(LONG_PTR)MAKELONG(atom, 0), szWindowName,
  538. dwStyle,
  539. rcPos.left, rcPos.top,
  540. rcPos.right - rcPos.left,
  541. rcPos.bottom - rcPos.top,
  542. hWndParent, (HMENU)(DWORD_PTR)nID,
  543. _Module.GetModuleInstance(), this);
  544. _ASSERTE(m_hWnd == hWnd);
  545. return hWnd;
  546. }
  547. BOOL CContainedWindow::SubclassWindow(HWND hWnd)
  548. {
  549. _ASSERTE(m_hWnd == NULL);
  550. _ASSERTE(::IsWindow(hWnd));
  551. m_thunk.Init(WindowProc, this);
  552. WNDPROC pProc = (WNDPROC)m_thunk.thunk.pThunk;
  553. WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc);
  554. if(pfnWndProc == NULL)
  555. return FALSE;
  556. m_pfnSuperWindowProc = pfnWndProc;
  557. m_hWnd = hWnd;
  558. return TRUE;
  559. }
  560. HWND CContainedWindow::UnsubclassWindow()
  561. {
  562. _ASSERTE(m_hWnd != NULL);
  563. if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc))
  564. return NULL;
  565. m_pfnSuperWindowProc = ::DefWindowProc;
  566. HWND hWnd = m_hWnd;
  567. m_hWnd = NULL;
  568. return hWnd;
  569. }
  570. #ifndef ATL_NO_NAMESPACE
  571. }; //namespace ATL
  572. #endif
  573. ///////////////////////////////////////////////////////////////////////////////
  574. //All Global stuff goes below this line
  575. ///////////////////////////////////////////////////////////////////////////////