OLD | NEW |
| (Empty) |
1 // Windows Template Library - WTL version 8.0 | |
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 // Microsoft Permissive License (Ms-PL) which can be found in the file | |
7 // Ms-PL.txt at the root of this distribution. | |
8 | |
9 #ifndef __ATLCTRLW_H__ | |
10 #define __ATLCTRLW_H__ | |
11 | |
12 #pragma once | |
13 | |
14 #ifndef __cplusplus | |
15 #error ATL requires C++ compilation (use a .cpp suffix) | |
16 #endif | |
17 | |
18 #ifdef _WIN32_WCE | |
19 #error atlctrlw.h is not supported on Windows CE | |
20 #endif | |
21 | |
22 #ifndef __ATLAPP_H__ | |
23 #error atlctrlw.h requires atlapp.h to be included first | |
24 #endif | |
25 | |
26 #ifndef __ATLCTRLS_H__ | |
27 #error atlctrlw.h requires atlctrls.h to be included first | |
28 #endif | |
29 | |
30 #if (_WIN32_IE < 0x0400) | |
31 #error atlctrlw.h requires _WIN32_IE >= 0x0400 | |
32 #endif | |
33 | |
34 // Define _WTL_CMDBAR_VISTA_MENUS as 0 to exclude Vista menus support | |
35 #if !defined(_WTL_CMDBAR_VISTA_MENUS) && (WINVER >= 0x0500) && (_WIN32_WINNT >=
0x0501) && (_WIN32_IE >= 0x0501) | |
36 #define _WTL_CMDBAR_VISTA_MENUS 1 | |
37 #endif | |
38 | |
39 #if _WTL_CMDBAR_VISTA_MENUS | |
40 #if !((_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)) | |
41 #error _WTL_CMDBAR_VISTA_MENUS requires (_WIN32_WINNT >= 0x0501) && (_WI
N32_IE >= 0x0501) | |
42 #endif | |
43 #endif | |
44 | |
45 | |
46 /////////////////////////////////////////////////////////////////////////////// | |
47 // Classes in this file: | |
48 // | |
49 // CCommandBarCtrlImpl<T, TBase, TWinTraits> | |
50 // CCommandBarCtrl | |
51 // CMDICommandBarCtrlImpl<T, TBase, TWinTraits> | |
52 // CMDICommandBarCtrl | |
53 | |
54 | |
55 namespace WTL | |
56 { | |
57 | |
58 /////////////////////////////////////////////////////////////////////////////// | |
59 // Command Bars | |
60 | |
61 // Window Styles: | |
62 #define CBRWS_TOP CCS_TOP | |
63 #define CBRWS_BOTTOM CCS_BOTTOM | |
64 #define CBRWS_NORESIZE CCS_NORESIZE | |
65 #define CBRWS_NOPARENTALIGN CCS_NOPARENTALIGN | |
66 #define CBRWS_NODIVIDER CCS_NODIVIDER | |
67 | |
68 // Extended styles | |
69 #define CBR_EX_TRANSPARENT 0x00000001L | |
70 #define CBR_EX_SHAREMENU 0x00000002L | |
71 #define CBR_EX_ALTFOCUSMODE 0x00000004L | |
72 #define CBR_EX_TRACKALWAYS 0x00000008L | |
73 #define CBR_EX_NOVISTAMENUS 0x00000010L | |
74 | |
75 // standard command bar styles | |
76 #define ATL_SIMPLE_CMDBAR_PANE_STYLE \ | |
77 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBRWS_NODIV
IDER | CBRWS_NORESIZE | CBRWS_NOPARENTALIGN) | |
78 | |
79 // Messages - support chevrons for frame windows | |
80 #define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar H
WND | |
81 #define CBRM_GETMENU (WM_USER + 302) // returns loaded or att
ached menu | |
82 #define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu | |
83 | |
84 typedef struct tagCBRPOPUPMENU | |
85 { | |
86 int cbSize; | |
87 HMENU hMenu; // popup menu do display | |
88 UINT uFlags; // TPM_* flags for ::TrackPopupMenuEx | |
89 int x; | |
90 int y; | |
91 LPTPMPARAMS lptpm; // ptr to TPMPARAMS for ::TrackPopupMenuEx | |
92 } CBRPOPUPMENU, *LPCBRPOPUPMENU; | |
93 | |
94 // helper class | |
95 template <class T> | |
96 class CSimpleStack : public ATL::CSimpleArray< T > | |
97 { | |
98 public: | |
99 BOOL Push(T t) | |
100 { | |
101 #ifdef _CMDBAR_EXTRA_TRACE | |
102 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - STACK-PUSH (%8.8X) size =
%i\n"), t, GetSize()); | |
103 #endif | |
104 return Add(t); | |
105 } | |
106 | |
107 T Pop() | |
108 { | |
109 int nLast = GetSize() - 1; | |
110 if(nLast < 0) | |
111 return NULL; // must be able to convert to NULL | |
112 T t = m_aT[nLast]; | |
113 #ifdef _CMDBAR_EXTRA_TRACE | |
114 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - STACK-POP (%8.8X) size = %
i\n"), t, GetSize()); | |
115 #endif | |
116 if(!RemoveAt(nLast)) | |
117 return NULL; | |
118 return t; | |
119 } | |
120 | |
121 T GetCurrent() | |
122 { | |
123 int nLast = GetSize() - 1; | |
124 if(nLast < 0) | |
125 return NULL; // must be able to convert to NULL | |
126 return m_aT[nLast]; | |
127 } | |
128 }; | |
129 | |
130 | |
131 /////////////////////////////////////////////////////////////////////////////// | |
132 // CCommandBarCtrlBase - base class for the Command Bar implementation | |
133 | |
134 class CCommandBarCtrlBase : public CToolBarCtrl | |
135 { | |
136 public: | |
137 struct _MsgHookData | |
138 { | |
139 HHOOK hMsgHook; | |
140 DWORD dwUsage; | |
141 | |
142 _MsgHookData() : hMsgHook(NULL), dwUsage(0) | |
143 { } | |
144 }; | |
145 | |
146 typedef ATL::CSimpleMap<DWORD, _MsgHookData*> CMsgHookMap; | |
147 static CMsgHookMap* s_pmapMsgHook; | |
148 | |
149 static HHOOK s_hCreateHook; | |
150 static bool s_bW2K; // For animation flag | |
151 static CCommandBarCtrlBase* s_pCurrentBar; | |
152 static bool s_bStaticInit; | |
153 | |
154 CSimpleStack<HWND> m_stackMenuWnd; | |
155 CSimpleStack<HMENU> m_stackMenuHandle; | |
156 | |
157 HWND m_hWndHook; | |
158 DWORD m_dwMagic; | |
159 | |
160 | |
161 CCommandBarCtrlBase() : m_hWndHook(NULL), m_dwMagic(1314) | |
162 { | |
163 // init static variables | |
164 if(!s_bStaticInit) | |
165 { | |
166 CStaticDataInitCriticalSectionLock lock; | |
167 if(FAILED(lock.Lock())) | |
168 { | |
169 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to l
ock critical section in CCommandBarCtrlBase::CCommandBarCtrlBase.\n")); | |
170 ATLASSERT(FALSE); | |
171 return; | |
172 } | |
173 | |
174 if(!s_bStaticInit) | |
175 { | |
176 // Just in case... | |
177 AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR
_CLASSES); | |
178 // Animation on Win2000 only | |
179 s_bW2K = !AtlIsOldWindows(); | |
180 // done | |
181 s_bStaticInit = true; | |
182 } | |
183 | |
184 lock.Unlock(); | |
185 } | |
186 } | |
187 | |
188 bool IsCommandBarBase() const { return m_dwMagic == 1314; } | |
189 }; | |
190 | |
191 __declspec(selectany) CCommandBarCtrlBase::CMsgHookMap* CCommandBarCtrlBase::s_p
mapMsgHook = NULL; | |
192 __declspec(selectany) HHOOK CCommandBarCtrlBase::s_hCreateHook = NULL; | |
193 __declspec(selectany) CCommandBarCtrlBase* CCommandBarCtrlBase::s_pCurrentBar =
NULL; | |
194 __declspec(selectany) bool CCommandBarCtrlBase::s_bW2K = false; | |
195 __declspec(selectany) bool CCommandBarCtrlBase::s_bStaticInit = false; | |
196 | |
197 | |
198 /////////////////////////////////////////////////////////////////////////////// | |
199 // CCommandBarCtrl - ATL implementation of Command Bars | |
200 | |
201 template <class T, class TBase = CCommandBarCtrlBase, class TWinTraits = ATL::CC
ontrolWinTraits> | |
202 class ATL_NO_VTABLE CCommandBarCtrlImpl : public ATL::CWindowImpl< T, TBase, TWi
nTraits > | |
203 { | |
204 public: | |
205 DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName()) | |
206 | |
207 // Declarations | |
208 struct _MenuItemData // menu item data | |
209 { | |
210 DWORD dwMagic; | |
211 LPTSTR lpstrText; | |
212 UINT fType; | |
213 UINT fState; | |
214 int iButton; | |
215 | |
216 _MenuItemData() { dwMagic = 0x1313; } | |
217 bool IsCmdBarMenuItem() { return (dwMagic == 0x1313); } | |
218 }; | |
219 | |
220 struct _ToolBarData // toolbar resource data | |
221 { | |
222 WORD wVersion; | |
223 WORD wWidth; | |
224 WORD wHeight; | |
225 WORD wItemCount; | |
226 //WORD aItems[wItemCount] | |
227 | |
228 WORD* items() | |
229 { return (WORD*)(this+1); } | |
230 }; | |
231 | |
232 // Constants | |
233 enum _CmdBarDrawConstants | |
234 { | |
235 s_kcxGap = 1, | |
236 s_kcxTextMargin = 2, | |
237 s_kcxButtonMargin = 3, | |
238 s_kcyButtonMargin = 3 | |
239 }; | |
240 | |
241 enum | |
242 { | |
243 _nMaxMenuItemTextLength = 100, | |
244 _chChevronShortcut = _T('/') | |
245 }; | |
246 | |
247 #ifndef DT_HIDEPREFIX | |
248 enum { DT_HIDEPREFIX = 0x00100000 }; | |
249 #endif // !DT_HIDEPREFIX | |
250 | |
251 // Data members | |
252 HMENU m_hMenu; | |
253 HIMAGELIST m_hImageList; | |
254 ATL::CSimpleValArray<WORD> m_arrCommand; | |
255 | |
256 DWORD m_dwExtendedStyle; // Command Bar specific extended styles | |
257 | |
258 ATL::CContainedWindow m_wndParent; | |
259 | |
260 bool m_bMenuActive:1; | |
261 bool m_bAttachedMenu:1; | |
262 bool m_bImagesVisible:1; | |
263 bool m_bPopupItem:1; | |
264 bool m_bContextMenu:1; | |
265 bool m_bEscapePressed:1; | |
266 bool m_bSkipMsg:1; | |
267 bool m_bParentActive:1; | |
268 bool m_bFlatMenus:1; | |
269 bool m_bUseKeyboardCues:1; | |
270 bool m_bShowKeyboardCues:1; | |
271 bool m_bAllowKeyboardCues:1; | |
272 bool m_bKeyboardInput:1; | |
273 bool m_bAlphaImages:1; | |
274 bool m_bLayoutRTL:1; | |
275 bool m_bSkipPostDown:1; | |
276 bool m_bVistaMenus:1; | |
277 | |
278 int m_nPopBtn; | |
279 int m_nNextPopBtn; | |
280 | |
281 SIZE m_szBitmap; | |
282 SIZE m_szButton; | |
283 | |
284 COLORREF m_clrMask; | |
285 CFont m_fontMenu; // used internally, only to measure text | |
286 | |
287 UINT m_uSysKey; | |
288 | |
289 HWND m_hWndFocus; // Alternate focus mode | |
290 | |
291 int m_cxExtraSpacing; | |
292 | |
293 #if _WTL_CMDBAR_VISTA_MENUS | |
294 ATL::CSimpleValArray<HBITMAP> m_arrVistaBitmap; // Bitmaps for Vista m
enus | |
295 #endif // _WTL_CMDBAR_VISTA_MENUS | |
296 | |
297 // Constructor/destructor | |
298 CCommandBarCtrlImpl() : | |
299 m_hMenu(NULL), | |
300 m_hImageList(NULL), | |
301 m_wndParent(this, 1), | |
302 m_bMenuActive(false), | |
303 m_bAttachedMenu(false), | |
304 m_nPopBtn(-1), | |
305 m_nNextPopBtn(-1), | |
306 m_bPopupItem(false), | |
307 m_bImagesVisible(true), | |
308 m_bSkipMsg(false), | |
309 m_uSysKey(0), | |
310 m_hWndFocus(NULL), | |
311 m_bContextMenu(false), | |
312 m_bEscapePressed(false), | |
313 m_clrMask(RGB(192, 192, 192)), | |
314 m_dwExtendedStyle(CBR_EX_TRANSPARENT | CBR_EX_SHAREMENU
| CBR_EX_TRACKALWAYS), | |
315 m_bParentActive(true), | |
316 m_bFlatMenus(false), | |
317 m_bUseKeyboardCues(false), | |
318 m_bShowKeyboardCues(false), | |
319 m_bAllowKeyboardCues(true), | |
320 m_bKeyboardInput(false), | |
321 m_cxExtraSpacing(0), | |
322 m_bAlphaImages(false), | |
323 m_bLayoutRTL(false), | |
324 m_bSkipPostDown(false), | |
325 m_bVistaMenus(false) | |
326 { | |
327 SetImageSize(16, 15); // default | |
328 } | |
329 | |
330 ~CCommandBarCtrlImpl() | |
331 { | |
332 if(m_wndParent.IsWindow()) | |
333 /*scary!*/ m_wndParent.UnsubclassWindow(); | |
334 | |
335 if(m_hMenu != NULL && (m_dwExtendedStyle & CBR_EX_SHAREMENU) ==
0) | |
336 ::DestroyMenu(m_hMenu); | |
337 | |
338 if(m_hImageList != NULL) | |
339 ::ImageList_Destroy(m_hImageList); | |
340 } | |
341 | |
342 // Attributes | |
343 DWORD GetCommandBarExtendedStyle() const | |
344 { | |
345 return m_dwExtendedStyle; | |
346 } | |
347 | |
348 DWORD SetCommandBarExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0
) | |
349 { | |
350 DWORD dwPrevStyle = m_dwExtendedStyle; | |
351 if(dwMask == 0) | |
352 m_dwExtendedStyle = dwExtendedStyle; | |
353 else | |
354 m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwE
xtendedStyle & dwMask); | |
355 return dwPrevStyle; | |
356 } | |
357 | |
358 CMenuHandle GetMenu() const | |
359 { | |
360 ATLASSERT(::IsWindow(m_hWnd)); | |
361 return m_hMenu; | |
362 } | |
363 | |
364 COLORREF GetImageMaskColor() const | |
365 { | |
366 return m_clrMask; | |
367 } | |
368 | |
369 COLORREF SetImageMaskColor(COLORREF clrMask) | |
370 { | |
371 COLORREF clrOld = m_clrMask; | |
372 m_clrMask = clrMask; | |
373 return clrOld; | |
374 } | |
375 | |
376 bool GetImagesVisible() const | |
377 { | |
378 return m_bImagesVisible; | |
379 } | |
380 | |
381 bool SetImagesVisible(bool bVisible) | |
382 { | |
383 bool bOld = m_bImagesVisible; | |
384 m_bImagesVisible = bVisible; | |
385 return bOld; | |
386 } | |
387 | |
388 void GetImageSize(SIZE& size) const | |
389 { | |
390 size = m_szBitmap; | |
391 } | |
392 | |
393 bool SetImageSize(SIZE& size) | |
394 { | |
395 return SetImageSize(size.cx, size.cy); | |
396 } | |
397 | |
398 bool SetImageSize(int cx, int cy) | |
399 { | |
400 if(m_hImageList != NULL) | |
401 { | |
402 if(::ImageList_GetImageCount(m_hImageList) == 0) // em
pty | |
403 { | |
404 ::ImageList_Destroy(m_hImageList); | |
405 m_hImageList = NULL; | |
406 } | |
407 else | |
408 { | |
409 return false; // can't set, image list exists | |
410 } | |
411 } | |
412 | |
413 if(cx == 0 || cy == 0) | |
414 return false; | |
415 | |
416 m_szBitmap.cx = cx; | |
417 m_szBitmap.cy = cy; | |
418 m_szButton.cx = m_szBitmap.cx + 2 * s_kcxButtonMargin; | |
419 m_szButton.cy = m_szBitmap.cy + 2 * s_kcyButtonMargin; | |
420 | |
421 return true; | |
422 } | |
423 | |
424 bool GetAlphaImages() const | |
425 { | |
426 return m_bAlphaImages; | |
427 } | |
428 | |
429 bool SetAlphaImages(bool bAlphaImages) | |
430 { | |
431 if(m_hImageList != NULL) | |
432 { | |
433 if(::ImageList_GetImageCount(m_hImageList) == 0) // em
pty | |
434 { | |
435 ::ImageList_Destroy(m_hImageList); | |
436 m_hImageList = NULL; | |
437 } | |
438 else | |
439 { | |
440 return false; // can't set, image list exists | |
441 } | |
442 } | |
443 | |
444 m_bAlphaImages = bAlphaImages; | |
445 return true; | |
446 } | |
447 | |
448 HWND GetCmdBar() const | |
449 { | |
450 ATLASSERT(::IsWindow(m_hWnd)); | |
451 return (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L); | |
452 } | |
453 | |
454 // Methods | |
455 HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL, | |
456 DWORD dwStyle = 0, DWORD dwExStyle = 0, | |
457 UINT nID = 0, LPVOID lpCreateParam = NULL) | |
458 { | |
459 // These styles are required for command bars | |
460 dwStyle |= TBSTYLE_LIST | TBSTYLE_FLAT; | |
461 #if (_MSC_VER >= 1300) | |
462 return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndPare
nt, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam); | |
463 #else // !(_MSC_VER >= 1300) | |
464 typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass; | |
465 return _baseClass::Create(hWndParent, rcPos, szWindowName, dwSty
le, dwExStyle, nID, lpCreateParam); | |
466 #endif // !(_MSC_VER >= 1300) | |
467 } | |
468 | |
469 BOOL AttachToWindow(HWND hWnd) | |
470 { | |
471 ATLASSERT(m_hWnd == NULL); | |
472 ATLASSERT(::IsWindow(hWnd)); | |
473 BOOL bRet = SubclassWindow(hWnd); | |
474 if(bRet) | |
475 { | |
476 m_bAttachedMenu = true; | |
477 T* pT = static_cast<T*>(this); | |
478 pT->GetSystemSettings(); | |
479 } | |
480 return bRet; | |
481 } | |
482 | |
483 BOOL LoadMenu(ATL::_U_STRINGorID menu) | |
484 { | |
485 ATLASSERT(::IsWindow(m_hWnd)); | |
486 | |
487 if(m_bAttachedMenu) // doesn't work in this mode | |
488 return FALSE; | |
489 if(menu.m_lpstr == NULL) | |
490 return FALSE; | |
491 | |
492 HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), me
nu.m_lpstr); | |
493 if(hMenu == NULL) | |
494 return FALSE; | |
495 | |
496 return AttachMenu(hMenu); | |
497 } | |
498 | |
499 BOOL AttachMenu(HMENU hMenu) | |
500 { | |
501 ATLASSERT(::IsWindow(m_hWnd)); | |
502 ATLASSERT(hMenu == NULL || ::IsMenu(hMenu)); | |
503 if(hMenu != NULL && !::IsMenu(hMenu)) | |
504 return FALSE; | |
505 | |
506 #if _WTL_CMDBAR_VISTA_MENUS | |
507 // remove Vista bitmaps if used | |
508 if(m_bVistaMenus && (m_hMenu != NULL)) | |
509 { | |
510 T* pT = static_cast<T*>(this); | |
511 pT->_RemoveVistaBitmapsFromMenu(); | |
512 } | |
513 #endif // _WTL_CMDBAR_VISTA_MENUS | |
514 | |
515 // destroy old menu, if needed, and set new one | |
516 if(m_hMenu != NULL && (m_dwExtendedStyle & CBR_EX_SHAREMENU) ==
0) | |
517 ::DestroyMenu(m_hMenu); | |
518 | |
519 m_hMenu = hMenu; | |
520 | |
521 if(m_bAttachedMenu) // Nothing else in this mode | |
522 return TRUE; | |
523 | |
524 // Build buttons according to menu | |
525 SetRedraw(FALSE); | |
526 | |
527 // Clear all buttons | |
528 int nCount = GetButtonCount(); | |
529 for(int i = 0; i < nCount; i++) | |
530 ATLVERIFY(DeleteButton(0) != FALSE); | |
531 | |
532 // Add buttons for each menu item | |
533 if(m_hMenu != NULL) | |
534 { | |
535 int nItems = ::GetMenuItemCount(m_hMenu); | |
536 | |
537 T* pT = static_cast<T*>(this); | |
538 pT; // avoid level 4 warning | |
539 TCHAR szString[pT->_nMaxMenuItemTextLength]; | |
540 for(int i = 0; i < nItems; i++) | |
541 { | |
542 CMenuItemInfo mii; | |
543 mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_SUBMEN
U; | |
544 mii.fType = MFT_STRING; | |
545 mii.dwTypeData = szString; | |
546 mii.cch = pT->_nMaxMenuItemTextLength; | |
547 BOOL bRet = ::GetMenuItemInfo(m_hMenu, i, TRUE,
&mii); | |
548 ATLASSERT(bRet); | |
549 // If we have more than the buffer, we assume we
have bitmaps bits | |
550 if(lstrlen(szString) > pT->_nMaxMenuItemTextLeng
th - 1) | |
551 { | |
552 mii.fType = MFT_BITMAP; | |
553 ::SetMenuItemInfo(m_hMenu, i, TRUE, &mii
); | |
554 szString[0] = 0; | |
555 } | |
556 | |
557 // NOTE: Command Bar currently supports only dro
p-down menu items | |
558 ATLASSERT(mii.hSubMenu != NULL); | |
559 | |
560 TBBUTTON btn = { 0 }; | |
561 btn.iBitmap = 0; | |
562 btn.idCommand = i; | |
563 btn.fsState = (BYTE)(((mii.fState & MFS_DISABLED
) == 0) ? TBSTATE_ENABLED : 0); | |
564 btn.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE
| TBSTYLE_DROPDOWN; | |
565 btn.dwData = 0; | |
566 btn.iString = 0; | |
567 | |
568 bRet = InsertButton(-1, &btn); | |
569 ATLASSERT(bRet); | |
570 | |
571 TBBUTTONINFO bi = { 0 }; | |
572 bi.cbSize = sizeof(TBBUTTONINFO); | |
573 bi.dwMask = TBIF_TEXT; | |
574 bi.pszText = szString; | |
575 | |
576 bRet = SetButtonInfo(i, &bi); | |
577 ATLASSERT(bRet); | |
578 } | |
579 } | |
580 | |
581 SetRedraw(TRUE); | |
582 Invalidate(); | |
583 UpdateWindow(); | |
584 | |
585 return TRUE; | |
586 } | |
587 | |
588 BOOL LoadImages(ATL::_U_STRINGorID image) | |
589 { | |
590 return _LoadImagesHelper(image, false); | |
591 } | |
592 | |
593 BOOL LoadMappedImages(UINT nIDImage, UINT nFlags = 0, LPCOLORMAP lpColor
Map = NULL, int nMapSize = 0) | |
594 { | |
595 return _LoadImagesHelper(nIDImage, true, nFlags , lpColorMap, nM
apSize); | |
596 } | |
597 | |
598 BOOL _LoadImagesHelper(ATL::_U_STRINGorID image, bool bMapped, UINT nFla
gs = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0) | |
599 { | |
600 ATLASSERT(::IsWindow(m_hWnd)); | |
601 HINSTANCE hInstance = ModuleHelper::GetResourceInstance(); | |
602 | |
603 HRSRC hRsrc = ::FindResource(hInstance, image.m_lpstr, (LPTSTR)R
T_TOOLBAR); | |
604 if(hRsrc == NULL) | |
605 return FALSE; | |
606 | |
607 HGLOBAL hGlobal = ::LoadResource(hInstance, hRsrc); | |
608 if(hGlobal == NULL) | |
609 return FALSE; | |
610 | |
611 _ToolBarData* pData = (_ToolBarData*)::LockResource(hGlobal); | |
612 if(pData == NULL) | |
613 return FALSE; | |
614 ATLASSERT(pData->wVersion == 1); | |
615 | |
616 WORD* pItems = pData->items(); | |
617 int nItems = pData->wItemCount; | |
618 | |
619 // Set internal data | |
620 SetImageSize(pData->wWidth, pData->wHeight); | |
621 | |
622 // Create image list if needed | |
623 if(m_hImageList == NULL) | |
624 { | |
625 // Check if the bitmap is 32-bit (alpha channel) bitmap
(valid for Windows XP only) | |
626 T* pT = static_cast<T*>(this); | |
627 m_bAlphaImages = AtlIsAlphaBitmapResource(image); | |
628 | |
629 if(!pT->CreateInternalImageList(pData->wItemCount)) | |
630 return FALSE; | |
631 } | |
632 | |
633 #if _WTL_CMDBAR_VISTA_MENUS | |
634 int nOldImageCount = ::ImageList_GetImageCount(m_hImageList); | |
635 #endif // _WTL_CMDBAR_VISTA_MENUS | |
636 | |
637 // Add bitmap to our image list | |
638 CBitmap bmp; | |
639 if(bMapped) | |
640 { | |
641 ATLASSERT(HIWORD(PtrToUlong(image.m_lpstr)) == 0); //
if mapped, must be a numeric ID | |
642 int nIDImage = (int)(short)LOWORD(PtrToUlong(image.m_lps
tr)); | |
643 bmp.LoadMappedBitmap(nIDImage, (WORD)nFlags, lpColorMap,
nMapSize); | |
644 } | |
645 else | |
646 { | |
647 if(m_bAlphaImages) | |
648 bmp = (HBITMAP)::LoadImage(ModuleHelper::GetReso
urceInstance(), image.m_lpstr, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFA
ULTSIZE); | |
649 else | |
650 bmp.LoadBitmap(image.m_lpstr); | |
651 } | |
652 ATLASSERT(bmp.m_hBitmap != NULL); | |
653 if(bmp.m_hBitmap == NULL) | |
654 return FALSE; | |
655 if(::ImageList_AddMasked(m_hImageList, bmp, m_clrMask) == -1) | |
656 return FALSE; | |
657 | |
658 // Fill the array with command IDs | |
659 for(int i = 0; i < nItems; i++) | |
660 { | |
661 if(pItems[i] != 0) | |
662 m_arrCommand.Add(pItems[i]); | |
663 } | |
664 | |
665 int nImageCount = ::ImageList_GetImageCount(m_hImageList); | |
666 ATLASSERT(nImageCount == m_arrCommand.GetSize()); | |
667 if(nImageCount != m_arrCommand.GetSize()) | |
668 return FALSE; | |
669 | |
670 #if _WTL_CMDBAR_VISTA_MENUS | |
671 if(RunTimeHelper::IsVista()) | |
672 { | |
673 T* pT = static_cast<T*>(this); | |
674 pT->_AddVistaBitmapsFromImageList(nOldImageCount, nImage
Count - nOldImageCount); | |
675 ATLASSERT(nImageCount == m_arrVistaBitmap.GetSize()); | |
676 } | |
677 #endif // _WTL_CMDBAR_VISTA_MENUS | |
678 | |
679 return TRUE; | |
680 } | |
681 | |
682 BOOL AddBitmap(ATL::_U_STRINGorID bitmap, int nCommandID) | |
683 { | |
684 ATLASSERT(::IsWindow(m_hWnd)); | |
685 CBitmap bmp; | |
686 bmp.LoadBitmap(bitmap.m_lpstr); | |
687 if(bmp.m_hBitmap == NULL) | |
688 return FALSE; | |
689 return AddBitmap(bmp, nCommandID); | |
690 } | |
691 | |
692 BOOL AddBitmap(HBITMAP hBitmap, UINT nCommandID) | |
693 { | |
694 ATLASSERT(::IsWindow(m_hWnd)); | |
695 T* pT = static_cast<T*>(this); | |
696 // Create image list if it doesn't exist | |
697 if(m_hImageList == NULL) | |
698 { | |
699 if(!pT->CreateInternalImageList(1)) | |
700 return FALSE; | |
701 } | |
702 // check bitmap size | |
703 CBitmapHandle bmp = hBitmap; | |
704 SIZE size = { 0, 0 }; | |
705 bmp.GetSize(size); | |
706 if(size.cx != m_szBitmap.cx || size.cy != m_szBitmap.cy) | |
707 { | |
708 ATLASSERT(FALSE); // must match size! | |
709 return FALSE; | |
710 } | |
711 // add bitmap | |
712 int nRet = ::ImageList_AddMasked(m_hImageList, hBitmap, m_clrMas
k); | |
713 if(nRet == -1) | |
714 return FALSE; | |
715 BOOL bRet = m_arrCommand.Add((WORD)nCommandID); | |
716 ATLASSERT(::ImageList_GetImageCount(m_hImageList) == m_arrComman
d.GetSize()); | |
717 #if _WTL_CMDBAR_VISTA_MENUS | |
718 if(RunTimeHelper::IsVista()) | |
719 { | |
720 pT->_AddVistaBitmapFromImageList(m_arrCommand.GetSize()
- 1); | |
721 ATLASSERT(m_arrVistaBitmap.GetSize() == m_arrCommand.Get
Size()); | |
722 } | |
723 #endif // _WTL_CMDBAR_VISTA_MENUS | |
724 return bRet; | |
725 } | |
726 | |
727 BOOL AddIcon(ATL::_U_STRINGorID icon, UINT nCommandID) | |
728 { | |
729 ATLASSERT(::IsWindow(m_hWnd)); | |
730 HICON hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), ic
on.m_lpstr); | |
731 if(hIcon == NULL) | |
732 return FALSE; | |
733 return AddIcon(hIcon, nCommandID); | |
734 } | |
735 | |
736 BOOL AddIcon(HICON hIcon, UINT nCommandID) | |
737 { | |
738 ATLASSERT(::IsWindow(m_hWnd)); | |
739 T* pT = static_cast<T*>(this); | |
740 // create image list if it doesn't exist | |
741 if(m_hImageList == NULL) | |
742 { | |
743 if(!pT->CreateInternalImageList(1)) | |
744 return FALSE; | |
745 } | |
746 | |
747 int nRet = ::ImageList_AddIcon(m_hImageList, hIcon); | |
748 if(nRet == -1) | |
749 return FALSE; | |
750 BOOL bRet = m_arrCommand.Add((WORD)nCommandID); | |
751 ATLASSERT(::ImageList_GetImageCount(m_hImageList) == m_arrComman
d.GetSize()); | |
752 #if _WTL_CMDBAR_VISTA_MENUS | |
753 if(RunTimeHelper::IsVista()) | |
754 { | |
755 pT->_AddVistaBitmapFromImageList(m_arrCommand.GetSize()
- 1); | |
756 ATLASSERT(m_arrVistaBitmap.GetSize() == m_arrCommand.Get
Size()); | |
757 } | |
758 #endif // _WTL_CMDBAR_VISTA_MENUS | |
759 return bRet; | |
760 } | |
761 | |
762 BOOL ReplaceBitmap(ATL::_U_STRINGorID bitmap, int nCommandID) | |
763 { | |
764 ATLASSERT(::IsWindow(m_hWnd)); | |
765 CBitmap bmp; | |
766 bmp.LoadBitmap(bitmap.m_lpstr); | |
767 if(bmp.m_hBitmap == NULL) | |
768 return FALSE; | |
769 return ReplaceBitmap(bmp, nCommandID); | |
770 } | |
771 | |
772 BOOL ReplaceBitmap(HBITMAP hBitmap, UINT nCommandID) | |
773 { | |
774 ATLASSERT(::IsWindow(m_hWnd)); | |
775 BOOL bRet = FALSE; | |
776 for(int i = 0; i < m_arrCommand.GetSize(); i++) | |
777 { | |
778 if(m_arrCommand[i] == nCommandID) | |
779 { | |
780 bRet = ::ImageList_Remove(m_hImageList, i); | |
781 if(bRet) | |
782 { | |
783 m_arrCommand.RemoveAt(i); | |
784 #if _WTL_CMDBAR_VISTA_MENUS | |
785 if(RunTimeHelper::IsVista()) | |
786 { | |
787 if(m_arrVistaBitmap[i] != NULL) | |
788 ::DeleteObject(m_arrVist
aBitmap[i]); | |
789 m_arrVistaBitmap.RemoveAt(i); | |
790 } | |
791 #endif // _WTL_CMDBAR_VISTA_MENUS | |
792 } | |
793 break; | |
794 } | |
795 } | |
796 if(bRet) | |
797 bRet = AddBitmap(hBitmap, nCommandID); | |
798 return bRet; | |
799 } | |
800 | |
801 BOOL ReplaceIcon(ATL::_U_STRINGorID icon, UINT nCommandID) | |
802 { | |
803 ATLASSERT(::IsWindow(m_hWnd)); | |
804 HICON hIcon = ::LoadIcon(ModuleHelper::GetResourceInstance(), ic
on.m_lpstr); | |
805 if(hIcon == NULL) | |
806 return FALSE; | |
807 return ReplaceIcon(hIcon, nCommandID); | |
808 } | |
809 | |
810 BOOL ReplaceIcon(HICON hIcon, UINT nCommandID) | |
811 { | |
812 ATLASSERT(::IsWindow(m_hWnd)); | |
813 BOOL bRet = FALSE; | |
814 for(int i = 0; i < m_arrCommand.GetSize(); i++) | |
815 { | |
816 if(m_arrCommand[i] == nCommandID) | |
817 { | |
818 bRet = (::ImageList_ReplaceIcon(m_hImageList, i,
hIcon) != -1); | |
819 #if _WTL_CMDBAR_VISTA_MENUS | |
820 if(RunTimeHelper::IsVista() && bRet != FALSE) | |
821 { | |
822 T* pT = static_cast<T*>(this); | |
823 pT->_ReplaceVistaBitmapFromImageList(i); | |
824 } | |
825 #endif // _WTL_CMDBAR_VISTA_MENUS | |
826 break; | |
827 } | |
828 } | |
829 return bRet; | |
830 } | |
831 | |
832 BOOL RemoveImage(int nCommandID) | |
833 { | |
834 ATLASSERT(::IsWindow(m_hWnd)); | |
835 | |
836 BOOL bRet = FALSE; | |
837 for(int i = 0; i < m_arrCommand.GetSize(); i++) | |
838 { | |
839 if(m_arrCommand[i] == nCommandID) | |
840 { | |
841 bRet = ::ImageList_Remove(m_hImageList, i); | |
842 if(bRet) | |
843 { | |
844 m_arrCommand.RemoveAt(i); | |
845 #if _WTL_CMDBAR_VISTA_MENUS | |
846 if(RunTimeHelper::IsVista()) | |
847 { | |
848 if(m_arrVistaBitmap[i] != NULL) | |
849 ::DeleteObject(m_arrVist
aBitmap[i]); | |
850 m_arrVistaBitmap.RemoveAt(i); | |
851 } | |
852 #endif // _WTL_CMDBAR_VISTA_MENUS | |
853 } | |
854 break; | |
855 } | |
856 } | |
857 return bRet; | |
858 } | |
859 | |
860 BOOL RemoveAllImages() | |
861 { | |
862 ATLASSERT(::IsWindow(m_hWnd)); | |
863 | |
864 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Removing all images\n")); | |
865 BOOL bRet = ::ImageList_RemoveAll(m_hImageList); | |
866 if(bRet) | |
867 { | |
868 m_arrCommand.RemoveAll(); | |
869 #if _WTL_CMDBAR_VISTA_MENUS | |
870 for(int i = 0; i < m_arrVistaBitmap.GetSize(); i++) | |
871 { | |
872 if(m_arrVistaBitmap[i] != NULL) | |
873 ::DeleteObject(m_arrVistaBitmap[i]); | |
874 } | |
875 m_arrVistaBitmap.RemoveAll(); | |
876 #endif // _WTL_CMDBAR_VISTA_MENUS | |
877 } | |
878 return bRet; | |
879 } | |
880 | |
881 BOOL TrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAMS
lpParams = NULL) | |
882 { | |
883 ATLASSERT(::IsWindow(m_hWnd)); | |
884 ATLASSERT(::IsMenu(hMenu)); | |
885 if(!::IsMenu(hMenu)) | |
886 return FALSE; | |
887 m_bContextMenu = true; | |
888 if(m_bUseKeyboardCues) | |
889 m_bShowKeyboardCues = m_bKeyboardInput; | |
890 T* pT = static_cast<T*>(this); | |
891 return pT->DoTrackPopupMenu(hMenu, uFlags, x, y, lpParams); | |
892 } | |
893 | |
894 BOOL SetMDIClient(HWND /*hWndMDIClient*/) | |
895 { | |
896 // Use CMDICommandBarCtrl for MDI support | |
897 ATLASSERT(FALSE); | |
898 return FALSE; | |
899 } | |
900 | |
901 // Message map and handlers | |
902 BEGIN_MSG_MAP(CCommandBarCtrlImpl) | |
903 MESSAGE_HANDLER(WM_CREATE, OnCreate) | |
904 MESSAGE_HANDLER(WM_DESTROY, OnDestroy) | |
905 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) | |
906 MESSAGE_HANDLER(WM_INITMENU, OnInitMenu) | |
907 MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup) | |
908 MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) | |
909 MESSAGE_HANDLER(GetAutoPopupMessage(), OnInternalAutoPopup) | |
910 MESSAGE_HANDLER(GetGetBarMessage(), OnInternalGetBar) | |
911 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) | |
912 MESSAGE_HANDLER(WM_MENUCHAR, OnMenuChar) | |
913 | |
914 MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown) | |
915 MESSAGE_HANDLER(WM_KEYUP, OnKeyUp) | |
916 MESSAGE_HANDLER(WM_CHAR, OnChar) | |
917 MESSAGE_HANDLER(WM_SYSKEYDOWN, OnSysKeyDown) | |
918 MESSAGE_HANDLER(WM_SYSKEYUP, OnSysKeyUp) | |
919 MESSAGE_HANDLER(WM_SYSCHAR, OnSysChar) | |
920 // public API handlers - these stay to support chevrons in atlframe.h | |
921 MESSAGE_HANDLER(CBRM_GETMENU, OnAPIGetMenu) | |
922 MESSAGE_HANDLER(CBRM_TRACKPOPUPMENU, OnAPITrackPopupMenu) | |
923 MESSAGE_HANDLER(CBRM_GETCMDBAR, OnAPIGetCmdBar) | |
924 | |
925 MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem) | |
926 MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem) | |
927 | |
928 MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg) | |
929 ALT_MSG_MAP(1) // Parent window messages | |
930 NOTIFY_CODE_HANDLER(TBN_HOTITEMCHANGE, OnParentHotItemChange) | |
931 NOTIFY_CODE_HANDLER(TBN_DROPDOWN, OnParentDropDown) | |
932 MESSAGE_HANDLER(WM_INITMENUPOPUP, OnParentInitMenuPopup) | |
933 MESSAGE_HANDLER(GetGetBarMessage(), OnParentInternalGetBar) | |
934 MESSAGE_HANDLER(WM_SYSCOMMAND, OnParentSysCommand) | |
935 MESSAGE_HANDLER(CBRM_GETMENU, OnParentAPIGetMenu) | |
936 MESSAGE_HANDLER(WM_MENUCHAR, OnParentMenuChar) | |
937 MESSAGE_HANDLER(CBRM_TRACKPOPUPMENU, OnParentAPITrackPopupMenu) | |
938 MESSAGE_HANDLER(CBRM_GETCMDBAR, OnParentAPIGetCmdBar) | |
939 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnParentSettingChange) | |
940 | |
941 MESSAGE_HANDLER(WM_DRAWITEM, OnParentDrawItem) | |
942 MESSAGE_HANDLER(WM_MEASUREITEM, OnParentMeasureItem) | |
943 | |
944 MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate) | |
945 NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnParentCustomDraw) | |
946 ALT_MSG_MAP(2) // MDI client window messages | |
947 // Use CMDICommandBarCtrl for MDI support | |
948 ALT_MSG_MAP(3) // Message hook messages | |
949 MESSAGE_HANDLER(WM_MOUSEMOVE, OnHookMouseMove) | |
950 MESSAGE_HANDLER(WM_SYSKEYDOWN, OnHookSysKeyDown) | |
951 MESSAGE_HANDLER(WM_SYSKEYUP, OnHookSysKeyUp) | |
952 MESSAGE_HANDLER(WM_SYSCHAR, OnHookSysChar) | |
953 MESSAGE_HANDLER(WM_KEYDOWN, OnHookKeyDown) | |
954 MESSAGE_HANDLER(WM_NEXTMENU, OnHookNextMenu) | |
955 MESSAGE_HANDLER(WM_CHAR, OnHookChar) | |
956 END_MSG_MAP() | |
957 | |
958 LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BO
OL& /*bHandled*/) | |
959 { | |
960 LPMSG pMsg = (LPMSG)lParam; | |
961 if(pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELA
ST) | |
962 m_bKeyboardInput = false; | |
963 else if(pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYL
AST) | |
964 m_bKeyboardInput = true; | |
965 LRESULT lRet = 0; | |
966 ProcessWindowMessage(pMsg->hwnd, pMsg->message, pMsg->wParam, pM
sg->lParam, lRet, 3); | |
967 return lRet; | |
968 } | |
969 | |
970 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandl
ed*/) | |
971 { | |
972 // Let the toolbar initialize itself | |
973 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); | |
974 // get and use system settings | |
975 T* pT = static_cast<T*>(this); | |
976 pT->GetSystemSettings(); | |
977 // Parent init | |
978 ATL::CWindow wndParent = GetParent(); | |
979 ATL::CWindow wndTopLevelParent = wndParent.GetTopLevelParent(); | |
980 m_wndParent.SubclassWindow(wndTopLevelParent); | |
981 // Toolbar Init | |
982 SetButtonStructSize(); | |
983 SetImageList(NULL); | |
984 | |
985 // Create message hook if needed | |
986 CWindowCreateCriticalSectionLock lock; | |
987 if(FAILED(lock.Lock())) | |
988 { | |
989 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock crit
ical section in CCommandBarCtrlImpl::OnCreate.\n")); | |
990 ATLASSERT(FALSE); | |
991 return -1; | |
992 } | |
993 | |
994 if(s_pmapMsgHook == NULL) | |
995 { | |
996 ATLTRY(s_pmapMsgHook = new CMsgHookMap); | |
997 ATLASSERT(s_pmapMsgHook != NULL); | |
998 } | |
999 | |
1000 if(s_pmapMsgHook != NULL) | |
1001 { | |
1002 DWORD dwThreadID = ::GetCurrentThreadId(); | |
1003 _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID); | |
1004 if(pData == NULL) | |
1005 { | |
1006 ATLTRY(pData = new _MsgHookData); | |
1007 ATLASSERT(pData != NULL); | |
1008 HHOOK hMsgHook = ::SetWindowsHookEx(WH_GETMESSAG
E, MessageHookProc, ModuleHelper::GetModuleInstance(), dwThreadID); | |
1009 ATLASSERT(hMsgHook != NULL); | |
1010 if(pData != NULL && hMsgHook != NULL) | |
1011 { | |
1012 pData->hMsgHook = hMsgHook; | |
1013 pData->dwUsage = 1; | |
1014 BOOL bRet = s_pmapMsgHook->Add(dwThreadI
D, pData); | |
1015 bRet; | |
1016 ATLASSERT(bRet); | |
1017 } | |
1018 } | |
1019 else | |
1020 { | |
1021 (pData->dwUsage)++; | |
1022 } | |
1023 } | |
1024 lock.Unlock(); | |
1025 | |
1026 // Get layout | |
1027 #if (WINVER >= 0x0500) | |
1028 m_bLayoutRTL = ((GetExStyle() & WS_EX_LAYOUTRTL) != 0); | |
1029 #endif // (WINVER >= 0x0500) | |
1030 | |
1031 return lRet; | |
1032 } | |
1033 | |
1034 LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHand
led*/) | |
1035 { | |
1036 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); | |
1037 | |
1038 #if _WTL_CMDBAR_VISTA_MENUS | |
1039 if(m_bVistaMenus && (m_hMenu != NULL)) | |
1040 { | |
1041 T* pT = static_cast<T*>(this); | |
1042 pT->_RemoveVistaBitmapsFromMenu(); | |
1043 } | |
1044 | |
1045 for(int i = 0; i < m_arrVistaBitmap.GetSize(); i++) | |
1046 { | |
1047 if(m_arrVistaBitmap[i] != NULL) | |
1048 ::DeleteObject(m_arrVistaBitmap[i]); | |
1049 } | |
1050 #endif // _WTL_CMDBAR_VISTA_MENUS | |
1051 | |
1052 if(m_bAttachedMenu) // nothing to do in this mode | |
1053 return lRet; | |
1054 | |
1055 CWindowCreateCriticalSectionLock lock; | |
1056 if(FAILED(lock.Lock())) | |
1057 { | |
1058 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock crit
ical section in CCommandBarCtrlImpl::OnDestroy.\n")); | |
1059 ATLASSERT(FALSE); | |
1060 return lRet; | |
1061 } | |
1062 | |
1063 if(s_pmapMsgHook != NULL) | |
1064 { | |
1065 DWORD dwThreadID = ::GetCurrentThreadId(); | |
1066 _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID); | |
1067 if(pData != NULL) | |
1068 { | |
1069 (pData->dwUsage)--; | |
1070 if(pData->dwUsage == 0) | |
1071 { | |
1072 BOOL bRet = ::UnhookWindowsHookEx(pData-
>hMsgHook); | |
1073 ATLASSERT(bRet); | |
1074 bRet = s_pmapMsgHook->Remove(dwThreadID)
; | |
1075 ATLASSERT(bRet); | |
1076 if(bRet) | |
1077 delete pData; | |
1078 } | |
1079 | |
1080 if(s_pmapMsgHook->GetSize() == 0) | |
1081 { | |
1082 delete s_pmapMsgHook; | |
1083 s_pmapMsgHook = NULL; | |
1084 } | |
1085 } | |
1086 } | |
1087 | |
1088 lock.Unlock(); | |
1089 | |
1090 return lRet; | |
1091 } | |
1092 | |
1093 LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHa
ndled) | |
1094 { | |
1095 #ifdef _CMDBAR_EXTRA_TRACE | |
1096 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnKeyDown\n")); | |
1097 #endif | |
1098 bHandled = FALSE; | |
1099 // Simulate Alt+Space for the parent | |
1100 if(wParam == VK_SPACE) | |
1101 { | |
1102 m_wndParent.PostMessage(WM_SYSKEYDOWN, wParam, lParam |
(1 << 29)); | |
1103 bHandled = TRUE; | |
1104 } | |
1105 #if (_WIN32_IE >= 0x0500) | |
1106 else if(wParam == VK_LEFT || wParam == VK_RIGHT) | |
1107 { | |
1108 WPARAM wpNext = m_bLayoutRTL ? VK_LEFT : VK_RIGHT; | |
1109 | |
1110 if(!m_bMenuActive) | |
1111 { | |
1112 T* pT = static_cast<T*>(this); | |
1113 int nBtn = GetHotItem(); | |
1114 int nNextBtn = (wParam == wpNext) ? pT->GetNextM
enuItem(nBtn) : pT->GetPreviousMenuItem(nBtn); | |
1115 if(nNextBtn == -2) | |
1116 { | |
1117 SetHotItem(-1); | |
1118 if(pT->DisplayChevronMenu()) | |
1119 bHandled = TRUE; | |
1120 } | |
1121 } | |
1122 } | |
1123 #endif // (_WIN32_IE >= 0x0500) | |
1124 return 0; | |
1125 } | |
1126 | |
1127 LRESULT OnKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& b
Handled) | |
1128 { | |
1129 #ifdef _CMDBAR_EXTRA_TRACE | |
1130 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnKeyUp\n")); | |
1131 #endif | |
1132 if(wParam != VK_SPACE) | |
1133 bHandled = FALSE; | |
1134 return 0; | |
1135 } | |
1136 | |
1137 LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bH
andled) | |
1138 { | |
1139 #ifdef _CMDBAR_EXTRA_TRACE | |
1140 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnChar\n")); | |
1141 #endif | |
1142 if(wParam != VK_SPACE) | |
1143 bHandled = FALSE; | |
1144 else | |
1145 return 0; | |
1146 // Security | |
1147 if(!m_wndParent.IsWindowEnabled() || ::GetFocus() != m_hWnd) | |
1148 return 0; | |
1149 | |
1150 // Handle mnemonic press when we have focus | |
1151 int nBtn = 0; | |
1152 if(wParam != VK_RETURN && !MapAccelerator((TCHAR)LOWORD(wParam),
nBtn)) | |
1153 { | |
1154 #if (_WIN32_IE >= 0x0500) | |
1155 if((TCHAR)LOWORD(wParam) != _chChevronShortcut) | |
1156 #endif // (_WIN32_IE >= 0x0500) | |
1157 ::MessageBeep(0); | |
1158 } | |
1159 else | |
1160 { | |
1161 #if (_WIN32_IE >= 0x0500) | |
1162 RECT rcClient = { 0 }; | |
1163 GetClientRect(&rcClient); | |
1164 RECT rcBtn = { 0 }; | |
1165 GetItemRect(nBtn, &rcBtn); | |
1166 TBBUTTON tbb = { 0 }; | |
1167 GetButton(nBtn, &tbb); | |
1168 if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState
& TBSTATE_HIDDEN) == 0 && rcBtn.right <= rcClient.right) | |
1169 { | |
1170 #endif // (_WIN32_IE >= 0x0500) | |
1171 PostMessage(WM_KEYDOWN, VK_DOWN, 0L); | |
1172 if(wParam != VK_RETURN) | |
1173 SetHotItem(nBtn); | |
1174 #if (_WIN32_IE >= 0x0500) | |
1175 } | |
1176 else | |
1177 { | |
1178 ::MessageBeep(0); | |
1179 bHandled = TRUE; | |
1180 } | |
1181 #endif // (_WIN32_IE >= 0x0500) | |
1182 } | |
1183 return 0; | |
1184 } | |
1185 | |
1186 LRESULT OnSysKeyDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/
, BOOL& bHandled) | |
1187 { | |
1188 #ifdef _CMDBAR_EXTRA_TRACE | |
1189 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysKeyDown\n")); | |
1190 #endif | |
1191 bHandled = FALSE; | |
1192 return 0; | |
1193 } | |
1194 | |
1195 LRESULT OnSysKeyUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/,
BOOL& bHandled) | |
1196 { | |
1197 #ifdef _CMDBAR_EXTRA_TRACE | |
1198 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysKeyUp\n")); | |
1199 #endif | |
1200 bHandled = FALSE; | |
1201 return 0; | |
1202 } | |
1203 | |
1204 LRESULT OnSysChar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, B
OOL& bHandled) | |
1205 { | |
1206 #ifdef _CMDBAR_EXTRA_TRACE | |
1207 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnSysChar\n")); | |
1208 #endif | |
1209 bHandled = FALSE; | |
1210 return 0; | |
1211 } | |
1212 | |
1213 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*
/, BOOL& bHandled) | |
1214 { | |
1215 if(m_bAttachedMenu || (m_dwExtendedStyle & CBR_EX_TRANSPARENT)) | |
1216 { | |
1217 bHandled = FALSE; | |
1218 return 0; | |
1219 } | |
1220 | |
1221 CDCHandle dc = (HDC)wParam; | |
1222 RECT rect = { 0 }; | |
1223 GetClientRect(&rect); | |
1224 dc.FillRect(&rect, COLOR_MENU); | |
1225 | |
1226 return 1; // don't do the default erase | |
1227 } | |
1228 | |
1229 LRESULT OnInitMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/,
BOOL& bHandled) | |
1230 { | |
1231 int nIndex = GetHotItem(); | |
1232 SendMessage(WM_MENUSELECT, MAKEWPARAM(nIndex, MF_POPUP|MF_HILITE
), (LPARAM)m_hMenu); | |
1233 bHandled = FALSE; | |
1234 return 1; | |
1235 } | |
1236 | |
1237 LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& b
Handled) | |
1238 { | |
1239 if((BOOL)HIWORD(lParam)) // System menu, do nothing | |
1240 { | |
1241 bHandled = FALSE; | |
1242 return 1; | |
1243 } | |
1244 | |
1245 if(!(m_bAttachedMenu || m_bMenuActive)) // Not attached or our
s, do nothing | |
1246 { | |
1247 bHandled = FALSE; | |
1248 return 1; | |
1249 } | |
1250 | |
1251 #ifdef _CMDBAR_EXTRA_TRACE | |
1252 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnInitMenuPopup\n")); | |
1253 #endif | |
1254 // forward to the parent or subclassed window, so it can handle
update UI | |
1255 LRESULT lRet = 0; | |
1256 if(m_bAttachedMenu) | |
1257 lRet = DefWindowProc(uMsg, wParam, (lParam || m_bContext
Menu) ? lParam : GetHotItem()); | |
1258 else | |
1259 lRet = m_wndParent.DefWindowProc(uMsg, wParam, (lParam |
| m_bContextMenu) ? lParam : GetHotItem()); | |
1260 | |
1261 #if _WTL_CMDBAR_VISTA_MENUS | |
1262 // If Vista menus are active, just set bitmaps and return | |
1263 if(m_bVistaMenus) | |
1264 { | |
1265 CMenuHandle menu = (HMENU)wParam; | |
1266 ATLASSERT(menu.m_hMenu != NULL); | |
1267 | |
1268 for(int i = 0; i < menu.GetMenuItemCount(); i++) | |
1269 { | |
1270 WORD nID = (WORD)menu.GetMenuItemID(i); | |
1271 int nIndex = m_arrCommand.Find(nID); | |
1272 | |
1273 CMenuItemInfo mii; | |
1274 mii.fMask = MIIM_BITMAP; | |
1275 mii.hbmpItem = (m_bImagesVisible && (nIndex != -
1)) ? m_arrVistaBitmap[nIndex] : NULL; | |
1276 menu.SetMenuItemInfo(i, TRUE, &mii); | |
1277 } | |
1278 | |
1279 return lRet; | |
1280 } | |
1281 #endif // _WTL_CMDBAR_VISTA_MENUS | |
1282 | |
1283 // Convert menu items to ownerdraw, add our data | |
1284 if(m_bImagesVisible) | |
1285 { | |
1286 CMenuHandle menuPopup = (HMENU)wParam; | |
1287 ATLASSERT(menuPopup.m_hMenu != NULL); | |
1288 | |
1289 T* pT = static_cast<T*>(this); | |
1290 pT; // avoid level 4 warning | |
1291 TCHAR szString[pT->_nMaxMenuItemTextLength]; | |
1292 BOOL bRet = FALSE; | |
1293 for(int i = 0; i < menuPopup.GetMenuItemCount(); i++) | |
1294 { | |
1295 CMenuItemInfo mii; | |
1296 mii.cch = pT->_nMaxMenuItemTextLength; | |
1297 mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_I
D | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; | |
1298 mii.dwTypeData = szString; | |
1299 bRet = menuPopup.GetMenuItemInfo(i, TRUE, &mii); | |
1300 ATLASSERT(bRet); | |
1301 | |
1302 if(!(mii.fType & MFT_OWNERDRAW)) // Not alread
y an ownerdraw item | |
1303 { | |
1304 mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM
_STATE; | |
1305 _MenuItemData* pMI = NULL; | |
1306 ATLTRY(pMI = new _MenuItemData); | |
1307 ATLASSERT(pMI != NULL); | |
1308 if(pMI != NULL) | |
1309 { | |
1310 pMI->fType = mii.fType; | |
1311 pMI->fState = mii.fState; | |
1312 mii.fType |= MFT_OWNERDRAW; | |
1313 pMI->iButton = -1; | |
1314 for(int j = 0; j < m_arrCommand.
GetSize(); j++) | |
1315 { | |
1316 if(m_arrCommand[j] == mi
i.wID) | |
1317 { | |
1318 pMI->iButton = j
; | |
1319 break; | |
1320 } | |
1321 } | |
1322 int cchLen = lstrlen(szString) +
1; | |
1323 pMI->lpstrText = NULL; | |
1324 ATLTRY(pMI->lpstrText = new TCHA
R[cchLen]); | |
1325 ATLASSERT(pMI->lpstrText != NULL
); | |
1326 if(pMI->lpstrText != NULL) | |
1327 SecureHelper::strcpy_x(p
MI->lpstrText, cchLen, szString); | |
1328 mii.dwItemData = (ULONG_PTR)pMI; | |
1329 bRet = menuPopup.SetMenuItemInfo
(i, TRUE, &mii); | |
1330 ATLASSERT(bRet); | |
1331 } | |
1332 } | |
1333 } | |
1334 | |
1335 // Add it to the list | |
1336 m_stackMenuHandle.Push(menuPopup.m_hMenu); | |
1337 } | |
1338 | |
1339 return lRet; | |
1340 } | |
1341 | |
1342 LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHan
dled) | |
1343 { | |
1344 if(!m_bAttachedMenu) // Not attached, do nothing, forward to p
arent | |
1345 { | |
1346 m_bPopupItem = (lParam != NULL) && ((HMENU)lParam != m_h
Menu) && (HIWORD(wParam) & MF_POPUP); | |
1347 if(m_wndParent.IsWindow()) | |
1348 m_wndParent.SendMessage(uMsg, wParam, lParam); | |
1349 bHandled = FALSE; | |
1350 return 1; | |
1351 } | |
1352 | |
1353 // Check if a menu is closing, do a cleanup | |
1354 if(HIWORD(wParam) == 0xFFFF && lParam == NULL) // Menu closing | |
1355 { | |
1356 #ifdef _CMDBAR_EXTRA_TRACE | |
1357 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnMenuSelect - CLO
SING!!!!\n")); | |
1358 #endif | |
1359 ATLASSERT(m_stackMenuWnd.GetSize() == 0); | |
1360 // Restore the menu items to the previous state for all
menus that were converted | |
1361 if(m_bImagesVisible) | |
1362 { | |
1363 HMENU hMenu = NULL; | |
1364 while((hMenu = m_stackMenuHandle.Pop()) != NULL) | |
1365 { | |
1366 CMenuHandle menuPopup = hMenu; | |
1367 ATLASSERT(menuPopup.m_hMenu != NULL); | |
1368 // Restore state and delete menu item da
ta | |
1369 BOOL bRet = FALSE; | |
1370 for(int i = 0; i < menuPopup.GetMenuItem
Count(); i++) | |
1371 { | |
1372 CMenuItemInfo mii; | |
1373 mii.fMask = MIIM_DATA | MIIM_TYP
E; | |
1374 bRet = menuPopup.GetMenuItemInfo
(i, TRUE, &mii); | |
1375 ATLASSERT(bRet); | |
1376 | |
1377 _MenuItemData* pMI = (_MenuItemD
ata*)mii.dwItemData; | |
1378 if(pMI != NULL && pMI->IsCmdBarM
enuItem()) | |
1379 { | |
1380 mii.fMask = MIIM_DATA |
MIIM_TYPE | MIIM_STATE; | |
1381 mii.fType = pMI->fType; | |
1382 mii.dwTypeData = pMI->lp
strText; | |
1383 mii.cch = lstrlen(pMI->l
pstrText); | |
1384 mii.dwItemData = NULL; | |
1385 | |
1386 bRet = menuPopup.SetMenu
ItemInfo(i, TRUE, &mii); | |
1387 ATLASSERT(bRet); | |
1388 | |
1389 delete [] pMI->lpstrText
; | |
1390 pMI->dwMagic = 0x6666; | |
1391 delete pMI; | |
1392 } | |
1393 } | |
1394 } | |
1395 } | |
1396 } | |
1397 | |
1398 bHandled = FALSE; | |
1399 return 1; | |
1400 } | |
1401 | |
1402 LRESULT OnInternalAutoPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lPara
m*/, BOOL& /*bHandled*/) | |
1403 { | |
1404 int nIndex = (int)wParam; | |
1405 T* pT = static_cast<T*>(this); | |
1406 pT->DoPopupMenu(nIndex, false); | |
1407 return 0; | |
1408 } | |
1409 | |
1410 LRESULT OnInternalGetBar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/
, BOOL& /*bHandled*/) | |
1411 { | |
1412 // Let's make sure we're not embedded in another process | |
1413 if((LPVOID)wParam != NULL) | |
1414 *((DWORD*)wParam) = GetCurrentProcessId(); | |
1415 if(IsWindowVisible()) | |
1416 return (LRESULT)static_cast<CCommandBarCtrlBase*>(this); | |
1417 else | |
1418 return NULL; | |
1419 } | |
1420 | |
1421 LRESULT OnSettingChange(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/,
BOOL& /*bHandled*/) | |
1422 { | |
1423 #ifndef SPI_GETKEYBOARDCUES | |
1424 const UINT SPI_SETKEYBOARDCUES = 0x100B; | |
1425 #endif // !SPI_GETKEYBOARDCUES | |
1426 #ifndef SPI_GETFLATMENU | |
1427 const UINT SPI_SETFLATMENU = 0x1023; | |
1428 #endif // !SPI_GETFLATMENU | |
1429 | |
1430 if(wParam == SPI_SETNONCLIENTMETRICS || wParam == SPI_SETKEYBOAR
DCUES || wParam == SPI_SETFLATMENU) | |
1431 { | |
1432 T* pT = static_cast<T*>(this); | |
1433 pT->GetSystemSettings(); | |
1434 } | |
1435 | |
1436 return 0; | |
1437 } | |
1438 | |
1439 LRESULT OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOO
L& /*bHandled*/) | |
1440 { | |
1441 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); | |
1442 | |
1443 LPWINDOWPOS lpWP = (LPWINDOWPOS)lParam; | |
1444 int cyMin = ::GetSystemMetrics(SM_CYMENU); | |
1445 if(lpWP->cy < cyMin) | |
1446 lpWP->cy = cyMin; | |
1447 | |
1448 return lRet; | |
1449 } | |
1450 | |
1451 LRESULT OnMenuChar(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bH
andled) | |
1452 { | |
1453 #ifdef _CMDBAR_EXTRA_TRACE | |
1454 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - OnMenuChar\n")); | |
1455 #endif | |
1456 bHandled = TRUE; | |
1457 T* pT = static_cast<T*>(this); | |
1458 | |
1459 LRESULT lRet; | |
1460 if(m_bMenuActive && LOWORD(wParam) != 0x0D) | |
1461 lRet = 0; | |
1462 else | |
1463 lRet = MAKELRESULT(1, 1); | |
1464 | |
1465 if(m_bMenuActive && HIWORD(wParam) == MF_POPUP) | |
1466 { | |
1467 // Convert character to lower/uppercase and possibly Uni
code, using current keyboard layout | |
1468 TCHAR ch = (TCHAR)LOWORD(wParam); | |
1469 CMenuHandle menu = (HMENU)lParam; | |
1470 int nCount = ::GetMenuItemCount(menu); | |
1471 int nRetCode = MNC_EXECUTE; | |
1472 BOOL bRet = FALSE; | |
1473 TCHAR szString[pT->_nMaxMenuItemTextLength]; | |
1474 WORD wMnem = 0; | |
1475 bool bFound = false; | |
1476 for(int i = 0; i < nCount; i++) | |
1477 { | |
1478 CMenuItemInfo mii; | |
1479 mii.cch = pT->_nMaxMenuItemTextLength; | |
1480 mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_I
D | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; | |
1481 mii.dwTypeData = szString; | |
1482 bRet = menu.GetMenuItemInfo(i, TRUE, &mii); | |
1483 if(!bRet || (mii.fType & MFT_SEPARATOR)) | |
1484 continue; | |
1485 _MenuItemData* pmd = (_MenuItemData*)mii.dwItemD
ata; | |
1486 if(pmd != NULL && pmd->IsCmdBarMenuItem()) | |
1487 { | |
1488 LPTSTR p = pmd->lpstrText; | |
1489 | |
1490 if(p != NULL) | |
1491 { | |
1492 while(*p && *p != _T('&')) | |
1493 p = ::CharNext(p); | |
1494 if(p != NULL && *p) | |
1495 { | |
1496 DWORD dwP = MAKELONG(*(+
+p), 0); | |
1497 DWORD dwC = MAKELONG(ch,
0); | |
1498 if(::CharLower((LPTSTR)U
LongToPtr(dwP)) == ::CharLower((LPTSTR)ULongToPtr(dwC))) | |
1499 { | |
1500 if(!bFound) | |
1501 { | |
1502 wMnem =
(WORD)i; | |
1503 bFound =
true; | |
1504 } | |
1505 else | |
1506 { | |
1507 nRetCode
= MNC_SELECT; | |
1508 break; | |
1509 } | |
1510 } | |
1511 } | |
1512 } | |
1513 } | |
1514 } | |
1515 if(bFound) | |
1516 { | |
1517 if(nRetCode == MNC_EXECUTE) | |
1518 { | |
1519 PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0
L); | |
1520 pT->GiveFocusBack(); | |
1521 } | |
1522 bHandled = TRUE; | |
1523 lRet = MAKELRESULT(wMnem, nRetCode); | |
1524 } | |
1525 } | |
1526 else if(!m_bMenuActive) | |
1527 { | |
1528 int nBtn = 0; | |
1529 if(!MapAccelerator((TCHAR)LOWORD(wParam), nBtn)) | |
1530 { | |
1531 bHandled = FALSE; | |
1532 PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); | |
1533 pT->GiveFocusBack(); | |
1534 | |
1535 #if (_WIN32_IE >= 0x0500) | |
1536 // check if we should display chevron menu | |
1537 if((TCHAR)LOWORD(wParam) == pT->_chChevronShortc
ut) | |
1538 { | |
1539 if(pT->DisplayChevronMenu()) | |
1540 bHandled = TRUE; | |
1541 } | |
1542 #endif // (_WIN32_IE >= 0x0500) | |
1543 } | |
1544 else if(m_wndParent.IsWindowEnabled()) | |
1545 { | |
1546 #if (_WIN32_IE >= 0x0500) | |
1547 RECT rcClient = { 0 }; | |
1548 GetClientRect(&rcClient); | |
1549 RECT rcBtn = { 0 }; | |
1550 GetItemRect(nBtn, &rcBtn); | |
1551 TBBUTTON tbb = { 0 }; | |
1552 GetButton(nBtn, &tbb); | |
1553 if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.
fsState & TBSTATE_HIDDEN) == 0 && rcBtn.right <= rcClient.right) | |
1554 { | |
1555 #endif // (_WIN32_IE >= 0x0500) | |
1556 if(m_bUseKeyboardCues && !m_bShowKeyboar
dCues) | |
1557 { | |
1558 m_bAllowKeyboardCues = true; | |
1559 ShowKeyboardCues(true); | |
1560 } | |
1561 pT->TakeFocus(); | |
1562 PostMessage(WM_KEYDOWN, VK_DOWN, 0L); | |
1563 SetHotItem(nBtn); | |
1564 #if (_WIN32_IE >= 0x0500) | |
1565 } | |
1566 else | |
1567 { | |
1568 ::MessageBeep(0); | |
1569 } | |
1570 #endif // (_WIN32_IE >= 0x0500) | |
1571 } | |
1572 } | |
1573 | |
1574 return lRet; | |
1575 } | |
1576 | |
1577 LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL
& bHandled) | |
1578 { | |
1579 LPDRAWITEMSTRUCT lpDrawItemStruct = (LPDRAWITEMSTRUCT)lParam; | |
1580 _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData; | |
1581 if(lpDrawItemStruct->CtlType == ODT_MENU && pmd != NULL && pmd->
IsCmdBarMenuItem()) | |
1582 { | |
1583 T* pT = static_cast<T*>(this); | |
1584 pT->DrawItem(lpDrawItemStruct); | |
1585 } | |
1586 else | |
1587 { | |
1588 bHandled = FALSE; | |
1589 } | |
1590 return (LRESULT)TRUE; | |
1591 } | |
1592 | |
1593 LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, B
OOL& bHandled) | |
1594 { | |
1595 LPMEASUREITEMSTRUCT lpMeasureItemStruct = (LPMEASUREITEMSTRUCT)l
Param; | |
1596 _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemDa
ta; | |
1597 if(lpMeasureItemStruct->CtlType == ODT_MENU && pmd != NULL && pm
d->IsCmdBarMenuItem()) | |
1598 { | |
1599 T* pT = static_cast<T*>(this); | |
1600 pT->MeasureItem(lpMeasureItemStruct); | |
1601 } | |
1602 else | |
1603 { | |
1604 bHandled = FALSE; | |
1605 } | |
1606 return (LRESULT)TRUE; | |
1607 } | |
1608 | |
1609 // API message handlers | |
1610 LRESULT OnAPIGetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/
, BOOL& /*bHandled*/) | |
1611 { | |
1612 return (LRESULT)m_hMenu; | |
1613 } | |
1614 | |
1615 LRESULT OnAPITrackPopupMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lPa
ram, BOOL& /*bHandled*/) | |
1616 { | |
1617 if(lParam == NULL) | |
1618 return FALSE; | |
1619 LPCBRPOPUPMENU lpCBRPopupMenu = (LPCBRPOPUPMENU)lParam; | |
1620 if(lpCBRPopupMenu->cbSize != sizeof(CBRPOPUPMENU)) | |
1621 return FALSE; | |
1622 | |
1623 T* pT = static_cast<T*>(this); | |
1624 return pT->TrackPopupMenu(lpCBRPopupMenu->hMenu, lpCBRPopupMenu-
>uFlags, lpCBRPopupMenu->x, lpCBRPopupMenu->y, lpCBRPopupMenu->lptpm); | |
1625 } | |
1626 | |
1627 LRESULT OnAPIGetCmdBar(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam
*/, BOOL& /*bHandled*/) | |
1628 { | |
1629 return (LRESULT)m_hWnd; | |
1630 } | |
1631 | |
1632 // Parent window message handlers | |
1633 LRESULT OnParentHotItemChange(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandl
ed) | |
1634 { | |
1635 LPNMTBHOTITEM lpNMHT = (LPNMTBHOTITEM)pnmh; | |
1636 | |
1637 // Check if this comes from us | |
1638 if(pnmh->hwndFrom != m_hWnd) | |
1639 { | |
1640 bHandled = FALSE; | |
1641 return 0; | |
1642 } | |
1643 | |
1644 bool bBlockTracking = false; | |
1645 if((m_dwExtendedStyle & CBR_EX_TRACKALWAYS) == 0) | |
1646 { | |
1647 DWORD dwProcessID; | |
1648 ::GetWindowThreadProcessId(::GetActiveWindow(), &dwProce
ssID); | |
1649 bBlockTracking = (::GetCurrentProcessId() != dwProcessID
); | |
1650 } | |
1651 | |
1652 if((!m_wndParent.IsWindowEnabled() || bBlockTracking) && (lpNMHT
->dwFlags & HICF_MOUSE)) | |
1653 { | |
1654 return 1; | |
1655 } | |
1656 else | |
1657 { | |
1658 #ifndef HICF_LMOUSE | |
1659 const DWORD HICF_LMOUSE = 0x00000080; // left mouse bu
tton selected | |
1660 #endif | |
1661 bHandled = FALSE; | |
1662 | |
1663 // Send WM_MENUSELECT to the app if it needs to display
a status text | |
1664 if(!(lpNMHT->dwFlags & HICF_MOUSE) | |
1665 && !(lpNMHT->dwFlags & HICF_ACCELERATOR) | |
1666 && !(lpNMHT->dwFlags & HICF_LMOUSE)) | |
1667 { | |
1668 if(lpNMHT->dwFlags & HICF_ENTERING) | |
1669 m_wndParent.SendMessage(WM_MENUSELECT, 0
, (LPARAM)m_hMenu); | |
1670 if(lpNMHT->dwFlags & HICF_LEAVING) | |
1671 m_wndParent.SendMessage(WM_MENUSELECT, M
AKEWPARAM(0, 0xFFFF), NULL); | |
1672 } | |
1673 | |
1674 return 0; | |
1675 } | |
1676 } | |
1677 | |
1678 LRESULT OnParentDropDown(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) | |
1679 { | |
1680 // Check if this comes from us | |
1681 if(pnmh->hwndFrom != m_hWnd) | |
1682 { | |
1683 bHandled = FALSE; | |
1684 return 1; | |
1685 } | |
1686 | |
1687 T* pT = static_cast<T*>(this); | |
1688 if(::GetFocus() != m_hWnd) | |
1689 pT->TakeFocus(); | |
1690 LPNMTOOLBAR pNMToolBar = (LPNMTOOLBAR)pnmh; | |
1691 int nIndex = CommandToIndex(pNMToolBar->iItem); | |
1692 m_bContextMenu = false; | |
1693 m_bEscapePressed = false; | |
1694 pT->DoPopupMenu(nIndex, true); | |
1695 | |
1696 return TBDDRET_DEFAULT; | |
1697 } | |
1698 | |
1699 LRESULT OnParentInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, B
OOL& bHandled) | |
1700 { | |
1701 return OnInitMenuPopup(uMsg, wParam, lParam, bHandled); | |
1702 } | |
1703 | |
1704 LRESULT OnParentInternalGetBar(UINT uMsg, WPARAM wParam, LPARAM lParam,
BOOL& bHandled) | |
1705 { | |
1706 return OnInternalGetBar(uMsg, wParam, lParam, bHandled); | |
1707 } | |
1708 | |
1709 LRESULT OnParentSysCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam
*/, BOOL& bHandled) | |
1710 { | |
1711 bHandled = FALSE; | |
1712 if((m_uSysKey == VK_MENU | |
1713 || (m_uSysKey == VK_F10 && !(::GetKeyState(VK_SHIFT) & 0
x80)) | |
1714 || m_uSysKey == VK_SPACE) | |
1715 && wParam == SC_KEYMENU) | |
1716 { | |
1717 T* pT = static_cast<T*>(this); | |
1718 if(::GetFocus() == m_hWnd) | |
1719 { | |
1720 pT->GiveFocusBack(); // exit menu "loop" | |
1721 PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); | |
1722 } | |
1723 else if(m_uSysKey != VK_SPACE && !m_bSkipMsg) | |
1724 { | |
1725 if(m_bUseKeyboardCues && !m_bShowKeyboardCues &&
m_bAllowKeyboardCues) | |
1726 ShowKeyboardCues(true); | |
1727 | |
1728 pT->TakeFocus(); // enter menu "loop" | |
1729 bHandled = TRUE; | |
1730 } | |
1731 else if(m_uSysKey != VK_SPACE) | |
1732 { | |
1733 bHandled = TRUE; | |
1734 } | |
1735 } | |
1736 m_bSkipMsg = false; | |
1737 return 0; | |
1738 } | |
1739 | |
1740 LRESULT OnParentAPIGetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL
& bHandled) | |
1741 { | |
1742 return OnAPIGetMenu(uMsg, wParam, lParam, bHandled); | |
1743 } | |
1744 | |
1745 LRESULT OnParentMenuChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&
bHandled) | |
1746 { | |
1747 return OnMenuChar(uMsg, wParam, lParam, bHandled); | |
1748 } | |
1749 | |
1750 LRESULT OnParentAPITrackPopupMenu(UINT uMsg, WPARAM wParam, LPARAM lPara
m, BOOL& bHandled) | |
1751 { | |
1752 return OnAPITrackPopupMenu(uMsg, wParam, lParam, bHandled); | |
1753 } | |
1754 | |
1755 LRESULT OnParentAPIGetCmdBar(UINT uMsg, WPARAM wParam, LPARAM lParam, BO
OL& bHandled) | |
1756 { | |
1757 return OnAPIGetCmdBar(uMsg, wParam, lParam, bHandled); | |
1758 } | |
1759 | |
1760 LRESULT OnParentSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, B
OOL& bHandled) | |
1761 { | |
1762 OnSettingChange(uMsg, wParam, lParam, bHandled); | |
1763 bHandled = FALSE; | |
1764 return 1; | |
1765 } | |
1766 | |
1767 LRESULT OnParentDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&
bHandled) | |
1768 { | |
1769 return OnDrawItem(uMsg, wParam, lParam, bHandled); | |
1770 } | |
1771 | |
1772 LRESULT OnParentMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOO
L& bHandled) | |
1773 { | |
1774 return OnMeasureItem(uMsg, wParam, lParam, bHandled); | |
1775 } | |
1776 | |
1777 LRESULT OnParentActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/
, BOOL& bHandled) | |
1778 { | |
1779 m_bParentActive = (LOWORD(wParam) != WA_INACTIVE); | |
1780 if(!m_bParentActive && m_bUseKeyboardCues && m_bShowKeyboardCues
) | |
1781 { | |
1782 ShowKeyboardCues(false); // this will repaint our wind
ow | |
1783 } | |
1784 else | |
1785 { | |
1786 Invalidate(); | |
1787 UpdateWindow(); | |
1788 } | |
1789 bHandled = FALSE; | |
1790 return 1; | |
1791 } | |
1792 | |
1793 LRESULT OnParentCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) | |
1794 { | |
1795 LRESULT lRet = CDRF_DODEFAULT; | |
1796 bHandled = FALSE; | |
1797 if(pnmh->hwndFrom == m_hWnd) | |
1798 { | |
1799 LPNMTBCUSTOMDRAW lpTBCustomDraw = (LPNMTBCUSTOMDRAW)pnmh
; | |
1800 if(lpTBCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT) | |
1801 { | |
1802 lRet = CDRF_NOTIFYITEMDRAW; | |
1803 bHandled = TRUE; | |
1804 } | |
1805 else if(lpTBCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPRE
PAINT) | |
1806 { | |
1807 if(m_bFlatMenus) | |
1808 { | |
1809 #ifndef COLOR_MENUHILIGHT | |
1810 const int COLOR_MENUHILIGHT = 29; | |
1811 #endif // !COLOR_MENUHILIGHT | |
1812 bool bDisabled = ((lpTBCustomDraw->nmcd.
uItemState & CDIS_DISABLED) == CDIS_DISABLED); | |
1813 if(!bDisabled && ((lpTBCustomDraw->nmcd.
uItemState & CDIS_HOT) == CDIS_HOT || | |
1814 (lpTBCustomDraw->nmcd.uItemState
& CDIS_SELECTED) == CDIS_SELECTED)) | |
1815 { | |
1816 ::FillRect(lpTBCustomDraw->nmcd.
hdc, &lpTBCustomDraw->nmcd.rc, ::GetSysColorBrush(COLOR_MENUHILIGHT)); | |
1817 ::FrameRect(lpTBCustomDraw->nmcd
.hdc, &lpTBCustomDraw->nmcd.rc, ::GetSysColorBrush(COLOR_HIGHLIGHT)); | |
1818 lpTBCustomDraw->clrText = ::GetS
ysColor(m_bParentActive ? COLOR_HIGHLIGHTTEXT : COLOR_GRAYTEXT); | |
1819 } | |
1820 else if(bDisabled || !m_bParentActive) | |
1821 { | |
1822 lpTBCustomDraw->clrText = ::GetS
ysColor(COLOR_GRAYTEXT); | |
1823 } | |
1824 CDCHandle dc = lpTBCustomDraw->nmcd.hdc; | |
1825 dc.SetTextColor(lpTBCustomDraw->clrText)
; | |
1826 dc.SetBkMode(lpTBCustomDraw->nStringBkMo
de); | |
1827 HFONT hFont = GetFont(); | |
1828 HFONT hFontOld = NULL; | |
1829 if(hFont != NULL) | |
1830 hFontOld = dc.SelectFont(hFont); | |
1831 const int cchText = 200; | |
1832 TCHAR szText[cchText] = { 0 }; | |
1833 TBBUTTONINFO tbbi = { 0 }; | |
1834 tbbi.cbSize = sizeof(TBBUTTONINFO); | |
1835 tbbi.dwMask = TBIF_TEXT; | |
1836 tbbi.pszText = szText; | |
1837 tbbi.cchText = cchText; | |
1838 GetButtonInfo((int)lpTBCustomDraw->nmcd.
dwItemSpec, &tbbi); | |
1839 dc.DrawText(szText, -1, &lpTBCustomDraw-
>nmcd.rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT
_HIDEPREFIX)); | |
1840 if(hFont != NULL) | |
1841 dc.SelectFont(hFontOld); | |
1842 lRet = CDRF_SKIPDEFAULT; | |
1843 bHandled = TRUE; | |
1844 } | |
1845 else if(!m_bParentActive) | |
1846 { | |
1847 lpTBCustomDraw->clrText = ::GetSysColor(
COLOR_GRAYTEXT); | |
1848 bHandled = TRUE; | |
1849 } | |
1850 } | |
1851 } | |
1852 return lRet; | |
1853 } | |
1854 | |
1855 // Message hook handlers | |
1856 LRESULT OnHookMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPara
m*/, BOOL& bHandled) | |
1857 { | |
1858 static POINT s_point = { -1, -1 }; | |
1859 DWORD dwPoint = ::GetMessagePos(); | |
1860 POINT point = { GET_X_LPARAM(dwPoint), GET_Y_LPARAM(dwPoint) }; | |
1861 | |
1862 bHandled = FALSE; | |
1863 if(m_bMenuActive) | |
1864 { | |
1865 if(::WindowFromPoint(point) == m_hWnd) | |
1866 { | |
1867 ScreenToClient(&point); | |
1868 int nHit = HitTest(&point); | |
1869 | |
1870 if((point.x != s_point.x || point.y != s_point.y
) && nHit >= 0 && nHit < ::GetMenuItemCount(m_hMenu) && nHit != m_nPopBtn && m_n
PopBtn != -1) | |
1871 { | |
1872 TBBUTTON tbb = { 0 }; | |
1873 GetButton(nHit, &tbb); | |
1874 if((tbb.fsState & TBSTATE_ENABLED) != 0) | |
1875 { | |
1876 m_nNextPopBtn = nHit | 0xFFFF000
0; | |
1877 HWND hWndMenu = m_stackMenuWnd.G
etCurrent(); | |
1878 ATLASSERT(hWndMenu != NULL); | |
1879 | |
1880 // this one is needed to close a
menu if mouse button was down | |
1881 ::PostMessage(hWndMenu, WM_LBUTT
ONUP, 0, MAKELPARAM(point.x, point.y)); | |
1882 // this one closes a popup menu | |
1883 ::PostMessage(hWndMenu, WM_KEYDO
WN, VK_ESCAPE, 0L); | |
1884 | |
1885 bHandled = TRUE; | |
1886 } | |
1887 } | |
1888 } | |
1889 } | |
1890 else | |
1891 { | |
1892 ScreenToClient(&point); | |
1893 } | |
1894 | |
1895 s_point = point; | |
1896 return 0; | |
1897 } | |
1898 | |
1899 LRESULT OnHookSysKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/
, BOOL& bHandled) | |
1900 { | |
1901 bHandled = FALSE; | |
1902 #ifdef _CMDBAR_EXTRA_TRACE | |
1903 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSKEYDOWN (0x%2.2
X)\n"), wParam); | |
1904 #endif | |
1905 | |
1906 if(wParam == VK_MENU && m_bParentActive && m_bUseKeyboardCues &&
!m_bShowKeyboardCues && m_bAllowKeyboardCues) | |
1907 ShowKeyboardCues(true); | |
1908 | |
1909 if(wParam != VK_SPACE && !m_bMenuActive && ::GetFocus() == m_hWn
d) | |
1910 { | |
1911 m_bAllowKeyboardCues = false; | |
1912 PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); | |
1913 T* pT = static_cast<T*>(this); | |
1914 pT->GiveFocusBack(); | |
1915 m_bSkipMsg = true; | |
1916 } | |
1917 else | |
1918 { | |
1919 if(wParam == VK_SPACE && m_bUseKeyboardCues && m_bShowKe
yboardCues) | |
1920 { | |
1921 m_bAllowKeyboardCues = true; | |
1922 ShowKeyboardCues(false); | |
1923 } | |
1924 m_uSysKey = (UINT)wParam; | |
1925 } | |
1926 return 0; | |
1927 } | |
1928 | |
1929 LRESULT OnHookSysKeyUp(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/,
BOOL& bHandled) | |
1930 { | |
1931 if(!m_bAllowKeyboardCues) | |
1932 m_bAllowKeyboardCues = true; | |
1933 bHandled = FALSE; | |
1934 wParam; | |
1935 #ifdef _CMDBAR_EXTRA_TRACE | |
1936 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSKEYUP (0x%2.2X)
\n"), wParam); | |
1937 #endif | |
1938 return 0; | |
1939 } | |
1940 | |
1941 LRESULT OnHookSysChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, B
OOL& bHandled) | |
1942 { | |
1943 bHandled = FALSE; | |
1944 #ifdef _CMDBAR_EXTRA_TRACE | |
1945 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_SYSCHAR (0x%2.2X)\
n"), wParam); | |
1946 #endif | |
1947 | |
1948 if(!m_bMenuActive && m_hWndHook != m_hWnd && wParam != VK_SPACE) | |
1949 bHandled = TRUE; | |
1950 return 0; | |
1951 } | |
1952 | |
1953 LRESULT OnHookKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, B
OOL& bHandled) | |
1954 { | |
1955 #ifdef _CMDBAR_EXTRA_TRACE | |
1956 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_KEYDOWN (0x%2.2X)\
n"), wParam); | |
1957 #endif | |
1958 bHandled = FALSE; | |
1959 T* pT = static_cast<T*>(this); | |
1960 | |
1961 if(wParam == VK_ESCAPE && m_stackMenuWnd.GetSize() <= 1) | |
1962 { | |
1963 if(m_bMenuActive && !m_bContextMenu) | |
1964 { | |
1965 int nHot = GetHotItem(); | |
1966 if(nHot == -1) | |
1967 nHot = m_nPopBtn; | |
1968 if(nHot == -1) | |
1969 nHot = 0; | |
1970 SetHotItem(nHot); | |
1971 bHandled = TRUE; | |
1972 pT->TakeFocus(); | |
1973 m_bEscapePressed = true; // To keep focus | |
1974 m_bSkipPostDown = false; | |
1975 } | |
1976 else if(::GetFocus() == m_hWnd && m_wndParent.IsWindow()
) | |
1977 { | |
1978 SetHotItem(-1); | |
1979 pT->GiveFocusBack(); | |
1980 bHandled = TRUE; | |
1981 } | |
1982 } | |
1983 else if(wParam == VK_RETURN || wParam == VK_UP || wParam == VK_D
OWN) | |
1984 { | |
1985 if(!m_bMenuActive && ::GetFocus() == m_hWnd && m_wndPare
nt.IsWindow()) | |
1986 { | |
1987 int nHot = GetHotItem(); | |
1988 if(nHot != -1) | |
1989 { | |
1990 if(wParam != VK_RETURN) | |
1991 { | |
1992 if(!m_bSkipPostDown) | |
1993 { | |
1994 // IE4 only: WM_KEYDOWN doesn't generate TBN_DROPDOWN, we need to simulate a mou
se click | |
1995 #if (_WIN32_IE < 0x0500) | |
1996 DWORD dwMajor = 0, dwMin
or = 0; | |
1997 ATL::AtlGetCommCtrlVersi
on(&dwMajor, &dwMinor); | |
1998 if(dwMajor <= 4 || (dwMa
jor == 5 && dwMinor < 80)) | |
1999 { | |
2000 RECT rect; | |
2001 GetItemRect(nHot
, &rect); | |
2002 PostMessage(WM_L
BUTTONDOWN, MK_LBUTTON, MAKELPARAM(rect.left, rect.top)); | |
2003 } | |
2004 #endif // (_WIN32_IE < 0x0500) | |
2005 PostMessage(WM_KEYDOWN,
VK_DOWN, 0L); | |
2006 m_bSkipPostDown = true; | |
2007 } | |
2008 else | |
2009 { | |
2010 ATLTRACE2(atlTraceUI, 0,
_T("CmdBar - skipping posting another VK_DOWN\n")); | |
2011 m_bSkipPostDown = false; | |
2012 } | |
2013 } | |
2014 } | |
2015 else | |
2016 { | |
2017 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Ca
n't find hot button\n")); | |
2018 } | |
2019 } | |
2020 if(wParam == VK_RETURN && m_bMenuActive) | |
2021 { | |
2022 PostMessage(TB_SETHOTITEM, (WPARAM)-1, 0L); | |
2023 m_nNextPopBtn = -1; | |
2024 pT->GiveFocusBack(); | |
2025 } | |
2026 } | |
2027 else if(wParam == VK_LEFT || wParam == VK_RIGHT) | |
2028 { | |
2029 WPARAM wpNext = m_bLayoutRTL ? VK_LEFT : VK_RIGHT; | |
2030 WPARAM wpPrev = m_bLayoutRTL ? VK_RIGHT : VK_LEFT; | |
2031 | |
2032 if(m_bMenuActive && !m_bContextMenu && !(wParam == wpNex
t && m_bPopupItem)) | |
2033 { | |
2034 bool bAction = false; | |
2035 if(wParam == wpPrev && s_pCurrentBar->m_stackMen
uWnd.GetSize() == 1) | |
2036 { | |
2037 m_nNextPopBtn = pT->GetPreviousMenuItem(
m_nPopBtn); | |
2038 if(m_nNextPopBtn != -1) | |
2039 bAction = true; | |
2040 } | |
2041 else if(wParam == wpNext) | |
2042 { | |
2043 m_nNextPopBtn = pT->GetNextMenuItem(m_nP
opBtn); | |
2044 if(m_nNextPopBtn != -1) | |
2045 bAction = true; | |
2046 } | |
2047 HWND hWndMenu = m_stackMenuWnd.GetCurrent(); | |
2048 ATLASSERT(hWndMenu != NULL); | |
2049 | |
2050 // Close the popup menu | |
2051 if(bAction) | |
2052 { | |
2053 ::PostMessage(hWndMenu, WM_KEYDOWN, VK_E
SCAPE, 0L); | |
2054 if(wParam == wpNext) | |
2055 { | |
2056 int cItem = m_stackMenuWnd.GetSi
ze() - 1; | |
2057 while(cItem >= 0) | |
2058 { | |
2059 hWndMenu = m_stackMenuWn
d[cItem]; | |
2060 if(hWndMenu != NULL) | |
2061 ::PostMessage(hW
ndMenu, WM_KEYDOWN, VK_ESCAPE, 0L); | |
2062 cItem--; | |
2063 } | |
2064 } | |
2065 #if (_WIN32_IE >= 0x0500) | |
2066 if(m_nNextPopBtn == -2) | |
2067 { | |
2068 m_nNextPopBtn = -1; | |
2069 pT->DisplayChevronMenu(); | |
2070 } | |
2071 #endif // (_WIN32_IE >= 0x0500) | |
2072 bHandled = TRUE; | |
2073 } | |
2074 } | |
2075 } | |
2076 return 0; | |
2077 } | |
2078 | |
2079 LRESULT OnHookNextMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam
*/, BOOL& bHandled) | |
2080 { | |
2081 #ifdef _CMDBAR_EXTRA_TRACE | |
2082 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_NEXTMENU\n")); | |
2083 #endif | |
2084 bHandled = FALSE; | |
2085 return 1; | |
2086 } | |
2087 | |
2088 LRESULT OnHookChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL
& bHandled) | |
2089 { | |
2090 #ifdef _CMDBAR_EXTRA_TRACE | |
2091 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Hook WM_CHAR (0x%2.2X)\n")
, wParam); | |
2092 #endif | |
2093 bHandled = (wParam == VK_ESCAPE); | |
2094 return 0; | |
2095 } | |
2096 | |
2097 // Implementation - ownerdraw overrideables and helpers | |
2098 void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) | |
2099 { | |
2100 T* pT = static_cast<T*>(this); | |
2101 if(m_bFlatMenus) | |
2102 pT->DrawItemFlat(lpDrawItemStruct); | |
2103 else | |
2104 pT->DrawItem3D(lpDrawItemStruct); | |
2105 | |
2106 } | |
2107 | |
2108 void DrawItem3D(LPDRAWITEMSTRUCT lpDrawItemStruct) | |
2109 { | |
2110 _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData; | |
2111 CDCHandle dc = lpDrawItemStruct->hDC; | |
2112 const RECT& rcItem = lpDrawItemStruct->rcItem; | |
2113 T* pT = static_cast<T*>(this); | |
2114 | |
2115 if(pmd->fType & MFT_SEPARATOR) | |
2116 { | |
2117 // draw separator | |
2118 RECT rc = rcItem; | |
2119 rc.top += (rc.bottom - rc.top) / 2; // vertical cen
ter | |
2120 dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separat
or line | |
2121 } | |
2122 else // not a separator | |
2123 { | |
2124 BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYE
D; | |
2125 BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELEC
TED; | |
2126 BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKE
D; | |
2127 BOOL bHasImage = FALSE; | |
2128 | |
2129 if(LOWORD(lpDrawItemStruct->itemID) == (WORD)-1) | |
2130 bSelected = FALSE; | |
2131 RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m
_szButton.cx, rcItem.top + m_szButton.cy }; // button rect | |
2132 ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) -
(rcButn.bottom - rcButn.top)) / 2); // center vertically | |
2133 | |
2134 int iButton = pmd->iButton; | |
2135 if(iButton >= 0) | |
2136 { | |
2137 bHasImage = TRUE; | |
2138 | |
2139 // calc drawing point | |
2140 SIZE sz = { rcButn.right - rcButn.left - m_szBit
map.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy }; | |
2141 sz.cx /= 2; | |
2142 sz.cy /= 2; | |
2143 POINT point = { rcButn.left + sz.cx, rcButn.top
+ sz.cy }; | |
2144 | |
2145 // fill background depending on state | |
2146 if(!bChecked || (bSelected && !bDisabled)) | |
2147 { | |
2148 if(!bDisabled) | |
2149 dc.FillRect(&rcButn, (bChecked &
& !bSelected) ? COLOR_3DLIGHT : COLOR_MENU); | |
2150 else | |
2151 dc.FillRect(&rcButn, COLOR_MENU)
; | |
2152 } | |
2153 else | |
2154 { | |
2155 COLORREF crTxt = dc.SetTextColor(::GetSy
sColor(COLOR_BTNFACE)); | |
2156 COLORREF crBk = dc.SetBkColor(::GetSysCo
lor(COLOR_BTNHILIGHT)); | |
2157 CBrush hbr(CDCHandle::GetHalftoneBrush()
); | |
2158 dc.SetBrushOrg(rcButn.left, rcButn.top); | |
2159 dc.FillRect(&rcButn, hbr); | |
2160 dc.SetTextColor(crTxt); | |
2161 dc.SetBkColor(crBk); | |
2162 } | |
2163 | |
2164 // draw disabled or normal | |
2165 if(!bDisabled) | |
2166 { | |
2167 // draw pushed-in or popped-out edge | |
2168 if(bSelected || bChecked) | |
2169 { | |
2170 RECT rc2 = rcButn; | |
2171 dc.DrawEdge(&rc2, bChecked ? BDR
_SUNKENOUTER : BDR_RAISEDINNER, BF_RECT); | |
2172 } | |
2173 // draw the image | |
2174 ::ImageList_Draw(m_hImageList, iButton,
dc, point.x, point.y, ILD_TRANSPARENT); | |
2175 } | |
2176 else | |
2177 { | |
2178 HBRUSH hBrushBackground = bChecked ? NUL
L : ::GetSysColorBrush(COLOR_MENU); | |
2179 pT->DrawBitmapDisabled(dc, iButton, poin
t, hBrushBackground); | |
2180 } | |
2181 } | |
2182 else | |
2183 { | |
2184 // no image - look for custom checked/unchecked
bitmaps | |
2185 CMenuItemInfo info; | |
2186 info.fMask = MIIM_CHECKMARKS | MIIM_TYPE; | |
2187 ::GetMenuItemInfo((HMENU)lpDrawItemStruct->hwndI
tem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info); | |
2188 if(bChecked || info.hbmpUnchecked != NULL) | |
2189 { | |
2190 BOOL bRadio = ((info.fType & MFT_RADIOCH
ECK) != 0); | |
2191 bHasImage = pT->DrawCheckmark(dc, rcButn
, bSelected, bDisabled, bRadio, bChecked ? info.hbmpChecked : info.hbmpUnchecked
); | |
2192 } | |
2193 } | |
2194 | |
2195 // draw item text | |
2196 int cxButn = m_szButton.cx; | |
2197 COLORREF colorBG = ::GetSysColor(bSelected ? COLOR_HIGHL
IGHT : COLOR_MENU); | |
2198 if(bSelected || lpDrawItemStruct->itemAction == ODA_SELE
CT) | |
2199 { | |
2200 RECT rcBG = rcItem; | |
2201 if(bHasImage) | |
2202 rcBG.left += cxButn + s_kcxGap; | |
2203 dc.FillRect(&rcBG, bSelected ? COLOR_HIGHLIGHT :
COLOR_MENU); | |
2204 } | |
2205 | |
2206 // calc text rectangle and colors | |
2207 RECT rcText = rcItem; | |
2208 rcText.left += cxButn + s_kcxGap + s_kcxTextMargin; | |
2209 rcText.right -= cxButn; | |
2210 dc.SetBkMode(TRANSPARENT); | |
2211 COLORREF colorText = ::GetSysColor(bDisabled ? (bSelect
ed ? COLOR_GRAYTEXT : COLOR_3DSHADOW) : (bSelected ? COLOR_HIGHLIGHTTEXT : COLOR
_MENUTEXT)); | |
2212 | |
2213 // font already selected by Windows | |
2214 if(bDisabled && (!bSelected || colorText == colorBG)) | |
2215 { | |
2216 // disabled - draw shadow text shifted down and
right 1 pixel (unles selected) | |
2217 RECT rcDisabled = rcText; | |
2218 ::OffsetRect(&rcDisabled, 1, 1); | |
2219 pT->DrawMenuText(dc, rcDisabled, pmd->lpstrText,
::GetSysColor(COLOR_3DHILIGHT)); | |
2220 } | |
2221 pT->DrawMenuText(dc, rcText, pmd->lpstrText, colorText);
// finally! | |
2222 } | |
2223 } | |
2224 | |
2225 void DrawItemFlat(LPDRAWITEMSTRUCT lpDrawItemStruct) | |
2226 { | |
2227 _MenuItemData* pmd = (_MenuItemData*)lpDrawItemStruct->itemData; | |
2228 CDCHandle dc = lpDrawItemStruct->hDC; | |
2229 const RECT& rcItem = lpDrawItemStruct->rcItem; | |
2230 T* pT = static_cast<T*>(this); | |
2231 | |
2232 #ifndef COLOR_MENUHILIGHT | |
2233 const int COLOR_MENUHILIGHT = 29; | |
2234 #endif // !COLOR_MENUHILIGHT | |
2235 | |
2236 BOOL bDisabled = lpDrawItemStruct->itemState & ODS_GRAYED; | |
2237 BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED; | |
2238 BOOL bChecked = lpDrawItemStruct->itemState & ODS_CHECKED; | |
2239 | |
2240 // paint background | |
2241 if(bSelected || lpDrawItemStruct->itemAction == ODA_SELECT) | |
2242 { | |
2243 if(bSelected) | |
2244 { | |
2245 dc.FillRect(&rcItem, ::GetSysColorBrush(COLOR_ME
NUHILIGHT)); | |
2246 dc.FrameRect(&rcItem, ::GetSysColorBrush(COLOR_H
IGHLIGHT)); | |
2247 } | |
2248 else | |
2249 { | |
2250 dc.FillRect(&rcItem, ::GetSysColorBrush(COLOR_ME
NU)); | |
2251 } | |
2252 } | |
2253 | |
2254 if(pmd->fType & MFT_SEPARATOR) | |
2255 { | |
2256 // draw separator | |
2257 RECT rc = rcItem; | |
2258 rc.top += (rc.bottom - rc.top) / 2; // vertical cen
ter | |
2259 dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separat
or line | |
2260 } | |
2261 else // not a separator | |
2262 { | |
2263 if(LOWORD(lpDrawItemStruct->itemID) == (WORD)-1) | |
2264 bSelected = FALSE; | |
2265 RECT rcButn = { rcItem.left, rcItem.top, rcItem.left + m
_szButton.cx, rcItem.top + m_szButton.cy }; // button rect | |
2266 ::OffsetRect(&rcButn, 0, ((rcItem.bottom - rcItem.top) -
(rcButn.bottom - rcButn.top)) / 2); // center vertically | |
2267 | |
2268 // draw background and border for checked items | |
2269 if(bChecked) | |
2270 { | |
2271 RECT rcCheck = rcButn; | |
2272 ::InflateRect(&rcCheck, -1, -1); | |
2273 if(bSelected) | |
2274 dc.FillRect(&rcCheck, ::GetSysColorBrush
(COLOR_MENU)); | |
2275 dc.FrameRect(&rcCheck, ::GetSysColorBrush(COLOR_
HIGHLIGHT)); | |
2276 } | |
2277 | |
2278 int iButton = pmd->iButton; | |
2279 if(iButton >= 0) | |
2280 { | |
2281 // calc drawing point | |
2282 SIZE sz = { rcButn.right - rcButn.left - m_szBit
map.cx, rcButn.bottom - rcButn.top - m_szBitmap.cy }; | |
2283 sz.cx /= 2; | |
2284 sz.cy /= 2; | |
2285 POINT point = { rcButn.left + sz.cx, rcButn.top
+ sz.cy }; | |
2286 | |
2287 // draw disabled or normal | |
2288 if(!bDisabled) | |
2289 { | |
2290 ::ImageList_Draw(m_hImageList, iButton,
dc, point.x, point.y, ILD_TRANSPARENT); | |
2291 } | |
2292 else | |
2293 { | |
2294 HBRUSH hBrushBackground = ::GetSysColorB
rush((bSelected && !(bDisabled && bChecked)) ? COLOR_MENUHILIGHT : COLOR_MENU); | |
2295 HBRUSH hBrushDisabledImage = ::GetSysCol
orBrush(COLOR_3DSHADOW); | |
2296 pT->DrawBitmapDisabled(dc, iButton, poin
t, hBrushBackground, hBrushBackground, hBrushDisabledImage); | |
2297 } | |
2298 } | |
2299 else | |
2300 { | |
2301 // no image - look for custom checked/unchecked
bitmaps | |
2302 CMenuItemInfo info; | |
2303 info.fMask = MIIM_CHECKMARKS | MIIM_TYPE; | |
2304 ::GetMenuItemInfo((HMENU)lpDrawItemStruct->hwndI
tem, lpDrawItemStruct->itemID, MF_BYCOMMAND, &info); | |
2305 if(bChecked || info.hbmpUnchecked != NULL) | |
2306 { | |
2307 BOOL bRadio = ((info.fType & MFT_RADIOCH
ECK) != 0); | |
2308 pT->DrawCheckmark(dc, rcButn, bSelected,
bDisabled, bRadio, bChecked ? info.hbmpChecked : info.hbmpUnchecked); | |
2309 } | |
2310 } | |
2311 | |
2312 // draw item text | |
2313 int cxButn = m_szButton.cx; | |
2314 // calc text rectangle and colors | |
2315 RECT rcText = rcItem; | |
2316 rcText.left += cxButn + s_kcxGap + s_kcxTextMargin; | |
2317 rcText.right -= cxButn; | |
2318 dc.SetBkMode(TRANSPARENT); | |
2319 COLORREF colorText = ::GetSysColor(bDisabled ? (bSelect
ed ? COLOR_GRAYTEXT : COLOR_3DSHADOW) : (bSelected ? COLOR_HIGHLIGHTTEXT : COLOR
_MENUTEXT)); | |
2320 | |
2321 pT->DrawMenuText(dc, rcText, pmd->lpstrText, colorText);
// finally! | |
2322 } | |
2323 } | |
2324 | |
2325 void DrawMenuText(CDCHandle& dc, RECT& rc, LPCTSTR lpstrText, COLORREF c
olor) | |
2326 { | |
2327 int nTab = -1; | |
2328 for(int i = 0; i < lstrlen(lpstrText); i++) | |
2329 { | |
2330 if(lpstrText[i] == _T('\t')) | |
2331 { | |
2332 nTab = i; | |
2333 break; | |
2334 } | |
2335 } | |
2336 dc.SetTextColor(color); | |
2337 dc.DrawText(lpstrText, nTab, &rc, DT_SINGLELINE | DT_LEFT | DT_V
CENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX)); | |
2338 if(nTab != -1) | |
2339 dc.DrawText(&lpstrText[nTab + 1], -1, &rc, DT_SINGLELINE
| DT_RIGHT | DT_VCENTER | (m_bShowKeyboardCues ? 0 : DT_HIDEPREFIX)); | |
2340 } | |
2341 | |
2342 void DrawBitmapDisabled(CDCHandle& dc, int nImage, POINT point, | |
2343 HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFAC
E), | |
2344 HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIG
HT), | |
2345 HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3D
SHADOW)) | |
2346 { | |
2347 #if (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501) | |
2348 if(m_bAlphaImages) | |
2349 { | |
2350 IMAGELISTDRAWPARAMS ildp = { 0 }; | |
2351 ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS); | |
2352 ildp.himl = m_hImageList; | |
2353 ildp.i = nImage; | |
2354 ildp.hdcDst = dc; | |
2355 ildp.x = point.x; | |
2356 ildp.y = point.y; | |
2357 ildp.cx = 0; | |
2358 ildp.cy = 0; | |
2359 ildp.xBitmap = 0; | |
2360 ildp.yBitmap = 0; | |
2361 ildp.fStyle = ILD_TRANSPARENT; | |
2362 ildp.fState = ILS_SATURATE; | |
2363 ildp.Frame = 0; | |
2364 ::ImageList_DrawIndirect(&ildp); | |
2365 } | |
2366 else | |
2367 #endif // (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501) | |
2368 { | |
2369 // create memory DC | |
2370 CDC dcMem; | |
2371 dcMem.CreateCompatibleDC(dc); | |
2372 // create mono or color bitmap | |
2373 CBitmap bmp; | |
2374 bmp.CreateCompatibleBitmap(dc, m_szBitmap.cx, m_szBitmap
.cy); | |
2375 ATLASSERT(bmp.m_hBitmap != NULL); | |
2376 // draw image into memory DC--fill BG white first | |
2377 HBITMAP hBmpOld = dcMem.SelectBitmap(bmp); | |
2378 dcMem.PatBlt(0, 0, m_szBitmap.cx, m_szBitmap.cy, WHITENE
SS); | |
2379 // If white is the text color, we can't use the normal p
ainting since | |
2380 // it would blend with the WHITENESS, but the mask is OK | |
2381 UINT uDrawStyle = (::GetSysColor(COLOR_BTNTEXT) == RGB(2
55, 255, 255)) ? ILD_MASK : ILD_NORMAL; | |
2382 ::ImageList_Draw(m_hImageList, nImage, dcMem, 0, 0, uDra
wStyle); | |
2383 dc.DitherBlt(point.x, point.y, m_szBitmap.cx, m_szBitmap
.cy, dcMem, NULL, 0, 0, hBrushBackground, hBrush3DEffect, hBrushDisabledImage); | |
2384 dcMem.SelectBitmap(hBmpOld); // restore | |
2385 } | |
2386 } | |
2387 | |
2388 // old name | |
2389 BOOL Draw3DCheckmark(CDCHandle& dc, const RECT& rc, BOOL bSelected, BOOL
bDisabled, BOOL bRadio, HBITMAP hBmpCheck) | |
2390 { | |
2391 return DrawCheckmark(dc, rc, bSelected, bDisabled, bRadio, hBmpC
heck); | |
2392 } | |
2393 | |
2394 BOOL DrawCheckmark(CDCHandle& dc, const RECT& rc, BOOL bSelected, BOOL b
Disabled, BOOL bRadio, HBITMAP hBmpCheck) | |
2395 { | |
2396 // get checkmark bitmap, if none, use Windows standard | |
2397 SIZE size = { 0, 0 }; | |
2398 CBitmapHandle bmp = hBmpCheck; | |
2399 if(hBmpCheck != NULL) | |
2400 { | |
2401 bmp.GetSize(size); | |
2402 } | |
2403 else | |
2404 { | |
2405 size.cx = ::GetSystemMetrics(SM_CXMENUCHECK); | |
2406 size.cy = ::GetSystemMetrics(SM_CYMENUCHECK); | |
2407 bmp.CreateCompatibleBitmap(dc, size.cx, size.cy); | |
2408 ATLASSERT(bmp.m_hBitmap != NULL); | |
2409 } | |
2410 // center bitmap in caller's rectangle | |
2411 RECT rcDest = rc; | |
2412 if((rc.right - rc.left) > size.cx) | |
2413 { | |
2414 rcDest.left = rc.left + (rc.right - rc.left - size.cx) /
2; | |
2415 rcDest.right = rcDest.left + size.cx; | |
2416 } | |
2417 if((rc.bottom - rc.top) > size.cy) | |
2418 { | |
2419 rcDest.top = rc.top + (rc.bottom - rc.top - size.cy) / 2
; | |
2420 rcDest.bottom = rcDest.top + size.cy; | |
2421 } | |
2422 // paint background | |
2423 if(!m_bFlatMenus) | |
2424 { | |
2425 if(bSelected && !bDisabled) | |
2426 { | |
2427 dc.FillRect(&rcDest, COLOR_MENU); | |
2428 } | |
2429 else | |
2430 { | |
2431 COLORREF clrTextOld = dc.SetTextColor(::GetSysCo
lor(COLOR_BTNFACE)); | |
2432 COLORREF clrBkOld = dc.SetBkColor(::GetSysColor(
COLOR_BTNHILIGHT)); | |
2433 CBrush hbr(CDCHandle::GetHalftoneBrush()); | |
2434 dc.SetBrushOrg(rcDest.left, rcDest.top); | |
2435 dc.FillRect(&rcDest, hbr); | |
2436 dc.SetTextColor(clrTextOld); | |
2437 dc.SetBkColor(clrBkOld); | |
2438 } | |
2439 } | |
2440 | |
2441 // create source image | |
2442 CDC dcSource; | |
2443 dcSource.CreateCompatibleDC(dc); | |
2444 HBITMAP hBmpOld = dcSource.SelectBitmap(bmp); | |
2445 // set colors | |
2446 const COLORREF clrBlack = RGB(0, 0, 0); | |
2447 const COLORREF clrWhite = RGB(255, 255, 255); | |
2448 COLORREF clrTextOld = dc.SetTextColor(clrBlack); | |
2449 COLORREF clrBkOld = dc.SetBkColor(clrWhite); | |
2450 // create mask | |
2451 CDC dcMask; | |
2452 dcMask.CreateCompatibleDC(dc); | |
2453 CBitmap bmpMask; | |
2454 bmpMask.CreateBitmap(size.cx, size.cy, 1, 1, NULL); | |
2455 HBITMAP hBmpOld1 = dcMask.SelectBitmap(bmpMask); | |
2456 | |
2457 // draw the checkmark transparently | |
2458 int cx = rcDest.right - rcDest.left; | |
2459 int cy = rcDest.bottom - rcDest.top; | |
2460 if(hBmpCheck != NULL) | |
2461 { | |
2462 // build mask based on transparent color | |
2463 dcSource.SetBkColor(m_clrMask); | |
2464 dcMask.SetBkColor(clrBlack); | |
2465 dcMask.SetTextColor(clrWhite); | |
2466 dcMask.BitBlt(0, 0, size.cx, size.cy, dcSource, 0, 0, SR
CCOPY); | |
2467 // draw bitmap using the mask | |
2468 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0,
0, SRCINVERT); | |
2469 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMask, 0, 0,
SRCAND); | |
2470 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSource, 0,
0, SRCINVERT); | |
2471 } | |
2472 else | |
2473 { | |
2474 const DWORD ROP_DSno = 0x00BB0226L; | |
2475 const DWORD ROP_DSa = 0x008800C6L; | |
2476 const DWORD ROP_DSo = 0x00EE0086L; | |
2477 const DWORD ROP_DSna = 0x00220326L; | |
2478 | |
2479 // draw mask | |
2480 RECT rcSource = { 0, 0, __min(size.cx, rc.right - rc.lef
t), __min(size.cy, rc.bottom - rc.top) }; | |
2481 dcMask.DrawFrameControl(&rcSource, DFC_MENU, bRadio ? DF
CS_MENUBULLET : DFCS_MENUCHECK); | |
2482 | |
2483 // draw shadow if disabled | |
2484 if(!m_bFlatMenus && bDisabled) | |
2485 { | |
2486 // offset by one pixel | |
2487 int x = rcDest.left + 1; | |
2488 int y = rcDest.top + 1; | |
2489 // paint source bitmap | |
2490 const int nColor = COLOR_3DHILIGHT; | |
2491 dcSource.FillRect(&rcSource, nColor); | |
2492 // draw checkmark - special case black and white
colors | |
2493 COLORREF clrCheck = ::GetSysColor(nColor); | |
2494 if(clrCheck == clrWhite) | |
2495 { | |
2496 dc.BitBlt(x, y, cx, cy, dcMask, 0, 0,
ROP_DSno); | |
2497 dc.BitBlt(x, y, cx, cy, dcSource, 0, 0,
ROP_DSa); | |
2498 } | |
2499 else | |
2500 { | |
2501 if(clrCheck != clrBlack) | |
2502 { | |
2503 ATLASSERT(dcSource.GetTextColor(
) == clrBlack); | |
2504 ATLASSERT(dcSource.GetBkColor()
== clrWhite); | |
2505 dcSource.BitBlt(0, 0, size.cx, s
ize.cy, dcMask, 0, 0, ROP_DSna); | |
2506 } | |
2507 dc.BitBlt(x, y, cx, cy, dcMask, 0, 0,
ROP_DSa); | |
2508 dc.BitBlt(x, y, cx, cy, dcSource, 0, 0,
ROP_DSo); | |
2509 } | |
2510 } | |
2511 | |
2512 // paint source bitmap | |
2513 const int nColor = bDisabled ? COLOR_BTNSHADOW : COLOR_M
ENUTEXT; | |
2514 dcSource.FillRect(&rcSource, nColor); | |
2515 // draw checkmark - special case black and white colors | |
2516 COLORREF clrCheck = ::GetSysColor(nColor); | |
2517 if(clrCheck == clrWhite) | |
2518 { | |
2519 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMas
k, 0, 0, ROP_DSno); | |
2520 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSou
rce, 0, 0, ROP_DSa); | |
2521 } | |
2522 else | |
2523 { | |
2524 if(clrCheck != clrBlack) | |
2525 { | |
2526 ATLASSERT(dcSource.GetTextColor() == clr
Black); | |
2527 ATLASSERT(dcSource.GetBkColor() == clrWh
ite); | |
2528 dcSource.BitBlt(0, 0, size.cx, size.cy,
dcMask, 0, 0, ROP_DSna); | |
2529 } | |
2530 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcMas
k, 0, 0, ROP_DSa); | |
2531 dc.BitBlt(rcDest.left, rcDest.top, cx, cy, dcSou
rce, 0, 0, ROP_DSo); | |
2532 } | |
2533 } | |
2534 // restore all | |
2535 dc.SetTextColor(clrTextOld); | |
2536 dc.SetBkColor(clrBkOld); | |
2537 dcSource.SelectBitmap(hBmpOld); | |
2538 dcMask.SelectBitmap(hBmpOld1); | |
2539 if(hBmpCheck == NULL) | |
2540 bmp.DeleteObject(); | |
2541 // draw pushed-in hilight | |
2542 if(!m_bFlatMenus && !bDisabled) | |
2543 { | |
2544 if(rc.right - rc.left > size.cx) | |
2545 ::InflateRect(&rcDest, 1,1); // inflate checkm
ark by one pixel all around | |
2546 dc.DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT); | |
2547 } | |
2548 | |
2549 return TRUE; | |
2550 } | |
2551 | |
2552 void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) | |
2553 { | |
2554 _MenuItemData* pmd = (_MenuItemData*)lpMeasureItemStruct->itemDa
ta; | |
2555 | |
2556 if(pmd->fType & MFT_SEPARATOR) // separator - use half system
height and zero width | |
2557 { | |
2558 lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_
CYMENU) / 2; | |
2559 lpMeasureItemStruct->itemWidth = 0; | |
2560 } | |
2561 else | |
2562 { | |
2563 // compute size of text - use DrawText with DT_CALCRECT | |
2564 CWindowDC dc(NULL); | |
2565 CFont fontBold; | |
2566 HFONT hOldFont = NULL; | |
2567 if(pmd->fState & MFS_DEFAULT) | |
2568 { | |
2569 // need bold version of font | |
2570 LOGFONT lf = { 0 }; | |
2571 m_fontMenu.GetLogFont(lf); | |
2572 lf.lfWeight += 200; | |
2573 fontBold.CreateFontIndirect(&lf); | |
2574 ATLASSERT(fontBold.m_hFont != NULL); | |
2575 hOldFont = dc.SelectFont(fontBold); | |
2576 } | |
2577 else | |
2578 { | |
2579 hOldFont = dc.SelectFont(m_fontMenu); | |
2580 } | |
2581 | |
2582 RECT rcText = { 0, 0, 0, 0 }; | |
2583 dc.DrawText(pmd->lpstrText, -1, &rcText, DT_SINGLELINE |
DT_LEFT | DT_VCENTER | DT_CALCRECT); | |
2584 int cx = rcText.right - rcText.left; | |
2585 dc.SelectFont(hOldFont); | |
2586 | |
2587 LOGFONT lf = { 0 }; | |
2588 m_fontMenu.GetLogFont(lf); | |
2589 int cy = lf.lfHeight; | |
2590 if(cy < 0) | |
2591 cy = -cy; | |
2592 const int cyMargin = 8; | |
2593 cy += cyMargin; | |
2594 | |
2595 // height of item is the bigger of these two | |
2596 lpMeasureItemStruct->itemHeight = __max(cy, (int)m_szBut
ton.cy); | |
2597 | |
2598 // width is width of text plus a bunch of stuff | |
2599 cx += 2 * s_kcxTextMargin; // L/R margin for readabili
ty | |
2600 cx += s_kcxGap; // space between button and
menu text | |
2601 cx += 2 * m_szButton.cx; // button width (L=button;
R=empty margin) | |
2602 cx += m_cxExtraSpacing; // extra between item text
and accelerator keys | |
2603 | |
2604 // Windows adds 1 to returned value | |
2605 cx -= ::GetSystemMetrics(SM_CXMENUCHECK) - 1; | |
2606 lpMeasureItemStruct->itemWidth = cx; // done deal | |
2607 } | |
2608 } | |
2609 | |
2610 // Implementation - Hook procs | |
2611 static LRESULT CALLBACK CreateHookProc(int nCode, WPARAM wParam, LPARAM
lParam) | |
2612 { | |
2613 const int cchClassName = 7; | |
2614 TCHAR szClassName[cchClassName] = { 0 }; | |
2615 | |
2616 if(nCode == HCBT_CREATEWND) | |
2617 { | |
2618 HWND hWndMenu = (HWND)wParam; | |
2619 #ifdef _CMDBAR_EXTRA_TRACE | |
2620 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - HCBT_CREATEWND (HW
ND = %8.8X)\n"), hWndMenu); | |
2621 #endif | |
2622 | |
2623 ::GetClassName(hWndMenu, szClassName, cchClassName); | |
2624 if(!lstrcmp(_T("#32768"), szClassName)) | |
2625 s_pCurrentBar->m_stackMenuWnd.Push(hWndMenu); | |
2626 } | |
2627 else if(nCode == HCBT_DESTROYWND) | |
2628 { | |
2629 HWND hWndMenu = (HWND)wParam; | |
2630 #ifdef _CMDBAR_EXTRA_TRACE | |
2631 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - HCBT_DESTROYWND (H
WND = %8.8X)\n"), hWndMenu); | |
2632 #endif | |
2633 | |
2634 ::GetClassName(hWndMenu, szClassName, cchClassName); | |
2635 if(!lstrcmp(_T("#32768"), szClassName)) | |
2636 { | |
2637 ATLASSERT(hWndMenu == s_pCurrentBar->m_stackMenu
Wnd.GetCurrent()); | |
2638 s_pCurrentBar->m_stackMenuWnd.Pop(); | |
2639 } | |
2640 } | |
2641 | |
2642 return ::CallNextHookEx(s_hCreateHook, nCode, wParam, lParam); | |
2643 } | |
2644 | |
2645 static LRESULT CALLBACK MessageHookProc(int nCode, WPARAM wParam, LPARAM
lParam) | |
2646 { | |
2647 LPMSG pMsg = (LPMSG)lParam; | |
2648 | |
2649 if(nCode == HC_ACTION && wParam == PM_REMOVE && pMsg->message !=
GetGetBarMessage() && pMsg->message != WM_FORWARDMSG) | |
2650 { | |
2651 CCommandBarCtrlBase* pCmdBar = NULL; | |
2652 HWND hWnd = pMsg->hwnd; | |
2653 DWORD dwPID = 0; | |
2654 while(pCmdBar == NULL && hWnd != NULL) | |
2655 { | |
2656 pCmdBar = (CCommandBarCtrlBase*)::SendMessage(hW
nd, GetGetBarMessage(), (WPARAM)&dwPID, 0L); | |
2657 hWnd = ::GetParent(hWnd); | |
2658 } | |
2659 | |
2660 if(pCmdBar != NULL && dwPID == GetCurrentProcessId()) | |
2661 { | |
2662 pCmdBar->m_hWndHook = pMsg->hwnd; | |
2663 ATLASSERT(pCmdBar->IsCommandBarBase()); | |
2664 | |
2665 if(::IsWindow(pCmdBar->m_hWnd)) | |
2666 pCmdBar->SendMessage(WM_FORWARDMSG, 0, (
LPARAM)pMsg); | |
2667 else | |
2668 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - Ho
ok skipping message, can't find command bar!\n")); | |
2669 } | |
2670 } | |
2671 | |
2672 LRESULT lRet = 0; | |
2673 ATLASSERT(s_pmapMsgHook != NULL); | |
2674 if(s_pmapMsgHook != NULL) | |
2675 { | |
2676 DWORD dwThreadID = ::GetCurrentThreadId(); | |
2677 _MsgHookData* pData = s_pmapMsgHook->Lookup(dwThreadID); | |
2678 if(pData != NULL) | |
2679 { | |
2680 lRet = ::CallNextHookEx(pData->hMsgHook, nCode,
wParam, lParam); | |
2681 } | |
2682 } | |
2683 return lRet; | |
2684 } | |
2685 | |
2686 // Implementation | |
2687 void DoPopupMenu(int nIndex, bool bAnimate) | |
2688 { | |
2689 #ifdef _CMDBAR_EXTRA_TRACE | |
2690 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - DoPopupMenu, bAnimate = %s
\n"), bAnimate ? "true" : "false"); | |
2691 #endif | |
2692 | |
2693 // Menu animation flags | |
2694 #ifndef TPM_VERPOSANIMATION | |
2695 const UINT TPM_VERPOSANIMATION = 0x1000L; | |
2696 #endif | |
2697 #ifndef TPM_NOANIMATION | |
2698 const UINT TPM_NOANIMATION = 0x4000L; | |
2699 #endif | |
2700 T* pT = static_cast<T*>(this); | |
2701 | |
2702 // get popup menu and it's position | |
2703 RECT rect = { 0 }; | |
2704 GetItemRect(nIndex, &rect); | |
2705 POINT pt = { rect.left, rect.bottom }; | |
2706 MapWindowPoints(NULL, &pt, 1); | |
2707 MapWindowPoints(NULL, &rect); | |
2708 TPMPARAMS TPMParams = { 0 }; | |
2709 TPMParams.cbSize = sizeof(TPMPARAMS); | |
2710 TPMParams.rcExclude = rect; | |
2711 HMENU hMenuPopup = ::GetSubMenu(m_hMenu, nIndex); | |
2712 ATLASSERT(hMenuPopup != NULL); | |
2713 | |
2714 // get button ID | |
2715 TBBUTTON tbb = { 0 }; | |
2716 GetButton(nIndex, &tbb); | |
2717 int nCmdID = tbb.idCommand; | |
2718 | |
2719 m_nPopBtn = nIndex; // remember current button's index | |
2720 | |
2721 // press button and display popup menu | |
2722 PressButton(nCmdID, TRUE); | |
2723 SetHotItem(nCmdID); | |
2724 pT->DoTrackPopupMenu(hMenuPopup, TPM_LEFTBUTTON | TPM_VERTICAL |
TPM_LEFTALIGN | TPM_TOPALIGN | | |
2725 (s_bW2K ? (bAnimate ? TPM_VERPOSANIMATION : TPM_NOANIMAT
ION) : 0), pt.x, pt.y, &TPMParams); | |
2726 PressButton(nCmdID, FALSE); | |
2727 if(::GetFocus() != m_hWnd) | |
2728 SetHotItem(-1); | |
2729 | |
2730 m_nPopBtn = -1; // restore | |
2731 | |
2732 // eat next message if click is on the same button | |
2733 MSG msg = { 0 }; | |
2734 if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, P
M_NOREMOVE) && ::PtInRect(&rect, msg.pt)) | |
2735 ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDO
WN, PM_REMOVE); | |
2736 | |
2737 // check if another popup menu should be displayed | |
2738 if(m_nNextPopBtn != -1) | |
2739 { | |
2740 PostMessage(GetAutoPopupMessage(), m_nNextPopBtn & 0xFFF
F); | |
2741 if(!(m_nNextPopBtn & 0xFFFF0000) && !m_bPopupItem) | |
2742 PostMessage(WM_KEYDOWN, VK_DOWN, 0); | |
2743 m_nNextPopBtn = -1; | |
2744 } | |
2745 else | |
2746 { | |
2747 m_bContextMenu = false; | |
2748 // If user didn't hit escape, give focus back | |
2749 if(!m_bEscapePressed) | |
2750 { | |
2751 if(m_bUseKeyboardCues && m_bShowKeyboardCues) | |
2752 m_bAllowKeyboardCues = false; | |
2753 pT->GiveFocusBack(); | |
2754 } | |
2755 else | |
2756 { | |
2757 SetHotItem(nCmdID); | |
2758 SetAnchorHighlight(TRUE); | |
2759 } | |
2760 } | |
2761 } | |
2762 | |
2763 BOOL DoTrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, LPTPMPARAM
S lpParams = NULL) | |
2764 { | |
2765 CMenuHandle menuPopup = hMenu; | |
2766 | |
2767 CWindowCreateCriticalSectionLock lock; | |
2768 if(FAILED(lock.Lock())) | |
2769 { | |
2770 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock crit
ical section in CCommandBarCtrlImpl::DoTrackPopupMenu.\n")); | |
2771 ATLASSERT(FALSE); | |
2772 return FALSE; | |
2773 } | |
2774 | |
2775 ATLASSERT(s_hCreateHook == NULL); | |
2776 | |
2777 s_pCurrentBar = static_cast<CCommandBarCtrlBase*>(this); | |
2778 | |
2779 s_hCreateHook = ::SetWindowsHookEx(WH_CBT, CreateHookProc, Modul
eHelper::GetModuleInstance(), GetCurrentThreadId()); | |
2780 ATLASSERT(s_hCreateHook != NULL); | |
2781 | |
2782 m_bPopupItem = false; | |
2783 m_bMenuActive = true; | |
2784 | |
2785 BOOL bTrackRet = menuPopup.TrackPopupMenuEx(uFlags, x, y, m_hWnd
, lpParams); | |
2786 m_bMenuActive = false; | |
2787 | |
2788 ::UnhookWindowsHookEx(s_hCreateHook); | |
2789 | |
2790 s_hCreateHook = NULL; | |
2791 s_pCurrentBar = NULL; | |
2792 | |
2793 lock.Unlock(); | |
2794 | |
2795 // cleanup - convert menus back to original state | |
2796 #ifdef _CMDBAR_EXTRA_TRACE | |
2797 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - TrackPopupMenu - cleanup\n
")); | |
2798 #endif | |
2799 | |
2800 ATLASSERT(m_stackMenuWnd.GetSize() == 0); | |
2801 | |
2802 UpdateWindow(); | |
2803 ATL::CWindow wndTL = GetTopLevelParent(); | |
2804 wndTL.UpdateWindow(); | |
2805 | |
2806 // restore the menu items to the previous state for all menus th
at were converted | |
2807 if(m_bImagesVisible) | |
2808 { | |
2809 HMENU hMenuSav = NULL; | |
2810 while((hMenuSav = m_stackMenuHandle.Pop()) != NULL) | |
2811 { | |
2812 menuPopup = hMenuSav; | |
2813 BOOL bRet = FALSE; | |
2814 // restore state and delete menu item data | |
2815 for(int i = 0; i < menuPopup.GetMenuItemCount();
i++) | |
2816 { | |
2817 CMenuItemInfo mii; | |
2818 mii.fMask = MIIM_DATA | MIIM_TYPE | MIIM
_ID; | |
2819 bRet = menuPopup.GetMenuItemInfo(i, TRUE
, &mii); | |
2820 ATLASSERT(bRet); | |
2821 | |
2822 _MenuItemData* pMI = (_MenuItemData*)mii
.dwItemData; | |
2823 if(pMI != NULL && pMI->IsCmdBarMenuItem(
)) | |
2824 { | |
2825 mii.fMask = MIIM_DATA | MIIM_TYP
E | MIIM_STATE; | |
2826 mii.fType = pMI->fType; | |
2827 mii.fState = pMI->fState; | |
2828 mii.dwTypeData = pMI->lpstrText; | |
2829 mii.cch = lstrlen(pMI->lpstrText
); | |
2830 mii.dwItemData = NULL; | |
2831 | |
2832 bRet = menuPopup.SetMenuItemInfo
(i, TRUE, &mii); | |
2833 // this one triggers WM_MEASUREI
TEM | |
2834 menuPopup.ModifyMenu(i, MF_BYPOS
ITION | mii.fType | mii.fState, mii.wID, pMI->lpstrText); | |
2835 ATLASSERT(bRet); | |
2836 | |
2837 delete [] pMI->lpstrText; | |
2838 delete pMI; | |
2839 } | |
2840 } | |
2841 } | |
2842 } | |
2843 return bTrackRet; | |
2844 } | |
2845 | |
2846 int GetPreviousMenuItem(int nBtn) const | |
2847 { | |
2848 if(nBtn == -1) | |
2849 return -1; | |
2850 #if (_WIN32_IE >= 0x0500) | |
2851 RECT rcClient; | |
2852 GetClientRect(&rcClient); | |
2853 #endif // (_WIN32_IE >= 0x0500) | |
2854 int nNextBtn; | |
2855 for(nNextBtn = nBtn - 1; nNextBtn != nBtn; nNextBtn--) | |
2856 { | |
2857 if(nNextBtn < 0) | |
2858 nNextBtn = ::GetMenuItemCount(m_hMenu) - 1; | |
2859 TBBUTTON tbb = { 0 }; | |
2860 GetButton(nNextBtn, &tbb); | |
2861 #if (_WIN32_IE >= 0x0500) | |
2862 RECT rcBtn; | |
2863 GetItemRect(nNextBtn, &rcBtn); | |
2864 if(rcBtn.right > rcClient.right) | |
2865 { | |
2866 nNextBtn = -2; // chevron | |
2867 break; | |
2868 } | |
2869 #endif // (_WIN32_IE >= 0x0500) | |
2870 if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState
& TBSTATE_HIDDEN) == 0) | |
2871 break; | |
2872 } | |
2873 return (nNextBtn != nBtn) ? nNextBtn : -1; | |
2874 } | |
2875 | |
2876 int GetNextMenuItem(int nBtn) const | |
2877 { | |
2878 if(nBtn == -1) | |
2879 return -1; | |
2880 #if (_WIN32_IE >= 0x0500) | |
2881 RECT rcClient = { 0 }; | |
2882 GetClientRect(&rcClient); | |
2883 #endif // (_WIN32_IE >= 0x0500) | |
2884 int nNextBtn = 0; | |
2885 int nCount = ::GetMenuItemCount(m_hMenu); | |
2886 for(nNextBtn = nBtn + 1; nNextBtn != nBtn; nNextBtn++) | |
2887 { | |
2888 if(nNextBtn >= nCount) | |
2889 nNextBtn = 0; | |
2890 TBBUTTON tbb = { 0 }; | |
2891 GetButton(nNextBtn, &tbb); | |
2892 #if (_WIN32_IE >= 0x0500) | |
2893 RECT rcBtn = { 0 }; | |
2894 GetItemRect(nNextBtn, &rcBtn); | |
2895 if(rcBtn.right > rcClient.right) | |
2896 { | |
2897 nNextBtn = -2; // chevron | |
2898 break; | |
2899 } | |
2900 #endif // (_WIN32_IE >= 0x0500) | |
2901 if((tbb.fsState & TBSTATE_ENABLED) != 0 && (tbb.fsState
& TBSTATE_HIDDEN) == 0) | |
2902 break; | |
2903 } | |
2904 return (nNextBtn != nBtn) ? nNextBtn : -1; | |
2905 } | |
2906 | |
2907 #if (_WIN32_IE >= 0x0500) | |
2908 bool DisplayChevronMenu() | |
2909 { | |
2910 // assume we are in a rebar | |
2911 HWND hWndReBar = GetParent(); | |
2912 int nCount = (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0
L); | |
2913 bool bRet = false; | |
2914 for(int i = 0; i < nCount; i++) | |
2915 { | |
2916 REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDIN
FO(), RBBIM_CHILD | RBBIM_STYLE }; | |
2917 BOOL bRetBandInfo = (BOOL)::SendMessage(hWndReBar, RB_GE
TBANDINFO, i, (LPARAM)&rbbi); | |
2918 if(bRetBandInfo && rbbi.hwndChild == m_hWnd) | |
2919 { | |
2920 if((rbbi.fStyle & RBBS_USECHEVRON) != 0) | |
2921 { | |
2922 ::PostMessage(hWndReBar, RB_PUSHCHEVRON,
i, 0L); | |
2923 PostMessage(WM_KEYDOWN, VK_DOWN, 0L); | |
2924 bRet = true; | |
2925 } | |
2926 break; | |
2927 } | |
2928 } | |
2929 return bRet; | |
2930 } | |
2931 #endif // (_WIN32_IE >= 0x0500) | |
2932 | |
2933 void GetSystemSettings() | |
2934 { | |
2935 // refresh our font | |
2936 NONCLIENTMETRICS info = { RunTimeHelper::SizeOf_NONCLIENTMETRICS
() }; | |
2937 BOOL bRet = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size
of(info), &info, 0); | |
2938 ATLASSERT(bRet); | |
2939 if(bRet) | |
2940 { | |
2941 LOGFONT logfont = { 0 }; | |
2942 if(m_fontMenu.m_hFont != NULL) | |
2943 m_fontMenu.GetLogFont(logfont); | |
2944 if(logfont.lfHeight != info.lfMenuFont.lfHeight || | |
2945 logfont.lfWidth != info.lfMenuFont.lfWidth || | |
2946 logfont.lfEscapement != info.lfMenuFont.lfEscapement
|| | |
2947 logfont.lfOrientation != info.lfMenuFont.lfOrientatio
n || | |
2948 logfont.lfWeight != info.lfMenuFont.lfWeight || | |
2949 logfont.lfItalic != info.lfMenuFont.lfItalic || | |
2950 logfont.lfUnderline != info.lfMenuFont.lfUnderline || | |
2951 logfont.lfStrikeOut != info.lfMenuFont.lfStrikeOut || | |
2952 logfont.lfCharSet != info.lfMenuFont.lfCharSet || | |
2953 logfont.lfOutPrecision != info.lfMenuFont.lfOutPrecis
ion || | |
2954 logfont.lfClipPrecision != info.lfMenuFont.lfClipPrec
ision || | |
2955 logfont.lfQuality != info.lfMenuFont.lfQuality || | |
2956 logfont.lfPitchAndFamily != info.lfMenuFont.lfPitchAn
dFamily || | |
2957 lstrcmp(logfont.lfFaceName, info.lfMenuFont.lfFaceNam
e) != 0) | |
2958 { | |
2959 HFONT hFontMenu = ::CreateFontIndirect(&info.lfM
enuFont); | |
2960 ATLASSERT(hFontMenu != NULL); | |
2961 if(hFontMenu != NULL) | |
2962 { | |
2963 if(m_fontMenu.m_hFont != NULL) | |
2964 m_fontMenu.DeleteObject(); | |
2965 m_fontMenu.Attach(hFontMenu); | |
2966 SetFont(m_fontMenu); | |
2967 AddStrings(_T("NS\0")); // for proper
item height | |
2968 AutoSize(); | |
2969 } | |
2970 } | |
2971 } | |
2972 | |
2973 // check if we need extra spacing for menu item text | |
2974 CWindowDC dc(m_hWnd); | |
2975 HFONT hFontOld = dc.SelectFont(m_fontMenu); | |
2976 RECT rcText = { 0, 0, 0, 0 }; | |
2977 dc.DrawText(_T("\t"), -1, &rcText, DT_SINGLELINE | DT_LEFT | DT_
VCENTER | DT_CALCRECT); | |
2978 if((rcText.right - rcText.left) < 4) | |
2979 { | |
2980 ::SetRectEmpty(&rcText); | |
2981 dc.DrawText(_T("x"), -1, &rcText, DT_SINGLELINE | DT_LEF
T | DT_VCENTER | DT_CALCRECT); | |
2982 m_cxExtraSpacing = rcText.right - rcText.left; | |
2983 } | |
2984 else | |
2985 { | |
2986 m_cxExtraSpacing = 0; | |
2987 } | |
2988 dc.SelectFont(hFontOld); | |
2989 | |
2990 // get Windows version | |
2991 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) }; | |
2992 ::GetVersionEx(&ovi); | |
2993 | |
2994 // query keyboard cues mode (Windows 2000 or later) | |
2995 if(ovi.dwMajorVersion >= 5) | |
2996 { | |
2997 #ifndef SPI_GETKEYBOARDCUES | |
2998 const UINT SPI_GETKEYBOARDCUES = 0x100A; | |
2999 #endif // !SPI_GETKEYBOARDCUES | |
3000 BOOL bRetVal = TRUE; | |
3001 bRet = ::SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &b
RetVal, 0); | |
3002 m_bUseKeyboardCues = (bRet && !bRetVal); | |
3003 m_bAllowKeyboardCues = true; | |
3004 ShowKeyboardCues(!m_bUseKeyboardCues); | |
3005 } | |
3006 | |
3007 // query flat menu mode (Windows XP or later) | |
3008 if((ovi.dwMajorVersion == 5 && ovi.dwMinorVersion >= 1) || (ovi.
dwMajorVersion > 5)) | |
3009 { | |
3010 #ifndef SPI_GETFLATMENU | |
3011 const UINT SPI_GETFLATMENU = 0x1022; | |
3012 #endif // !SPI_GETFLATMENU | |
3013 BOOL bRetVal = FALSE; | |
3014 bRet = ::SystemParametersInfo(SPI_GETFLATMENU, 0, &bRetV
al, 0); | |
3015 m_bFlatMenus = (bRet && bRetVal); | |
3016 } | |
3017 | |
3018 #if _WTL_CMDBAR_VISTA_MENUS | |
3019 // check if we should use Vista menus | |
3020 bool bVistaMenus = (RunTimeHelper::IsVista() && RunTimeHelper::I
sCommCtrl6() && ((m_dwExtendedStyle & CBR_EX_NOVISTAMENUS) == 0)); | |
3021 | |
3022 if(bVistaMenus) | |
3023 { | |
3024 HMODULE hThemeDLL = ::LoadLibrary(_T("uxtheme.dll")); | |
3025 if(hThemeDLL != NULL) | |
3026 { | |
3027 typedef BOOL (STDAPICALLTYPE *PFN_IsThemeActive)
(); | |
3028 PFN_IsThemeActive pfnIsThemeActive = (PFN_IsThem
eActive)::GetProcAddress(hThemeDLL, "IsThemeActive"); | |
3029 ATLASSERT(pfnIsThemeActive != NULL); | |
3030 bVistaMenus = bVistaMenus && (pfnIsThemeActive !
= NULL) && (pfnIsThemeActive() != FALSE); | |
3031 | |
3032 typedef BOOL (STDAPICALLTYPE *PFN_IsAppThemed)()
; | |
3033 PFN_IsAppThemed pfnIsAppThemed = (PFN_IsAppTheme
d)::GetProcAddress(hThemeDLL, "IsAppThemed"); | |
3034 ATLASSERT(pfnIsAppThemed != NULL); | |
3035 bVistaMenus = bVistaMenus && (pfnIsAppThemed !=
NULL) && (pfnIsAppThemed() != FALSE); | |
3036 | |
3037 ::FreeLibrary(hThemeDLL); | |
3038 } | |
3039 } | |
3040 | |
3041 if(!bVistaMenus && m_bVistaMenus && (m_hMenu != NULL) && (m_arrC
ommand.GetSize() > 0)) | |
3042 { | |
3043 T* pT = static_cast<T*>(this); | |
3044 pT->_RemoveVistaBitmapsFromMenu(); | |
3045 } | |
3046 | |
3047 m_bVistaMenus = bVistaMenus; | |
3048 #endif // _WTL_CMDBAR_VISTA_MENUS | |
3049 | |
3050 #ifdef _CMDBAR_EXTRA_TRACE | |
3051 ATLTRACE2(atlTraceUI, 0, _T("CmdBar - GetSystemSettings:\n m
_bFlatMenus = %s\n m_bUseKeyboardCues = %s m_bVistaMenus = %s\n"), | |
3052 m_bFlatMenus ? "true" : "false", m_bUseKeyboardCues ? "t
rue" : "false", m_bVistaMenus ? "true" : "false"); | |
3053 #endif | |
3054 } | |
3055 | |
3056 // Implementation - alternate focus mode support | |
3057 void TakeFocus() | |
3058 { | |
3059 if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_hWndFocus == N
ULL) | |
3060 m_hWndFocus = ::GetFocus(); | |
3061 SetFocus(); | |
3062 } | |
3063 | |
3064 void GiveFocusBack() | |
3065 { | |
3066 if(m_bParentActive) | |
3067 { | |
3068 if((m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && ::IsWind
ow(m_hWndFocus)) | |
3069 ::SetFocus(m_hWndFocus); | |
3070 else if(!(m_dwExtendedStyle & CBR_EX_ALTFOCUSMODE) && m_
wndParent.IsWindow()) | |
3071 m_wndParent.SetFocus(); | |
3072 } | |
3073 m_hWndFocus = NULL; | |
3074 SetAnchorHighlight(FALSE); | |
3075 if(m_bUseKeyboardCues && m_bShowKeyboardCues) | |
3076 ShowKeyboardCues(false); | |
3077 m_bSkipPostDown = false; | |
3078 } | |
3079 | |
3080 void ShowKeyboardCues(bool bShow) | |
3081 { | |
3082 m_bShowKeyboardCues = bShow; | |
3083 SetDrawTextFlags(DT_HIDEPREFIX, m_bShowKeyboardCues ? 0 : DT_HID
EPREFIX); | |
3084 Invalidate(); | |
3085 UpdateWindow(); | |
3086 } | |
3087 | |
3088 // Implementation - internal message helpers | |
3089 static UINT GetAutoPopupMessage() | |
3090 { | |
3091 static UINT uAutoPopupMessage = 0; | |
3092 if(uAutoPopupMessage == 0) | |
3093 { | |
3094 CStaticDataInitCriticalSectionLock lock; | |
3095 if(FAILED(lock.Lock())) | |
3096 { | |
3097 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to l
ock critical section in CCommandBarCtrlImpl::GetAutoPopupMessage.\n")); | |
3098 ATLASSERT(FALSE); | |
3099 return 0; | |
3100 } | |
3101 | |
3102 if(uAutoPopupMessage == 0) | |
3103 uAutoPopupMessage = ::RegisterWindowMessage(_T("
WTL_CmdBar_InternalAutoPopupMsg")); | |
3104 | |
3105 lock.Unlock(); | |
3106 } | |
3107 ATLASSERT(uAutoPopupMessage != 0); | |
3108 return uAutoPopupMessage; | |
3109 } | |
3110 | |
3111 static UINT GetGetBarMessage() | |
3112 { | |
3113 static UINT uGetBarMessage = 0; | |
3114 if(uGetBarMessage == 0) | |
3115 { | |
3116 CStaticDataInitCriticalSectionLock lock; | |
3117 if(FAILED(lock.Lock())) | |
3118 { | |
3119 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to l
ock critical section in CCommandBarCtrlImpl::GetGetBarMessage.\n")); | |
3120 ATLASSERT(FALSE); | |
3121 return 0; | |
3122 } | |
3123 | |
3124 if(uGetBarMessage == 0) | |
3125 uGetBarMessage = ::RegisterWindowMessage(_T("WTL
_CmdBar_InternalGetBarMsg")); | |
3126 | |
3127 lock.Unlock(); | |
3128 } | |
3129 ATLASSERT(uGetBarMessage != 0); | |
3130 return uGetBarMessage; | |
3131 } | |
3132 | |
3133 // Implementation | |
3134 bool CreateInternalImageList(int cImages) | |
3135 { | |
3136 UINT uFlags = (m_bAlphaImages ? ILC_COLOR32 : ILC_COLOR24) | ILC
_MASK; | |
3137 m_hImageList = ::ImageList_Create(m_szBitmap.cx, m_szBitmap.cy,
uFlags, cImages, 1); | |
3138 ATLASSERT(m_hImageList != NULL); | |
3139 return (m_hImageList != NULL); | |
3140 } | |
3141 | |
3142 // Implementation - support for Vista menus | |
3143 #if _WTL_CMDBAR_VISTA_MENUS | |
3144 void _AddVistaBitmapsFromImageList(int nStartIndex, int nCount) | |
3145 { | |
3146 // Create display compatible memory DC | |
3147 HDC hDC = ::GetDC(NULL); | |
3148 CDC dcMem; | |
3149 dcMem.CreateCompatibleDC(hDC); | |
3150 HBITMAP hBitmapSave = dcMem.GetCurrentBitmap(); | |
3151 | |
3152 T* pT = static_cast<T*>(this); | |
3153 // Create bitmaps for all menu items | |
3154 for(int i = 0; i < nCount; i++) | |
3155 { | |
3156 HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nStartInd
ex + i, hDC, dcMem); | |
3157 dcMem.SelectBitmap(hBitmapSave); | |
3158 m_arrVistaBitmap.Add(hBitmap); | |
3159 } | |
3160 } | |
3161 | |
3162 void _AddVistaBitmapFromImageList(int nIndex) | |
3163 { | |
3164 // Create display compatible memory DC | |
3165 HDC hDC = ::GetDC(NULL); | |
3166 CDC dcMem; | |
3167 dcMem.CreateCompatibleDC(hDC); | |
3168 HBITMAP hBitmapSave = dcMem.GetCurrentBitmap(); | |
3169 | |
3170 // Create bitmap for menu item | |
3171 T* pT = static_cast<T*>(this); | |
3172 HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nIndex, hDC, dcMe
m); | |
3173 | |
3174 // Select saved bitmap back and add bitmap to the array | |
3175 dcMem.SelectBitmap(hBitmapSave); | |
3176 m_arrVistaBitmap.Add(hBitmap); | |
3177 } | |
3178 | |
3179 void _ReplaceVistaBitmapFromImageList(int nIndex) | |
3180 { | |
3181 // Delete existing bitmap | |
3182 if(m_arrVistaBitmap[nIndex] != NULL) | |
3183 ::DeleteObject(m_arrVistaBitmap[nIndex]); | |
3184 | |
3185 // Create display compatible memory DC | |
3186 HDC hDC = ::GetDC(NULL); | |
3187 CDC dcMem; | |
3188 dcMem.CreateCompatibleDC(hDC); | |
3189 HBITMAP hBitmapSave = dcMem.GetCurrentBitmap(); | |
3190 | |
3191 // Create bitmap for menu item | |
3192 T* pT = static_cast<T*>(this); | |
3193 HBITMAP hBitmap = pT->_CreateVistaBitmapHelper(nIndex, hDC, dcMe
m); | |
3194 | |
3195 // Select saved bitmap back and replace bitmap in the array | |
3196 dcMem.SelectBitmap(hBitmapSave); | |
3197 m_arrVistaBitmap.SetAtIndex(nIndex, hBitmap); | |
3198 } | |
3199 | |
3200 HBITMAP _CreateVistaBitmapHelper(int nIndex, HDC hDCSource, HDC hDCTarge
t) | |
3201 { | |
3202 // Create 32-bit bitmap | |
3203 BITMAPINFO bi = { 0 }; | |
3204 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); | |
3205 bi.bmiHeader.biWidth = m_szBitmap.cx; | |
3206 bi.bmiHeader.biHeight = m_szBitmap.cy; | |
3207 bi.bmiHeader.biPlanes = 1; | |
3208 bi.bmiHeader.biBitCount = 32; | |
3209 bi.bmiHeader.biCompression = BI_RGB; | |
3210 bi.bmiHeader.biSizeImage = 0; | |
3211 bi.bmiHeader.biXPelsPerMeter = 0; | |
3212 bi.bmiHeader.biYPelsPerMeter = 0; | |
3213 bi.bmiHeader.biClrUsed = 0; | |
3214 bi.bmiHeader.biClrImportant = 0; | |
3215 HBITMAP hBitmap = ::CreateDIBSection(hDCSource, &bi, DIB_RGB_COL
ORS, NULL, NULL, 0); | |
3216 ATLASSERT(hBitmap != NULL); | |
3217 | |
3218 // Select bitmap into target DC and draw from image list to it | |
3219 if(hBitmap != NULL) | |
3220 { | |
3221 ::SelectObject(hDCTarget, hBitmap); | |
3222 | |
3223 IMAGELISTDRAWPARAMS ildp = { 0 }; | |
3224 ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS); | |
3225 ildp.himl = m_hImageList; | |
3226 ildp.i = nIndex; | |
3227 ildp.hdcDst = hDCTarget; | |
3228 ildp.x = 0; | |
3229 ildp.y = 0; | |
3230 ildp.cx = 0; | |
3231 ildp.cy = 0; | |
3232 ildp.xBitmap = 0; | |
3233 ildp.yBitmap = 0; | |
3234 ildp.fStyle = ILD_TRANSPARENT; | |
3235 ildp.fState = ILS_ALPHA; | |
3236 ildp.Frame = 255; | |
3237 ::ImageList_DrawIndirect(&ildp); | |
3238 } | |
3239 | |
3240 return hBitmap; | |
3241 } | |
3242 | |
3243 void _RemoveVistaBitmapsFromMenu() | |
3244 { | |
3245 CMenuHandle menu = m_hMenu; | |
3246 for(int i = 0; i < m_arrCommand.GetSize(); i++) | |
3247 { | |
3248 CMenuItemInfo mii; | |
3249 mii.fMask = MIIM_BITMAP; | |
3250 mii.hbmpItem = NULL; | |
3251 menu.SetMenuItemInfo(m_arrCommand[i], FALSE, &mii); | |
3252 } | |
3253 } | |
3254 #endif // _WTL_CMDBAR_VISTA_MENUS | |
3255 }; | |
3256 | |
3257 | |
3258 class CCommandBarCtrl : public CCommandBarCtrlImpl<CCommandBarCtrl> | |
3259 { | |
3260 public: | |
3261 DECLARE_WND_SUPERCLASS(_T("WTL_CommandBar"), GetWndClassName()) | |
3262 }; | |
3263 | |
3264 | |
3265 /////////////////////////////////////////////////////////////////////////////// | |
3266 // CMDICommandBarCtrl - ATL implementation of Command Bars for MDI apps | |
3267 | |
3268 template <class T, class TBase = CCommandBarCtrlBase, class TWinTraits = ATL::CC
ontrolWinTraits> | |
3269 class ATL_NO_VTABLE CMDICommandBarCtrlImpl : public CCommandBarCtrlImpl< T, TBas
e, TWinTraits> | |
3270 { | |
3271 public: | |
3272 // Data members | |
3273 ATL::CContainedWindow m_wndMDIClient; | |
3274 bool m_bChildMaximized; | |
3275 HWND m_hWndChildMaximized; | |
3276 HICON m_hIconChildMaximized; | |
3277 int m_nBtnPressed; | |
3278 int m_nBtnWasPressed; | |
3279 | |
3280 int m_cxyOffset; // offset between nonclient elements | |
3281 int m_cxIconWidth; // small icon width | |
3282 int m_cyIconHeight; // small icon height | |
3283 int m_cxBtnWidth; // nonclient button width | |
3284 int m_cyBtnHeight; // nonclient button height | |
3285 int m_cxLeft; // left nonclient area width | |
3286 int m_cxRight; // right nonclient area width | |
3287 | |
3288 // Theme declarations and data members | |
3289 #ifndef _WTL_NO_AUTO_THEME | |
3290 #ifndef _UXTHEME_H_ | |
3291 typedef HANDLE HTHEME; | |
3292 #endif // !_UXTHEME_H_ | |
3293 typedef HTHEME (STDAPICALLTYPE *PFN_OpenThemeData)(HWND hwnd, LPCWSTR ps
zClassList); | |
3294 typedef HRESULT (STDAPICALLTYPE *PFN_CloseThemeData)(HTHEME hTheme); | |
3295 typedef HRESULT (STDAPICALLTYPE *PFN_DrawThemeBackground)(HTHEME hTheme,
HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pCl
ipRect); | |
3296 typedef HRESULT (STDAPICALLTYPE *PFN_DrawThemeParentBackground)(HWND hwn
d, HDC hdc, OPTIONAL RECT* prc); | |
3297 | |
3298 HMODULE m_hThemeDLL; | |
3299 HTHEME m_hTheme; | |
3300 PFN_DrawThemeBackground m_pfnDrawThemeBackground; | |
3301 PFN_DrawThemeParentBackground m_pfnDrawThemeParentBackground; | |
3302 #endif // !_WTL_NO_AUTO_THEME | |
3303 | |
3304 // Constructor/destructor | |
3305 CMDICommandBarCtrlImpl() : | |
3306 m_wndMDIClient(this, 2), m_bChildMaximized(false), | |
3307 m_hWndChildMaximized(NULL), m_hIconChildMaximized(NULL),
| |
3308 m_nBtnPressed(-1), m_nBtnWasPressed(-1), | |
3309 #ifndef _WTL_NO_AUTO_THEME | |
3310 m_hThemeDLL(NULL), m_hTheme(NULL), m_pfnDrawThemeBackgro
und(NULL), m_pfnDrawThemeParentBackground(NULL), | |
3311 #endif // !_WTL_NO_AUTO_THEME | |
3312 m_cxyOffset(2), | |
3313 m_cxIconWidth(16), m_cyIconHeight(16), | |
3314 m_cxBtnWidth(16), m_cyBtnHeight(14), | |
3315 m_cxLeft(20), m_cxRight(55) | |
3316 { } | |
3317 | |
3318 ~CMDICommandBarCtrlImpl() | |
3319 { | |
3320 if(m_wndMDIClient.IsWindow()) | |
3321 /*scary!*/ m_wndMDIClient.UnsubclassWindow(); | |
3322 } | |
3323 | |
3324 // Operations | |
3325 BOOL SetMDIClient(HWND hWndMDIClient) | |
3326 { | |
3327 ATLASSERT(::IsWindow(m_hWnd)); | |
3328 ATLASSERT(::IsWindow(hWndMDIClient)); | |
3329 if(!::IsWindow(hWndMDIClient)) | |
3330 return FALSE; | |
3331 | |
3332 #ifdef _DEBUG | |
3333 // BLOCK: Test if the passed window is MDICLIENT | |
3334 { | |
3335 LPCTSTR lpszMDIClientClass = _T("MDICLIENT"); | |
3336 const int nNameLen = 9 + 1; // "MDICLIENT" + NULL | |
3337 TCHAR szClassName[nNameLen] = { 0 }; | |
3338 ::GetClassName(hWndMDIClient, szClassName, nNameLen); | |
3339 ATLASSERT(lstrcmpi(szClassName, lpszMDIClientClass) == 0
); | |
3340 } | |
3341 #endif // _DEBUG | |
3342 | |
3343 if(m_wndMDIClient.IsWindow()) | |
3344 /*scary!*/ m_wndMDIClient.UnsubclassWindow(); | |
3345 | |
3346 return m_wndMDIClient.SubclassWindow(hWndMDIClient); | |
3347 } | |
3348 | |
3349 // Message maps | |
3350 typedef CCommandBarCtrlImpl< T, TBase, TWinTraits > _baseClass; | |
3351 BEGIN_MSG_MAP(CMDICommandBarCtrlImpl) | |
3352 MESSAGE_HANDLER(WM_CREATE, OnCreate) | |
3353 MESSAGE_HANDLER(WM_DESTROY, OnDestroy) | |
3354 #ifndef _WTL_NO_AUTO_THEME | |
3355 MESSAGE_HANDLER(_GetThemeChangedMsg(), OnThemeChanged) | |
3356 #endif // !_WTL_NO_AUTO_THEME | |
3357 MESSAGE_HANDLER(WM_SIZE, OnSize) | |
3358 MESSAGE_HANDLER(WM_NCCALCSIZE, OnNcCalcSize) | |
3359 MESSAGE_HANDLER(WM_NCPAINT, OnNcPaint) | |
3360 MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest) | |
3361 MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnNcLButtonDown) | |
3362 MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) | |
3363 MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) | |
3364 MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClk) | |
3365 MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged) | |
3366 CHAIN_MSG_MAP(_baseClass) | |
3367 ALT_MSG_MAP(1) // Parent window messages | |
3368 MESSAGE_HANDLER(WM_ACTIVATE, OnParentActivate) | |
3369 CHAIN_MSG_MAP_ALT(_baseClass, 1) | |
3370 ALT_MSG_MAP(2) // MDI client window messages | |
3371 MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu) | |
3372 // no chaining needed since this was moved from the base class h
ere | |
3373 ALT_MSG_MAP(3) // Message hook messages | |
3374 MESSAGE_RANGE_HANDLER(0, 0xFFFF, OnAllHookMessages) | |
3375 CHAIN_MSG_MAP_ALT(_baseClass, 3) | |
3376 END_MSG_MAP() | |
3377 | |
3378 // Additional MDI message handlers | |
3379 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled
) | |
3380 { | |
3381 LRESULT lRet = _baseClass::OnCreate(uMsg, wParam, lParam, bHandl
ed); | |
3382 if(lRet == (LRESULT)-1) | |
3383 return lRet; | |
3384 | |
3385 #ifndef _WTL_NO_AUTO_THEME | |
3386 // this will fail if theming is not supported | |
3387 m_hThemeDLL = ::LoadLibrary(_T("uxtheme.dll")); | |
3388 if(m_hThemeDLL != NULL) | |
3389 { | |
3390 m_pfnDrawThemeBackground = (PFN_DrawThemeBackground)::Ge
tProcAddress(m_hThemeDLL, "DrawThemeBackground"); | |
3391 ATLASSERT(m_pfnDrawThemeBackground != NULL); | |
3392 if(m_pfnDrawThemeBackground != NULL) | |
3393 { | |
3394 T* pT = static_cast<T*>(this); | |
3395 pT->_OpenThemeData(); | |
3396 } | |
3397 else | |
3398 { | |
3399 ::FreeLibrary(m_hThemeDLL); | |
3400 m_hThemeDLL = NULL; | |
3401 } | |
3402 m_pfnDrawThemeParentBackground = (PFN_DrawThemeParentBac
kground)::GetProcAddress(m_hThemeDLL, "DrawThemeParentBackground"); | |
3403 ATLASSERT(m_pfnDrawThemeParentBackground != NULL); | |
3404 } | |
3405 #endif // !_WTL_NO_AUTO_THEME | |
3406 | |
3407 return lRet; | |
3408 } | |
3409 | |
3410 LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandle
d) | |
3411 { | |
3412 LRESULT lRet = _baseClass::OnDestroy(uMsg, wParam, lParam, bHand
led); | |
3413 | |
3414 #ifndef _WTL_NO_AUTO_THEME | |
3415 if(m_hThemeDLL != NULL) | |
3416 { | |
3417 T* pT = static_cast<T*>(this); | |
3418 pT->_CloseThemeData(); | |
3419 ::FreeLibrary(m_hThemeDLL); | |
3420 m_hThemeDLL = NULL; | |
3421 } | |
3422 #endif // !_WTL_NO_AUTO_THEME | |
3423 | |
3424 return lRet; | |
3425 } | |
3426 | |
3427 #ifndef _WTL_NO_AUTO_THEME | |
3428 LRESULT OnThemeChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam
*/, BOOL& /*bHandled*/) | |
3429 { | |
3430 if(m_hThemeDLL != NULL) | |
3431 { | |
3432 T* pT = static_cast<T*>(this); | |
3433 pT->_CloseThemeData(); | |
3434 pT->_OpenThemeData(); | |
3435 } | |
3436 return 0; | |
3437 } | |
3438 #endif // !_WTL_NO_AUTO_THEME | |
3439 | |
3440 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled
*/) | |
3441 { | |
3442 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); | |
3443 T* pT = static_cast<T*>(this); | |
3444 pT->_AdjustBtnSize(GET_Y_LPARAM(lParam)); | |
3445 return lRet; | |
3446 } | |
3447 | |
3448 LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bH
andled*/) | |
3449 { | |
3450 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); | |
3451 | |
3452 if(m_bChildMaximized && (BOOL)wParam) | |
3453 { | |
3454 LPNCCALCSIZE_PARAMS lpParams = (LPNCCALCSIZE_PARAMS)lPar
am; | |
3455 if(m_bLayoutRTL) | |
3456 { | |
3457 lpParams->rgrc[0].left += m_cxRight; | |
3458 lpParams->rgrc[0].right -= m_cxLeft; | |
3459 } | |
3460 else | |
3461 { | |
3462 lpParams->rgrc[0].left += m_cxLeft; | |
3463 lpParams->rgrc[0].right -= m_cxRight; | |
3464 } | |
3465 } | |
3466 | |
3467 return lRet; | |
3468 } | |
3469 | |
3470 LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHand
led*/) | |
3471 { | |
3472 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); | |
3473 | |
3474 if(!m_bChildMaximized) | |
3475 return lRet; | |
3476 | |
3477 ATLASSERT(m_hWndChildMaximized != NULL && m_hIconChildMaximized
!= NULL); | |
3478 | |
3479 // get DC and window rectangle | |
3480 CWindowDC dc(m_hWnd); | |
3481 RECT rect; | |
3482 GetWindowRect(&rect); | |
3483 int cxWidth = rect.right - rect.left; | |
3484 int cyHeight = rect.bottom - rect.top; | |
3485 | |
3486 // paint left side nonclient background and draw icon | |
3487 ::SetRect(&rect, 0, 0, m_cxLeft, cyHeight); | |
3488 #ifndef _WTL_NO_AUTO_THEME | |
3489 if(m_hTheme != NULL) | |
3490 { | |
3491 if(m_pfnDrawThemeParentBackground != NULL) | |
3492 m_pfnDrawThemeParentBackground(m_hWnd, dc, &rect
); | |
3493 else | |
3494 dc.FillRect(&rect, COLOR_WINDOW); | |
3495 } | |
3496 else | |
3497 #endif // !_WTL_NO_AUTO_THEME | |
3498 { | |
3499 if((m_dwExtendedStyle & CBR_EX_TRANSPARENT) != 0) | |
3500 dc.FillRect(&rect, COLOR_3DFACE); | |
3501 else | |
3502 dc.FillRect(&rect, COLOR_MENU); | |
3503 } | |
3504 | |
3505 RECT rcIcon = { 0 }; | |
3506 T* pT = static_cast<T*>(this); | |
3507 pT->_CalcIconRect(cxWidth, cyHeight, rcIcon); | |
3508 dc.DrawIconEx(rcIcon.left, rcIcon.top, m_hIconChildMaximized, m_
cxIconWidth, m_cyIconHeight); | |
3509 | |
3510 // paint right side nonclient background | |
3511 ::SetRect(&rect, cxWidth - m_cxRight, 0, cxWidth, cyHeight); | |
3512 #ifndef _WTL_NO_AUTO_THEME | |
3513 if(m_hTheme != NULL) | |
3514 { | |
3515 if(m_pfnDrawThemeParentBackground != NULL) | |
3516 { | |
3517 // this is to account for the left non-client ar
ea | |
3518 POINT ptOrg = { 0, 0 }; | |
3519 dc.GetViewportOrg(&ptOrg); | |
3520 dc.SetViewportOrg(ptOrg.x + m_cxLeft, ptOrg.y); | |
3521 ::OffsetRect(&rect, -m_cxLeft, 0); | |
3522 | |
3523 m_pfnDrawThemeParentBackground(m_hWnd, dc, &rect
); | |
3524 | |
3525 // restore | |
3526 dc.SetViewportOrg(ptOrg); | |
3527 ::OffsetRect(&rect, m_cxLeft, 0); | |
3528 } | |
3529 else | |
3530 { | |
3531 dc.FillRect(&rect, COLOR_3DFACE); | |
3532 } | |
3533 } | |
3534 else | |
3535 #endif // !_WTL_NO_AUTO_THEME | |
3536 { | |
3537 if((m_dwExtendedStyle & CBR_EX_TRANSPARENT) != 0) | |
3538 dc.FillRect(&rect, COLOR_3DFACE); | |
3539 else | |
3540 dc.FillRect(&rect, COLOR_MENU); | |
3541 } | |
3542 | |
3543 // draw buttons | |
3544 RECT arrRect[3] = { 0 }; | |
3545 pT->_CalcBtnRects(cxWidth, cyHeight, arrRect); | |
3546 pT->_DrawMDIButton(dc, arrRect, -1); // draw all buttons | |
3547 | |
3548 return lRet; | |
3549 } | |
3550 | |
3551 LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHa
ndled*/) | |
3552 { | |
3553 LRESULT lRet = DefWindowProc(uMsg, wParam, lParam); | |
3554 if(m_bChildMaximized) | |
3555 { | |
3556 RECT rect = { 0 }; | |
3557 GetWindowRect(&rect); | |
3558 POINT pt = { GET_X_LPARAM(lParam) - rect.left, GET_Y_LPA
RAM(lParam) - rect.top }; | |
3559 if(m_bLayoutRTL) | |
3560 { | |
3561 if((pt.x < m_cxRight) || (pt.x > ((rect.right -
rect.left) - m_cxLeft))) | |
3562 lRet = HTBORDER; | |
3563 } | |
3564 else | |
3565 { | |
3566 if((pt.x < m_cxLeft) || (pt.x > ((rect.right - r
ect.left) - m_cxRight))) | |
3567 lRet = HTBORDER; | |
3568 } | |
3569 } | |
3570 return lRet; | |
3571 } | |
3572 | |
3573 LRESULT OnNcLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam,
BOOL& bHandled) | |
3574 { | |
3575 if(!m_bChildMaximized) | |
3576 { | |
3577 bHandled = FALSE; | |
3578 return 1; | |
3579 } | |
3580 | |
3581 ATLASSERT(_DebugCheckChild()); | |
3582 | |
3583 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; | |
3584 RECT rect = { 0 }; | |
3585 GetWindowRect(&rect); | |
3586 pt.x -= rect.left; | |
3587 pt.y -= rect.top; | |
3588 | |
3589 RECT rcIcon = { 0 }; | |
3590 T* pT = static_cast<T*>(this); | |
3591 pT->_CalcIconRect(rect.right - rect.left, rect.bottom - rect.top
, rcIcon, m_bLayoutRTL); | |
3592 RECT arrRect[3] = { 0 }; | |
3593 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top
, arrRect, m_bLayoutRTL); | |
3594 | |
3595 if(::PtInRect(&rcIcon, pt)) | |
3596 { | |
3597 #ifdef _CMDBAR_EXTRA_TRACE | |
3598 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: i
con\n")); | |
3599 #endif | |
3600 #ifndef TPM_VERPOSANIMATION | |
3601 const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu anim
ation flag | |
3602 #endif | |
3603 CMenuHandle menu = ::GetSystemMenu(m_hWndChildMaximized,
FALSE); | |
3604 UINT uRet = (UINT)menu.TrackPopupMenu(TPM_LEFTBUTTON | T
PM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | | |
3605 (s_bW2K ? TPM_VERPOSANIMATION : 0), m_bLayoutRTL
? rect.right : rect.left, rect.bottom, m_hWndChildMaximized); | |
3606 | |
3607 // eat next message if click is on the same button | |
3608 ::OffsetRect(&rcIcon, rect.left, rect.top); | |
3609 MSG msg = { 0 }; | |
3610 if(::PeekMessage(&msg, m_hWnd, WM_NCLBUTTONDOWN, WM_NCLB
UTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rcIcon, msg.pt)) | |
3611 ::PeekMessage(&msg, m_hWnd, WM_NCLBUTTONDOWN, WM
_NCLBUTTONDOWN, PM_REMOVE); | |
3612 | |
3613 if(uRet != 0) | |
3614 ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAN
D, uRet, 0L); | |
3615 } | |
3616 else if(::PtInRect(&arrRect[0], pt)) | |
3617 { | |
3618 #ifdef _CMDBAR_EXTRA_TRACE | |
3619 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: c
lose button\n")); | |
3620 #endif | |
3621 m_nBtnWasPressed = m_nBtnPressed = 0; | |
3622 } | |
3623 else if(::PtInRect(&arrRect[1], pt)) | |
3624 { | |
3625 #ifdef _CMDBAR_EXTRA_TRACE | |
3626 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: r
estore button\n")); | |
3627 #endif | |
3628 m_nBtnWasPressed = m_nBtnPressed = 1; | |
3629 } | |
3630 else if(::PtInRect(&arrRect[2], pt)) | |
3631 { | |
3632 #ifdef _CMDBAR_EXTRA_TRACE | |
3633 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButtonDown: m
inimize button\n")); | |
3634 #endif | |
3635 m_nBtnWasPressed = m_nBtnPressed = 2; | |
3636 } | |
3637 else | |
3638 { | |
3639 bHandled = FALSE; | |
3640 } | |
3641 | |
3642 // draw the button state if it was pressed | |
3643 if(m_nBtnPressed != -1) | |
3644 { | |
3645 SetCapture(); | |
3646 CWindowDC dc(m_hWnd); | |
3647 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom -
rect.top, arrRect); | |
3648 pT->_DrawMDIButton(dc, arrRect, m_nBtnPressed); | |
3649 } | |
3650 | |
3651 return 0; | |
3652 } | |
3653 | |
3654 LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOO
L& bHandled) | |
3655 { | |
3656 if(!m_bChildMaximized || ::GetCapture() != m_hWnd || m_nBtnWasPr
essed == -1) | |
3657 { | |
3658 bHandled = FALSE; | |
3659 return 1; | |
3660 } | |
3661 | |
3662 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; | |
3663 ClientToScreen(&pt); | |
3664 RECT rect = { 0 }; | |
3665 GetWindowRect(&rect); | |
3666 pt.x -= rect.left; | |
3667 pt.y -= rect.top; | |
3668 RECT arrRect[3] = { 0 }; | |
3669 T* pT = static_cast<T*>(this); | |
3670 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top
, arrRect, m_bLayoutRTL); | |
3671 int nOldBtnPressed = m_nBtnPressed; | |
3672 m_nBtnPressed = ::PtInRect(&arrRect[m_nBtnWasPressed], pt) ? m_n
BtnWasPressed : -1; | |
3673 if(nOldBtnPressed != m_nBtnPressed) | |
3674 { | |
3675 CWindowDC dc(m_hWnd); | |
3676 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom -
rect.top, arrRect); | |
3677 pT->_DrawMDIButton(dc, arrRect, (m_nBtnPressed != -1) ?
m_nBtnPressed : nOldBtnPressed); | |
3678 } | |
3679 | |
3680 return 0; | |
3681 } | |
3682 | |
3683 LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOO
L& bHandled) | |
3684 { | |
3685 if(!m_bChildMaximized || ::GetCapture() != m_hWnd || m_nBtnWasPr
essed == -1) | |
3686 { | |
3687 bHandled = FALSE; | |
3688 return 1; | |
3689 } | |
3690 | |
3691 ATLASSERT(_DebugCheckChild()); | |
3692 | |
3693 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; | |
3694 ClientToScreen(&pt); | |
3695 RECT rect = { 0 }; | |
3696 GetWindowRect(&rect); | |
3697 pt.x -= rect.left; | |
3698 pt.y -= rect.top; | |
3699 | |
3700 int nBtn = m_nBtnWasPressed; | |
3701 ReleaseCapture(); | |
3702 | |
3703 RECT arrRect[3] = { 0 }; | |
3704 T* pT = static_cast<T*>(this); | |
3705 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top
, arrRect, m_bLayoutRTL); | |
3706 if(::PtInRect(&arrRect[nBtn], pt)) | |
3707 { | |
3708 switch(nBtn) | |
3709 { | |
3710 case 0: // close | |
3711 #ifdef _CMDBAR_EXTRA_TRACE | |
3712 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButto
nUp: close button\n")); | |
3713 #endif | |
3714 ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAN
D, SC_CLOSE, 0L); | |
3715 break; | |
3716 case 1: // restore | |
3717 #ifdef _CMDBAR_EXTRA_TRACE | |
3718 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButto
nUp: restore button\n")); | |
3719 #endif | |
3720 ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAN
D, SC_RESTORE, 0L); | |
3721 break; | |
3722 case 2: // minimize | |
3723 #ifdef _CMDBAR_EXTRA_TRACE | |
3724 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - LButto
nUp: minimize button\n")); | |
3725 #endif | |
3726 ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAN
D, SC_MINIMIZE, 0L); | |
3727 break; | |
3728 default: | |
3729 break; | |
3730 } | |
3731 } | |
3732 | |
3733 return 0; | |
3734 } | |
3735 | |
3736 LRESULT OnNcLButtonDblClk(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lPara
m, BOOL& bHandled) | |
3737 { | |
3738 if(!m_bChildMaximized || m_nBtnWasPressed != -1) | |
3739 { | |
3740 bHandled = FALSE; | |
3741 return 1; | |
3742 } | |
3743 | |
3744 ATLASSERT(_DebugCheckChild()); | |
3745 | |
3746 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; | |
3747 RECT rect = { 0 }; | |
3748 GetWindowRect(&rect); | |
3749 pt.x -= rect.left; | |
3750 pt.y -= rect.top; | |
3751 | |
3752 RECT rcIcon = { 0 }; | |
3753 T* pT = static_cast<T*>(this); | |
3754 pT->_CalcIconRect(rect.right - rect.left, rect.bottom - rect.top
, rcIcon, m_bLayoutRTL); | |
3755 RECT arrRect[3] = { 0 }; | |
3756 pT->_CalcBtnRects(rect.right - rect.left, rect.bottom - rect.top
, arrRect, m_bLayoutRTL); | |
3757 | |
3758 if(::PtInRect(&rcIcon, pt)) | |
3759 { | |
3760 CMenuHandle menu = ::GetSystemMenu(m_hWndChildMaximized,
FALSE); | |
3761 UINT uDefID = menu.GetMenuDefaultItem(); | |
3762 if(uDefID == (UINT)-1) | |
3763 uDefID = SC_CLOSE; | |
3764 ::SendMessage(m_hWndChildMaximized, WM_SYSCOMMAND, uDefI
D, 0L); | |
3765 } | |
3766 | |
3767 return 0; | |
3768 } | |
3769 | |
3770 LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPar
am*/, BOOL& bHandled) | |
3771 { | |
3772 if(m_bChildMaximized) | |
3773 { | |
3774 if(m_nBtnPressed != -1) | |
3775 { | |
3776 ATLASSERT(m_nBtnPressed == m_nBtnWasPressed);
// must be | |
3777 m_nBtnPressed = -1; | |
3778 RECT rect = { 0 }; | |
3779 GetWindowRect(&rect); | |
3780 RECT arrRect[3] = { 0 }; | |
3781 T* pT = static_cast<T*>(this); | |
3782 pT->_CalcBtnRects(rect.right - rect.left, rect.b
ottom - rect.top, arrRect); | |
3783 CWindowDC dc(m_hWnd); | |
3784 pT->_DrawMDIButton(dc, arrRect, m_nBtnWasPressed
); | |
3785 } | |
3786 m_nBtnWasPressed = -1; | |
3787 } | |
3788 else | |
3789 { | |
3790 bHandled = FALSE; | |
3791 } | |
3792 return 0; | |
3793 } | |
3794 | |
3795 // Parent window message handlers | |
3796 LRESULT OnParentActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/
, BOOL& bHandled) | |
3797 { | |
3798 m_bParentActive = (LOWORD(wParam) != WA_INACTIVE); | |
3799 RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATE
NOW); | |
3800 bHandled = FALSE; | |
3801 return 1; | |
3802 } | |
3803 | |
3804 // MDI client window message handlers | |
3805 LRESULT OnMDISetMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bH
andled*/) | |
3806 { | |
3807 m_wndMDIClient.DefWindowProc(uMsg, NULL, lParam); | |
3808 HMENU hOldMenu = GetMenu(); | |
3809 BOOL bRet = AttachMenu((HMENU)wParam); | |
3810 bRet; // avoid level 4 warning | |
3811 ATLASSERT(bRet); | |
3812 | |
3813 #if (_WIN32_IE >= 0x0400) | |
3814 T* pT = static_cast<T*>(this); | |
3815 pT->UpdateRebarBandIdealSize(); | |
3816 #endif // (_WIN32_IE >= 0x0400) | |
3817 | |
3818 return (LRESULT)hOldMenu; | |
3819 } | |
3820 | |
3821 // All messages from the message hook | |
3822 LRESULT OnAllHookMessages(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL&
bHandled) | |
3823 { | |
3824 T* pT = static_cast<T*>(this); | |
3825 pT->_ProcessAllHookMessages(uMsg, wParam, lParam); | |
3826 | |
3827 bHandled = FALSE; | |
3828 return 1; | |
3829 } | |
3830 | |
3831 // Overrideables | |
3832 // override this to provide different ideal size | |
3833 void UpdateRebarBandIdealSize() | |
3834 { | |
3835 // assuming we are in a rebar, change ideal size to our size | |
3836 // we hope that if we are not in a rebar, nCount will be 0 | |
3837 int nCount = (int)::SendMessage(GetParent(), RB_GETBANDCOUNT, 0,
0L); | |
3838 for(int i = 0; i < nCount; i++) | |
3839 { | |
3840 REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBARBANDINF
O(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE }; | |
3841 ::SendMessage(GetParent(), RB_GETBANDINFO, i, (LPARAM)&r
bi); | |
3842 if(rbi.hwndChild == m_hWnd) | |
3843 { | |
3844 rbi.fMask = RBBIM_IDEALSIZE; | |
3845 rbi.cxIdeal = m_bChildMaximized ? m_cxLeft + m_c
xRight : 0; | |
3846 int nBtnCount = GetButtonCount(); | |
3847 if(nBtnCount > 0) | |
3848 { | |
3849 RECT rect = { 0 }; | |
3850 GetItemRect(nBtnCount - 1, &rect); | |
3851 rbi.cxIdeal += rect.right; | |
3852 } | |
3853 ::SendMessage(GetParent(), RB_SETBANDINFO, i, (L
PARAM)&rbi); | |
3854 break; | |
3855 } | |
3856 } | |
3857 } | |
3858 | |
3859 // all hook messages - check for the maximized MDI child window change | |
3860 void _ProcessAllHookMessages(UINT uMsg, WPARAM /*wParam*/, LPARAM /*lPar
am*/) | |
3861 { | |
3862 if(uMsg == WM_MDIGETACTIVE || uMsg == WM_MDISETMENU) | |
3863 return; | |
3864 | |
3865 BOOL bMaximized = FALSE; | |
3866 HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, WM_MDIGETAC
TIVE, 0, (LPARAM)&bMaximized); | |
3867 bool bMaxOld = m_bChildMaximized; | |
3868 m_bChildMaximized = (hWndChild != NULL && bMaximized); | |
3869 HICON hIconOld = m_hIconChildMaximized; | |
3870 | |
3871 if(m_bChildMaximized) | |
3872 { | |
3873 if(m_hWndChildMaximized != hWndChild) | |
3874 { | |
3875 ATL::CWindow wnd = m_hWndChildMaximized = hWndCh
ild; | |
3876 m_hIconChildMaximized = wnd.GetIcon(FALSE); | |
3877 if(m_hIconChildMaximized == NULL) | |
3878 { | |
3879 m_hIconChildMaximized = wnd.GetIcon(TRUE
); | |
3880 if(m_hIconChildMaximized == NULL) | |
3881 { | |
3882 // no icon set with WM_SETICON,
get the class one | |
3883 // need conditional code because types don't match in winuser.h | |
3884 #ifdef _WIN64 | |
3885 m_hIconChildMaximized = (HICON):
:GetClassLongPtr(wnd, GCLP_HICONSM); | |
3886 #else | |
3887 m_hIconChildMaximized = (HICON)L
ongToHandle(::GetClassLongPtr(wnd, GCLP_HICONSM)); | |
3888 #endif | |
3889 } | |
3890 } | |
3891 } | |
3892 } | |
3893 else | |
3894 { | |
3895 m_hWndChildMaximized = NULL; | |
3896 m_hIconChildMaximized = NULL; | |
3897 } | |
3898 | |
3899 if(bMaxOld != m_bChildMaximized) | |
3900 { | |
3901 #ifdef _CMDBAR_EXTRA_TRACE | |
3902 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - All messages h
ook change: m_bChildMaximized = %s\n"), m_bChildMaximized ? "true" : "false"); | |
3903 #endif | |
3904 // assuming we are in a rebar, change our size to accomo
date new state | |
3905 // we hope that if we are not in a rebar, nCount will be
0 | |
3906 int nCount = (int)::SendMessage(GetParent(), RB_GETBANDC
OUNT, 0, 0L); | |
3907 int cxDiff = (m_bChildMaximized ? 1 : -1) * (m_cxLeft +
m_cxRight); | |
3908 for(int i = 0; i < nCount; i++) | |
3909 { | |
3910 #if (_WIN32_IE >= 0x0500) | |
3911 REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBA
RBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_STYLE }; | |
3912 ::SendMessage(GetParent(), RB_GETBANDINFO, i, (L
PARAM)&rbi); | |
3913 if(rbi.hwndChild == m_hWnd) | |
3914 { | |
3915 if((rbi.fStyle & RBBS_USECHEVRON) != 0) | |
3916 { | |
3917 rbi.fMask = RBBIM_CHILDSIZE | RB
BIM_IDEALSIZE; | |
3918 rbi.cxMinChild += cxDiff; | |
3919 rbi.cxIdeal += cxDiff; | |
3920 ::SendMessage(GetParent(), RB_SE
TBANDINFO, i, (LPARAM)&rbi); | |
3921 } | |
3922 break; | |
3923 } | |
3924 #elif (_WIN32_IE >= 0x0400) | |
3925 REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBA
RBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_IDEALSIZE }; | |
3926 ::SendMessage(GetParent(), RB_GETBANDINFO, i, (L
PARAM)&rbi); | |
3927 if(rbi.hwndChild == m_hWnd) | |
3928 { | |
3929 rbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEA
LSIZE; | |
3930 rbi.cxMinChild += cxDiff; | |
3931 rbi.cxIdeal += cxDiff; | |
3932 ::SendMessage(GetParent(), RB_SETBANDINF
O, i, (LPARAM)&rbi); | |
3933 break; | |
3934 } | |
3935 #else // (_WIN32_IE < 0x0400) | |
3936 REBARBANDINFO rbi = { RunTimeHelper::SizeOf_REBA
RBANDINFO(), RBBIM_CHILD | RBBIM_CHILDSIZE }; | |
3937 ::SendMessage(GetParent(), RB_GETBANDINFO, i, (L
PARAM)&rbi); | |
3938 if(rbi.hwndChild == m_hWnd) | |
3939 { | |
3940 rbi.fMask = RBBIM_CHILDSIZE; | |
3941 rbi.cxMinChild += cxDiff; | |
3942 ::SendMessage(GetParent(), RB_SETBANDINF
O, i, (LPARAM)&rbi); | |
3943 break; | |
3944 } | |
3945 #endif // (_WIN32_IE < 0x0400) | |
3946 } | |
3947 } | |
3948 | |
3949 if(bMaxOld != m_bChildMaximized || hIconOld != m_hIconChildMaxim
ized) | |
3950 { | |
3951 // force size change and redraw everything | |
3952 RECT rect = { 0 }; | |
3953 GetWindowRect(&rect); | |
3954 ::MapWindowPoints(NULL, GetParent(), (LPPOINT)&rect, 2); | |
3955 SetRedraw(FALSE); | |
3956 SetWindowPos(NULL, 0, 0, 1, 1, SWP_NOZORDER | SWP_NOMOVE
); | |
3957 SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE); | |
3958 SetRedraw(TRUE); | |
3959 RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RD
W_UPDATENOW); | |
3960 } | |
3961 } | |
3962 | |
3963 // Implementation | |
3964 void GetSystemSettings() | |
3965 { | |
3966 #ifdef _CMDBAR_EXTRA_TRACE | |
3967 ATLTRACE2(atlTraceUI, 0, _T("MDI CmdBar - GetSystemSettings\n"))
; | |
3968 #endif | |
3969 _baseClass::GetSystemSettings(); | |
3970 | |
3971 NONCLIENTMETRICS info = { RunTimeHelper::SizeOf_NONCLIENTMETRICS
() }; | |
3972 BOOL bRet = ::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size
of(info), &info, 0); | |
3973 ATLASSERT(bRet); | |
3974 if(bRet) | |
3975 { | |
3976 m_cxIconWidth = ::GetSystemMetrics(SM_CXSMICON); | |
3977 m_cyIconHeight = ::GetSystemMetrics(SM_CYSMICON); | |
3978 m_cxLeft = m_cxIconWidth; | |
3979 | |
3980 #ifndef _WTL_NO_AUTO_THEME | |
3981 if(m_hTheme != NULL) | |
3982 { | |
3983 m_cxBtnWidth = info.iCaptionWidth - 2 * m_cxyOff
set; | |
3984 m_cyBtnHeight = info.iCaptionHeight - 2 * m_cxyO
ffset; | |
3985 m_cxRight = 3 * m_cxBtnWidth; | |
3986 } | |
3987 else | |
3988 #endif // !_WTL_NO_AUTO_THEME | |
3989 { | |
3990 m_cxBtnWidth = info.iCaptionWidth - m_cxyOffset; | |
3991 m_cyBtnHeight = info.iCaptionHeight - 2 * m_cxyO
ffset; | |
3992 m_cxRight = 3 * m_cxBtnWidth + m_cxyOffset; | |
3993 } | |
3994 } | |
3995 | |
3996 RECT rect = { 0 }; | |
3997 GetClientRect(&rect); | |
3998 T* pT = static_cast<T*>(this); | |
3999 pT->_AdjustBtnSize(rect.bottom); | |
4000 } | |
4001 | |
4002 void _AdjustBtnSize(int cyHeight) | |
4003 { | |
4004 if(cyHeight > 1 && m_cyBtnHeight > cyHeight) | |
4005 { | |
4006 #ifndef _WTL_NO_AUTO_THEME | |
4007 if(m_hTheme != NULL) | |
4008 { | |
4009 m_cyBtnHeight = cyHeight; | |
4010 m_cxBtnWidth = cyHeight; | |
4011 m_cxRight = 3 * m_cxBtnWidth; | |
4012 } | |
4013 else | |
4014 #endif // !_WTL_NO_AUTO_THEME | |
4015 { | |
4016 m_cyBtnHeight = cyHeight; | |
4017 m_cxBtnWidth = cyHeight + m_cxyOffset; | |
4018 m_cxRight = 3 * m_cxBtnWidth + m_cxyOffset; | |
4019 } | |
4020 } | |
4021 } | |
4022 | |
4023 void _CalcIconRect(int cxWidth, int cyHeight, RECT& rect, bool bInvertX
= false) const | |
4024 { | |
4025 int xStart = (m_cxLeft - m_cxIconWidth) / 2; | |
4026 if(xStart < 0) | |
4027 xStart = 0; | |
4028 int yStart = (cyHeight - m_cyIconHeight) / 2; | |
4029 if(yStart < 0) | |
4030 yStart = 0; | |
4031 | |
4032 if(bInvertX) | |
4033 ::SetRect(&rect, cxWidth - (xStart + m_cxBtnWidth), ySta
rt, cxWidth - xStart, yStart + m_cyBtnHeight); | |
4034 else | |
4035 ::SetRect(&rect, xStart, yStart, xStart + m_cxBtnWidth,
yStart + m_cyBtnHeight); | |
4036 } | |
4037 | |
4038 void _CalcBtnRects(int cxWidth, int cyHeight, RECT arrRect[3], bool bInv
ertX = false) const | |
4039 { | |
4040 int yStart = (cyHeight - m_cyBtnHeight) / 2; | |
4041 if(yStart < 0) | |
4042 yStart = 0; | |
4043 | |
4044 RECT rcBtn = { cxWidth - m_cxBtnWidth, yStart, cxWidth, yStart +
m_cyBtnHeight }; | |
4045 int nDirection = -1; | |
4046 if(bInvertX) | |
4047 { | |
4048 ::SetRect(&rcBtn, 0, yStart, m_cxBtnWidth, yStart + m_cy
BtnHeight); | |
4049 nDirection = 1; | |
4050 } | |
4051 | |
4052 arrRect[0] = rcBtn; | |
4053 #ifndef _WTL_NO_AUTO_THEME | |
4054 if(m_hTheme != NULL) | |
4055 ::OffsetRect(&rcBtn, nDirection * m_cxBtnWidth, 0); | |
4056 else | |
4057 #endif // !_WTL_NO_AUTO_THEME | |
4058 ::OffsetRect(&rcBtn, nDirection * (m_cxBtnWidth + m_cxyO
ffset), 0); | |
4059 arrRect[1] = rcBtn; | |
4060 ::OffsetRect(&rcBtn, nDirection * m_cxBtnWidth, 0); | |
4061 arrRect[2] = rcBtn; | |
4062 } | |
4063 | |
4064 void _DrawMDIButton(CWindowDC& dc, LPRECT pRects, int nBtn) | |
4065 { | |
4066 #ifndef _WTL_NO_AUTO_THEME | |
4067 if(m_hTheme != NULL) | |
4068 { | |
4069 #ifndef TMSCHEMA_H | |
4070 const int WP_MDICLOSEBUTTON = 20; | |
4071 const int CBS_NORMAL = 1; | |
4072 const int CBS_PUSHED = 3; | |
4073 const int CBS_DISABLED = 4; | |
4074 const int WP_MDIRESTOREBUTTON = 22; | |
4075 const int RBS_NORMAL = 1; | |
4076 const int RBS_PUSHED = 3; | |
4077 const int RBS_DISABLED = 4; | |
4078 const int WP_MDIMINBUTTON = 16; | |
4079 const int MINBS_NORMAL = 1; | |
4080 const int MINBS_PUSHED = 3; | |
4081 const int MINBS_DISABLED = 4; | |
4082 #endif // TMSCHEMA_H | |
4083 if(nBtn == -1 || nBtn == 0) | |
4084 m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDICLO
SEBUTTON, m_bParentActive ? ((m_nBtnPressed == 0) ? CBS_PUSHED : CBS_NORMAL) : C
BS_DISABLED, &pRects[0], NULL); | |
4085 if(nBtn == -1 || nBtn == 1) | |
4086 m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDIRES
TOREBUTTON, m_bParentActive ? ((m_nBtnPressed == 1) ? RBS_PUSHED : RBS_NORMAL) :
RBS_DISABLED, &pRects[1], NULL); | |
4087 if(nBtn == -1 || nBtn == 2) | |
4088 m_pfnDrawThemeBackground(m_hTheme, dc, WP_MDIMIN
BUTTON, m_bParentActive ? ((m_nBtnPressed == 2) ? MINBS_PUSHED : MINBS_NORMAL) :
MINBS_DISABLED, &pRects[2], NULL); | |
4089 } | |
4090 else | |
4091 #endif // !_WTL_NO_AUTO_THEME | |
4092 { | |
4093 if(nBtn == -1 || nBtn == 0) | |
4094 dc.DrawFrameControl(&pRects[0], DFC_CAPTION, DFC
S_CAPTIONCLOSE | ((m_nBtnPressed == 0) ? DFCS_PUSHED : 0)); | |
4095 if(nBtn == -1 || nBtn == 1) | |
4096 dc.DrawFrameControl(&pRects[1], DFC_CAPTION, DFC
S_CAPTIONRESTORE | ((m_nBtnPressed == 1) ? DFCS_PUSHED : 0)); | |
4097 if(nBtn == -1 || nBtn == 2) | |
4098 dc.DrawFrameControl(&pRects[2], DFC_CAPTION, DFC
S_CAPTIONMIN | ((m_nBtnPressed == 2) ? DFCS_PUSHED : 0)); | |
4099 } | |
4100 } | |
4101 | |
4102 #ifndef _WTL_NO_AUTO_THEME | |
4103 static UINT _GetThemeChangedMsg() | |
4104 { | |
4105 #ifndef WM_THEMECHANGED | |
4106 static const UINT WM_THEMECHANGED = 0x031A; | |
4107 #endif // !WM_THEMECHANGED | |
4108 return WM_THEMECHANGED; | |
4109 } | |
4110 | |
4111 void _OpenThemeData() | |
4112 { | |
4113 ATLASSERT(m_hThemeDLL != NULL); | |
4114 | |
4115 PFN_OpenThemeData pfnOpenThemeData = (PFN_OpenThemeData)::GetPro
cAddress(m_hThemeDLL, "OpenThemeData"); | |
4116 ATLASSERT(pfnOpenThemeData != NULL); | |
4117 if(pfnOpenThemeData != NULL) | |
4118 m_hTheme = pfnOpenThemeData(m_hWnd, L"Window"); | |
4119 } | |
4120 | |
4121 void _CloseThemeData() | |
4122 { | |
4123 ATLASSERT(m_hThemeDLL != NULL); | |
4124 | |
4125 if(m_hTheme == NULL) | |
4126 return; // nothing to do | |
4127 | |
4128 PFN_CloseThemeData pfnCloseThemeData = (PFN_CloseThemeData)::Get
ProcAddress(m_hThemeDLL, "CloseThemeData"); | |
4129 ATLASSERT(pfnCloseThemeData != NULL); | |
4130 if(pfnCloseThemeData != NULL) | |
4131 { | |
4132 pfnCloseThemeData(m_hTheme); | |
4133 m_hTheme = NULL; | |
4134 } | |
4135 } | |
4136 #endif // !_WTL_NO_AUTO_THEME | |
4137 | |
4138 bool _DebugCheckChild() | |
4139 { | |
4140 #ifdef _DEBUG | |
4141 BOOL bMaximized = FALSE; | |
4142 HWND hWndChild = (HWND)::SendMessage(m_wndMDIClient, WM_MDIGETAC
TIVE, 0, (LPARAM)&bMaximized); | |
4143 return (bMaximized && hWndChild == m_hWndChildMaximized); | |
4144 #else // !_DEBUG | |
4145 return true; | |
4146 #endif // !_DEBUG | |
4147 } | |
4148 }; | |
4149 | |
4150 class CMDICommandBarCtrl : public CMDICommandBarCtrlImpl<CMDICommandBarCtrl> | |
4151 { | |
4152 public: | |
4153 DECLARE_WND_SUPERCLASS(_T("WTL_MDICommandBar"), GetWndClassName()) | |
4154 }; | |
4155 | |
4156 }; // namespace WTL | |
4157 | |
4158 #endif // __ATLCTRLW_H__ | |
OLD | NEW |