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.

1816 lines
51 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10. #ifndef __ATLFRAME_H__
  11. #define __ATLFRAME_H__
  12. #ifndef __cplusplus
  13. #error ATL requires C++ compilation (use a .cpp suffix)
  14. #endif
  15. #ifndef __ATLWIN_H__
  16. #error atlframe.h requires atlwin.h to be included first
  17. #endif
  18. #if (_ATL_VER < 0x0300)
  19. #ifndef __ATLWIN21_H__
  20. #error atlframe.h requires atlwin21.h to be included first when used with ATL 2.0/2.1
  21. #endif
  22. #endif //(_ATL_VER < 0x0300)
  23. #include <commctrl.h>
  24. #include <atlres.h>
  25. namespace ATL
  26. {
  27. /////////////////////////////////////////////////////////////////////////////
  28. // Forward declarations
  29. template <class T, class TBase = CWindow, class TWinTraits = CFrameWinTraits> class CFrameWindowImpl;
  30. #ifndef UNDER_CE
  31. class CMDIWindow;
  32. template <class T, class TBase = CMDIWindow, class TWinTraits = CFrameWinTraits> class CMDIFrameWindowImpl;
  33. template <class T, class TBase = CMDIWindow, class TWinTraits = CMDIChildWinTraits> class CMDIChildWindowImpl;
  34. #endif //!UNDER_CE
  35. template <class T> class COwnerDraw;
  36. class CUpdateUIBase;
  37. template <class T> class CUpdateUI;
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CFrameWndClassInfo - Manages frame window Windows class information
  40. class CFrameWndClassInfo
  41. {
  42. public:
  43. #ifndef UNDER_CE
  44. WNDCLASSEX m_wc;
  45. #else // CE specific
  46. WNDCLASS m_wc;
  47. #endif //!UNDER_CE
  48. LPCTSTR m_lpszOrigName;
  49. WNDPROC pWndProc;
  50. #ifndef UNDER_CE
  51. LPCTSTR m_lpszCursorID;
  52. BOOL m_bSystemCursor;
  53. #endif //!UNDER_CE
  54. ATOM m_atom;
  55. TCHAR m_szAutoName[sizeof("ATL:") + (sizeof(PVOID)*2)+1];
  56. UINT m_uCommonResourceID;
  57. ATOM Register(WNDPROC* pProc)
  58. {
  59. if (m_atom == 0)
  60. {
  61. ::EnterCriticalSection(&_Module.m_csWindowCreate);
  62. if(m_atom == 0)
  63. {
  64. HINSTANCE hInst = _Module.GetModuleInstance();
  65. if (m_lpszOrigName != NULL)
  66. {
  67. ATLASSERT(pProc != NULL);
  68. LPCTSTR lpsz = m_wc.lpszClassName;
  69. WNDPROC proc = m_wc.lpfnWndProc;
  70. #ifndef UNDER_CE
  71. WNDCLASSEX wc;
  72. wc.cbSize = sizeof(WNDCLASSEX);
  73. if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
  74. #else // CE specific
  75. WNDCLASS wc;
  76. if(!::GetClassInfo(NULL, m_lpszOrigName, &wc))
  77. #endif //!UNDER_CE
  78. {
  79. ::LeaveCriticalSection(&_Module.m_csWindowCreate);
  80. return 0;
  81. }
  82. #ifndef UNDER_CE
  83. memcpy(&m_wc, &wc, sizeof(WNDCLASSEX));
  84. #else // CE specific
  85. memcpy(&m_wc, &wc, sizeof(WNDCLASS));
  86. #endif //!UNDER_CE
  87. pWndProc = m_wc.lpfnWndProc;
  88. m_wc.lpszClassName = lpsz;
  89. m_wc.lpfnWndProc = proc;
  90. }
  91. else
  92. {
  93. #ifndef UNDER_CE
  94. m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst,
  95. m_lpszCursorID);
  96. #else // CE specific
  97. m_wc.hCursor = NULL;
  98. #endif //!UNDER_CE
  99. }
  100. m_wc.hInstance = hInst;
  101. m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
  102. if (m_wc.lpszClassName == NULL)
  103. {
  104. #ifdef _WIN64 // %p isn't available on Win2k/Win9x
  105. wsprintf(m_szAutoName, _T("ATL:%p"), &m_wc);
  106. #else
  107. wsprintf(m_szAutoName, _T("ATL:%8.8X"), PtrToUlong(&m_wc));
  108. #endif
  109. m_wc.lpszClassName = m_szAutoName;
  110. }
  111. #ifndef UNDER_CE
  112. WNDCLASSEX wcTemp;
  113. memcpy(&wcTemp, &m_wc, sizeof(WNDCLASSEX));
  114. m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
  115. #else // CE specific
  116. WNDCLASS wcTemp;
  117. memcpy(&wcTemp, &m_wc, sizeof(WNDCLASS));
  118. m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
  119. #endif //!UNDER_CE
  120. if (m_atom == 0)
  121. {
  122. if(m_uCommonResourceID != 0) // use it if not zero
  123. {
  124. m_wc.hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
  125. #ifndef UNDER_CE
  126. m_wc.hIconSm = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
  127. #endif //!UNDER_CE
  128. }
  129. #ifndef UNDER_CE
  130. m_atom = ::RegisterClassEx(&m_wc);
  131. #else // CE specific
  132. m_atom = ::RegisterClass(&m_wc);
  133. #endif //!UNDER_CE
  134. }
  135. }
  136. ::LeaveCriticalSection(&_Module.m_csWindowCreate);
  137. }
  138. if (m_lpszOrigName != NULL)
  139. {
  140. ATLASSERT(pProc != NULL);
  141. ATLASSERT(pWndProc != NULL);
  142. *pProc = pWndProc;
  143. }
  144. return m_atom;
  145. }
  146. };
  147. #ifndef UNDER_CE
  148. #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
  149. static CFrameWndClassInfo& GetWndClassInfo() \
  150. { \
  151. static CFrameWndClassInfo wc = \
  152. { \
  153. { sizeof(WNDCLASSEX), 0, StartWindowProc, \
  154. 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
  155. NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
  156. }; \
  157. return wc; \
  158. }
  159. #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
  160. static CFrameWndClassInfo& GetWndClassInfo() \
  161. { \
  162. static CFrameWndClassInfo wc = \
  163. { \
  164. { sizeof(WNDCLASSEX), style, StartWindowProc, \
  165. 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
  166. NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
  167. }; \
  168. return wc; \
  169. }
  170. #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
  171. static CFrameWndClassInfo& GetWndClassInfo() \
  172. { \
  173. static CFrameWndClassInfo wc = \
  174. { \
  175. { sizeof(WNDCLASSEX), 0, StartWindowProc, \
  176. 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
  177. OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \
  178. }; \
  179. return wc; \
  180. }
  181. #else // CE specific
  182. #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
  183. static CFrameWndClassInfo& GetWndClassInfo() \
  184. { \
  185. static CFrameWndClassInfo wc = \
  186. { \
  187. { 0, StartWindowProc, \
  188. 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \
  189. NULL, NULL, 0, _T(""), uCommonResourceID \
  190. }; \
  191. return wc; \
  192. }
  193. #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
  194. static CFrameWndClassInfo& GetWndClassInfo() \
  195. { \
  196. static CFrameWndClassInfo wc = \
  197. { \
  198. { style, StartWindowProc, \
  199. 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
  200. NULL, NULL, 0, _T(""), uCommonResourceID \
  201. }; \
  202. return wc; \
  203. }
  204. #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
  205. static CFrameWndClassInfo& GetWndClassInfo() \
  206. { \
  207. static CFrameWndClassInfo wc = \
  208. { \
  209. { NULL, StartWindowProc, \
  210. 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \
  211. OrigWndClassName, NULL, 0, _T(""), uCommonResourceID \
  212. }; \
  213. return wc; \
  214. }
  215. #endif //!UNDER_CE
  216. // Command Chaining Macros
  217. #define CHAIN_COMMANDS(theChainClass) \
  218. { \
  219. if(uMsg == WM_COMMAND && theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
  220. return TRUE; \
  221. }
  222. #define CHAIN_COMMANDS_MEMBER(theChainMember) \
  223. { \
  224. if(uMsg == WM_COMMAND && theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
  225. return TRUE; \
  226. }
  227. #define CHAIN_COMMANDS_ALT(theChainClass, msgMapID) \
  228. { \
  229. if(uMsg == WM_COMMAND && theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
  230. return TRUE; \
  231. }
  232. #define CHAIN_COMMANDS_ALT_MEMBER(theChainMember, msgMapID) \
  233. { \
  234. if(uMsg == WM_COMMAND && theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
  235. return TRUE; \
  236. }
  237. // Client window command chaining macro
  238. #define CHAIN_CLIENT_COMMANDS() \
  239. if(uMsg == WM_COMMAND && m_hWndClient != NULL) \
  240. ::SendMessage(m_hWndClient, uMsg, wParam, lParam);
  241. /////////////////////////////////////////////////////////////////////////////
  242. // CFrameWindowImpl
  243. template <class TBase = CWindow, class TWinTraits = CFrameWinTraits>
  244. class ATL_NO_VTABLE CFrameWindowImplBase : public CWindowImplBaseT< TBase, TWinTraits >
  245. {
  246. public:
  247. HWND m_hWndToolBar;
  248. HWND m_hWndStatusBar;
  249. HWND m_hWndClient;
  250. HACCEL m_hAccel;
  251. CFrameWindowImplBase() : m_hWndToolBar(NULL), m_hWndStatusBar(NULL), m_hWndClient(NULL), m_hAccel(NULL)
  252. {
  253. }
  254. DECLARE_FRAME_WND_CLASS(NULL, 0)
  255. struct _AtlToolBarData
  256. {
  257. WORD wVersion;
  258. WORD wWidth;
  259. WORD wHeight;
  260. WORD wItemCount;
  261. //WORD aItems[wItemCount]
  262. WORD* items()
  263. { return (WORD*)(this+1); }
  264. };
  265. static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID,
  266. BOOL bInitialSeparator = FALSE,
  267. DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS,
  268. UINT nID = ATL_IDW_TOOLBAR)
  269. {
  270. HINSTANCE hInst = _Module.GetResourceInstance();
  271. HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID), RT_TOOLBAR);
  272. if (hRsrc == NULL)
  273. return NULL;
  274. HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc);
  275. if (hGlobal == NULL)
  276. return NULL;
  277. _AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGlobal);
  278. if (pData == NULL)
  279. return NULL;
  280. ATLASSERT(pData->wVersion == 1);
  281. WORD* pItems = pData->items();
  282. int nItems = pData->wItemCount + (bInitialSeparator ? 1 : 0);
  283. TBBUTTON* pTBBtn = (TBBUTTON*)_alloca(nItems * sizeof(TBBUTTON));
  284. // set initial separator (half width)
  285. if(bInitialSeparator)
  286. {
  287. pTBBtn[0].iBitmap = 4;
  288. pTBBtn[0].idCommand = 0;
  289. pTBBtn[0].fsState = 0;
  290. pTBBtn[0].fsStyle = TBSTYLE_SEP;
  291. pTBBtn[0].dwData = 0;
  292. pTBBtn[0].iString = 0;
  293. }
  294. int nBmp = 0;
  295. for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCount; i++, j++)
  296. {
  297. if(pItems[i] != 0)
  298. {
  299. pTBBtn[j].iBitmap = nBmp++;
  300. pTBBtn[j].idCommand = pItems[i];
  301. pTBBtn[j].fsState = TBSTATE_ENABLED;
  302. pTBBtn[j].fsStyle = TBSTYLE_BUTTON;
  303. pTBBtn[j].dwData = 0;
  304. pTBBtn[j].iString = 0;
  305. }
  306. else
  307. {
  308. pTBBtn[j].iBitmap = 8;
  309. pTBBtn[j].idCommand = 0;
  310. pTBBtn[j].fsState = 0;
  311. pTBBtn[j].fsStyle = TBSTYLE_SEP;
  312. pTBBtn[j].dwData = 0;
  313. pTBBtn[j].iString = 0;
  314. }
  315. }
  316. HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle, 0,0,100,100,
  317. hWndParent, (HMENU)nID, _Module.GetModuleInstance(), NULL);
  318. ::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L);
  319. TBADDBITMAP tbab;
  320. tbab.hInst = hInst;
  321. tbab.nID = nResourceID;
  322. ::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab);
  323. ::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn);
  324. ::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth, pData->wHeight));
  325. ::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth + 7, pData->wHeight + 7));
  326. return hWnd;
  327. }
  328. BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
  329. {
  330. ATLASSERT(!::IsWindow(m_hWndStatusBar));
  331. m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWnd, nID);
  332. return (m_hWndStatusBar != NULL);
  333. }
  334. 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)
  335. {
  336. TCHAR szText[128]; // max text lentgth is 127 for status bars
  337. szText[0] = 0;
  338. ::LoadString(_Module.GetResourceInstance(), nTextID, szText, 127);
  339. return CreateSimpleStatusBar(szText, dwStyle, nID);
  340. }
  341. void UpdateLayout()
  342. {
  343. RECT rect;
  344. GetClientRect(&rect);
  345. // resize toolbar
  346. if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBar, GWL_STYLE) & WS_VISIBLE))
  347. {
  348. ::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0);
  349. RECT rectTB;
  350. ::GetWindowRect(m_hWndToolBar, &rectTB);
  351. rect.top += rectTB.bottom - rectTB.top;
  352. }
  353. // resize status bar
  354. if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE))
  355. {
  356. ::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0);
  357. RECT rectSB;
  358. ::GetWindowRect(m_hWndStatusBar, &rectSB);
  359. rect.bottom -= rectSB.bottom - rectSB.top;
  360. }
  361. // resize client window
  362. if(m_hWndClient != NULL)
  363. ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
  364. rect.right - rect.left, rect.bottom - rect.top,
  365. SWP_NOZORDER | SWP_NOACTIVATE);
  366. }
  367. BOOL PreTranslateMessage(MSG* pMsg)
  368. {
  369. if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
  370. return TRUE;
  371. return FALSE;
  372. }
  373. typedef CFrameWindowImplBase< TBase, TWinTraits > thisClass;
  374. BEGIN_MSG_MAP(thisClass)
  375. MESSAGE_HANDLER(WM_SIZE, OnSize)
  376. MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
  377. #ifndef UNDER_CE
  378. MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
  379. #endif //!UNDER_CE
  380. MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
  381. MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
  382. NOTIFY_CODE_HANDLER(TTN_NEEDTEXT, OnToolTipText)
  383. END_MSG_MAP()
  384. LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
  385. {
  386. if(wParam != SIZE_MINIMIZED)
  387. UpdateLayout();
  388. bHandled = FALSE;
  389. return 1;
  390. }
  391. LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  392. {
  393. if(m_hWndClient != NULL) // view will paint itself instead
  394. return 1;
  395. bHandled = FALSE;
  396. return 0;
  397. }
  398. #ifndef UNDER_CE
  399. LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  400. {
  401. bHandled = FALSE;
  402. if(m_hWndStatusBar == NULL)
  403. return 1;
  404. WORD wFlags = HIWORD(wParam);
  405. if(wFlags == 0xFFFF && lParam == NULL) // menu closing
  406. ::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L);
  407. else
  408. {
  409. TCHAR szBuff[256];
  410. szBuff[0] = 0;
  411. if(!(wFlags & MF_POPUP))
  412. {
  413. WORD wID = LOWORD(wParam);
  414. // check for special cases
  415. if(wID >= 0xF000 && wID < 0xF1F0) // system menu IDs
  416. wID = (WORD)(((wID - 0xF000) >> 4) + ATL_IDS_SCFIRST);
  417. else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FILE_MRU_LAST) // MRU items
  418. wID = ATL_IDS_MRU_FILE;
  419. else if(wID >= ATL_IDM_FIRST_MDICHILD) // MDI child windows
  420. wID = ATL_IDS_MDICHILD;
  421. if(::LoadString(_Module.GetResourceInstance(), wID, szBuff, 255))
  422. {
  423. for(int i = 0; szBuff[i] != 0 && i < 256; i++)
  424. {
  425. if(szBuff[i] == _T('\n'))
  426. {
  427. szBuff[i] = 0;
  428. break;
  429. }
  430. }
  431. }
  432. }
  433. ::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L);
  434. ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)szBuff);
  435. }
  436. return 1;
  437. }
  438. #endif //!UNDER_CE
  439. LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled)
  440. {
  441. if(m_hWndClient != NULL && ::IsWindowVisible(m_hWndClient))
  442. ::SetFocus(m_hWndClient);
  443. bHandled = FALSE;
  444. return 1;
  445. }
  446. LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled)
  447. {
  448. if(!(GetStyle() & (WS_CHILD | WS_POPUP)))
  449. ::PostQuitMessage(1);
  450. bHandled = FALSE;
  451. return 1;
  452. }
  453. LRESULT OnToolTipText(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
  454. {
  455. TOOLTIPTEXT* pTTT = (TOOLTIPTEXT*)pnmh;
  456. pTTT->szText[0] = 0;
  457. if((idCtrl != 0) && !(pTTT->uFlags & TTF_IDISHWND))
  458. {
  459. TCHAR szBuff[256];
  460. szBuff[0] = 0;
  461. if(::LoadString(_Module.GetResourceInstance(), idCtrl, szBuff, 255))
  462. {
  463. for(int i = 0; szBuff[i] != 0 && i < 256; i++)
  464. {
  465. if(szBuff[i] == _T('\n'))
  466. {
  467. lstrcpyn(pTTT->szText, &szBuff[i+1], sizeof(pTTT->szText)/sizeof(pTTT->szText[0]));
  468. break;
  469. }
  470. }
  471. }
  472. }
  473. return 0;
  474. }
  475. };
  476. template <class T, class TBase = CWindow, class TWinTraits = CFrameWinTraits>
  477. class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinTraits >
  478. {
  479. public:
  480. HWND Create(HWND hWndParent = NULL, RECT& Rect = CWindow::rcDefault, LPCTSTR szWindowName = NULL,
  481. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  482. HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
  483. {
  484. T* pT = static_cast<T*>(this);
  485. return pT->Create(hWndParent, &Rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
  486. }
  487. HWND Create(HWND hWndParent = NULL, LPRECT lpRect = NULL, LPCTSTR szWindowName = NULL,
  488. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  489. HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
  490. {
  491. ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
  492. static RECT rect = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
  493. if(lpRect == NULL)
  494. lpRect = &rect;
  495. dwStyle = T::GetWndStyle(dwStyle);
  496. dwExStyle = T::GetWndExStyle(dwExStyle);
  497. return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, *lpRect, szWindowName,
  498. dwStyle, dwExStyle, (UINT)hMenu, atom, lpCreateParam);
  499. }
  500. HWND CreateEx(HWND hWndParent = NULL, LPRECT lpRect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
  501. {
  502. TCHAR szWindowName[256];
  503. szWindowName[0] = 0;
  504. ::LoadString(_Module.GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, 255);
  505. HMENU hMenu = ::LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
  506. T* pT = static_cast<T*>(this);
  507. HWND hWnd = pT->Create(hWndParent, lpRect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
  508. if(hWnd != NULL)
  509. m_hAccel = ::LoadAccelerators(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
  510. return hWnd;
  511. }
  512. BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS, UINT nID = ATL_IDW_TOOLBAR)
  513. {
  514. ATLASSERT(!::IsWindow(m_hWndToolBar));
  515. if(nResourceID == 0)
  516. nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
  517. m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
  518. return (m_hWndToolBar != NULL);
  519. }
  520. };
  521. /////////////////////////////////////////////////////////////////////////////
  522. // CMDIWindow
  523. #ifndef UNDER_CE
  524. class CMDIWindow : public CWindow
  525. {
  526. public:
  527. HWND m_hWndMDIClient;
  528. HMENU m_hMenu;
  529. // Constructors
  530. CMDIWindow(HWND hWnd = NULL) : CWindow(hWnd), m_hWndMDIClient(NULL), m_hMenu(NULL) { }
  531. CMDIWindow& operator=(HWND hWnd)
  532. {
  533. m_hWnd = hWnd;
  534. return *this;
  535. }
  536. // Operations
  537. HWND MDIGetActive(BOOL* lpbMaximized = NULL)
  538. {
  539. ATLASSERT(::IsWindow(m_hWndMDIClient));
  540. return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)lpbMaximized);
  541. }
  542. void MDIActivate(HWND hWndChildToActivate)
  543. {
  544. ATLASSERT(::IsWindow(m_hWndMDIClient));
  545. ATLASSERT(::IsWindow(hWndChildToActivate));
  546. ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChildToActivate, 0);
  547. }
  548. void MDINext(HWND hWndChild, BOOL bPrevious = FALSE)
  549. {
  550. ATLASSERT(::IsWindow(m_hWndMDIClient));
  551. ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild));
  552. ::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (LPARAM)bPrevious);
  553. }
  554. void MDIMaximize(HWND hWndChildToMaximize)
  555. {
  556. ATLASSERT(::IsWindow(m_hWndMDIClient));
  557. ATLASSERT(::IsWindow(hWndChildToMaximize));
  558. ::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChildToMaximize, 0);
  559. }
  560. void MDIRestore(HWND hWndChildToRestore)
  561. {
  562. ATLASSERT(::IsWindow(m_hWndMDIClient));
  563. ATLASSERT(::IsWindow(hWndChildToRestore));
  564. ::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, (WPARAM)hWndChildToRestore, 0);
  565. }
  566. void MDIDestroy(HWND hWndChildToDestroy)
  567. {
  568. ATLASSERT(::IsWindow(m_hWndMDIClient));
  569. ATLASSERT(::IsWindow(hWndChildToDestroy));
  570. ::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildToDestroy, 0);
  571. }
  572. BOOL MDICascade(UINT uFlags = 0)
  573. {
  574. ATLASSERT(::IsWindow(m_hWndMDIClient));
  575. return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPARAM)uFlags, 0);
  576. }
  577. BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL)
  578. {
  579. ATLASSERT(::IsWindow(m_hWndMDIClient));
  580. return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)uFlags, 0);
  581. }
  582. void MDIIconArrange()
  583. {
  584. ATLASSERT(::IsWindow(m_hWndMDIClient));
  585. ::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0);
  586. }
  587. HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow)
  588. {
  589. ATLASSERT(::IsWindow(m_hWndMDIClient));
  590. return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuFrame, (LPARAM)hMenuWindow);
  591. }
  592. HMENU MDIRefreshMenu()
  593. {
  594. ATLASSERT(::IsWindow(m_hWndMDIClient));
  595. return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
  596. }
  597. // Additional operations
  598. static HMENU GetStandardWindowMenu(HMENU hMenu)
  599. {
  600. int nCount = ::GetMenuItemCount(hMenu);
  601. if(nCount == -1)
  602. return NULL;
  603. int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSITION);
  604. if(nLen == 0)
  605. return NULL;
  606. LPTSTR lpszText = (LPTSTR)_alloca((nLen + 1) * sizeof(TCHAR));
  607. if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYPOSITION) != nLen)
  608. return NULL;
  609. if(lstrcmp(lpszText, _T("&Window")))
  610. return NULL;
  611. return ::GetSubMenu(hMenu, nCount - 2);
  612. }
  613. void SetMDIFrameMenu()
  614. {
  615. HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu);
  616. MDISetMenu(m_hMenu, hWindowMenu);
  617. MDIRefreshMenu();
  618. ::DrawMenuBar(GetMDIFrame());
  619. }
  620. HWND GetMDIFrame()
  621. {
  622. return ::GetParent(m_hWndMDIClient);
  623. }
  624. };
  625. /////////////////////////////////////////////////////////////////////////////
  626. // CMDIFrameWindowImpl
  627. // MDI child command chaining macro
  628. #define CHAIN_MDI_CHILD_COMMANDS() \
  629. if(uMsg == WM_COMMAND) \
  630. { \
  631. HWND hWndChild = MDIGetActive(); \
  632. if(hWndChild != NULL) \
  633. ::SendMessage(hWndChild, uMsg, wParam, lParam); \
  634. }
  635. template <class T, class TBase = CMDIWindow, class TWinTraits = CFrameWinTraits>
  636. class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
  637. {
  638. public:
  639. HWND Create(HWND hWndParent = NULL, LPRECT lpRect = NULL, LPCTSTR szWindowName = NULL,
  640. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  641. HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
  642. {
  643. m_hMenu = hMenu;
  644. ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
  645. static RECT rect = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
  646. if(lpRect == NULL)
  647. lpRect = &rect;
  648. dwStyle = T::GetWndStyle(dwStyle);
  649. dwExStyle = T::GetWndExStyle(dwExStyle);
  650. return CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, *lpRect, szWindowName, dwStyle, dwExStyle,
  651. (UINT)hMenu, atom, lpCreateParam);
  652. }
  653. HWND CreateEx(HWND hWndParent = NULL, LPRECT lpRect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
  654. {
  655. TCHAR szWindowName[256];
  656. szWindowName[0] = 0;
  657. ::LoadString(_Module.GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, 255);
  658. HMENU hMenu = ::LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
  659. T* pT = static_cast<T*>(this);
  660. HWND hWnd = pT->Create(hWndParent, lpRect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
  661. if(hWnd != NULL)
  662. m_hAccel = ::LoadAccelerators(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
  663. return hWnd;
  664. }
  665. BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS, UINT nID = ATL_IDW_TOOLBAR)
  666. {
  667. ATLASSERT(!::IsWindow(m_hWndToolBar));
  668. if(nResourceID == 0)
  669. nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
  670. m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
  671. return (m_hWndToolBar != NULL);
  672. }
  673. virtual WNDPROC GetWindowProc()
  674. {
  675. return MDIFrameWindowProc;
  676. }
  677. static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  678. {
  679. CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameWindowImpl< T, TBase, TWinTraits >*)hWnd;
  680. #if (_ATL_VER >= 0x0300)
  681. // set a ptr to this message and save the old value
  682. MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };
  683. const MSG* pOldMsg = pThis->m_pCurrentMsg;
  684. pThis->m_pCurrentMsg = &msg;
  685. #endif //(_ATL_VER >= 0x0300)
  686. // pass to the message map to process
  687. LRESULT lRes;
  688. BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
  689. #if (_ATL_VER >= 0x0300)
  690. // restore saved value for the current message
  691. ATLASSERT(pThis->m_pCurrentMsg == &msg);
  692. pThis->m_pCurrentMsg = pOldMsg;
  693. #endif //(_ATL_VER >= 0x0300)
  694. // do the default processing if message was not handled
  695. if(!bRet)
  696. {
  697. if(uMsg != WM_NCDESTROY)
  698. lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  699. else
  700. {
  701. // unsubclass, if needed
  702. LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
  703. lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
  704. if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
  705. ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
  706. // clear out window handle
  707. HWND hWnd = pThis->m_hWnd;
  708. pThis->m_hWnd = NULL;
  709. // clean up after window is destroyed
  710. pThis->OnFinalMessage(hWnd);
  711. }
  712. }
  713. return lRes;
  714. }
  715. #if (_ATL_VER >= 0x0300)
  716. // Overriden to call DefWindowProc which uses DefFrameProc
  717. LRESULT DefWindowProc()
  718. {
  719. const MSG* pMsg = m_pCurrentMsg;
  720. LRESULT lRes = 0;
  721. if (pMsg != NULL)
  722. lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
  723. return lRes;
  724. }
  725. #endif //(_ATL_VER >= 0x0300)
  726. LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  727. {
  728. return ::DefFrameProc(m_hWnd, m_hWndClient, uMsg, wParam, lParam);
  729. }
  730. BOOL PreTranslateMessage(MSG* pMsg)
  731. {
  732. if(CFrameWindowImplBase<TBase, TWinTraits>::PreTranslateMessage(pMsg))
  733. return TRUE;
  734. return ::TranslateMDISysAccel(m_hWndClient, pMsg);
  735. }
  736. HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD)
  737. {
  738. DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES;
  739. DWORD dwExStyle = WS_EX_CLIENTEDGE;
  740. CLIENTCREATESTRUCT ccs;
  741. ccs.hWindowMenu = hWindowMenu;
  742. ccs.idFirstChild = nFirstChildID;
  743. if(GetStyle() & (WS_HSCROLL | WS_VSCROLL))
  744. {
  745. // parent MDI frame's scroll styles move to the MDICLIENT
  746. dwStyle |= (GetStyle() & (WS_HSCROLL | WS_VSCROLL));
  747. // fast way to turn off the scrollbar bits (without a resize)
  748. ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0, SWP_NOREDRAW | SWP_FRAMECHANGED);
  749. }
  750. // Create MDICLIENT window
  751. m_hWndClient = ::CreateWindowEx(dwExStyle, _T("MDIClient"), NULL,
  752. dwStyle, 0, 0, 1, 1, m_hWnd, (HMENU)nID,
  753. _Module.GetModuleInstance(), (LPVOID)&ccs);
  754. if (m_hWndClient == NULL)
  755. {
  756. ATLTRACE2(atlTraceWindowing, 0, _T("MDI Frame failed to create MDICLIENT.\n"));
  757. return NULL;
  758. }
  759. // Move it to the top of z-order
  760. ::BringWindowToTop(m_hWndClient);
  761. // set as MDI client window
  762. m_hWndMDIClient = m_hWndClient;
  763. // update to proper size
  764. T* pT = static_cast<T*>(this);
  765. pT->UpdateLayout();
  766. return m_hWndClient;
  767. }
  768. typedef CMDIFrameWindowImpl< T, TBase, TWinTraits > thisClass;
  769. typedef CFrameWindowImplBase<TBase, TWinTraits > baseClass;
  770. BEGIN_MSG_MAP(thisClass)
  771. MESSAGE_HANDLER(WM_SIZE, OnSize)
  772. MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
  773. MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu)
  774. CHAIN_MSG_MAP(baseClass)
  775. END_MSG_MAP()
  776. LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  777. {
  778. if(wParam != SIZE_MINIMIZED)
  779. {
  780. T* pT = static_cast<T*>(this);
  781. pT->UpdateLayout();
  782. }
  783. // message must be handled, otherwise DefFrameProc would resize the client again
  784. return 0;
  785. }
  786. LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
  787. {
  788. // don't allow CFrameWindowImplBase to handle this one
  789. return DefWindowProc(uMsg, wParam, lParam);
  790. }
  791. LRESULT OnMDISetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
  792. {
  793. SetMDIFrameMenu();
  794. return 0;
  795. }
  796. };
  797. /////////////////////////////////////////////////////////////////////////////
  798. // CMDIChildWindowImpl
  799. template <class T, class TBase = CMDIWindow, class TWinTraits = CMDIChildWinTraits>
  800. class ATL_NO_VTABLE CMDIChildWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
  801. {
  802. public:
  803. HWND Create(HWND hWndParent, LPRECT lpRect = NULL, LPCTSTR szWindowName = NULL,
  804. DWORD dwStyle = 0, DWORD dwExStyle = 0,
  805. UINT nMenuID = 0, LPVOID lpCreateParam = NULL)
  806. {
  807. ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
  808. static RECT rect = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
  809. if(lpRect == NULL)
  810. lpRect = &rect;
  811. if(nMenuID != 0)
  812. m_hMenu = ::LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(nMenuID));
  813. dwStyle = T::GetWndStyle(dwStyle);
  814. dwExStyle = T::GetWndExStyle(dwExStyle);
  815. dwExStyle |= WS_EX_MDICHILD; // force this one
  816. m_pfnSuperWindowProc = ::DefMDIChildProc;
  817. m_hWndMDIClient = hWndParent;
  818. ATLASSERT(::IsWindow(m_hWndMDIClient));
  819. HWND hWnd = CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, *lpRect, szWindowName, dwStyle, dwExStyle,
  820. 0, atom, lpCreateParam);
  821. if(hWnd != NULL && ::IsWindowVisible(m_hWnd) && !::IsChild(hWnd, ::GetFocus()))
  822. ::SetFocus(hWnd);
  823. return hWnd;
  824. }
  825. HWND CreateEx(HWND hWndParent, LPRECT lpRect = NULL, LPCTSTR lpcstrWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
  826. {
  827. TCHAR szWindowName[256];
  828. szWindowName[0] = 0;
  829. if(lpcstrWindowName == NULL)
  830. {
  831. ::LoadString(_Module.GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, 255);
  832. lpcstrWindowName = szWindowName;
  833. }
  834. T* pT = static_cast<T*>(this);
  835. HWND hWnd = pT->Create(hWndParent, lpRect, lpcstrWindowName, dwStyle, dwExStyle, T::GetWndClassInfo().m_uCommonResourceID, lpCreateParam);
  836. if(hWnd != NULL)
  837. m_hAccel = ::LoadAccelerators(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
  838. return hWnd;
  839. }
  840. BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS, UINT nID = ATL_IDW_TOOLBAR)
  841. {
  842. ATLASSERT(!::IsWindow(m_hWndToolBar));
  843. if(nResourceID == 0)
  844. nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
  845. m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
  846. return (m_hWndToolBar != NULL);
  847. }
  848. BOOL UpdateClientEdge(LPRECT lpRect = NULL)
  849. {
  850. // only adjust for active MDI child window
  851. HWND hWndChild = MDIGetActive();
  852. if(hWndChild != NULL && hWndChild != m_hWnd)
  853. return FALSE;
  854. // need to adjust the client edge style as max/restore happens
  855. DWORD dwStyle = ::GetWindowLong(m_hWndMDIClient, GWL_EXSTYLE);
  856. DWORD dwNewStyle = dwStyle;
  857. if(hWndChild != NULL && !(GetExStyle() & WS_EX_CLIENTEDGE) &&
  858. (GetStyle() & WS_MAXIMIZE))
  859. dwNewStyle &= ~(WS_EX_CLIENTEDGE);
  860. else
  861. dwNewStyle |= WS_EX_CLIENTEDGE;
  862. if(dwStyle != dwNewStyle)
  863. {
  864. // SetWindowPos will not move invalid bits
  865. ::RedrawWindow(m_hWndMDIClient, NULL, NULL,
  866. RDW_INVALIDATE | RDW_ALLCHILDREN);
  867. // remove/add WS_EX_CLIENTEDGE to MDI client area
  868. ::SetWindowLong(m_hWndMDIClient, GWL_EXSTYLE, dwNewStyle);
  869. ::SetWindowPos(m_hWndMDIClient, NULL, 0, 0, 0, 0,
  870. SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE |
  871. SWP_NOZORDER | SWP_NOCOPYBITS);
  872. // return new client area
  873. if (lpRect != NULL)
  874. ::GetClientRect(m_hWndMDIClient, lpRect);
  875. return TRUE;
  876. }
  877. return FALSE;
  878. }
  879. typedef CMDIChildWindowImpl< T, TBase, TWinTraits > thisClass;
  880. typedef CFrameWindowImplBase<TBase, TWinTraits > baseClass;
  881. BEGIN_MSG_MAP(thisClass)
  882. MESSAGE_HANDLER(WM_SIZE, OnSize)
  883. MESSAGE_HANDLER(WM_WINDOWPOSCHANGING, OnWindowPosChanging)
  884. MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
  885. MESSAGE_HANDLER(WM_MDIACTIVATE, OnMDIActivate)
  886. MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
  887. CHAIN_MSG_MAP(baseClass)
  888. END_MSG_MAP()
  889. LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  890. {
  891. DefWindowProc(uMsg, wParam, lParam); // needed for MDI children
  892. CFrameWindowImplBase<TBase, TWinTraits >::OnSize(uMsg, wParam, lParam, bHandled);
  893. bHandled = TRUE;
  894. return 0;
  895. }
  896. LRESULT OnWindowPosChanging(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
  897. {
  898. // update MDI client edge and adjust MDI child rect
  899. LPWINDOWPOS lpWndPos = (LPWINDOWPOS)lParam;
  900. if(!(lpWndPos->flags & SWP_NOSIZE))
  901. {
  902. CWindow wnd(m_hWndMDIClient);
  903. RECT rectClient;
  904. if(UpdateClientEdge(&rectClient) && (GetStyle() & WS_MAXIMIZE))
  905. {
  906. ::AdjustWindowRectEx(&rectClient, GetStyle(), FALSE, GetExStyle());
  907. lpWndPos->x = rectClient.left;
  908. lpWndPos->y = rectClient.top;
  909. lpWndPos->cx = rectClient.right - rectClient.left;
  910. lpWndPos->cy = rectClient.bottom - rectClient.top;
  911. }
  912. }
  913. bHandled = FALSE;
  914. return 1;
  915. }
  916. LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
  917. {
  918. return ::SendMessage(GetMDIFrame(), uMsg, wParam, lParam);
  919. }
  920. LRESULT OnMDIActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
  921. {
  922. if((HWND)lParam == m_hWnd && m_hMenu != NULL)
  923. SetMDIFrameMenu();
  924. else if((HWND)lParam == NULL)
  925. ::SendMessage(GetMDIFrame(), WM_MDISETMENU, 0, 0);
  926. bHandled = FALSE;
  927. return 1;
  928. }
  929. LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  930. {
  931. UpdateClientEdge();
  932. bHandled = FALSE;
  933. return 1;
  934. }
  935. };
  936. #endif //!UNDER_CE
  937. /////////////////////////////////////////////////////////////////////////////
  938. // COwnerDraw - MI class for owner-draw support
  939. template <class T>
  940. class COwnerDraw
  941. {
  942. public:
  943. BEGIN_MSG_MAP(COwnerDraw< T >)
  944. MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
  945. MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
  946. MESSAGE_HANDLER(WM_COMPAREITEM, OnCompareItem)
  947. MESSAGE_HANDLER(WM_DELETEITEM, OnDeleteItem)
  948. ALT_MSG_MAP(1)
  949. MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)
  950. MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem)
  951. MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem)
  952. MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem)
  953. END_MSG_MAP()
  954. // message handlers
  955. LRESULT OnDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  956. {
  957. T* pT = static_cast<T*>(this);
  958. pT->DrawItem((LPDRAWITEMSTRUCT)lParam);
  959. return (LRESULT)TRUE;
  960. }
  961. LRESULT OnMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  962. {
  963. T* pT = static_cast<T*>(this);
  964. pT->MeasureItem((LPMEASUREITEMSTRUCT)lParam);
  965. return (LRESULT)TRUE;
  966. }
  967. LRESULT OnCompareItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  968. {
  969. T* pT = static_cast<T*>(this);
  970. return (LRESULT)pT->CompareItem((LPCOMPAREITEMSTRUCT)lParam);
  971. }
  972. LRESULT OnDeleteItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  973. {
  974. T* pT = static_cast<T*>(this);
  975. pT->DeleteItem((LPDELETEITEMSTRUCT)lParam);
  976. return (LRESULT)TRUE;
  977. }
  978. // overrideables
  979. void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
  980. {
  981. // must be implemented
  982. ATLASSERT(FALSE);
  983. }
  984. void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
  985. {
  986. if(lpMeasureItemStruct->CtlType != ODT_MENU)
  987. {
  988. // return default height for a system font
  989. T* pT = static_cast<T*>(this);
  990. HWND hWnd = pT->GetDlgItem(lpMeasureItemStruct->CtlID);
  991. CClientDC dc(hWnd);
  992. TEXTMETRIC tm;
  993. dc.GetTextMetrics(&tm);
  994. lpMeasureItemStruct->itemHeight = tm.tmHeight;
  995. }
  996. else
  997. lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU);
  998. }
  999. int CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
  1000. {
  1001. // all items are equal
  1002. return 0;
  1003. }
  1004. void DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct)
  1005. {
  1006. // default - nothing
  1007. }
  1008. };
  1009. /////////////////////////////////////////////////////////////////////////////
  1010. // Update UI structures and constants
  1011. // UI element type
  1012. #define UPDUI_MENUPOPUP 0x0001
  1013. #define UPDUI_MENUBAR 0x0002
  1014. #define UPDUI_CHILDWND 0x0004
  1015. #define UPDUI_TOOLBAR 0x0008
  1016. #define UPDUI_STATUSBAR 0x0010
  1017. // state
  1018. #define UPDUI_ENABLED 0x0000
  1019. #define UPDUI_DISABLED 0x0100
  1020. #define UPDUI_CHECKED 0x0200
  1021. #define UPDUI_CHECKED2 0x0400
  1022. #define UPDUI_RADIO 0x0800
  1023. #define UPDUI_DEFAULT 0x1000
  1024. #define UPDUI_TEXT 0x2000
  1025. // element data
  1026. struct _AtlUpdateUIElement
  1027. {
  1028. HWND m_hWnd;
  1029. WORD m_wType;
  1030. BOOL operator ==(_AtlUpdateUIElement e)
  1031. {
  1032. if(m_hWnd == e.m_hWnd && m_wType == e.m_wType)
  1033. return TRUE;
  1034. return FALSE;
  1035. }
  1036. };
  1037. // map data
  1038. struct _AtlUpdateUIMap
  1039. {
  1040. WORD m_nID;
  1041. WORD m_wType;
  1042. };
  1043. // instance data
  1044. struct _AtlUpdateUIData
  1045. {
  1046. WORD m_wState;
  1047. void* m_lpData;
  1048. };
  1049. // these should be inside the class definition
  1050. #define BEGIN_UPDATE_UI_MAP(thisClass) \
  1051. static const _AtlUpdateUIMap* GetUpdateUIMap() \
  1052. { \
  1053. static const _AtlUpdateUIMap theMap[] = \
  1054. {
  1055. #define UPDATE_ELEMENT(nID, wType) \
  1056. { nID, wType },
  1057. #define END_UPDATE_UI_MAP() \
  1058. { (WORD)-1, 0 } \
  1059. }; \
  1060. return theMap; \
  1061. }
  1062. ///////////////////////////////////////////////////////////////////////////////
  1063. // CUpdateUI - manages UI elements updating
  1064. class CUpdateUIBase
  1065. {
  1066. public:
  1067. CSimpleArray<_AtlUpdateUIElement> m_UIElements; // elements data
  1068. const _AtlUpdateUIMap* m_pUIMap; // static UI data
  1069. _AtlUpdateUIData* m_pUIData; // instance UI data
  1070. WORD m_wDirtyType; // global dirty flag
  1071. // Constructor, destructor
  1072. CUpdateUIBase() : m_pUIMap(NULL), m_pUIData(NULL), m_wDirtyType(0)
  1073. { }
  1074. ~CUpdateUIBase()
  1075. {
  1076. if(m_pUIMap != NULL && m_pUIData != NULL)
  1077. {
  1078. const _AtlUpdateUIMap* pUIMap = m_pUIMap;
  1079. _AtlUpdateUIData* pUIData = m_pUIData;
  1080. while(pUIMap->m_nID != (WORD)-1)
  1081. {
  1082. if(pUIData->m_wState & UPDUI_TEXT)
  1083. free(pUIData->m_lpData);
  1084. pUIMap++;
  1085. pUIData++;
  1086. }
  1087. delete [] m_pUIData;
  1088. }
  1089. }
  1090. // Add elements
  1091. BOOL UIAddMenu(HWND hWnd) // menu bar (main menu)
  1092. {
  1093. if(hWnd == NULL)
  1094. return FALSE;
  1095. _AtlUpdateUIElement e;
  1096. e.m_hWnd = hWnd;
  1097. e.m_wType = UPDUI_MENUBAR;
  1098. return m_UIElements.Add(e);
  1099. }
  1100. BOOL UIAddToolBar(HWND hWnd) // toolbar
  1101. {
  1102. if(hWnd == NULL)
  1103. return FALSE;
  1104. _AtlUpdateUIElement e;
  1105. e.m_hWnd = hWnd;
  1106. e.m_wType = UPDUI_TOOLBAR;
  1107. return m_UIElements.Add(e);
  1108. }
  1109. BOOL UIAddStatusBar(HWND hWnd) // status bar
  1110. {
  1111. if(hWnd == NULL)
  1112. return FALSE;
  1113. _AtlUpdateUIElement e;
  1114. e.m_hWnd = hWnd;
  1115. e.m_wType = UPDUI_STATUSBAR;
  1116. return m_UIElements.Add(e);
  1117. }
  1118. BOOL UIAddWindow(HWND hWnd) // child window
  1119. {
  1120. if(hWnd == NULL)
  1121. return FALSE;
  1122. _AtlUpdateUIElement e;
  1123. e.m_hWnd = hWnd;
  1124. e.m_wType = UPDUI_CHILDWND;
  1125. return m_UIElements.Add(e);
  1126. }
  1127. // message map for popup menu updates
  1128. BEGIN_MSG_MAP(CUpdateUIBase)
  1129. MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
  1130. END_MSG_MAP()
  1131. LRESULT OnInitMenuPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
  1132. {
  1133. bHandled = FALSE;
  1134. HMENU hMenu = (HMENU)wParam;
  1135. if(hMenu == NULL)
  1136. return 1;
  1137. _AtlUpdateUIData* pUIData = m_pUIData;
  1138. if(pUIData == NULL)
  1139. return 1;
  1140. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1141. while(pMap->m_nID != (WORD)-1)
  1142. {
  1143. if(pMap->m_wType & UPDUI_MENUPOPUP)
  1144. UIUpdateMenuElement(pMap->m_nID, pUIData, hMenu, FALSE);
  1145. pMap++;
  1146. pUIData++;
  1147. }
  1148. return 0;
  1149. }
  1150. // methods for setting UI element state
  1151. BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE)
  1152. {
  1153. BOOL bRet = FALSE;
  1154. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1155. _AtlUpdateUIData* p = m_pUIData;
  1156. for( ; pMap->m_nID != (WORD)-1; pMap++, p++)
  1157. {
  1158. if(nID == (int)pMap->m_nID)
  1159. {
  1160. if(bEnable)
  1161. {
  1162. if(p->m_wState & UPDUI_DISABLED)
  1163. {
  1164. p->m_wState |= pMap->m_wType;
  1165. p->m_wState &= ~UPDUI_DISABLED;
  1166. }
  1167. }
  1168. else
  1169. {
  1170. if(!(p->m_wState & UPDUI_DISABLED))
  1171. {
  1172. p->m_wState |= pMap->m_wType;
  1173. p->m_wState |= UPDUI_DISABLED;
  1174. }
  1175. }
  1176. if(bForceUpdate)
  1177. p->m_wState |= pMap->m_wType;
  1178. if(p->m_wState & pMap->m_wType)
  1179. m_wDirtyType |= pMap->m_wType;
  1180. bRet = TRUE;
  1181. break;
  1182. }
  1183. }
  1184. return bRet;
  1185. }
  1186. BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE)
  1187. {
  1188. BOOL bRet = FALSE;
  1189. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1190. _AtlUpdateUIData* p = m_pUIData;
  1191. for( ; pMap->m_nID != (WORD)-1; pMap++, p++)
  1192. {
  1193. if(nID == (int)pMap->m_nID)
  1194. {
  1195. switch(nCheck)
  1196. {
  1197. case 0:
  1198. if((p->m_wState & UPDUI_CHECKED) || (p->m_wState & UPDUI_CHECKED2))
  1199. {
  1200. p->m_wState |= pMap->m_wType;
  1201. p->m_wState &= ~(UPDUI_CHECKED | UPDUI_CHECKED2);
  1202. }
  1203. break;
  1204. case 1:
  1205. if(!(p->m_wState & UPDUI_CHECKED))
  1206. {
  1207. p->m_wState |= pMap->m_wType;
  1208. p->m_wState &= ~UPDUI_CHECKED2;
  1209. p->m_wState |= UPDUI_CHECKED;
  1210. }
  1211. break;
  1212. case 2:
  1213. if(!(p->m_wState & UPDUI_CHECKED2))
  1214. {
  1215. p->m_wState |= pMap->m_wType;
  1216. p->m_wState &= ~UPDUI_CHECKED;
  1217. p->m_wState |= UPDUI_CHECKED2;
  1218. }
  1219. break;
  1220. }
  1221. if(bForceUpdate)
  1222. p->m_wState |= pMap->m_wType;
  1223. if(p->m_wState & pMap->m_wType)
  1224. m_wDirtyType |= pMap->m_wType;
  1225. bRet = TRUE;
  1226. break;
  1227. }
  1228. }
  1229. return bRet;
  1230. }
  1231. BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE)
  1232. {
  1233. BOOL bRet = FALSE;
  1234. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1235. _AtlUpdateUIData* p = m_pUIData;
  1236. for( ; pMap->m_nID != (WORD)-1; pMap++, p++)
  1237. {
  1238. if(nID == (int)pMap->m_nID)
  1239. {
  1240. if(bRadio)
  1241. {
  1242. if(!(p->m_wState & UPDUI_RADIO))
  1243. {
  1244. p->m_wState |= pMap->m_wType;
  1245. p->m_wState |= UPDUI_RADIO;
  1246. }
  1247. }
  1248. else
  1249. {
  1250. if(p->m_wState & UPDUI_RADIO)
  1251. {
  1252. p->m_wState |= pMap->m_wType;
  1253. p->m_wState &= ~UPDUI_RADIO;
  1254. }
  1255. }
  1256. if(bForceUpdate)
  1257. p->m_wState |= pMap->m_wType;
  1258. if(p->m_wState & pMap->m_wType)
  1259. m_wDirtyType |= pMap->m_wType;
  1260. bRet = TRUE;
  1261. break;
  1262. }
  1263. }
  1264. return bRet;
  1265. }
  1266. BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE)
  1267. {
  1268. ATLASSERT(lpstrText != NULL);
  1269. BOOL bRet = FALSE;
  1270. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1271. _AtlUpdateUIData* p = m_pUIData;
  1272. for( ; pMap->m_nID != (WORD)-1; pMap++, p++)
  1273. {
  1274. if(nID == (int)pMap->m_nID)
  1275. {
  1276. if(p->m_lpData != NULL && lstrcmp((LPTSTR)p->m_lpData, lpstrText))
  1277. {
  1278. if(p->m_lpData != NULL)
  1279. free(p->m_lpData);
  1280. int nStrLen = lstrlen(lpstrText);
  1281. p->m_lpData = malloc(nStrLen + sizeof(TCHAR));
  1282. if(p->m_lpData == NULL)
  1283. {
  1284. ATLTRACE2(atlTraceWindowing, 0, _T("SetText - malloc failed\n"));
  1285. break;
  1286. }
  1287. lstrcpy((LPTSTR)p->m_lpData, lpstrText);
  1288. p->m_wState |= (UPDUI_TEXT | pMap->m_wType);
  1289. }
  1290. if(bForceUpdate)
  1291. p->m_wState |= (UPDUI_TEXT | pMap->m_wType);
  1292. if(p->m_wState | pMap->m_wType)
  1293. m_wDirtyType |= pMap->m_wType;
  1294. bRet = TRUE;
  1295. break;
  1296. }
  1297. }
  1298. return bRet;
  1299. }
  1300. // methods for complete state set/get
  1301. BOOL UISetState(int nID, DWORD dwState)
  1302. {
  1303. BOOL bRet = FALSE;
  1304. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1305. _AtlUpdateUIData* p = m_pUIData;
  1306. for( ; pMap->m_nID != (WORD)-1; pMap++, p++)
  1307. {
  1308. if(nID == (int)pMap->m_nID)
  1309. {
  1310. p->m_wState |= dwState | pMap->m_wType;
  1311. m_wDirtyType |= pMap->m_wType;
  1312. bRet = TRUE;
  1313. break;
  1314. }
  1315. }
  1316. return bRet;
  1317. }
  1318. DWORD UIGetState(int nID)
  1319. {
  1320. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1321. _AtlUpdateUIData* p = m_pUIData;
  1322. for( ; pMap->m_nID != (WORD)-1; pMap++, p++)
  1323. {
  1324. if(nID == (int)pMap->m_nID)
  1325. return p->m_wState;
  1326. }
  1327. return 0;
  1328. }
  1329. // methods for updating UI
  1330. #ifndef UNDER_CE
  1331. //REVIEW
  1332. BOOL UIUpdateMenu(BOOL bForceUpdate = FALSE)
  1333. {
  1334. if(!(m_wDirtyType & UPDUI_MENUBAR) && !bForceUpdate)
  1335. return TRUE;
  1336. _AtlUpdateUIData* pUIData = m_pUIData;
  1337. if(pUIData == NULL)
  1338. return FALSE;
  1339. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1340. HMENU hMenu;
  1341. for(int i = 0; i < m_UIElements.GetSize(); i++)
  1342. {
  1343. if(m_UIElements[i].m_wType == UPDUI_MENUBAR)
  1344. {
  1345. pMap = m_pUIMap;
  1346. pUIData = m_pUIData;
  1347. hMenu = ::GetMenu(m_UIElements[i].m_hWnd);
  1348. if(hMenu == NULL)
  1349. continue;
  1350. while(pMap->m_nID != (WORD)-1)
  1351. {
  1352. if((pUIData->m_wState & UPDUI_MENUBAR) && (pMap->m_wType & UPDUI_MENUBAR))
  1353. UIUpdateMenuElement(pMap->m_nID, pUIData, hMenu, TRUE);
  1354. pMap++;
  1355. pUIData++;
  1356. }
  1357. //REVIEW ::DrawMenuBar(m_UIElements[i].m_hWnd);
  1358. }
  1359. }
  1360. m_wDirtyType &= ~UPDUI_MENUBAR;
  1361. return TRUE;
  1362. }
  1363. #endif //!UNDER_CE
  1364. BOOL UIUpdateToolBar(BOOL bForceUpdate = FALSE)
  1365. {
  1366. if(!(m_wDirtyType & UPDUI_TOOLBAR) && !bForceUpdate)
  1367. return TRUE;
  1368. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1369. _AtlUpdateUIData* pUIData = m_pUIData;
  1370. if(pUIData == NULL)
  1371. return FALSE;
  1372. for(int i = 0; i < m_UIElements.GetSize(); i++)
  1373. {
  1374. if(m_UIElements[i].m_wType == UPDUI_TOOLBAR)
  1375. {
  1376. pMap = m_pUIMap;
  1377. pUIData = m_pUIData;
  1378. while(pMap->m_nID != (WORD)-1)
  1379. {
  1380. if((pUIData->m_wState & UPDUI_TOOLBAR) && (pMap->m_wType & UPDUI_TOOLBAR))
  1381. UIUpdateToolBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
  1382. pMap++;
  1383. pUIData++;
  1384. }
  1385. }
  1386. }
  1387. m_wDirtyType &= ~UPDUI_TOOLBAR;
  1388. return TRUE;
  1389. }
  1390. BOOL UIUpdateStatusBar(BOOL bForceUpdate = FALSE)
  1391. {
  1392. if(!(m_wDirtyType & UPDUI_STATUSBAR) && !bForceUpdate)
  1393. return TRUE;
  1394. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1395. _AtlUpdateUIData* pUIData = m_pUIData;
  1396. if(pUIData == NULL)
  1397. return FALSE;
  1398. for(int i = 0; i < m_UIElements.GetSize(); i++)
  1399. {
  1400. if(m_UIElements[i].m_wType == UPDUI_STATUSBAR)
  1401. {
  1402. pMap = m_pUIMap;
  1403. pUIData = m_pUIData;
  1404. while(pMap->m_nID != (WORD)-1)
  1405. {
  1406. if((pUIData->m_wState & UPDUI_STATUSBAR) && (pMap->m_wType & UPDUI_STATUSBAR))
  1407. UIUpdateStatusBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
  1408. pMap++;
  1409. pUIData++;
  1410. }
  1411. }
  1412. }
  1413. m_wDirtyType &= ~UPDUI_STATUSBAR;
  1414. return TRUE;
  1415. }
  1416. BOOL UIUpdateChildWnd(BOOL bForceUpdate = FALSE)
  1417. {
  1418. if(!(m_wDirtyType & UPDUI_CHILDWND) && !bForceUpdate)
  1419. return TRUE;
  1420. const _AtlUpdateUIMap* pMap = m_pUIMap;
  1421. _AtlUpdateUIData* pUIData = m_pUIData;
  1422. if(pUIData == NULL)
  1423. return FALSE;
  1424. for(int i = 0; i < m_UIElements.GetSize(); i++)
  1425. {
  1426. if(m_UIElements[i].m_wType == UPDUI_CHILDWND)
  1427. {
  1428. pMap = m_pUIMap;
  1429. pUIData = m_pUIData;
  1430. while(pMap->m_nID != (WORD)-1)
  1431. {
  1432. if((pUIData->m_wState & UPDUI_CHILDWND) && (pMap->m_wType & UPDUI_CHILDWND))
  1433. UIUpdateChildWndElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
  1434. pMap++;
  1435. pUIData++;
  1436. }
  1437. }
  1438. }
  1439. m_wDirtyType &= ~UPDUI_CHILDWND;
  1440. return TRUE;
  1441. }
  1442. // internal element specific methods
  1443. #ifndef UNDER_CE
  1444. static void UIUpdateMenuElement(int nID, _AtlUpdateUIData* pUIData, HMENU hMenu, BOOL bClearState)
  1445. {
  1446. MENUITEMINFO mii;
  1447. memset(&mii, 0, sizeof(MENUITEMINFO));
  1448. mii.cbSize = sizeof(MENUITEMINFO);
  1449. mii.fMask = MIIM_STATE;
  1450. mii.wID = nID;
  1451. if(pUIData->m_wState & UPDUI_DISABLED)
  1452. mii.fState |= MFS_DISABLED | MFS_GRAYED;
  1453. else
  1454. mii.fState |= MFS_ENABLED;
  1455. if(pUIData->m_wState & UPDUI_CHECKED)
  1456. mii.fState |= MFS_CHECKED;
  1457. else
  1458. mii.fState |= MFS_UNCHECKED;
  1459. if(pUIData->m_wState & UPDUI_DEFAULT)
  1460. mii.fState |= MFS_DEFAULT;
  1461. if(pUIData->m_wState & UPDUI_TEXT)
  1462. {
  1463. mii.fMask |= MIIM_TYPE;
  1464. mii.fType = MFT_STRING;
  1465. mii.dwTypeData = (LPTSTR)pUIData->m_lpData;
  1466. }
  1467. ::SetMenuItemInfo(hMenu, nID, FALSE, &mii);
  1468. if(pUIData->m_wState & UPDUI_TEXT)
  1469. {
  1470. free(pUIData->m_lpData);
  1471. pUIData->m_wState &= ~UPDUI_TEXT;
  1472. }
  1473. if(bClearState)
  1474. pUIData->m_wState &= ~UPDUI_MENUBAR;
  1475. }
  1476. #else // CE specific
  1477. static void UIUpdateMenuElement(int nID, _AtlUpdateUIData* pUIData, HMENU hMenu, BOOL bClearState)
  1478. {
  1479. UINT uState = 0;
  1480. if(pUIData->m_wState & UPDUI_DISABLED)
  1481. uState = MF_GRAYED;
  1482. else
  1483. uState = MF_ENABLED;
  1484. ::EnableMenuItem(hMenu, nID, uState);
  1485. if(pUIData->m_wState & UPDUI_CHECKED)
  1486. uState = 1;
  1487. else
  1488. uState = 0;
  1489. ::CheckMenuItem(hMenu, nID, uState);
  1490. //CE if(pUIData->m_wState & UPDUI_DEFAULT)
  1491. //CE mii.fState |= MFS_DEFAULT;
  1492. if(pUIData->m_wState & UPDUI_TEXT)
  1493. {
  1494. MENUITEMINFO mii;
  1495. memset(&mii, 0, sizeof(MENUITEMINFO));
  1496. mii.cbSize = sizeof(MENUITEMINFO);
  1497. mii.fMask = MIIM_TYPE;
  1498. mii.wID = nID;
  1499. mii.fType = MFT_STRING;
  1500. mii.dwTypeData = (LPTSTR)pUIData->m_lpData;
  1501. ::SetMenuItemInfo(hMenu, nID, FALSE, &mii);
  1502. free(pUIData->m_lpData);
  1503. pUIData->m_wState &= ~UPDUI_TEXT;
  1504. }
  1505. if(bClearState)
  1506. pUIData->m_wState &= ~UPDUI_MENUBAR;
  1507. }
  1508. #endif //!UNDER_CE
  1509. static void UIUpdateToolBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndToolBar)
  1510. {
  1511. //REVIEW: only handles enabled/disabled and checked state, and radio (press)
  1512. ::SendMessage(hWndToolBar, TB_ENABLEBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE);
  1513. ::SendMessage(hWndToolBar, TB_CHECKBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED) ? TRUE : FALSE);
  1514. ::SendMessage(hWndToolBar, TB_INDETERMINATE, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED2) ? TRUE : FALSE);
  1515. ::SendMessage(hWndToolBar, TB_PRESSBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_RADIO) ? TRUE : FALSE);
  1516. pUIData->m_wState &= ~UPDUI_TOOLBAR;
  1517. }
  1518. static void UIUpdateStatusBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndStatusBar)
  1519. {
  1520. if(pUIData->m_wState | UPDUI_TEXT)
  1521. {
  1522. ::SendMessage(hWndStatusBar, SB_SETTEXT, nID, (LPARAM)pUIData->m_lpData);
  1523. free(pUIData->m_lpData);
  1524. pUIData->m_wState &= ~UPDUI_TEXT;
  1525. }
  1526. pUIData->m_wState &= ~UPDUI_STATUSBAR;
  1527. }
  1528. static void UIUpdateChildWndElement(int nID, _AtlUpdateUIData* pUIData, HWND hWnd)
  1529. {
  1530. HWND hChild = ::GetDlgItem(hWnd, nID);
  1531. ::EnableWindow(hChild, (pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE);
  1532. // for check and radio, assume that window is a button
  1533. int nCheck = BST_UNCHECKED;
  1534. if(pUIData->m_wState & UPDUI_CHECKED || pUIData->m_wState & UPDUI_RADIO)
  1535. nCheck = BST_CHECKED;
  1536. else if(pUIData->m_wState & UPDUI_CHECKED2)
  1537. nCheck = BST_INDETERMINATE;
  1538. ::SendMessage(hChild, BM_SETCHECK, nCheck, 0L);
  1539. if(pUIData->m_wState & UPDUI_DEFAULT)
  1540. {
  1541. DWORD dwRet = ::SendMessage(hWnd, DM_GETDEFID, 0, 0L);
  1542. if(HIWORD(dwRet) == DC_HASDEFID)
  1543. {
  1544. HWND hOldDef = ::GetDlgItem(hWnd, LOWORD(dwRet));
  1545. // remove BS_DEFPUSHBUTTON
  1546. ::SendMessage(hOldDef, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  1547. }
  1548. ::SendMessage(hWnd, DM_SETDEFID, nID, 0L);
  1549. }
  1550. if(pUIData->m_wState & UPDUI_TEXT)
  1551. {
  1552. ::SetWindowText(hChild, (LPTSTR)pUIData->m_lpData);
  1553. free(pUIData->m_lpData);
  1554. pUIData->m_wState &= ~UPDUI_TEXT;
  1555. }
  1556. pUIData->m_wState &= ~UPDUI_CHILDWND;
  1557. }
  1558. };
  1559. template <class T>
  1560. class CUpdateUI : public CUpdateUIBase
  1561. {
  1562. public:
  1563. CUpdateUI()
  1564. {
  1565. T* pT = static_cast<T*>(this);
  1566. pT;
  1567. const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap();
  1568. m_pUIMap = pMap;
  1569. ATLASSERT(m_pUIMap != NULL);
  1570. for(int nCount = 1; pMap->m_nID != (WORD)-1; nCount++)
  1571. pMap++;
  1572. ATLTRY(m_pUIData = new _AtlUpdateUIData[nCount]);
  1573. ATLASSERT(m_pUIData != NULL);
  1574. if(m_pUIData != NULL)
  1575. memset(m_pUIData, 0, sizeof(_AtlUpdateUIData) * nCount);
  1576. }
  1577. };
  1578. }; //namespace ATL
  1579. #endif // __ATLFRAME_H__