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