/thirdparty/wtl/atlframe.h

http://crashrpt.googlecode.com/ · C Header · 3678 lines · 2942 code · 488 blank · 248 comment · 704 complexity · 418035ec778967ae3632c7f33f3fcf3c MD5 · raw file

Large files are truncated click here to view the full file

  1. // Windows Template Library - WTL version 8.1
  2. // Copyright (C) Microsoft Corporation. All rights reserved.
  3. //
  4. // This file is a part of the Windows Template Library.
  5. // The use and distribution terms for this software are covered by the
  6. // Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
  7. // which can be found in the file CPL.TXT at the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by
  9. // the terms of this license. You must not remove this notice, or
  10. // any other, from this software.
  11. #ifndef __ATLFRAME_H__
  12. #define __ATLFRAME_H__
  13. #pragma once
  14. #ifndef __ATLAPP_H__
  15. #error atlframe.h requires atlapp.h to be included first
  16. #endif
  17. #ifndef __ATLWIN_H__
  18. #error atlframe.h requires atlwin.h to be included first
  19. #endif
  20. ///////////////////////////////////////////////////////////////////////////////
  21. // Classes in this file:
  22. //
  23. // CFrameWindowImpl<T, TBase, TWinTraits>
  24. // CMDIWindow
  25. // CMDIFrameWindowImpl<T, TBase, TWinTraits>
  26. // CMDIChildWindowImpl<T, TBase, TWinTraits>
  27. // COwnerDraw<T>
  28. // CUpdateUIBase
  29. // CUpdateUI<T>
  30. // CDynamicUpdateUI<T>
  31. // CAutoUpdateUI<T>
  32. // CDialogResize<T>
  33. // CDoubleBufferImpl<T>
  34. // CDoubleBufferWindowImpl<T, TBase, TWinTraits>
  35. //
  36. // Global functions:
  37. // AtlCreateSimpleToolBar()
  38. namespace WTL
  39. {
  40. ///////////////////////////////////////////////////////////////////////////////
  41. // CFrameWndClassInfo - Manages frame window Windows class information
  42. class CFrameWndClassInfo
  43. {
  44. public:
  45. #ifndef _WIN32_WCE
  46. enum { cchAutoName = 5 + sizeof(void*) * 2 }; // sizeof(void*) * 2 is the number of digits %p outputs
  47. WNDCLASSEX m_wc;
  48. #else // CE specific
  49. enum { cchAutoName = MAX_PATH }; // MAX_PATH because this can be set in the wizard generated CMainFrame::ActivatePreviousInstance to a user defined string.
  50. WNDCLASS m_wc;
  51. #endif // !_WIN32_WCE
  52. LPCTSTR m_lpszOrigName;
  53. WNDPROC pWndProc;
  54. LPCTSTR m_lpszCursorID;
  55. BOOL m_bSystemCursor;
  56. ATOM m_atom;
  57. TCHAR m_szAutoName[cchAutoName];
  58. UINT m_uCommonResourceID;
  59. #ifndef _WIN32_WCE
  60. ATOM Register(WNDPROC* pProc)
  61. {
  62. if (m_atom == 0)
  63. {
  64. CWindowCreateCriticalSectionLock lock;
  65. if(FAILED(lock.Lock()))
  66. {
  67. ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
  68. ATLASSERT(FALSE);
  69. return 0;
  70. }
  71. if(m_atom == 0)
  72. {
  73. HINSTANCE hInst = ModuleHelper::GetModuleInstance();
  74. if (m_lpszOrigName != NULL)
  75. {
  76. ATLASSERT(pProc != NULL);
  77. LPCTSTR lpsz = m_wc.lpszClassName;
  78. WNDPROC proc = m_wc.lpfnWndProc;
  79. WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
  80. // try process local class first
  81. if(!::GetClassInfoEx(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
  82. {
  83. // try global class
  84. if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
  85. {
  86. lock.Unlock();
  87. return 0;
  88. }
  89. }
  90. m_wc = wc;
  91. pWndProc = m_wc.lpfnWndProc;
  92. m_wc.lpszClassName = lpsz;
  93. m_wc.lpfnWndProc = proc;
  94. }
  95. else
  96. {
  97. m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
  98. }
  99. m_wc.hInstance = hInst;
  100. m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
  101. if (m_wc.lpszClassName == NULL)
  102. {
  103. #if (_WIN32_WINNT >= 0x0500) || defined(_WIN64)
  104. SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%p"), &m_wc);
  105. #else // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
  106. SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
  107. #endif // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
  108. m_wc.lpszClassName = m_szAutoName;
  109. }
  110. WNDCLASSEX wcTemp = m_wc;
  111. m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
  112. if (m_atom == 0)
  113. {
  114. if(m_uCommonResourceID != 0) // use it if not zero
  115. {
  116. m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
  117. m_wc.hIconSm = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  118. }
  119. m_atom = ::RegisterClassEx(&m_wc);
  120. }
  121. }
  122. lock.Unlock();
  123. }
  124. if (m_lpszOrigName != NULL)
  125. {
  126. ATLASSERT(pProc != NULL);
  127. ATLASSERT(pWndProc != NULL);
  128. *pProc = pWndProc;
  129. }
  130. return m_atom;
  131. }
  132. #else // CE specific
  133. ATOM Register(WNDPROC* pProc)
  134. {
  135. if (m_atom == 0)
  136. {
  137. CWindowCreateCriticalSectionLock lock;
  138. if(FAILED(lock.Lock()))
  139. {
  140. ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
  141. ATLASSERT(FALSE);
  142. return 0;
  143. }
  144. if(m_atom == 0)
  145. {
  146. HINSTANCE hInst = ModuleHelper::GetModuleInstance();
  147. if (m_lpszOrigName != NULL)
  148. {
  149. ATLASSERT(pProc != NULL);
  150. LPCTSTR lpsz = m_wc.lpszClassName;
  151. WNDPROC proc = m_wc.lpfnWndProc;
  152. WNDCLASS wc = { 0 };
  153. // try process local class first
  154. if(!::GetClassInfo(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
  155. {
  156. // try global class
  157. if(!::GetClassInfo(NULL, m_lpszOrigName, &wc))
  158. {
  159. lock.Unlock();
  160. return 0;
  161. }
  162. }
  163. m_wc = wc;
  164. pWndProc = m_wc.lpfnWndProc;
  165. m_wc.lpszClassName = lpsz;
  166. m_wc.lpfnWndProc = proc;
  167. }
  168. else
  169. {
  170. #if defined(GWES_CURSOR) || defined(GWES_MCURSOR)
  171. m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
  172. #else // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
  173. m_wc.hCursor = NULL;
  174. #endif // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
  175. }
  176. m_wc.hInstance = hInst;
  177. m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
  178. if (m_wc.lpszClassName == NULL)
  179. {
  180. wsprintf(m_szAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
  181. m_wc.lpszClassName = m_szAutoName;
  182. }
  183. WNDCLASS wcTemp = m_wc;
  184. m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
  185. if (m_atom == 0)
  186. {
  187. if(m_uCommonResourceID != 0) // use it if not zero
  188. m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
  189. m_atom = ::RegisterClass(&m_wc);
  190. }
  191. }
  192. lock.Unlock();
  193. }
  194. if (m_lpszOrigName != NULL)
  195. {
  196. ATLASSERT(pProc != NULL);
  197. ATLASSERT(pWndProc != NULL);
  198. *pProc = pWndProc;
  199. }
  200. return m_atom;
  201. }
  202. #endif // _WIN32_WCE
  203. };
  204. ///////////////////////////////////////////////////////////////////////////////
  205. // Macros for declaring frame window WNDCLASS
  206. #ifndef _WIN32_WCE
  207. #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
  208. static WTL::CFrameWndClassInfo& GetWndClassInfo() \
  209. { \
  210. static WTL::CFrameWndClassInfo wc = \
  211. { \
  212. { sizeof(WNDCLASSEX), 0, StartWindowProc, \
  213. 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
  214. NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
  215. }; \
  216. return wc; \
  217. }
  218. #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
  219. static WTL::CFrameWndClassInfo& GetWndClassInfo() \
  220. { \
  221. static WTL::CFrameWndClassInfo wc = \
  222. { \
  223. { sizeof(WNDCLASSEX), style, StartWindowProc, \
  224. 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
  225. NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
  226. }; \
  227. return wc; \
  228. }
  229. #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
  230. static WTL::CFrameWndClassInfo& GetWndClassInfo() \
  231. { \
  232. static WTL::CFrameWndClassInfo wc = \
  233. { \
  234. { sizeof(WNDCLASSEX), 0, StartWindowProc, \
  235. 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
  236. OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \
  237. }; \
  238. return wc; \
  239. }
  240. #else // CE specific
  241. #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
  242. static WTL::CFrameWndClassInfo& GetWndClassInfo() \
  243. { \
  244. static WTL::CFrameWndClassInfo wc = \
  245. { \
  246. { 0, StartWindowProc, \
  247. 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \
  248. NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
  249. }; \
  250. return wc; \
  251. }
  252. #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
  253. static WTL::CFrameWndClassInfo& GetWndClassInfo() \
  254. { \
  255. static WTL::CFrameWndClassInfo wc = \
  256. { \
  257. { style, StartWindowProc, \
  258. 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
  259. NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
  260. }; \
  261. return wc; \
  262. }
  263. #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
  264. static WTL::CFrameWndClassInfo& GetWndClassInfo() \
  265. { \
  266. static WTL::CFrameWndClassInfo wc = \
  267. { \
  268. { NULL, StartWindowProc, \
  269. 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \
  270. OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
  271. }; \
  272. return wc; \
  273. }
  274. #endif // !_WIN32_WCE
  275. ///////////////////////////////////////////////////////////////////////////////
  276. // CFrameWindowImpl
  277. // Client window command chaining macro (only for frame windows)
  278. #define CHAIN_CLIENT_COMMANDS() \
  279. if(uMsg == WM_COMMAND && m_hWndClient != NULL) \
  280. ::SendMessage(m_hWndClient, uMsg, wParam, lParam);
  281. // standard toolbar styles
  282. #define ATL_SIMPLE_TOOLBAR_STYLE \
  283. (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS)
  284. // toolbar in a rebar pane
  285. #define ATL_SIMPLE_TOOLBAR_PANE_STYLE \
  286. (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT)
  287. // standard rebar styles
  288. #if (_WIN32_IE >= 0x0400)
  289. #define ATL_SIMPLE_REBAR_STYLE \
  290. (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE)
  291. #else
  292. #define ATL_SIMPLE_REBAR_STYLE \
  293. (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS)
  294. #endif // !(_WIN32_IE >= 0x0400)
  295. // rebar without borders
  296. #if (_WIN32_IE >= 0x0400)
  297. #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
  298. (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER)
  299. #else
  300. #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
  301. (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | CCS_NODIVIDER)
  302. #endif // !(_WIN32_IE >= 0x0400)
  303. // command bar support
  304. #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
  305. #define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar HWND
  306. #define CBRM_GETMENU (WM_USER + 302) // returns loaded or attached menu
  307. #define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu
  308. struct _AtlFrameWnd_CmdBarPopupMenu
  309. {
  310. int cbSize;
  311. HMENU hMenu;
  312. UINT uFlags;
  313. int x;
  314. int y;
  315. LPTPMPARAMS lptpm;
  316. };
  317. #define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu
  318. #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
  319. template <class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
  320. class ATL_NO_VTABLE CFrameWindowImplBase : public ATL::CWindowImplBaseT< TBase, TWinTraits >
  321. {
  322. public:
  323. DECLARE_FRAME_WND_CLASS(NULL, 0)
  324. #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
  325. struct _ChevronMenuInfo
  326. {
  327. HMENU hMenu;
  328. LPNMREBARCHEVRON lpnm;
  329. bool bCmdBar;
  330. };
  331. #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
  332. // Data members
  333. HWND m_hWndToolBar;
  334. HWND m_hWndStatusBar;
  335. HWND m_hWndClient;
  336. #ifdef _WIN32_WCE
  337. HWND m_hWndCECommandBar;
  338. #endif // _WIN32_WCE
  339. HACCEL m_hAccel;
  340. // Constructor
  341. CFrameWindowImplBase() :
  342. m_hWndToolBar(NULL),
  343. m_hWndStatusBar(NULL),
  344. m_hWndClient(NULL),
  345. #ifdef _WIN32_WCE
  346. m_hWndCECommandBar(NULL),
  347. #endif // _WIN32_WCE
  348. m_hAccel(NULL)
  349. { }
  350. // Methods
  351. HWND Create(HWND hWndParent, ATL::_U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, ATL::_U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
  352. {
  353. ATLASSERT(m_hWnd == NULL);
  354. if(atom == 0)
  355. return NULL;
  356. ModuleHelper::AddCreateWndData(&m_thunk.cd, this);
  357. if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD))
  358. MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
  359. if(rect.m_lpRect == NULL)
  360. rect.m_lpRect = &TBase::rcDefault;
  361. HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName,
  362. dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left,
  363. rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu,
  364. ModuleHelper::GetModuleInstance(), lpCreateParam);
  365. ATLASSERT(hWnd == NULL || m_hWnd == hWnd);
  366. return hWnd;
  367. }
  368. static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE,
  369. DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
  370. {
  371. HINSTANCE hInst = ModuleHelper::GetResourceInstance();
  372. HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID), RT_TOOLBAR);
  373. if (hRsrc == NULL)
  374. return NULL;
  375. HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc);
  376. if (hGlobal == NULL)
  377. return NULL;
  378. _AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGlobal);
  379. if (pData == NULL)
  380. return NULL;
  381. ATLASSERT(pData->wVersion == 1);
  382. WORD* pItems = pData->items();
  383. int nItems = pData->wItemCount + (bInitialSeparator ? 1 : 0);
  384. CTempBuffer<TBBUTTON, _WTL_STACK_ALLOC_THRESHOLD> buff;
  385. TBBUTTON* pTBBtn = buff.Allocate(nItems);
  386. ATLASSERT(pTBBtn != NULL);
  387. if(pTBBtn == NULL)
  388. return NULL;
  389. const int cxSeparator = 8;
  390. // set initial separator (half width)
  391. if(bInitialSeparator)
  392. {
  393. pTBBtn[0].iBitmap = cxSeparator / 2;
  394. pTBBtn[0].idCommand = 0;
  395. pTBBtn[0].fsState = 0;
  396. pTBBtn[0].fsStyle = TBSTYLE_SEP;
  397. pTBBtn[0].dwData = 0;
  398. pTBBtn[0].iString = 0;
  399. }
  400. int nBmp = 0;
  401. for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCount; i++, j++)
  402. {
  403. if(pItems[i] != 0)
  404. {
  405. pTBBtn[j].iBitmap = nBmp++;
  406. pTBBtn[j].idCommand = pItems[i];
  407. pTBBtn[j].fsState = TBSTATE_ENABLED;
  408. pTBBtn[j].fsStyle = TBSTYLE_BUTTON;
  409. pTBBtn[j].dwData = 0;
  410. pTBBtn[j].iString = 0;
  411. }
  412. else
  413. {
  414. pTBBtn[j].iBitmap = cxSeparator;
  415. pTBBtn[j].idCommand = 0;
  416. pTBBtn[j].fsState = 0;
  417. pTBBtn[j].fsStyle = TBSTYLE_SEP;
  418. pTBBtn[j].dwData = 0;
  419. pTBBtn[j].iString = 0;
  420. }
  421. }
  422. #ifndef _WIN32_WCE
  423. HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
  424. if(hWnd == NULL)
  425. {
  426. ATLASSERT(FALSE);
  427. return NULL;
  428. }
  429. #else // CE specific
  430. dwStyle;
  431. nID;
  432. // The toolbar must go onto the existing CommandBar or MenuBar
  433. HWND hWnd = hWndParent;
  434. #endif // _WIN32_WCE
  435. ::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L);
  436. // check if font is taller than our bitmaps
  437. CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L);
  438. if(font.IsNull())
  439. font = (HFONT)::GetStockObject(SYSTEM_FONT);
  440. LOGFONT lf = { 0 };
  441. font.GetLogFont(lf);
  442. WORD cyFontHeight = (WORD)abs(lf.lfHeight);
  443. #ifndef _WIN32_WCE
  444. WORD bitsPerPixel = AtlGetBitmapResourceBitsPerPixel(nResourceID);
  445. if(bitsPerPixel > 4)
  446. {
  447. COLORREF crMask = CLR_DEFAULT;
  448. if(bitsPerPixel == 32)
  449. {
  450. // 32-bit color bitmap with alpha channel (valid for Windows XP and later)
  451. crMask = CLR_NONE;
  452. }
  453. HIMAGELIST hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nResourceID), pData->wWidth, 1, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
  454. ATLASSERT(hImageList != NULL);
  455. ::SendMessage(hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
  456. }
  457. else
  458. #endif // !_WIN32_WCE
  459. {
  460. TBADDBITMAP tbab = { 0 };
  461. tbab.hInst = hInst;
  462. tbab.nID = nResourceID;
  463. ::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab);
  464. }
  465. ::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn);
  466. ::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth, max(pData->wHeight, cyFontHeight)));
  467. const int cxyButtonMargin = 7;
  468. ::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth + cxyButtonMargin, max(pData->wHeight, cyFontHeight) + cxyButtonMargin));
  469. return hWnd;
  470. }
  471. #ifndef _WIN32_WCE
  472. static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
  473. {
  474. // Ensure style combinations for proper rebar painting
  475. if(dwStyle & CCS_NODIVIDER && dwStyle & WS_BORDER)
  476. dwStyle &= ~WS_BORDER;
  477. else if(!(dwStyle & WS_BORDER) && !(dwStyle & CCS_NODIVIDER))
  478. dwStyle |= CCS_NODIVIDER;
  479. // Create rebar window
  480. HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
  481. if(hWndReBar == NULL)
  482. {
  483. ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n"));
  484. return NULL;
  485. }
  486. // Initialize and send the REBARINFO structure
  487. REBARINFO rbi = { sizeof(REBARINFO), 0 };
  488. if(::SendMessage(hWndReBar, RB_SETBARINFO, 0, (LPARAM)&rbi) == 0)
  489. {
  490. ATLTRACE2(atlTraceUI, 0, _T("Failed to initialize rebar.\n"));
  491. ::DestroyWindow(hWndReBar);
  492. return NULL;
  493. }
  494. return hWndReBar;
  495. }
  496. BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
  497. {
  498. ATLASSERT(!::IsWindow(m_hWndToolBar));
  499. m_hWndToolBar = CreateSimpleReBarCtrl(m_hWnd, dwStyle, nID);
  500. return (m_hWndToolBar != NULL);
  501. }
  502. static BOOL AddSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nID = 0, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
  503. {
  504. ATLASSERT(::IsWindow(hWndReBar)); // must be already created
  505. #ifdef _DEBUG
  506. // block - check if this is really a rebar
  507. {
  508. TCHAR lpszClassName[sizeof(REBARCLASSNAME)] = { 0 };
  509. ::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLASSNAME));
  510. ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0);
  511. }
  512. #endif // _DEBUG
  513. ATLASSERT(::IsWindow(hWndBand)); // must be already created
  514. // Get number of buttons on the toolbar
  515. int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0, 0L);
  516. // Set band info structure
  517. REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
  518. #if (_WIN32_IE >= 0x0400)
  519. rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE;
  520. #else
  521. rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE;
  522. #endif // !(_WIN32_IE >= 0x0400)
  523. if(lpstrTitle != NULL)
  524. rbBand.fMask |= RBBIM_TEXT;
  525. rbBand.fStyle = RBBS_CHILDEDGE;
  526. #if (_WIN32_IE >= 0x0500)
  527. if(nBtnCount > 0) // add chevron style for toolbar with buttons
  528. rbBand.fStyle |= RBBS_USECHEVRON;
  529. #endif // (_WIN32_IE >= 0x0500)
  530. if(bNewRow)
  531. rbBand.fStyle |= RBBS_BREAK;
  532. rbBand.lpText = (LPTSTR)lpstrTitle;
  533. rbBand.hwndChild = hWndBand;
  534. if(nID == 0) // calc band ID
  535. nID = ATL_IDW_BAND_FIRST + (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L);
  536. rbBand.wID = nID;
  537. // Calculate the size of the band
  538. BOOL bRet = FALSE;
  539. RECT rcTmp = { 0 };
  540. if(nBtnCount > 0)
  541. {
  542. bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBtnCount - 1, (LPARAM)&rcTmp);
  543. ATLASSERT(bRet);
  544. rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right;
  545. rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
  546. if(bFullWidthAlways)
  547. {
  548. rbBand.cxMinChild = rbBand.cx;
  549. }
  550. else if(lpstrTitle == NULL)
  551. {
  552. bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, 0, (LPARAM)&rcTmp);
  553. ATLASSERT(bRet);
  554. rbBand.cxMinChild = rcTmp.right;
  555. }
  556. else
  557. {
  558. rbBand.cxMinChild = 0;
  559. }
  560. }
  561. else // no buttons, either not a toolbar or really has no buttons
  562. {
  563. bRet = ::GetWindowRect(hWndBand, &rcTmp);
  564. ATLASSERT(bRet);
  565. rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rcTmp.left);
  566. rbBand.cxMinChild = bFullWidthAlways ? rbBand.cx : 0;
  567. rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
  568. }
  569. #if (_WIN32_IE >= 0x0400)
  570. rbBand.cxIdeal = rbBand.cx;
  571. #endif // (_WIN32_IE >= 0x0400)
  572. // Add the band
  573. LRESULT lRes = ::SendMessage(hWndReBar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
  574. if(lRes == 0)
  575. {
  576. ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the rebar.\n"));
  577. return FALSE;
  578. }
  579. #if (_WIN32_IE >= 0x0501)
  580. DWORD dwExStyle = (DWORD)::SendMessage(hWndBand, TB_GETEXTENDEDSTYLE, 0, 0L);
  581. ::SendMessage(hWndBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBSTYLE_EX_HIDECLIPPEDBUTTONS);
  582. #endif // (_WIN32_IE >= 0x0501)
  583. return TRUE;
  584. }
  585. BOOL AddSimpleReBarBand(HWND hWndBand, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
  586. {
  587. ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing rebar
  588. ATLASSERT(::IsWindow(hWndBand)); // must be created
  589. return AddSimpleReBarBandCtrl(m_hWndToolBar, hWndBand, 0, lpstrTitle, bNewRow, cxWidth, bFullWidthAlways);
  590. }
  591. #if (_WIN32_IE >= 0x0400)
  592. void SizeSimpleReBarBands()
  593. {
  594. ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing rebar
  595. int nCount = (int)::SendMessage(m_hWndToolBar, RB_GETBANDCOUNT, 0, 0L);
  596. for(int i = 0; i < nCount; i++)
  597. {
  598. REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
  599. rbBand.fMask = RBBIM_SIZE;
  600. BOOL bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_GETBANDINFO, i, (LPARAM)&rbBand);
  601. ATLASSERT(bRet);
  602. RECT rect = { 0, 0, 0, 0 };
  603. ::SendMessage(m_hWndToolBar, RB_GETBANDBORDERS, i, (LPARAM)&rect);
  604. rbBand.cx += rect.left + rect.right;
  605. bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_SETBANDINFO, i, (LPARAM)&rbBand);
  606. ATLASSERT(bRet);
  607. }
  608. }
  609. #endif // (_WIN32_IE >= 0x0400)
  610. #endif // _WIN32_WCE
  611. #ifndef _WIN32_WCE
  612. BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
  613. #else // CE specific
  614. BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
  615. #endif // _WIN32_WCE
  616. {
  617. ATLASSERT(!::IsWindow(m_hWndStatusBar));
  618. m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWnd, nID);
  619. return (m_hWndStatusBar != NULL);
  620. }
  621. #ifndef _WIN32_WCE
  622. BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
  623. #else // CE specific
  624. BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
  625. #endif // _WIN32_WCE
  626. {
  627. const int cchMax = 128; // max text length is 127 for status bars (+1 for null)
  628. TCHAR szText[cchMax] = { 0 };
  629. ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax);
  630. return CreateSimpleStatusBar(szText, dwStyle, nID);
  631. }
  632. #ifdef _WIN32_WCE
  633. BOOL CreateSimpleCECommandBar(LPTSTR pszMenu = NULL, WORD iButton = 0, DWORD dwFlags = 0, int nCmdBarID = 1)
  634. {
  635. ATLASSERT(m_hWndCECommandBar == NULL);
  636. ATLASSERT(m_hWndToolBar == NULL);
  637. m_hWndCECommandBar = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), m_hWnd, nCmdBarID);
  638. if(m_hWndCECommandBar == NULL)
  639. return FALSE;
  640. m_hWndToolBar = m_hWndCECommandBar;
  641. BOOL bRet = TRUE;
  642. if(pszMenu != NULL)
  643. bRet &= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar, IS_INTRESOURCE(pszMenu) ? ModuleHelper::GetResourceInstance() : NULL, pszMenu, iButton);
  644. bRet &= ::CommandBar_AddAdornments(m_hWndCECommandBar, dwFlags, 0);
  645. return bRet;
  646. }
  647. #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
  648. BOOL CreateSimpleCEMenuBar(UINT nToolBarId = ATL_IDW_MENU_BAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0)
  649. {
  650. ATLASSERT(m_hWndCECommandBar == NULL);
  651. SHMENUBARINFO mbi = { 0 };
  652. mbi.cbSize = sizeof(mbi);
  653. mbi.hwndParent = m_hWnd;
  654. mbi.dwFlags = dwFlags;
  655. mbi.nToolBarId = nToolBarId;
  656. mbi.hInstRes = ModuleHelper::GetResourceInstance();
  657. mbi.nBmpId = nBmpId;
  658. mbi.cBmpImages = cBmpImages;
  659. mbi.hwndMB = NULL; // This gets set by SHCreateMenuBar
  660. BOOL bRet = ::SHCreateMenuBar(&mbi);
  661. if(bRet != FALSE)
  662. {
  663. m_hWndCECommandBar = mbi.hwndMB;
  664. SizeToMenuBar();
  665. }
  666. return bRet;
  667. }
  668. void SizeToMenuBar() // for menu bar only
  669. {
  670. ATLASSERT(::IsWindow(m_hWnd));
  671. ATLASSERT(::IsWindow(m_hWndCECommandBar));
  672. RECT rect = { 0 };
  673. GetWindowRect(&rect);
  674. RECT rectMB = { 0 };
  675. ::GetWindowRect(m_hWndCECommandBar, &rectMB);
  676. int cy = ::IsWindowVisible(m_hWndCECommandBar) ? rectMB.top - rect.top : rectMB.bottom - rect.top;
  677. SetWindowPos(NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDER | SWP_NOMOVE);
  678. }
  679. #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
  680. #endif // _WIN32_WCE
  681. void UpdateLayout(BOOL bResizeBars = TRUE)
  682. {
  683. RECT rect = { 0 };
  684. GetClientRect(&rect);
  685. // position bars and offset their dimensions
  686. UpdateBarsPosition(rect, bResizeBars);
  687. // resize client window
  688. if(m_hWndClient != NULL)
  689. ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
  690. rect.right - rect.left, rect.bottom - rect.top,
  691. SWP_NOZORDER | SWP_NOACTIVATE);
  692. }
  693. void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE)
  694. {
  695. // resize toolbar
  696. if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBar, GWL_STYLE) & WS_VISIBLE))
  697. {
  698. if(bResizeBars != FALSE)
  699. {
  700. ::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0);
  701. ::InvalidateRect(m_hWndToolBar, NULL, TRUE);
  702. }
  703. RECT rectTB = { 0 };
  704. ::GetWindowRect(m_hWndToolBar, &rectTB);
  705. rect.top += rectTB.bottom - rectTB.top;
  706. }
  707. // resize status bar
  708. if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE))
  709. {
  710. if(bResizeBars != FALSE)
  711. ::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0);
  712. RECT rectSB = { 0 };
  713. ::GetWindowRect(m_hWndStatusBar, &rectSB);
  714. rect.bottom -= rectSB.bottom - rectSB.top;
  715. }
  716. }
  717. BOOL PreTranslateMessage(MSG* pMsg)
  718. {
  719. if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
  720. return TRUE;
  721. return FALSE;
  722. }
  723. BEGIN_MSG_MAP(CFrameWindowImplBase)
  724. MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
  725. #ifndef _WIN32_WCE
  726. MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
  727. #endif // !_WIN32_WCE
  728. MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
  729. MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
  730. #ifndef _WIN32_WCE
  731. NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA, OnToolTipTextA)
  732. NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW, OnToolTipTextW)
  733. #endif // !_WIN32_WCE
  734. END_MSG_MAP()
  735. LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  736. {
  737. if(m_hWndClient != NULL) // view will paint itself instead
  738. return 1;
  739. bHandled = FALSE;
  740. return 0;
  741. }
  742. #ifndef _WIN32_WCE
  743. LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  744. {
  745. bHandled = FALSE;
  746. if(m_hWndStatusBar == NULL)
  747. return 1;
  748. WORD wFlags = HIWORD(wParam);
  749. if(wFlags == 0xFFFF && lParam == NULL) // menu closing
  750. {
  751. ::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L);
  752. }
  753. else
  754. {
  755. const int cchBuff = 256;
  756. TCHAR szBuff[cchBuff] = { 0 };
  757. if(!(wFlags & MF_POPUP))
  758. {
  759. WORD wID = LOWORD(wParam);
  760. // check for special cases
  761. if(wID >= 0xF000 && wID < 0xF1F0) // system menu IDs
  762. wID = (WORD)(((wID - 0xF000) >> 4) + ATL_IDS_SCFIRST);
  763. else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FILE_MRU_LAST) // MRU items
  764. wID = ATL_IDS_MRU_FILE;
  765. else if(wID >= ATL_IDM_FIRST_MDICHILD && wID <= ATL_IDM_LAST_MDICHILD) // MDI child windows
  766. wID = ATL_IDS_MDICHILD;
  767. int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), wID, szBuff, cchBuff);
  768. for(int i = 0; i < nRet; i++)
  769. {
  770. if(szBuff[i] == _T('\n'))
  771. {
  772. szBuff[i] = 0;
  773. break;
  774. }
  775. }
  776. }
  777. ::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L);
  778. ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)szBuff);
  779. }
  780. return 1;
  781. }
  782. #endif // !_WIN32_WCE
  783. LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled)
  784. {
  785. if(m_hWndClient != NULL)
  786. ::SetFocus(m_hWndClient);
  787. bHandled = FALSE;
  788. return 1;
  789. }
  790. LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled)
  791. {
  792. if((GetStyle() & (WS_CHILD | WS_POPUP)) == 0)
  793. ::PostQuitMessage(1);
  794. bHandled = FALSE;
  795. return 1;
  796. }
  797. #ifndef _WIN32_WCE
  798. LRESULT OnToolTipTextA(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
  799. {
  800. LPNMTTDISPINFOA pDispInfo = (LPNMTTDISPINFOA)pnmh;
  801. pDispInfo->szText[0] = 0;
  802. if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
  803. {
  804. const int cchBuff = 256;
  805. char szBuff[cchBuff] = { 0 };
  806. int nRet = ::LoadStringA(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
  807. for(int i = 0; i < nRet; i++)
  808. {
  809. if(szBuff[i] == '\n')
  810. {
  811. SecureHelper::strncpyA_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
  812. break;
  813. }
  814. }
  815. #if (_WIN32_IE >= 0x0300)
  816. if(nRet > 0) // string was loaded, save it
  817. pDispInfo->uFlags |= TTF_DI_SETITEM;
  818. #endif // (_WIN32_IE >= 0x0300)
  819. }
  820. return 0;
  821. }
  822. LRESULT OnToolTipTextW(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
  823. {
  824. LPNMTTDISPINFOW pDispInfo = (LPNMTTDISPINFOW)pnmh;
  825. pDispInfo->szText[0] = 0;
  826. if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
  827. {
  828. const int cchBuff = 256;
  829. wchar_t szBuff[cchBuff] = { 0 };
  830. int nRet = ::LoadStringW(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
  831. for(int i = 0; i < nRet; i++)
  832. {
  833. if(szBuff[i] == L'\n')
  834. {
  835. SecureHelper::strncpyW_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
  836. break;
  837. }
  838. }
  839. #if (_WIN32_IE >= 0x0300)
  840. if(nRet > 0) // string was loaded, save it
  841. pDispInfo->uFlags |= TTF_DI_SETITEM;
  842. #endif // (_WIN32_IE >= 0x0300)
  843. }
  844. return 0;
  845. }
  846. #endif // !_WIN32_WCE
  847. // Implementation - chevron menu support
  848. #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
  849. bool PrepareChevronMenu(_ChevronMenuInfo& cmi)
  850. {
  851. // get rebar and toolbar
  852. REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() };
  853. rbbi.fMask = RBBIM_CHILD;
  854. BOOL bRet = (BOOL)::SendMessage(cmi.lpnm->hdr.hwndFrom, RB_GETBANDINFO, cmi.lpnm->uBand, (LPARAM)&rbbi);
  855. ATLASSERT(bRet);
  856. // assume the band is a toolbar
  857. ATL::CWindow wnd = rbbi.hwndChild;
  858. int nCount = (int)wnd.SendMessage(TB_BUTTONCOUNT);
  859. if(nCount <= 0) // probably not a toolbar
  860. return false;
  861. // check if it's a command bar
  862. CMenuHandle menuCmdBar = (HMENU)wnd.SendMessage(CBRM_GETMENU);
  863. cmi.bCmdBar = (menuCmdBar.m_hMenu != NULL);
  864. // build a menu from hidden items
  865. CMenuHandle menu;
  866. bRet = menu.CreatePopupMenu();
  867. ATLASSERT(bRet);
  868. RECT rcClient = { 0 };
  869. bRet = wnd.GetClientRect(&rcClient);
  870. ATLASSERT(bRet);
  871. for(int i = 0; i < nCount; i++)
  872. {
  873. TBBUTTON tbb = { 0 };
  874. bRet = (BOOL)wnd.SendMessage(TB_GETBUTTON, i, (LPARAM)&tbb);
  875. ATLASSERT(bRet);
  876. // skip hidden buttons
  877. if((tbb.fsState & TBSTATE_HIDDEN) != 0)
  878. continue;
  879. RECT rcButton = { 0 };
  880. bRet = (BOOL)wnd.SendMessage(TB_GETITEMRECT, i, (LPARAM)&rcButton);
  881. ATLASSERT(bRet);
  882. bool bEnabled = ((tbb.fsState & TBSTATE_ENABLED) != 0);
  883. if(rcButton.right > rcClient.right)
  884. {
  885. if(tbb.fsStyle & BTNS_SEP)
  886. {
  887. if(menu.GetMenuItemCount() > 0)
  888. menu.AppendMenu(MF_SEPARATOR);
  889. }
  890. else if(cmi.bCmdBar)
  891. {
  892. const int cchBuff = 200;
  893. TCHAR szBuff[cchBuff] = { 0 };
  894. CMenuItemInfo mii;
  895. mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
  896. mii.dwTypeData = szBuff;
  897. mii.cch = cchBuff;
  898. bRet = menuCmdBar.GetMenuItemInfo(i, TRUE, &mii);
  899. ATLASSERT(bRet);
  900. // Note: CmdBar currently supports only drop-down items
  901. ATLASSERT(::IsMenu(mii.hSubMenu));
  902. bRet = menu.AppendMenu(MF_STRING | MF_POPUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeData);
  903. ATLASSERT(bRet);
  904. }
  905. else
  906. {
  907. // get button's text
  908. const int cchBuff = 200;
  909. TCHAR szBuff[cchBuff] = { 0 };
  910. LPTSTR lpstrText = szBuff;
  911. TBBUTTONINFO tbbi = { 0 };
  912. tbbi.cbSize = sizeof(TBBUTTONINFO);
  913. tbbi.dwMask = TBIF_TEXT;
  914. tbbi.pszText = szBuff;
  915. tbbi.cchText = cchBuff;
  916. if(wnd.SendMessage(TB_GETBUTTONINFO, tbb.idCommand, (LPARAM)&tbbi) == -1 || lstrlen(szBuff) == 0)
  917. {
  918. // no text for this button, try a resource string
  919. lpstrText = _T("");
  920. int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), tbb.idCommand, szBuff, cchBuff);
  921. for(int n = 0; n < nRet; n++)
  922. {
  923. if(szBuff[n] == _T('\n'))
  924. {
  925. lpstrText = &szBuff[n + 1];
  926. break;
  927. }
  928. }
  929. }
  930. bRet = menu.AppendMenu(MF_STRING | (bEnabled ? MF_ENABLED : MF_GRAYED), tbb.idCommand, lpstrText);
  931. ATLASSERT(bRet);
  932. }
  933. }
  934. }
  935. if(menu.GetMenuItemCount() == 0) // no hidden buttons after all
  936. {
  937. menu.DestroyMenu();
  938. ::MessageBeep((UINT)-1);
  939. return false;
  940. }
  941. cmi.hMenu = menu;
  942. return true;
  943. }
  944. void DisplayChevronMenu(_ChevronMenuInfo& cmi)
  945. {
  946. #ifndef TPM_VERPOSANIMATION
  947. const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu animation flag
  948. #endif
  949. // convert chevron rect to screen coordinates
  950. ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
  951. POINT pt = { cmi.lpnm->rc.left, cmi.lpnm->rc.bottom };
  952. wndFrom.MapWindowPoints(NULL, &pt, 1);
  953. RECT rc = cmi.lpnm->rc;
  954. wndFrom.MapWindowPoints(NULL, &rc);
  955. // set up flags and rect
  956. UINT uMenuFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | (!AtlIsOldWindows() ? TPM_VERPOSANIMATION : 0);
  957. TPMPARAMS TPMParams = { 0 };
  958. TPMParams.cbSize = sizeof(TPMPARAMS);
  959. TPMParams.rcExclude = rc;
  960. // check if this window has a command bar
  961. HWND hWndCmdBar = (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L);
  962. if(::IsWindow(hWndCmdBar))
  963. {
  964. CBRPOPUPMENU CBRPopupMenu = { sizeof(CBRPOPUPMENU), cmi.hMenu, uMenuFlags, pt.x, pt.y, &TPMParams };
  965. ::SendMessage(hWndCmdBar, CBRM_TRACKPOPUPMENU, 0, (LPARAM)&CBRPopupMenu);
  966. }
  967. else
  968. {
  969. CMenuHandle menu = cmi.hMenu;
  970. menu.TrackPopupMenuEx(uMenuFlags, pt.x, pt.y, m_hWnd, &TPMParams);
  971. }
  972. }
  973. void CleanupChevronMenu(_ChevronMenuInfo& cmi)
  974. {
  975. CMenuHandle menu = cmi.hMenu;
  976. // if menu is from a command bar, detach submenus so they are not destroyed
  977. if(cmi.bCmdBar)
  978. {
  979. for(int i = menu.GetMenuItemCount() - 1; i >=0; i--)
  980. menu.RemoveMenu(i, MF_BYPOSITION);
  981. }
  982. // destroy menu
  983. menu.DestroyMenu();
  984. // convert chevron rect to screen coordinates
  985. ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
  986. RECT rc = cmi.lpnm->rc;
  987. wndFrom.MapWindowPoints(NULL, &rc);
  988. // eat next message if click is on the same button
  989. MSG msg = { 0 };
  990. if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rc, msg.pt))
  991. ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
  992. }
  993. #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
  994. };
  995. template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
  996. class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinTraits >
  997. {
  998. public:
  999. HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
  1000. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  1001. HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
  1002. {
  1003. ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
  1004. dwStyle = T::GetWndStyle(dwStyle);
  1005. dwExStyle = T::GetWndExStyle(dwExStyle);
  1006. if(rect.m_lpRect == NULL)
  1007. rect.m_lpRect = &TBase::rcDefault;
  1008. return CFrameWindowImplBase< TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
  1009. }
  1010. HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
  1011. {
  1012. const int cchName = 256;
  1013. TCHAR szWindowName[cchName] = { 0 };
  1014. #ifndef _WIN32_WCE
  1015. ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
  1016. HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
  1017. #else // CE specific
  1018. ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
  1019. // This always needs to be NULL for Windows CE.
  1020. // Frame Window menus have to go onto the CommandBar.
  1021. // Use CreateSimpleCECommandBar
  1022. HMENU hMenu = NULL;
  1023. #endif // _WIN32_WCE
  1024. T* pT = static_cast<T*>(this);
  1025. HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
  1026. if(hWnd != NULL)
  1027. m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
  1028. return hWnd;
  1029. }
  1030. BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
  1031. {
  1032. if(nResourceID == 0)
  1033. nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
  1034. #ifndef _WIN32_WCE
  1035. ATLASSERT(!::IsWindow(m_hWndToolBar));
  1036. m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
  1037. return (m_hWndToolBar != NULL);
  1038. #else // CE specific
  1039. HWND hWnd= T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
  1040. return (hWnd != NULL);
  1041. #endif // _WIN32_WCE
  1042. }
  1043. #ifdef _WIN32_WCE
  1044. // CE specific variant that returns the handle of the toolbar
  1045. HWND CreateSimpleCEToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
  1046. {
  1047. if(nResourceID == 0)
  1048. nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
  1049. return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
  1050. }
  1051. #endif // _WIN32_WCE
  1052. // message map and handlers
  1053. typedef CFrameWindowImplBase< TBase, TWinTraits > _baseClass;
  1054. BEGIN_MSG_MAP(CFrameWindowImpl)
  1055. MESSAGE_HANDLER(WM_SIZE, OnSize)
  1056. #ifndef _ATL_NO_REBAR_SUPPORT
  1057. #if (_WIN32_IE >= 0x0400)
  1058. NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
  1059. #endif // (_WIN32_IE >= 0x0400)
  1060. #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
  1061. NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
  1062. #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
  1063. #endif // !_ATL_NO_REBAR_SUPPORT
  1064. CHAIN_MSG_MAP(_baseClass)
  1065. END_MSG_MAP()
  1066. LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
  1067. {
  1068. if(wParam != SIZE_MINIMIZED)
  1069. {
  1070. T* pT = static_cast<T*>(this);
  1071. pT->UpdateLayout();
  1072. }
  1073. bHandled = FALSE;
  1074. return 1;
  1075. }
  1076. #ifndef _ATL_NO_REBAR_SUPPORT
  1077. #if (_WIN32_IE >= 0x0400)
  1078. LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
  1079. {
  1080. T* pT = static_cast<T*>(this);
  1081. pT->UpdateLayout(FALSE);
  1082. return 0;
  1083. }
  1084. #endif // (_WIN32_IE >= 0x0400)
  1085. #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
  1086. LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
  1087. {
  1088. T* pT = static_cast<T*>(this);
  1089. _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
  1090. if(!pT->PrepareChevronMenu(cmi))
  1091. {
  1092. bHandled = FALSE;
  1093. return 1;
  1094. }
  1095. // display a popup menu with hidden items
  1096. pT->DisplayChevronMenu(cmi);
  1097. // cleanup
  1098. pT->CleanupChevronMenu(cmi);
  1099. return 0;
  1100. }
  1101. #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
  1102. #endif // !_ATL_NO_REBAR_SUPPORT
  1103. };
  1104. ///////////////////////////////////////////////////////////////////////////////
  1105. // AtlCreateSimpleToolBar - helper for creating simple toolbars
  1106. #ifndef _WIN32_WCE
  1107. inline HWND AtlCreateSimpleToolBar(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE,
  1108. DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
  1109. {
  1110. return CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(hWndParent, nResourceID, bInitialSeparator, dwStyle, nID);
  1111. }
  1112. #endif // !_WIN32_WCE
  1113. ///////////////////////////////////////////////////////////////////////////////
  1114. // CMDIWindow
  1115. #ifndef _WIN32_WCE
  1116. #ifndef _WTL_MDIWINDOWMENU_TEXT
  1117. #define _WTL_MDIWINDOWMENU_TEXT _T("&Window")
  1118. #endif
  1119. class CMDIWindow : public ATL::CWindow
  1120. {
  1121. public:
  1122. // Data members
  1123. HWND m_hWndMDIClient;
  1124. HMENU m_hMenu;
  1125. // Constructors
  1126. CMDIWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd), m_hWndMDIClient(NULL), m_hMenu(NULL)
  1127. { }
  1128. CMDIWindow& operator =(HWND hWnd)
  1129. {
  1130. m_hWnd = hWnd;
  1131. return *this;
  1132. }
  1133. // Operations
  1134. HWND MDIGetActive(BOOL* lpbMaximized = NULL)
  1135. {
  1136. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1137. return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)lpbMaximized);
  1138. }
  1139. void MDIActivate(HWND hWndChildToActivate)
  1140. {
  1141. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1142. ATLASSERT(::IsWindow(hWndChildToActivate));
  1143. ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChildToActivate, 0);
  1144. }
  1145. void MDINext(HWND hWndChild, BOOL bPrevious = FALSE)
  1146. {
  1147. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1148. ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild));
  1149. ::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (LPARAM)bPrevious);
  1150. }
  1151. void MDIMaximize(HWND hWndChildToMaximize)
  1152. {
  1153. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1154. ATLASSERT(::IsWindow(hWndChildToMaximize));
  1155. ::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChildToMaximize, 0);
  1156. }
  1157. void MDIRestore(HWND hWndChildToRestore)
  1158. {
  1159. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1160. ATLASSERT(::IsWindow(hWndChildToRestore));
  1161. ::SendMessage(m_hWndMDIClient, WM_MDIRESTORE, (WPARAM)hWndChildToRestore, 0);
  1162. }
  1163. void MDIDestroy(HWND hWndChildToDestroy)
  1164. {
  1165. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1166. ATLASSERT(::IsWindow(hWndChildToDestroy));
  1167. ::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildToDestroy, 0);
  1168. }
  1169. BOOL MDICascade(UINT uFlags = 0)
  1170. {
  1171. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1172. return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPARAM)uFlags, 0);
  1173. }
  1174. BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL)
  1175. {
  1176. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1177. return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)uFlags, 0);
  1178. }
  1179. void MDIIconArrange()
  1180. {
  1181. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1182. ::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0);
  1183. }
  1184. HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow)
  1185. {
  1186. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1187. return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuFrame, (LPARAM)hMenuWindow);
  1188. }
  1189. HMENU MDIRefreshMenu()
  1190. {
  1191. ATLASSERT(::IsWindow(m_hWndMDIClient));
  1192. return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
  1193. }
  1194. // Additional operations
  1195. static HMENU GetStandardWindowMenu(HMENU hMenu)
  1196. {
  1197. int nCount = ::GetMenuItemCount(hMenu);
  1198. if(nCount == -1)
  1199. return NULL;
  1200. int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSITION);
  1201. if(nLen == 0)
  1202. return NULL;
  1203. CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
  1204. LPTSTR lpszText = buff.Allocate(nLen + 1);
  1205. if(lpszText == NULL)
  1206. return NULL;
  1207. if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYPOSITION) != nLen)
  1208. return NULL;
  1209. if(lstrcmp(lpszText, _WTL_MDIWINDOWMENU_TEXT) != 0)
  1210. return NULL;
  1211. return ::GetSubMenu(hMenu, nCount - 2);
  1212. }
  1213. void SetMDIFrameMenu()
  1214. {
  1215. HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu);
  1216. MDISetMenu(m_hMenu, hWindowMenu);
  1217. MDIRefreshMenu();
  1218. ::DrawMenuBar(GetMDIFrame());
  1219. }
  1220. HWND GetMDIFrame() const
  1221. {
  1222. return ::GetParent(m_hWndMDIClient);
  1223. }
  1224. };
  1225. #endif // !_WIN32_WCE
  1226. ///////////////////////////////////////////////////////////////////////////////
  1227. // CMDIFrameWindowImpl
  1228. #ifndef _WIN32_WCE
  1229. // MDI child command chaining macro (only for MDI frame windows)
  1230. #define CHAIN_MDI_CHILD_COMMANDS() \
  1231. if(uMsg == WM_COMMAND) \
  1232. { \
  1233. HWND hWndChild = MDIGetActive(); \
  1234. if(hWndChild != NULL) \
  1235. ::SendMessage(hWndChild, uMsg, wParam, lParam); \
  1236. }
  1237. template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTraits>
  1238. class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
  1239. {
  1240. public:
  1241. HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
  1242. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  1243. HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
  1244. {
  1245. m_hMenu = hMenu;
  1246. ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
  1247. dwStyle = T::GetWndStyle(dwStyle);
  1248. dwExStyle = T::GetWndExStyle(dwExStyle);
  1249. if(rect.m_lpRect == NULL)
  1250. rect.m_lpRect = &TBase::rcDefault;
  1251. return CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
  1252. }
  1253. HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
  1254. {
  1255. const int cchName = 256;
  1256. TCHAR szWindowName[cchName] = { 0 };
  1257. ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
  1258. HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
  1259. T* pT = static_cast<T*>(this);
  1260. HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
  1261. if(hWnd != NULL)
  1262. m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
  1263. return hWnd;
  1264. }
  1265. BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
  1266. {
  1267. ATLASSERT(!::IsWindow(m_hWndToolBar));
  1268. if(nResourceID == 0)
  1269. nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
  1270. m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
  1271. return (m_hWndToolBar != NULL);
  1272. }
  1273. virtual WNDPROC GetWindowProc()
  1274. {
  1275. return MDIFrameWindowProc;
  1276. }
  1277. static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1278. {
  1279. CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameWindowImpl< T, TBase, TWinTraits >*)hWnd;
  1280. // set a ptr to this message and save the old value
  1281. #if (_ATL_VER >= 0x0700)
  1282. ATL::_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
  1283. const ATL::_ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
  1284. #else // !(_ATL_VER >= 0x0700)
  1285. MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };
  1286. const MSG* pOldMsg = pThis->m_pCurrentMsg;
  1287. #endif // !(_ATL_VER >= 0x0700)
  1288. pThis->m_pCurrentMsg = &msg;
  1289. // pass to the message map to process
  1290. LRESULT lRes = 0;
  1291. BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
  1292. // restore saved value for the current message
  1293. ATLASSERT(pThis->m_pCurrentMsg == &msg);
  1294. pThis->m_pCurrentMsg = pOldMsg;
  1295. // do the default processing if message was not handled
  1296. if(!bRet)
  1297. {
  1298. if(uMsg != WM_NCDESTROY)
  1299. lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  1300. else
  1301. {
  1302. // unsubclass, if needed
  1303. LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
  1304. lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  1305. if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
  1306. ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
  1307. #if (_ATL_VER >= 0x0700)
  1308. // mark window as destryed
  1309. pThis->m_dwState |= WINSTATE_DESTROYED;
  1310. #else // !(_ATL_VER >= 0x0700)
  1311. // clear out window handle
  1312. HWND hWnd = pThis->m_hWnd;
  1313. pThis->m_hWnd = NULL;
  1314. // clean up after window is destroyed
  1315. pThis->OnFinalMessage(hWnd);
  1316. #endif // !(_ATL_VER >= 0x0700)
  1317. }
  1318. }
  1319. #if (_ATL_VER >= 0x0700)
  1320. if(pThis->m_dwState & WINSTATE_DESTROYED && pThis->m_pCurrentMsg == NULL)
  1321. {
  1322. // clear out window handle
  1323. HWND hWnd = pThis->m_hWnd;
  1324. pThis->m_hWnd = NULL;
  1325. pThis->m_dwState &= ~WINSTATE_DESTROYED;
  1326. // clean up after window is destroyed
  1327. pThis->OnFinalMessage(hWnd);
  1328. }
  1329. #endif // (_ATL_VER >= 0x0700)
  1330. return lRes;
  1331. }
  1332. // Overriden to call DefWindowProc which uses DefFrameProc
  1333. LRESULT DefWindowProc()
  1334. {
  1335. const MSG* pMsg = m_pCurrentMsg;
  1336. LRESULT lRes = 0;
  1337. if (pMsg != NULL)
  1338. lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
  1339. return lRes;
  1340. }
  1341. LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  1342. {
  1343. return ::DefFrameProc(m_hWnd, m_hWndMDIClient, uMsg, wParam, lParam);
  1344. }
  1345. BOOL PreTranslateMessage(MSG* pMsg)
  1346. {
  1347. if(CFrameWindowImplBase<TBase, TWinTraits>::PreTranslateMessage(pMsg))
  1348. return TRUE;
  1349. return ::TranslateMDISysAccel(m_hWndMDIClient, pMsg);
  1350. }
  1351. HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD)
  1352. {
  1353. DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES;
  1354. DWORD dwExStyle = WS_EX_CLIENTEDGE;
  1355. CLIENTCREATESTRUCT ccs = { 0 };
  1356. ccs.hWindowMenu = hWindowMenu;
  1357. ccs.idFirstChild = nFirstChildID;
  1358. if((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) != 0)
  1359. {
  1360. // parent MDI frame's scroll styles move to the MDICLIENT
  1361. dwStyl