1 // Win32++ Version 7.3
\r
2 // Released: 30th November 2011
\r
6 // url: https://sourceforge.net/projects/win32-framework
\r
9 // Copyright (c) 2005-2011 David Nash
\r
11 // Permission is hereby granted, free of charge, to
\r
12 // any person obtaining a copy of this software and
\r
13 // associated documentation files (the "Software"),
\r
14 // to deal in the Software without restriction, including
\r
15 // without limitation the rights to use, copy, modify,
\r
16 // merge, publish, distribute, sublicense, and/or sell
\r
17 // copies of the Software, and to permit persons to whom
\r
18 // the Software is furnished to do so, subject to the
\r
19 // following conditions:
\r
21 // The above copyright notice and this permission notice
\r
22 // shall be included in all copies or substantial portions
\r
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
\r
26 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
\r
27 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
\r
28 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
\r
29 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
\r
30 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
31 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
32 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
\r
33 // OR OTHER DEALINGS IN THE SOFTWARE.
\r
35 ////////////////////////////////////////////////////////
\r
38 ////////////////////////////////////////////////////////
\r
40 // Declaration of the CFrame and CMenuBar classes
\r
42 // The classes declared in this file support SDI (Single Document Interface)
\r
43 // frames on Win32/Win64 operating systems (not Windows CE). For Windows CE,
\r
44 // use wceframe.h instead. SDI frames are a simple frame which supports a
\r
45 // single view window. Refer to mdi.h for frames that support several
\r
48 // CFrame also includes each of the following classes as members:
\r
49 // * CReBar for managing the frame's rebar control.
\r
50 // * CMenuBar for managing the menu inside the rebar.
\r
51 // * CToolBar for managing the frame's toolbar.
\r
52 // * CStatusBar for managing the frame's status bar.
\r
53 // In each case these members are exposed by a GetXXX function, allowing
\r
54 // them to be accessed or sent messages.
\r
56 // CFrame is responsible for creating a "frame" window. This window has a
\r
57 // menu and and several child windows, including a toolbar (usualy hosted
\r
58 // within a rebar), a status bar, and a view positioned over the frame
\r
59 // window's non-client area. The "view" window is a seperate CWnd object
\r
60 // assigned to the frame with the SetView function.
\r
62 // When compiling an application with these classes, it will need to be linked
\r
63 // with Comctl32.lib.
\r
65 // To create a SDI frame application, inherit a CMainFrame class from CFrame.
\r
66 // Use the Frame sample application as the starting point for your own frame
\r
68 // Refer to the Notepad and Scribble samples for examples on how to use these
\r
69 // classes to create a frame application.
\r
72 #ifndef _WIN32XX_FRAME_H_
\r
73 #define _WIN32XX_FRAME_H_
\r
75 #include "wincore.h"
\r
78 #include "statusbar.h"
\r
79 #include "toolbar.h"
\r
81 #include "default_resource.h"
\r
84 #define RBN_MINMAX (RBN_FIRST - 21)
\r
86 #ifndef TMT_BORDERSIZE
\r
87 #define TMT_BORDERSIZE 2403
\r
89 #ifndef TMT_CONTENTMARGINS
\r
90 #define TMT_CONTENTMARGINS 3602
\r
92 #ifndef VSCLASS_MENU
\r
93 #define VSCLASS_MENU L"MENU"
\r
96 #define ODS_NOACCEL 0x0100
\r
98 #ifndef ODS_HOTLIGHT
\r
99 #define ODS_HOTLIGHT 0x0040
\r
101 #ifndef ODS_INACTIVE
\r
102 #define ODS_INACTIVE 0x0080
\r
104 #ifndef DT_HIDEPREFIX
\r
105 #define DT_HIDEPREFIX 0x00100000
\r
113 ////////////////////////////////////////////////
\r
114 // Declarations for structures for themes
\r
118 BOOL UseThemes; // TRUE if themes are used
\r
119 COLORREF clrHot1; // Colour 1 for top menu. Color of selected menu item
\r
120 COLORREF clrHot2; // Colour 2 for top menu. Color of checkbox
\r
121 COLORREF clrPressed1; // Colour 1 for pressed top menu and side bar
\r
122 COLORREF clrPressed2; // Colour 2 for pressed top menu and side bar
\r
123 COLORREF clrOutline; // Colour for border outline
\r
126 // define some structs and enums from uxtheme.h and vssym32.h
\r
127 typedef struct _MARGINS
\r
129 int cxLeftWidth; // width of left border that retains its size
\r
130 int cxRightWidth; // width of right border that retains its size
\r
131 int cyTopHeight; // height of top border that retains its size
\r
132 int cyBottomHeight; // height of bottom border that retains its size
\r
133 } MARGINS, *PMARGINS;
\r
135 class CMargins : public MARGINS
\r
138 CMargins(int cxLeft, int cxRight, int cyTop, int cyBottom)
\r
140 cxLeftWidth = cxLeft; cxRightWidth = cxRight;
\r
141 cyTopHeight = cyTop; cyBottomHeight = cyBottom;
\r
145 cxLeftWidth = 0; cxRightWidth = 0;
\r
146 cyTopHeight = 0; cyBottomHeight = 0;
\r
148 int Width() const { return cxLeftWidth + cxRightWidth; }
\r
149 int Height() const { return cyTopHeight + cyBottomHeight; }
\r
150 void SetMargins(int cxLeft, int cxRight, int cyTop, int cyBottom)
\r
152 cxLeftWidth = cxLeft; cxRightWidth = cxRight;
\r
153 cyTopHeight = cyTop; cyBottomHeight = cyBottom;
\r
159 TS_MIN, // minimum size
\r
160 TS_TRUE, // size without stretching
\r
161 TS_DRAW // size that theme mgr will use to draw part
\r
164 enum POPUPCHECKSTATES
\r
166 MC_CHECKMARKNORMAL = 1,
\r
167 MC_CHECKMARKDISABLED = 2,
\r
168 MC_BULLETNORMAL = 3,
\r
169 MC_BULLETDISABLED = 4,
\r
172 enum POPUPCHECKBACKGROUNDSTATES
\r
179 enum POPUPITEMSTATES
\r
184 MPI_DISABLEDHOT = 4,
\r
187 enum POPUPSUBMENUSTATES
\r
195 MENU_MENUITEM_TMSCHEMA = 1,
\r
196 MENU_MENUDROPDOWN_TMSCHEMA = 2,
\r
197 MENU_MENUBARITEM_TMSCHEMA = 3,
\r
198 MENU_MENUBARDROPDOWN_TMSCHEMA = 4,
\r
199 MENU_CHEVRON_TMSCHEMA = 5,
\r
200 MENU_SEPARATOR_TMSCHEMA = 6,
\r
201 MENU_BARBACKGROUND = 7,
\r
203 MENU_POPUPBACKGROUND = 9,
\r
204 MENU_POPUPBORDERS = 10,
\r
205 MENU_POPUPCHECK = 11,
\r
206 MENU_POPUPCHECKBACKGROUND = 12,
\r
207 MENU_POPUPGUTTER = 13,
\r
208 MENU_POPUPITEM = 14,
\r
209 MENU_POPUPSEPARATOR = 15,
\r
210 MENU_POPUPSUBMENU = 16,
\r
211 MENU_SYSTEMCLOSE = 17,
\r
212 MENU_SYSTEMMAXIMIZE = 18,
\r
213 MENU_SYSTEMMINIMIZE = 19,
\r
214 MENU_SYSTEMRESTORE = 20,
\r
218 // Forward declaration of CFrame. Its defined later.
\r
221 struct MenuItemData
\r
222 // Each Dropdown menu item has this data
\r
227 std::vector<TCHAR> vItemText;
\r
229 MenuItemData() : hMenu(0), nPos(0) { vItemText.assign(MAX_MENU_STRING, _T('\0')); }
\r
230 LPTSTR GetItemText() {return &vItemText[0];}
\r
234 ////////////////////////////////////
\r
235 // Declaration of the CMenuBar class
\r
237 class CMenuBar : public CToolBar
\r
239 friend class CFrame;
\r
243 virtual ~CMenuBar();
\r
244 virtual void SetMenu(HMENU hMenu);
\r
245 virtual void SetMenuBarTheme(MenuTheme& Theme);
\r
247 HMENU GetMenu() const {return m_hTopMenu;}
\r
248 MenuTheme& GetMenuBarTheme() {return m_ThemeMenu;}
\r
252 virtual void OnCreate();
\r
253 virtual LRESULT OnCustomDraw(NMHDR* pNMHDR);
\r
254 virtual void OnKeyDown(WPARAM wParam, LPARAM lParam);
\r
255 virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);
\r
256 virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);
\r
257 virtual void OnMenuChar(WPARAM wParam, LPARAM lParam);
\r
258 virtual BOOL OnMenuInput(UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
259 virtual void OnMouseLeave();
\r
260 virtual void OnMouseMove(WPARAM wParam, LPARAM lParam);
\r
261 virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);
\r
262 virtual void OnSysCommand(WPARAM wParam, LPARAM lParam);
\r
263 virtual void OnWindowPosChanged();
\r
264 virtual void PreCreate(CREATESTRUCT &cs);
\r
265 virtual void PreRegisterClass(WNDCLASS &wc);
\r
266 virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
269 CMenuBar(const CMenuBar&); // Disable copy construction
\r
270 CMenuBar& operator = (const CMenuBar&); // Disable assignment operator
\r
271 void DoAltKey(WORD KeyCode);
\r
272 void DoPopupMenu();
\r
273 void DrawAllMDIButtons(CDC& DrawDC);
\r
274 void DrawMDIButton(CDC& DrawDC, int iButton, UINT uState);
\r
276 HWND GetActiveMDIChild();
\r
278 BOOL IsMDIChildMaxed() const;
\r
279 BOOL IsMDIFrame() const;
\r
280 void ReleaseFocus();
\r
281 void SetHotItem(int nHot);
\r
282 static LRESULT CALLBACK StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam);
\r
291 BOOL m_bExitAfter; // Exit after Popup menu ends
\r
292 BOOL m_bKeyMode; // keyboard navigation mode
\r
293 BOOL m_bMenuActive; // popup menu active
\r
294 BOOL m_bSelPopup; // a popup (cascade) menu is selected
\r
295 HMENU m_hPopupMenu; // handle to the popup menu
\r
296 HMENU m_hSelMenu; // handle to the casceded popup menu
\r
297 HMENU m_hTopMenu; // handle to the top level menu
\r
298 HWND m_hPrevFocus; // handle to window which had focus
\r
299 CRect m_MDIRect[3]; // array of CRect for MDI buttons
\r
300 int m_nHotItem; // hot item
\r
301 int m_nMDIButton; // the MDI button (MDIButtonType) pressed
\r
302 CPoint m_OldMousePos; // old Mouse position
\r
303 MenuTheme m_ThemeMenu; // Theme structure
\r
304 CFrame* m_pFrame; // Pointer to the frame
\r
306 }; // class CMenuBar
\r
309 /////////////////////////////////////
\r
310 // Declaration of the CMenuMetrics class
\r
311 // This class is used by CFrame to retrieve the size of the components
\r
312 // used to perform owner-drawing of menu items. Windows Visual Styles
\r
313 // are used to render menu items for systems running Aero (Vista and above).
\r
314 // Win32++ custom themes are used to render menu items for systems without Aero.
\r
318 CMenuMetrics(CFrame* pFrame);
\r
321 CRect GetCheckBackgroundRect(CRect rcItem);
\r
322 CRect GetCheckRect(CRect rcItem);
\r
323 CRect GetGutterRect(CRect rcItem);
\r
324 CRect GetSelectionRect(CRect rcItem);
\r
325 CRect GetSeperatorRect(CRect rcItem);
\r
326 CRect GetTextRect(CRect rcItem);
\r
327 CSize GetTextSize(MenuItemData* pmd);
\r
329 int ToItemStateId(UINT uItemState);
\r
330 int ToCheckBackgroundStateId(int iStateId);
\r
331 int ToCheckStateId(UINT fType, int iStateId);
\r
333 // Wrappers for Windows API functions
\r
334 HRESULT CloseThemeData();
\r
335 HRESULT DrawThemeBackground(HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect);
\r
336 HRESULT DrawThemeText(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect);
\r
337 HRESULT GetThemePartSize(HDC hdc, int iPartId, int iStateId, LPCRECT prc, THEMESIZE eSize, SIZE* psz);
\r
338 HRESULT GetThemeInt(int iPartId, int iStateId, int iPropId, int* piVal);
\r
339 HRESULT GetThemeMargins(HDC hdc, int iPartId, int iStateId, int iPropId, LPRECT prc, MARGINS* pMargins);
\r
340 HRESULT GetThemeTextExtent(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect);
\r
341 BOOL IsThemeBackgroundPartiallyTransparent(int iPartId, int iStateId);
\r
342 HANDLE OpenThemeData(HWND hwnd, LPCWSTR pszClassList);
\r
344 HANDLE m_hTheme; // Theme handle
\r
345 CFrame* m_pFrame; // Pointer to the frame window
\r
347 CMargins m_marCheck; // Check margins
\r
348 CMargins m_marCheckBackground; // Check background margins
\r
349 CMargins m_marItem; // Item margins
\r
350 CMargins m_marText; // Text margins
\r
352 CSize m_sizeCheck; // Check size metric
\r
353 CSize m_sizeSeparator; // Separator size metric
\r
356 typedef HRESULT WINAPI CLOSETHEMEDATA(HANDLE);
\r
357 typedef HRESULT WINAPI DRAWTHEMEBACKGROUND(HANDLE, HDC, int, int, const RECT*, const RECT*);
\r
358 typedef HRESULT WINAPI DRAWTHEMETEXT(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, LPCRECT);
\r
359 typedef HRESULT WINAPI GETTHEMEPARTSIZE(HANDLE, HDC, int, int, LPCRECT, THEMESIZE, SIZE*);
\r
360 typedef HRESULT WINAPI GETTHEMEINT(HANDLE, int, int, int, int*);
\r
361 typedef HRESULT WINAPI GETTHEMEMARGINS(HANDLE, HDC, int, int, int, LPRECT, MARGINS*);
\r
362 typedef HRESULT WINAPI GETTHEMETEXTEXTENT(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, LPCRECT, LPCRECT);
\r
363 typedef HRESULT WINAPI ISTHEMEBGPARTTRANSPARENT(HANDLE, int, int);
\r
364 typedef HANDLE WINAPI OPENTHEMEDATA(HWND, LPCWSTR);
\r
366 // Pointers to functions defined in uxTheme.dll
\r
367 CLOSETHEMEDATA* m_pfnCloseThemeData;
\r
368 DRAWTHEMEBACKGROUND* m_pfnDrawThemeBackground;
\r
369 DRAWTHEMETEXT* m_pfnDrawThemeText;
\r
370 GETTHEMEPARTSIZE* m_pfnGetThemePartSize;
\r
371 GETTHEMEINT* m_pfnGetThemeInt;
\r
372 GETTHEMEMARGINS* m_pfnGetThemeMargins;
\r
373 GETTHEMETEXTEXTENT* m_pfnGetThemeTextExtent;
\r
374 ISTHEMEBGPARTTRANSPARENT* m_pfnIsThemeBGPartTransparent;
\r
375 OPENTHEMEDATA* m_pfnOpenThemeData;
\r
379 //////////////////////////////////
\r
380 // Declaration of the CFrame class
\r
382 class CFrame : public CWnd
\r
384 friend class CMenuBar;
\r
385 typedef Shared_Ptr<MenuItemData> ItemDataPtr;
\r
391 // Override these functions as required
\r
392 virtual void AdjustFrameRect(RECT rcView) const;
\r
393 virtual CString GetThemeName() const;
\r
394 virtual CRect GetViewRect() const;
\r
395 virtual BOOL IsMDIFrame() const { return FALSE; }
\r
396 virtual void SetStatusIndicators();
\r
397 virtual void SetStatusText();
\r
398 virtual void RecalcLayout();
\r
399 virtual MenuTheme& GetMenuTheme() const { return (MenuTheme&) m_ThemeMenu; }
\r
400 virtual ReBarTheme& GetReBarTheme() const { return (ReBarTheme&)GetReBar().GetReBarTheme(); }
\r
401 virtual ToolBarTheme& GetToolBarTheme() const { return (ToolBarTheme&)GetToolBar().GetToolBarTheme(); }
\r
403 // Virtual Attributes
\r
404 // If you need to modify the default behaviour of the menubar, rebar,
\r
405 // statusbar or toolbar, inherit from those classes, and override
\r
406 // the following attribute functions.
\r
407 virtual CMenuBar& GetMenuBar() const { return (CMenuBar&)m_MenuBar; }
\r
408 virtual CReBar& GetReBar() const { return (CReBar&)m_ReBar; }
\r
409 virtual CStatusBar& GetStatusBar() const { return (CStatusBar&)m_StatusBar; }
\r
410 virtual CToolBar& GetToolBar() const { return (CToolBar&)m_ToolBar; }
\r
412 // These functions aren't virtual, and shouldn't be overridden
\r
413 HACCEL GetFrameAccel() const { return m_hAccel; }
\r
414 CMenu& GetFrameMenu() const { return (CMenu&)m_Menu; }
\r
415 std::vector<CString> GetMRUEntries() const { return m_vMRUEntries; }
\r
416 CString GetRegistryKeyName() const { return m_strKeyName; }
\r
417 CWnd* GetView() const { return m_pView; }
\r
418 CString GetMRUEntry(UINT nIndex);
\r
419 void SetFrameMenu(INT ID_MENU);
\r
420 void SetFrameMenu(HMENU hMenu);
\r
421 void SetMenuTheme(MenuTheme& Theme);
\r
422 void SetView(CWnd& wndView);
\r
423 BOOL IsMenuBarUsed() const { return (GetMenuBar() != 0); }
\r
424 BOOL IsReBarSupported() const { return (GetComCtlVersion() > 470); }
\r
425 BOOL IsReBarUsed() const { return (GetReBar() != 0); }
\r
428 // Override these functions as required
\r
429 virtual BOOL AddMenuIcon(int nID_MenuItem, HICON hIcon);
\r
430 virtual UINT AddMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID);
\r
431 virtual void AddMenuBarBand();
\r
432 virtual void AddMRUEntry(LPCTSTR szMRUEntry);
\r
433 virtual void AddToolBarBand(CToolBar& TB, DWORD dwStyle, UINT nID);
\r
434 virtual void AddToolBarButton(UINT nID, BOOL bEnabled = TRUE, LPCTSTR szText = 0);
\r
435 virtual void CreateToolBar();
\r
436 virtual void DrawMenuItem(LPDRAWITEMSTRUCT pdis);
\r
437 virtual void DrawMenuItemBkgnd(LPDRAWITEMSTRUCT pdis);
\r
438 virtual void DrawMenuItemCheckmark(LPDRAWITEMSTRUCT pdis);
\r
439 virtual void DrawMenuItemIcon(LPDRAWITEMSTRUCT pdis);
\r
440 virtual void DrawMenuItemText(LPDRAWITEMSTRUCT pdis);
\r
441 virtual int GetMenuItemPos(HMENU hMenu, LPCTSTR szItem);
\r
442 virtual BOOL LoadRegistrySettings(LPCTSTR szKeyName);
\r
443 virtual BOOL LoadRegistryMRUSettings(UINT nMaxMRU = 0);
\r
444 virtual void MeasureMenuItem(MEASUREITEMSTRUCT *pmis);
\r
445 virtual void OnActivate(WPARAM wParam, LPARAM lParam);
\r
446 virtual void OnClose();
\r
447 virtual void OnCreate();
\r
448 virtual void OnDestroy();
\r
449 virtual LRESULT OnDrawItem(WPARAM wParam, LPARAM lParam);
\r
450 virtual void OnExitMenuLoop();
\r
451 virtual void OnHelp();
\r
452 virtual void OnInitMenuPopup(WPARAM wParam, LPARAM lParam);
\r
453 virtual LRESULT OnMeasureItem(WPARAM wParam, LPARAM lParam);
\r
454 virtual LRESULT OnMenuChar(WPARAM wParam, LPARAM lParam);
\r
455 virtual void OnMenuSelect(WPARAM wParam, LPARAM lParam);
\r
456 virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
\r
457 virtual void OnSetFocus();
\r
458 virtual void OnSysColorChange();
\r
459 virtual LRESULT OnSysCommand(WPARAM wParam, LPARAM lParam);
\r
460 virtual void OnTimer(WPARAM wParam);
\r
461 virtual void OnViewStatusBar();
\r
462 virtual void OnViewToolBar();
\r
463 virtual void PreCreate(CREATESTRUCT& cs);
\r
464 virtual void PreRegisterClass(WNDCLASS &wc);
\r
465 virtual void RemoveMRUEntry(LPCTSTR szMRUEntry);
\r
466 virtual BOOL SaveRegistrySettings();
\r
467 virtual void SetMenuBarBandSize();
\r
468 virtual UINT SetMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID);
\r
469 virtual void SetupToolBar();
\r
470 virtual void SetTheme();
\r
471 virtual void SetToolBarImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID);
\r
472 virtual void ShowMenu(BOOL bShow);
\r
473 virtual void ShowStatusBar(BOOL bShow);
\r
474 virtual void ShowToolBar(BOOL bShow);
\r
475 virtual void UpdateMRUMenu();
\r
476 virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
480 ID_STATUS_TIMER = 1,
\r
483 Shared_Ptr<CMenuMetrics> m_pMenuMetrics; // Smart pointer for CMenuMetrics
\r
484 CString m_strStatusText; // CString for status text
\r
485 BOOL m_bShowIndicatorStatus; // set to TRUE to see indicators in status bar
\r
486 BOOL m_bShowMenuStatus; // set to TRUE to see menu and toolbar updates in status bar
\r
487 BOOL m_bUseReBar; // set to TRUE if ReBars are to be used
\r
488 BOOL m_bUseThemes; // set to TRUE if themes are to be used
\r
489 BOOL m_bUseToolBar; // set to TRUE if the toolbar is used
\r
490 BOOL m_bShowStatusBar; // A flag to indicate if the StatusBar should be displayed
\r
491 BOOL m_bShowToolBar; // A flag to indicate if the ToolBar should be displayed
\r
492 MenuTheme m_ThemeMenu; // Theme structure for popup menus
\r
493 HIMAGELIST m_himlMenu; // Imagelist of menu icons
\r
494 HIMAGELIST m_himlMenuDis; // Imagelist of disabled menu icons
\r
497 CFrame(const CFrame&); // Disable copy construction
\r
498 CFrame& operator = (const CFrame&); // Disable assignment operator
\r
499 void LoadCommonControls();
\r
501 std::vector<ItemDataPtr> m_vMenuItemData; // vector of MenuItemData pointers
\r
502 std::vector<CString> m_vMRUEntries; // Vector of CStrings for MRU entires
\r
503 std::vector<UINT> m_vMenuIcons; // vector of menu icon resource IDs
\r
504 CDialog m_AboutDialog; // Help about dialog
\r
505 CMenuBar m_MenuBar; // CMenuBar object
\r
506 CReBar m_ReBar; // CReBar object
\r
507 CStatusBar m_StatusBar; // CStatusBar object
\r
508 CToolBar m_ToolBar; // CToolBar object
\r
509 CMenu m_Menu; // handle to the frame menu
\r
510 CFont m_fntMenuBar; // MenuBar font
\r
511 CFont m_fntStatusBar; // StatusBar font
\r
512 HACCEL m_hAccel; // handle to the frame's accelerator table
\r
513 CWnd* m_pView; // pointer to the View CWnd object
\r
514 LPCTSTR m_OldStatus[3]; // Array of TCHAR pointers;
\r
515 CString m_strKeyName; // CString for Registry key name
\r
516 CString m_strTooltip; // CString for tool tips
\r
517 CString m_XPThemeName; // CString for Windows Theme Name
\r
518 UINT m_nMaxMRU; // maximum number of MRU entries
\r
519 CRect m_rcPosition; // CRect of the starting window position
\r
520 HWND m_hOldFocus; // The window which had focus prior to the app'a deactivation
\r
521 int m_nOldID; // The previous ToolBar ID displayed in the statusbar
\r
528 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
534 /////////////////////////////////////
\r
535 // Definitions for the CMenuBar class
\r
537 inline CMenuBar::CMenuBar()
\r
539 m_bExitAfter = FALSE;
\r
542 m_bSelPopup = FALSE;
\r
544 m_bMenuActive = FALSE;
\r
545 m_bKeyMode = FALSE;
\r
546 m_hPrevFocus = NULL;
\r
550 ZeroMemory(&m_ThemeMenu, sizeof(MenuTheme));
\r
553 inline CMenuBar::~CMenuBar()
\r
557 inline void CMenuBar::DoAltKey(WORD KeyCode)
\r
559 //Handle key pressed with Alt held down
\r
561 if (SendMessage(TB_MAPACCELERATOR, KeyCode, (LPARAM) &ID))
\r
566 m_bMenuActive = TRUE;
\r
567 PostMessage(UWM_POPUPMENU, 0L, 0L);
\r
570 ::MessageBeep(MB_OK);
\r
573 inline void CMenuBar::DoPopupMenu()
\r
576 // Simulate a down arrow key press
\r
577 PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
\r
579 m_bKeyMode = FALSE;
\r
580 m_bExitAfter = FALSE;
\r
581 m_OldMousePos = GetCursorPos();
\r
583 HWND hMaxMDIChild = NULL;
\r
584 if (IsMDIChildMaxed())
\r
585 hMaxMDIChild = GetActiveMDIChild();
\r
587 // Load the submenu
\r
588 int nMaxedOffset = IsMDIChildMaxed()? 1:0;
\r
589 m_hPopupMenu = ::GetSubMenu(m_hTopMenu, m_nHotItem - nMaxedOffset);
\r
590 if (IsMDIChildMaxed() && (0 == m_nHotItem) )
\r
591 m_hPopupMenu = ::GetSystemMenu(hMaxMDIChild, FALSE);
\r
593 // Retrieve the bounding rectangle for the toolbar button
\r
594 CRect rc = GetItemRect(m_nHotItem);
\r
596 // convert rectangle to desktop coordinates
\r
597 ClientToScreen(rc);
\r
599 // Position popup above toolbar if it won't fit below
\r
601 tpm.cbSize = sizeof(TPMPARAMS);
\r
602 tpm.rcExclude = rc;
\r
604 // Set the hot button
\r
605 SendMessage(TB_SETHOTITEM, m_nHotItem, 0L);
\r
606 SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(TRUE, 0));
\r
608 m_bSelPopup = FALSE;
\r
610 m_bMenuActive = TRUE;
\r
612 // We hook mouse input to process mouse and keyboard input during
\r
613 // the popup menu. Messages are sent to StaticMsgHook.
\r
615 // Remove any remaining hook first
\r
616 TLSData* pTLSData = (TLSData*)::TlsGetValue(GetApp()->GetTlsIndex());
\r
617 pTLSData->pMenuBar = this;
\r
618 if (pTLSData->hHook != NULL)
\r
619 ::UnhookWindowsHookEx(pTLSData->hHook);
\r
621 // Hook messages about to be processed by the shortcut menu
\r
622 pTLSData->hHook = ::SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)StaticMsgHook, NULL, ::GetCurrentThreadId());
\r
624 // Display the shortcut menu
\r
625 BOOL bRightToLeft = FALSE;
\r
627 #if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
\r
628 bRightToLeft = ((GetAncestor()->GetWindowLongPtr(GWL_EXSTYLE)) & WS_EX_LAYOUTRTL);
\r
631 int xPos = bRightToLeft? rc.right : rc.left;
\r
632 UINT nID = ::TrackPopupMenuEx(m_hPopupMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
\r
633 xPos, rc.bottom, m_hWnd, &tpm);
\r
635 // We get here once the TrackPopupMenuEx has ended
\r
636 m_bMenuActive = FALSE;
\r
638 // Remove the message hook
\r
639 ::UnhookWindowsHookEx(pTLSData->hHook);
\r
640 pTLSData->hHook = NULL;
\r
642 // Process MDI Child system menu
\r
643 if (IsMDIChildMaxed())
\r
645 if (::GetSystemMenu(hMaxMDIChild, FALSE) == m_hPopupMenu )
\r
648 ::SendMessage(hMaxMDIChild, WM_SYSCOMMAND, nID, 0L);
\r
652 // Resestablish Focus
\r
657 inline void CMenuBar::DrawAllMDIButtons(CDC& DrawDC)
\r
662 if (IsMDIChildMaxed())
\r
664 int cx = GetSystemMetrics(SM_CXSMICON);
\r
665 int cy = GetSystemMetrics(SM_CYSMICON);
\r
666 CRect rc = GetClientRect();
\r
670 // Assign values to each element of the CRect array
\r
671 for (int i = 0 ; i < 3 ; ++i)
\r
673 int left = rc.right - (i+1)*cx - gap*(i+1);
\r
674 int top = rc.bottom/2 - cy/2;
\r
675 int right = rc.right - i*cx - gap*(i+1);
\r
676 int bottom = rc.bottom/2 + cy/2;
\r
677 ::SetRect(&m_MDIRect[2 - i], left, top, right, bottom);
\r
680 // Hide the MDI button if it won't fit
\r
681 for (int k = 0 ; k <= 2 ; ++k)
\r
684 if (m_MDIRect[k].left < GetMaxSize().cx)
\r
686 ::SetRectEmpty(&m_MDIRect[k]);
\r
690 DrawMDIButton(DrawDC, MDI_MIN, 0);
\r
691 DrawMDIButton(DrawDC, MDI_RESTORE, 0);
\r
692 DrawMDIButton(DrawDC, MDI_CLOSE, 0);
\r
696 inline void CMenuBar::DrawMDIButton(CDC& DrawDC, int iButton, UINT uState)
\r
698 if (!IsRectEmpty(&m_MDIRect[iButton]))
\r
704 // Draw a grey outline
\r
705 DrawDC.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE));
\r
706 DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
\r
707 DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom);
\r
708 DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top);
\r
709 DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top);
\r
710 DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
\r
715 // Draw outline, white at top, black on bottom
\r
716 DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
\r
717 DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
\r
718 DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom);
\r
719 DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top);
\r
720 DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
\r
721 DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top);
\r
722 DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
\r
728 // Draw outline, black on top, white on bottom
\r
729 DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
\r
730 DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
\r
731 DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom);
\r
732 DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top);
\r
733 DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
\r
734 DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top);
\r
735 DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
\r
740 DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
\r
745 // Manually Draw Minimise button
\r
746 DrawDC.MoveTo(m_MDIRect[0].left + 4, m_MDIRect[0].bottom -4);
\r
747 DrawDC.LineTo(m_MDIRect[0].right - 4, m_MDIRect[0].bottom - 4);
\r
749 DrawDC.MoveTo(m_MDIRect[0].left + 4, m_MDIRect[0].bottom -5);
\r
750 DrawDC.LineTo(m_MDIRect[0].right - 4, m_MDIRect[0].bottom - 5);
\r
753 // Manually Draw Restore Button
\r
754 DrawDC.MoveTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 7);
\r
755 DrawDC.LineTo(m_MDIRect[1].left + 3, m_MDIRect[1].bottom -4);
\r
756 DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].bottom -4);
\r
757 DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].top + 7);
\r
758 DrawDC.LineTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 7);
\r
760 DrawDC.MoveTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 8);
\r
761 DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].top + 8);
\r
763 DrawDC.MoveTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 7);
\r
764 DrawDC.LineTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 4);
\r
765 DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].top + 4);
\r
766 DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].bottom -6);
\r
767 DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].bottom -6);
\r
769 DrawDC.MoveTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 5);
\r
770 DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].top + 5);
\r
773 // Manually Draw Close Button
\r
774 DrawDC.MoveTo(m_MDIRect[2].left + 4, m_MDIRect[2].top +5);
\r
775 DrawDC.LineTo(m_MDIRect[2].right - 4, m_MDIRect[2].bottom -3);
\r
777 DrawDC.MoveTo(m_MDIRect[2].left + 5, m_MDIRect[2].top +5);
\r
778 DrawDC.LineTo(m_MDIRect[2].right - 4, m_MDIRect[2].bottom -4);
\r
780 DrawDC.MoveTo(m_MDIRect[2].left + 4, m_MDIRect[2].top +6);
\r
781 DrawDC.LineTo(m_MDIRect[2].right - 5, m_MDIRect[2].bottom -3);
\r
783 DrawDC.MoveTo(m_MDIRect[2].right -5, m_MDIRect[2].top +5);
\r
784 DrawDC.LineTo(m_MDIRect[2].left + 3, m_MDIRect[2].bottom -3);
\r
786 DrawDC.MoveTo(m_MDIRect[2].right -5, m_MDIRect[2].top +6);
\r
787 DrawDC.LineTo(m_MDIRect[2].left + 4, m_MDIRect[2].bottom -3);
\r
789 DrawDC.MoveTo(m_MDIRect[2].right -6, m_MDIRect[2].top +5);
\r
790 DrawDC.LineTo(m_MDIRect[2].left + 3, m_MDIRect[2].bottom -4);
\r
796 inline void CMenuBar::ExitMenu()
\r
799 m_bKeyMode = FALSE;
\r
800 m_bMenuActive = FALSE;
\r
801 SendMessage(TB_PRESSBUTTON, m_nHotItem, (LPARAM) MAKELONG (FALSE, 0));
\r
804 CPoint pt = GetCursorPos();
\r
805 ScreenToClient(pt);
\r
807 // Update mouse mouse position for hot tracking
\r
808 SendMessage(WM_MOUSEMOVE, 0L, MAKELONG(pt.x, pt.y));
\r
811 inline HWND CMenuBar::GetActiveMDIChild()
\r
813 HWND hwndMDIChild = NULL;
\r
816 hwndMDIChild = (HWND)::SendMessage(m_pFrame->GetView()->GetHwnd(), WM_MDIGETACTIVE, 0L, 0L);
\r
819 return hwndMDIChild;
\r
822 inline void CMenuBar::GrabFocus()
\r
824 if (::GetFocus() != m_hWnd)
\r
825 m_hPrevFocus = ::SetFocus(m_hWnd);
\r
826 ::SetCapture(m_hWnd);
\r
827 ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
\r
830 inline BOOL CMenuBar::IsMDIChildMaxed() const
\r
832 BOOL bMaxed = FALSE;
\r
834 if (IsMDIFrame() && m_pFrame->GetView()->IsWindow())
\r
836 m_pFrame->GetView()->SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMaxed);
\r
842 inline BOOL CMenuBar::IsMDIFrame() const
\r
844 return (m_pFrame->IsMDIFrame());
\r
847 inline void CMenuBar::OnMenuChar(WPARAM wParam, LPARAM lParam)
\r
849 UNREFERENCED_PARAMETER(lParam);
\r
851 if (!m_bMenuActive)
\r
852 DoAltKey(LOWORD(wParam));
\r
855 inline void CMenuBar::OnCreate()
\r
857 // We must send this message before sending the TB_ADDBITMAP or TB_ADDBUTTONS message
\r
858 SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0L);
\r
860 m_pFrame = (CFrame*)GetAncestor();
\r
864 inline LRESULT CMenuBar::OnCustomDraw(NMHDR* pNMHDR)
\r
865 // CustomDraw is used to render the MenuBar's toolbar buttons
\r
867 if (m_ThemeMenu.UseThemes)
\r
869 LPNMTBCUSTOMDRAW lpNMCustomDraw = (LPNMTBCUSTOMDRAW)pNMHDR;
\r
871 switch (lpNMCustomDraw->nmcd.dwDrawStage)
\r
873 // Begin paint cycle
\r
874 case CDDS_PREPAINT:
\r
875 // Send NM_CUSTOMDRAW item draw, and post-paint notification messages.
\r
876 return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT ;
\r
878 // An item is about to be drawn
\r
879 case CDDS_ITEMPREPAINT:
\r
881 CDC DrawDC(lpNMCustomDraw->nmcd.hdc);
\r
882 CRect rcRect = lpNMCustomDraw->nmcd.rc;
\r
883 int nState = lpNMCustomDraw->nmcd.uItemState;
\r
884 DWORD dwItem = (DWORD)lpNMCustomDraw->nmcd.dwItemSpec;
\r
886 // Leave a pixel gap above and below the drawn rectangle
\r
887 if (IsAeroThemed())
\r
888 rcRect.InflateRect(0, -2);
\r
890 rcRect.InflateRect(0, -1);
\r
892 if (IsMDIChildMaxed() && (0 == dwItem))
\r
893 // Draw over MDI Max button
\r
895 HICON hIcon = (HICON)::SendMessage(GetActiveMDIChild(), WM_GETICON, ICON_SMALL, 0L);
\r
897 hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
\r
899 int cx = ::GetSystemMetrics (SM_CXSMICON);
\r
900 int cy = ::GetSystemMetrics (SM_CYSMICON);
\r
901 int y = 1 + (GetWindowRect().Height() - cy)/2;
\r
902 int x = (rcRect.Width() - cx)/2;
\r
903 DrawDC.DrawIconEx(x, y, hIcon, cx, cy, 0, NULL, DI_NORMAL);
\r
906 return CDRF_SKIPDEFAULT; // No further drawing
\r
909 else if (nState & (CDIS_HOT | CDIS_SELECTED))
\r
911 if ((nState & CDIS_SELECTED) || (GetButtonState(dwItem) & TBSTATE_PRESSED))
\r
913 DrawDC.GradientFill(m_ThemeMenu.clrPressed1, m_ThemeMenu.clrPressed2, rcRect, FALSE);
\r
915 else if (nState & CDIS_HOT)
\r
917 DrawDC.GradientFill(m_ThemeMenu.clrHot1, m_ThemeMenu.clrHot2, rcRect, FALSE);
\r
921 DrawDC.CreatePen(PS_SOLID, 1, m_ThemeMenu.clrOutline);
\r
922 DrawDC.MoveTo(rcRect.left, rcRect.bottom);
\r
923 DrawDC.LineTo(rcRect.left, rcRect.top);
\r
924 DrawDC.LineTo(rcRect.right-1, rcRect.top);
\r
925 DrawDC.LineTo(rcRect.right-1, rcRect.bottom);
\r
926 DrawDC.MoveTo(rcRect.right-1, rcRect.bottom);
\r
927 DrawDC.LineTo(rcRect.left, rcRect.bottom);
\r
929 TCHAR str[80] = _T("");
\r
930 int nLength = (int)SendMessage(TB_GETBUTTONTEXT, lpNMCustomDraw->nmcd.dwItemSpec, 0L);
\r
931 if ((nLength > 0) && (nLength < 80))
\r
932 SendMessage(TB_GETBUTTONTEXT, lpNMCustomDraw->nmcd.dwItemSpec, (LPARAM)str);
\r
934 // Draw highlight text
\r
935 CFont* pFont = GetFont();
\r
936 ::SelectObject(DrawDC, pFont->GetHandle());
\r
938 rcRect.bottom += 1;
\r
939 int iMode = DrawDC.SetBkMode(TRANSPARENT);
\r
940 DrawDC.DrawText(str, lstrlen(str), rcRect, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
\r
942 DrawDC.SetBkMode(iMode);
\r
944 return CDRF_SKIPDEFAULT; // No further drawing
\r
948 return CDRF_DODEFAULT ; // Do default drawing
\r
950 // Painting cycle has completed
\r
951 case CDDS_POSTPAINT:
\r
952 // Draw MDI Minimise, Restore and Close buttons
\r
954 CDC DrawDC(lpNMCustomDraw->nmcd.hdc);
\r
955 DrawAllMDIButtons(DrawDC);
\r
964 inline void CMenuBar::OnKeyDown(WPARAM wParam, LPARAM lParam)
\r
966 UNREFERENCED_PARAMETER(lParam);
\r
976 // Bring up the system menu
\r
977 GetAncestor()->PostMessage(WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE);
\r
980 // Handle VK_DOWN,VK_UP and VK_RETURN together
\r
984 // Always use PostMessage for USER_POPUPMENU (not SendMessage)
\r
985 PostMessage(UWM_POPUPMENU, 0L, 0L);
\r
989 // Move left to next topmenu item
\r
990 (m_nHotItem > 0)? SetHotItem(m_nHotItem -1) : SetHotItem(GetButtonCount()-1);
\r
994 // Move right to next topmenu item
\r
995 (m_nHotItem < GetButtonCount() -1)? SetHotItem(m_nHotItem +1) : SetHotItem(0);
\r
999 // Handle Accelerator keys with Alt toggled down
\r
1003 if (SendMessage(TB_MAPACCELERATOR, wParam, (LPARAM) &ID))
\r
1006 PostMessage(UWM_POPUPMENU, 0L, 0L);
\r
1009 ::MessageBeep(MB_OK);
\r
1012 } // switch (wParam)
\r
1015 inline void CMenuBar::OnLButtonDown(WPARAM wParam, LPARAM lParam)
\r
1017 UNREFERENCED_PARAMETER(wParam);
\r
1023 pt.x = GET_X_LPARAM(lParam);
\r
1024 pt.y = GET_Y_LPARAM(lParam);
\r
1028 if (IsMDIChildMaxed())
\r
1030 CClientDC MenuBarDC(this);
\r
1031 m_nMDIButton = -1;
\r
1033 if (m_MDIRect[0].PtInRect(pt)) m_nMDIButton = 0;
\r
1034 if (m_MDIRect[1].PtInRect(pt)) m_nMDIButton = 1;
\r
1035 if (m_MDIRect[2].PtInRect(pt)) m_nMDIButton = 2;
\r
1037 if (m_nMDIButton >= 0)
\r
1039 DrawMDIButton(MenuBarDC, MDI_MIN, (0 == m_nMDIButton)? 2 : 0);
\r
1040 DrawMDIButton(MenuBarDC, MDI_RESTORE, (1 == m_nMDIButton)? 2 : 0);
\r
1041 DrawMDIButton(MenuBarDC, MDI_CLOSE, (2 == m_nMDIButton)? 2 : 0);
\r
1044 // Bring up the MDI Child window's system menu when the icon is pressed
\r
1045 if (0 == HitTest())
\r
1048 PostMessage(UWM_POPUPMENU, 0L, 0L);
\r
1054 inline void CMenuBar::OnLButtonUp(WPARAM wParam, LPARAM lParam)
\r
1056 UNREFERENCED_PARAMETER(wParam);
\r
1058 pt.x = GET_X_LPARAM(lParam);
\r
1059 pt.y = GET_Y_LPARAM(lParam);
\r
1063 HWND MDIClient = m_pFrame->GetView()->GetHwnd();
\r
1064 HWND MDIChild = GetActiveMDIChild();
\r
1066 if (IsMDIChildMaxed())
\r
1068 CPoint pt = GetCursorPos();
\r
1069 ScreenToClient(pt);
\r
1071 // Process the MDI button action when the left mouse button is up
\r
1072 if (m_MDIRect[0].PtInRect(pt))
\r
1074 if (MDI_MIN == m_nMDIButton)
\r
1075 ::ShowWindow(MDIChild, SW_MINIMIZE);
\r
1078 if (m_MDIRect[1].PtInRect(pt))
\r
1080 if (MDI_RESTORE == m_nMDIButton)
\r
1081 ::PostMessage(MDIClient, WM_MDIRESTORE, (WPARAM)MDIChild, 0L);
\r
1084 if (m_MDIRect[2].PtInRect(pt))
\r
1086 if (MDI_CLOSE == m_nMDIButton)
\r
1087 ::PostMessage(MDIChild, WM_CLOSE, 0L, 0L);
\r
1095 inline BOOL CMenuBar::OnMenuInput(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
1096 // When a popup menu is active, StaticMsgHook directs all menu messages here
\r
1101 m_bExitAfter = FALSE;
\r
1106 // Use default processing if inside a Sub Menu
\r
1107 if ((m_hSelMenu) &&(m_hSelMenu != m_hPopupMenu))
\r
1110 m_bMenuActive = FALSE;
\r
1111 m_bKeyMode = TRUE;
\r
1112 SendMessage(WM_CANCELMODE, 0L, 0L);
\r
1113 SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
\r
1114 SendMessage(TB_SETHOTITEM, m_nHotItem, 0L);
\r
1118 // Use default processing if inside a Sub Menu
\r
1119 if ((m_hSelMenu) &&(m_hSelMenu != m_hPopupMenu))
\r
1122 SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
\r
1124 // Move left to next topmenu item
\r
1125 (m_nHotItem > 0)? --m_nHotItem : m_nHotItem = GetButtonCount()-1;
\r
1126 SendMessage(WM_CANCELMODE, 0L, 0L);
\r
1128 // Always use PostMessage for USER_POPUPMENU (not SendMessage)
\r
1129 PostMessage(UWM_POPUPMENU, 0L, 0L);
\r
1130 PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
\r
1134 // Use default processing to open Sub Menu
\r
1138 SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
\r
1140 // Move right to next topmenu item
\r
1141 (m_nHotItem < GetButtonCount()-1)? ++m_nHotItem : m_nHotItem = 0;
\r
1142 SendMessage(WM_CANCELMODE, 0L, 0L);
\r
1144 // Always use PostMessage for USER_POPUPMENU (not SendMessage)
\r
1145 PostMessage(UWM_POPUPMENU, 0L, 0L);
\r
1146 PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
\r
1150 m_bExitAfter = TRUE;
\r
1153 } // switch (wParam)
\r
1155 } // case WM_KEYDOWN
\r
1160 m_bExitAfter = TRUE;
\r
1163 case WM_LBUTTONDOWN:
\r
1165 m_bExitAfter = TRUE;
\r
1166 if (HitTest() >= 0)
\r
1168 // Cancel popup when we hit a button a second time
\r
1169 SendMessage(WM_CANCELMODE, 0L, 0L);
\r
1175 case WM_LBUTTONDBLCLK:
\r
1176 // Perform default action for DblClick on MDI Maxed icon
\r
1177 if (IsMDIChildMaxed() && (0 == HitTest()))
\r
1179 CWnd* pMDIChild = FromHandle(GetActiveMDIChild());
\r
1180 CMenu* pChildMenu = pMDIChild->GetSystemMenu(FALSE);
\r
1182 UINT nID = pChildMenu->GetDefaultItem(FALSE, 0);
\r
1184 pMDIChild->PostMessage(WM_SYSCOMMAND, nID, 0L);
\r
1187 m_bExitAfter = TRUE;
\r
1190 case WM_MENUSELECT:
\r
1192 // store info about selected item
\r
1193 m_hSelMenu = (HMENU)lParam;
\r
1194 m_bSelPopup = ((HIWORD(wParam) & MF_POPUP) != 0);
\r
1196 // Reflect message back to the frame window
\r
1197 GetAncestor()->SendMessage(WM_MENUSELECT, wParam, lParam);
\r
1201 case WM_MOUSEMOVE:
\r
1204 pt.x = GET_X_LPARAM(lParam);
\r
1205 pt.y = GET_Y_LPARAM(lParam);
\r
1207 // Skip if mouse hasn't moved
\r
1208 if ((pt.x == m_OldMousePos.x) && (pt.y == m_OldMousePos.y))
\r
1211 m_OldMousePos.x = pt.x;
\r
1212 m_OldMousePos.y = pt.y;
\r
1213 ScreenToClient(pt);
\r
1215 // Reflect messages back to the MenuBar for hot tracking
\r
1216 SendMessage(WM_MOUSEMOVE, 0L, MAKELPARAM(pt.x, pt.y));
\r
1224 inline void CMenuBar::OnMouseLeave()
\r
1228 if (IsMDIChildMaxed())
\r
1230 CClientDC MenuBarDC(this);
\r
1232 DrawMDIButton(MenuBarDC, MDI_MIN, 0);
\r
1233 DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);
\r
1234 DrawMDIButton(MenuBarDC, MDI_CLOSE, 0);
\r
1239 inline void CMenuBar::OnMouseMove(WPARAM wParam, LPARAM lParam)
\r
1242 pt.x = GET_X_LPARAM(lParam);
\r
1243 pt.y = GET_Y_LPARAM(lParam);
\r
1247 if (IsMDIChildMaxed())
\r
1249 CClientDC MenuBarDC(this);
\r
1250 int MDIButton = -1;
\r
1251 if (m_MDIRect[0].PtInRect(pt)) MDIButton = 0;
\r
1252 if (m_MDIRect[1].PtInRect(pt)) MDIButton = 1;
\r
1253 if (m_MDIRect[2].PtInRect(pt)) MDIButton = 2;
\r
1255 if (MK_LBUTTON == wParam) // mouse moved with left mouse button is held down
\r
1257 // toggle the MDI button image pressed/unpressed as required
\r
1258 if (MDIButton >= 0)
\r
1260 DrawMDIButton(MenuBarDC, MDI_MIN, ((0 == MDIButton) && (0 == m_nMDIButton))? 2 : 0);
\r
1261 DrawMDIButton(MenuBarDC, MDI_RESTORE, ((1 == MDIButton) && (1 == m_nMDIButton))? 2 : 0);
\r
1262 DrawMDIButton(MenuBarDC, MDI_CLOSE, ((2 == MDIButton) && (2 == m_nMDIButton))? 2 : 0);
\r
1266 DrawMDIButton(MenuBarDC, MDI_MIN, 0);
\r
1267 DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);
\r
1268 DrawMDIButton(MenuBarDC, MDI_CLOSE, 0);
\r
1271 else // mouse moved without left mouse button held down
\r
1273 if (MDIButton >= 0)
\r
1275 DrawMDIButton(MenuBarDC, MDI_MIN, (0 == MDIButton)? 1 : 0);
\r
1276 DrawMDIButton(MenuBarDC, MDI_RESTORE, (1 == MDIButton)? 1 : 0);
\r
1277 DrawMDIButton(MenuBarDC, MDI_CLOSE, (2 == MDIButton)? 1 : 0);
\r
1281 DrawMDIButton(MenuBarDC, MDI_MIN, 0);
\r
1282 DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);
\r
1283 DrawMDIButton(MenuBarDC, MDI_CLOSE, 0);
\r
1290 inline LRESULT CMenuBar::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
\r
1292 UNREFERENCED_PARAMETER(wParam);
\r
1294 switch (((LPNMHDR)lParam)->code)
\r
1296 case NM_CUSTOMDRAW:
\r
1298 return OnCustomDraw((LPNMHDR) lParam);
\r
1301 case TBN_DROPDOWN:
\r
1302 // Always use PostMessage for USER_POPUPMENU (not SendMessage)
\r
1303 PostMessage(UWM_POPUPMENU, 0L, 0L);
\r
1306 case TBN_HOTITEMCHANGE:
\r
1307 // This is the notification that a hot item change is about to occur
\r
1308 // This is used to bring up a new popup menu when required
\r
1310 CPoint pt = GetCursorPos();
\r
1311 if (this == WindowFromPoint(pt)) // MenuBar window must be on top
\r
1313 DWORD flag = ((LPNMTBHOTITEM)lParam)->dwFlags;
\r
1314 if ((flag & HICF_MOUSE) && !(flag & HICF_LEAVING))
\r
1316 int nButton = HitTest();
\r
1317 if ((m_bMenuActive) && (nButton != m_nHotItem))
\r
1319 SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
\r
1320 m_nHotItem = nButton;
\r
1321 SendMessage(WM_CANCELMODE, 0L, 0L);
\r
1323 //Always use PostMessage for USER_POPUPMENU (not SendMessage)
\r
1324 PostMessage(UWM_POPUPMENU, 0L, 0L);
\r
1326 m_nHotItem = nButton;
\r
1329 // Handle escape from popup menu
\r
1330 if ((flag & HICF_LEAVING) && m_bKeyMode)
\r
1332 m_nHotItem = ((LPNMTBHOTITEM)lParam)->idOld;
\r
1333 PostMessage(TB_SETHOTITEM, m_nHotItem, 0L);
\r
1338 } //case TBN_HOTITEMCHANGE:
\r
1340 } // switch(((LPNMHDR)lParam)->code)
\r
1342 } // CMenuBar::OnNotify(...)
\r
1344 inline void CMenuBar::OnWindowPosChanged()
\r
1346 InvalidateRect(&m_MDIRect[0], TRUE);
\r
1347 InvalidateRect(&m_MDIRect[1], TRUE);
\r
1348 InvalidateRect(&m_MDIRect[2], TRUE);
\r
1350 CClientDC MenuBarDC(this);
\r
1351 DrawAllMDIButtons(MenuBarDC);
\r
1355 inline void CMenuBar::PreCreate(CREATESTRUCT &cs)
\r
1357 cs.style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS | TBSTYLE_LIST | TBSTYLE_FLAT | CCS_NODIVIDER | CCS_NORESIZE;
\r
1360 inline void CMenuBar::PreRegisterClass(WNDCLASS &wc)
\r
1362 // Set the Window Class
\r
1363 wc.lpszClassName = TOOLBARCLASSNAME;
\r
1366 inline void CMenuBar::ReleaseFocus()
\r
1369 ::SetFocus(m_hPrevFocus);
\r
1371 m_hPrevFocus = NULL;
\r
1372 ::ReleaseCapture();
\r
1375 inline void CMenuBar::SetHotItem(int nHot)
\r
1377 m_nHotItem = nHot;
\r
1378 SendMessage(TB_SETHOTITEM, m_nHotItem, 0L);
\r
1381 inline void CMenuBar::SetMenu(HMENU hMenu)
\r
1383 assert(::IsWindow(m_hWnd));
\r
1385 m_hTopMenu = hMenu;
\r
1386 int nMaxedOffset = (IsMDIChildMaxed()? 1:0);
\r
1388 // Remove any existing buttons
\r
1389 while (SendMessage(TB_BUTTONCOUNT, 0L, 0L) > 0)
\r
1391 if(!SendMessage(TB_DELETEBUTTON, 0L, 0L))
\r
1395 // Set the Bitmap size to zero
\r
1396 SendMessage(TB_SETBITMAPSIZE, 0L, MAKELPARAM(0, 0));
\r
1398 if (IsMDIChildMaxed())
\r
1400 // Create an extra button for the MDI child system menu
\r
1401 // Later we will custom draw the window icon over this button
\r
1402 TBBUTTON tbb = {0};
\r
1403 tbb.fsState = TBSTATE_ENABLED;
\r
1404 tbb.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE ;
\r
1405 tbb.iString = (INT_PTR)_T(" ");
\r
1406 SendMessage(TB_ADDBUTTONS, 1, (WPARAM)&tbb);
\r
1407 SetButtonText(0, _T(" "));
\r
1410 for (int i = 0 ; i < ::GetMenuItemCount(hMenu); ++i)
\r
1412 // Assign the ToolBar Button struct
\r
1413 TBBUTTON tbb = {0};
\r
1414 tbb.idCommand = i + nMaxedOffset; // Each button needs a unique ID
\r
1415 tbb.fsState = TBSTATE_ENABLED;
\r
1416 tbb.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE | TBSTYLE_DROPDOWN;
\r
1417 tbb.iString = (INT_PTR)_T(" ");
\r
1418 SendMessage(TB_ADDBUTTONS, 1, (WPARAM)&tbb);
\r
1420 // Add the menu title to the string table
\r
1421 std::vector<TCHAR> vMenuName( MAX_MENU_STRING+1, _T('\0') );
\r
1422 TCHAR* szMenuName = &vMenuName[0];
\r
1423 GetMenuString(hMenu, i, szMenuName, MAX_MENU_STRING, MF_BYPOSITION);
\r
1424 SetButtonText(i + nMaxedOffset, szMenuName);
\r
1428 inline void CMenuBar::SetMenuBarTheme(MenuTheme& Theme)
\r
1430 m_ThemeMenu.UseThemes = Theme.UseThemes;
\r
1431 m_ThemeMenu.clrHot1 = Theme.clrHot1;
\r
1432 m_ThemeMenu.clrHot2 = Theme.clrHot2;
\r
1433 m_ThemeMenu.clrPressed1 = Theme.clrPressed1;
\r
1434 m_ThemeMenu.clrPressed2 = Theme.clrPressed2;
\r
1435 m_ThemeMenu.clrOutline = Theme.clrOutline;
\r
1441 inline LRESULT CALLBACK CMenuBar::StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam)
\r
1444 MSG* pMsg = (MSG*)lParam;
\r
1445 TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
\r
1447 CMenuBar* pMenuBar = (CMenuBar*)pTLSData->pMenuBar;
\r
1449 if (pMenuBar && (MSGF_MENU == nCode))
\r
1451 // process menu message
\r
1452 if (pMenuBar->OnMenuInput(pMsg->message, pMsg->wParam, pMsg->lParam))
\r
1458 return CallNextHookEx(pTLSData->hHook, nCode, wParam, lParam);
\r
1461 inline void CMenuBar::OnSysCommand(WPARAM wParam, LPARAM lParam)
\r
1463 if (SC_KEYMENU == wParam)
\r
1467 // Alt/F10 key toggled
\r
1469 m_bKeyMode = TRUE;
\r
1470 int nMaxedOffset = (IsMDIChildMaxed()? 1:0);
\r
1471 SetHotItem(nMaxedOffset);
\r
1474 // Handle key pressed with Alt held down
\r
1475 DoAltKey((WORD)lParam);
\r
1479 inline LRESULT CMenuBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
1484 return 0L; // Discard these messages
\r
1486 m_pFrame->OnDrawItem(wParam, lParam);
\r
1487 return TRUE; // handled
\r
1488 case WM_EXITMENULOOP:
\r
1491 m_pFrame->OnExitMenuLoop();
\r
1493 case WM_INITMENUPOPUP:
\r
1494 m_pFrame->OnInitMenuPopup(wParam, lParam);
\r
1497 OnKeyDown(wParam, lParam);
\r
1498 return 0L; // Discard these messages
\r
1499 case WM_KILLFOCUS:
\r
1502 case WM_LBUTTONDOWN:
\r
1503 // Do default processing first
\r
1504 CallWindowProc(GetPrevWindowProc(), uMsg, wParam, lParam);
\r
1506 OnLButtonDown(wParam, lParam);
\r
1508 case WM_LBUTTONUP:
\r
1509 OnLButtonUp(wParam, lParam);
\r
1511 case WM_MEASUREITEM:
\r
1512 m_pFrame->OnMeasureItem(wParam, lParam);
\r
1513 return TRUE; // handled
\r
1514 case WM_MOUSELEAVE:
\r
1517 case WM_MOUSEMOVE:
\r
1518 OnMouseMove(wParam, lParam);
\r
1520 case UWM_POPUPMENU:
\r
1523 case WM_SYSKEYDOWN:
\r
1524 if ((VK_MENU == wParam) || (VK_F10 == wParam))
\r
1528 if ((VK_MENU == wParam) || (VK_F10 == wParam))
\r
1534 case UWM_GETMENUTHEME:
\r
1536 MenuTheme& tm = GetMenuBarTheme();
\r
1537 return (LRESULT)&tm;
\r
1539 case WM_WINDOWPOSCHANGED:
\r
1540 OnWindowPosChanged();
\r
1542 case WM_WINDOWPOSCHANGING:
\r
1543 // Bypass CToolBar::WndProcDefault for this message
\r
1544 return CWnd::WndProcDefault(uMsg, wParam, lParam);
\r
1546 } // switch (uMsg)
\r
1548 return CToolBar::WndProcDefault(uMsg, wParam, lParam);
\r
1549 } // LRESULT CMenuBar::WndProcDefault(...)
\r
1552 inline CMenuMetrics::CMenuMetrics(CFrame* pFrame) : m_pfnCloseThemeData(0), m_pfnDrawThemeBackground(0), m_pfnDrawThemeText(0),
\r
1553 m_pfnGetThemePartSize(0), m_pfnGetThemeInt(0), m_pfnGetThemeMargins(0),
\r
1554 m_pfnGetThemeTextExtent(0), m_pfnIsThemeBGPartTransparent(0), m_pfnOpenThemeData(0)
\r
1557 m_pFrame = pFrame;
\r
1562 inline void CMenuMetrics::Initialize()
\r
1566 HMODULE hModule = ::LoadLibrary(_T("UXTHEME.DLL"));
\r
1569 m_pfnCloseThemeData = (CLOSETHEMEDATA*)::GetProcAddress(hModule, "CloseThemeData");
\r
1570 m_pfnDrawThemeBackground = (DRAWTHEMEBACKGROUND*)::GetProcAddress(hModule, "DrawThemeBackground");
\r
1571 m_pfnDrawThemeText = (DRAWTHEMETEXT*)::GetProcAddress(hModule, "DrawThemeText");
\r
1572 m_pfnGetThemePartSize = (GETTHEMEPARTSIZE*)::GetProcAddress(hModule, "GetThemePartSize");
\r
1573 m_pfnGetThemeInt = (GETTHEMEINT*)::GetProcAddress(hModule, "GetThemeInt");
\r
1574 m_pfnGetThemeMargins = (GETTHEMEMARGINS*)::GetProcAddress(hModule, "GetThemeMargins");
\r
1575 m_pfnGetThemeTextExtent = (GETTHEMETEXTEXTENT*)::GetProcAddress(hModule, "GetThemeTextExtent");
\r
1576 m_pfnIsThemeBGPartTransparent = (ISTHEMEBGPARTTRANSPARENT*)::GetProcAddress(hModule, "IsThemeBackgroundPartiallyTransparent");
\r
1577 m_pfnOpenThemeData = (OPENTHEMEDATA*)::GetProcAddress(hModule, "OpenThemeData");
\r
1578 ::FreeLibrary(hModule);
\r
1587 m_hTheme = OpenThemeData(*m_pFrame, VSCLASS_MENU);
\r
1591 int iBorderSize = 0; // Border space between item text and accelerator
\r
1592 int iBgBorderSize = 0; // Border space between item text and gutter
\r
1593 GetThemePartSize(NULL, MENU_POPUPCHECK, 0, NULL, TS_TRUE, &m_sizeCheck);
\r
1594 GetThemePartSize(NULL, MENU_POPUPSEPARATOR, 0, NULL, TS_TRUE, &m_sizeSeparator);
\r
1595 GetThemeInt(MENU_POPUPITEM, 0, TMT_BORDERSIZE, &iBorderSize);
\r
1596 GetThemeInt(MENU_POPUPBACKGROUND, 0, TMT_BORDERSIZE, &iBgBorderSize);
\r
1597 GetThemeMargins(NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &m_marCheck);
\r
1598 GetThemeMargins(NULL, MENU_POPUPCHECKBACKGROUND, 0, TMT_CONTENTMARGINS, NULL, &m_marCheckBackground);
\r
1599 GetThemeMargins(NULL, MENU_POPUPITEM, 0, TMT_CONTENTMARGINS, NULL, &m_marItem);
\r
1601 // Popup text margins
\r
1602 m_marText = m_marItem;
\r
1603 m_marText.cxRightWidth = iBorderSize;
\r
1604 m_marText.cxLeftWidth = iBgBorderSize;
\r
1608 m_sizeCheck.SetSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
\r
1609 m_sizeSeparator.SetSize(1, 7);
\r
1610 m_marCheck.SetMargins(4, 4, 2, 2);
\r
1611 m_marCheckBackground.SetMargins(0, 0, 0, 0);
\r
1612 m_marItem.SetMargins(0, 0, 0, 0);
\r
1613 m_marText.SetMargins(8, 16, 0, 0);
\r
1617 inline CMenuMetrics::~CMenuMetrics()
\r
1619 if (m_hTheme) CloseThemeData();
\r
1622 inline HRESULT CMenuMetrics::CloseThemeData()
\r
1624 if (m_pfnCloseThemeData)
\r
1625 return (*m_pfnCloseThemeData)(m_hTheme);
\r
1630 inline HRESULT CMenuMetrics::DrawThemeBackground(HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect)
\r
1632 if (m_pfnDrawThemeBackground)
\r
1633 return (*m_pfnDrawThemeBackground)(m_hTheme, hdc, iPartId, iStateId, pRect, pClipRect);
\r
1638 inline HRESULT CMenuMetrics::DrawThemeText(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect)
\r
1640 if (m_pfnDrawThemeText)
\r
1641 return (*m_pfnDrawThemeText)(m_hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, pRect);
\r
1646 inline HRESULT CMenuMetrics::GetThemePartSize(HDC hdc, int iPartId, int iStateId, LPCRECT prc, THEMESIZE eSize, SIZE* psz)
\r
1648 if (m_pfnGetThemePartSize)
\r
1649 return (*m_pfnGetThemePartSize)(m_hTheme, hdc, iPartId, iStateId, prc, eSize, psz);
\r
1654 inline HRESULT CMenuMetrics::GetThemeInt(int iPartId, int iStateId, int iPropId, int* piVal)
\r
1656 if (m_pfnGetThemeInt)
\r
1657 return (*m_pfnGetThemeInt)(m_hTheme, iPartId, iStateId, iPropId, piVal);
\r
1662 inline HRESULT CMenuMetrics::GetThemeMargins(HDC hdc, int iPartId, int iStateId, int iPropId, LPRECT prc, MARGINS* pMargins)
\r
1664 if (m_pfnGetThemeMargins)
\r
1665 return (*m_pfnGetThemeMargins)(m_hTheme, hdc, iPartId, iStateId, iPropId, prc, pMargins);
\r
1670 inline HRESULT CMenuMetrics::GetThemeTextExtent(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect)
\r
1672 if (m_pfnGetThemeTextExtent)
\r
1673 return (*m_pfnGetThemeTextExtent)(m_hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, pBoundingRect, pExtentRect);
\r
1678 inline BOOL CMenuMetrics::IsThemeBackgroundPartiallyTransparent(int iPartId, int iStateId)
\r
1680 if (m_pfnIsThemeBGPartTransparent)
\r
1681 return (*m_pfnIsThemeBGPartTransparent)(m_hTheme, iPartId, iStateId);
\r
1686 inline HANDLE CMenuMetrics::OpenThemeData(HWND hwnd, LPCWSTR pszClassList)
\r
1688 if (m_pfnOpenThemeData)
\r
1689 return (*m_pfnOpenThemeData)(hwnd, pszClassList);
\r
1694 inline CRect CMenuMetrics::GetCheckBackgroundRect(CRect rcItem)
\r
1696 int x = rcItem.left + m_marCheckBackground.cxLeftWidth;
\r
1697 int y = rcItem.top + m_marCheckBackground.cyTopHeight;
\r
1698 int cx = m_sizeCheck.cx + m_marCheck.Width();
\r
1699 int cy = m_sizeCheck.cy + m_marCheck.Height();
\r
1701 return CRect(x, y, x + cx, y + cy);
\r
1704 inline CRect CMenuMetrics::GetGutterRect(CRect rcItem)
\r
1706 int x = rcItem.left;
\r
1707 int y = rcItem.top;
\r
1708 int cx = m_marItem.cxLeftWidth + m_marCheckBackground.Width() + m_marCheck.Width() + m_sizeCheck.cx;
\r
1709 int cy = rcItem.Height();
\r
1711 return CRect(x, y, x + cx, y + cy);
\r
1714 inline CRect CMenuMetrics::GetCheckRect(CRect rcItem)
\r
1716 int x = rcItem.left + m_marCheckBackground.cxLeftWidth + m_marCheck.cxLeftWidth;
\r
1717 int y = rcItem.top + m_marCheckBackground.cyTopHeight + m_marCheck.cyTopHeight;
\r
1719 return CRect(x, y, x + m_sizeCheck.cx, y + m_sizeCheck.cy);
\r
1722 inline CRect CMenuMetrics::GetSelectionRect(CRect rcItem)
\r
1724 int x = rcItem.left + m_marItem.cxLeftWidth;
\r
1725 int y = rcItem.top;
\r
1727 return CRect(x, y, rcItem.right - m_marItem.cxRightWidth, y + rcItem.Height());
\r
1730 inline CRect CMenuMetrics::GetSeperatorRect(CRect rcItem)
\r
1732 int left = GetGutterRect(rcItem).right;
\r
1733 int top = rcItem.top;
\r
1734 int right = rcItem.right - m_marItem.cxRightWidth;
\r
1735 int bottom = rcItem.top + m_sizeSeparator.cy;
\r
1737 return CRect(left, top, right, bottom);
\r
1740 inline CSize CMenuMetrics::GetTextSize(MenuItemData* pmd)
\r
1744 CClientDC DesktopDC(NULL);
\r
1745 LPCTSTR szItemText = pmd->GetItemText();
\r
1747 if (IsAeroThemed())
\r
1750 GetThemeTextExtent(DesktopDC, MENU_POPUPITEM, 0, T2W(szItemText), lstrlen(szItemText),
\r
1751 DT_LEFT | DT_SINGLELINE, NULL, &rcText);
\r
1753 sizeText.SetSize(rcText.right + m_marText.Width(), rcText.bottom + m_marText.Height());
\r
1757 // Get the font used in menu items
\r
1758 NONCLIENTMETRICS nm = {0};
\r
1759 nm.cbSize = GetSizeofNonClientMetrics();
\r
1760 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nm), &nm, 0);
\r
1762 // Default menu items are bold, so take this into account
\r
1763 if ((int)::GetMenuDefaultItem(pmd->hMenu, TRUE, GMDI_USEDISABLED) != -1)
\r
1764 nm.lfMenuFont.lfWeight = FW_BOLD;
\r
1766 // Calculate the size of the text
\r
1767 DesktopDC.CreateFontIndirect(&nm.lfMenuFont);
\r
1768 sizeText = DesktopDC.GetTextExtentPoint32(szItemText, lstrlen(szItemText));
\r
1769 // sizeText.cx += m_marText.Width();
\r
1770 sizeText.cx += m_marText.cxRightWidth;
\r
1771 sizeText.cy += m_marText.Height();
\r
1774 if (_tcschr(szItemText, _T('\t')))
\r
1775 sizeText.cx += 8; // Add POST_TEXT_GAP if the text includes a tab
\r
1780 inline CRect CMenuMetrics::GetTextRect(CRect rcItem)
\r
1782 int left = GetGutterRect(rcItem).Width() + m_marText.cxLeftWidth;
\r
1783 int top = rcItem.top + m_marText.cyTopHeight;
\r
1784 int right = rcItem.right - m_marItem.cxRightWidth - m_marText.cxRightWidth;
\r
1785 int bottom = rcItem.bottom - m_marText.cyBottomHeight;
\r
1787 return CRect(left, top, right, bottom);
\r
1790 inline int CMenuMetrics::ToItemStateId(UINT uItemState)
\r
1792 const bool fDisabled = ((uItemState & (ODS_INACTIVE | ODS_DISABLED)) != 0);
\r
1793 const bool fHot = ((uItemState & (ODS_HOTLIGHT | ODS_SELECTED)) != 0);
\r
1794 POPUPITEMSTATES iState;
\r
1797 iState = (fHot ? MPI_DISABLEDHOT : MPI_DISABLED);
\r
1801 iState= MPI_NORMAL;
\r
1806 inline int CMenuMetrics::ToCheckBackgroundStateId(int iStateId)
\r
1808 POPUPCHECKBACKGROUNDSTATES iStateIdCheckBackground;
\r
1810 // Determine the check background state.
\r
1811 if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT)
\r
1812 iStateIdCheckBackground = MCB_DISABLED;
\r
1814 iStateIdCheckBackground = MCB_NORMAL;
\r
1816 return iStateIdCheckBackground;
\r
1819 inline int CMenuMetrics::ToCheckStateId(UINT fType, int iStateId)
\r
1821 POPUPCHECKSTATES iStateIdCheck;
\r
1823 if (fType & MFT_RADIOCHECK)
\r
1825 if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT)
\r
1826 iStateIdCheck = MC_BULLETDISABLED;
\r
1828 iStateIdCheck = MC_BULLETNORMAL;
\r
1832 if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT)
\r
1833 iStateIdCheck = MC_CHECKMARKDISABLED;
\r
1835 iStateIdCheck = MC_CHECKMARKNORMAL;
\r
1838 return iStateIdCheck;
\r
1842 ///////////////////////////////////
\r
1843 // Definitions for the CFrame class
\r
1845 inline CFrame::CFrame() : m_pMenuMetrics(0), m_strStatusText(_T("Ready")), m_bShowIndicatorStatus(TRUE), m_bShowMenuStatus(TRUE),
\r
1846 m_bUseReBar(FALSE), m_bUseThemes(TRUE), m_bUseToolBar(TRUE), m_bShowStatusBar(TRUE), m_bShowToolBar(TRUE),
\r
1847 m_himlMenu(0), m_himlMenuDis(0), m_AboutDialog(IDW_ABOUT), m_pView(NULL), m_nMaxMRU(0), m_hOldFocus(0), m_nOldID(-1)
\r
1849 ZeroMemory(&m_ThemeMenu, sizeof(m_ThemeMenu));
\r
1851 // Do either InitCommonControls or InitCommonControlsEx
\r
1852 LoadCommonControls();
\r
1854 // By default, we use the rebar if we can
\r
1855 if (GetComCtlVersion() > 470)
\r
1856 m_bUseReBar = TRUE;
\r
1858 for (int i = 0 ; i < 3 ; ++i)
\r
1859 m_OldStatus[i] = _T('\0');
\r
1861 NONCLIENTMETRICS nm = {0};
\r
1862 nm.cbSize = GetSizeofNonClientMetrics();
\r
1863 SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &nm, 0);
\r
1864 m_fntMenuBar.CreateFontIndirect(&nm.lfMenuFont);
\r
1865 m_fntStatusBar.CreateFontIndirect(&nm.lfStatusFont);
\r
1868 inline CFrame::~CFrame()
\r
1870 if (m_himlMenu) ImageList_Destroy(m_himlMenu);
\r
1871 if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
\r
1874 inline BOOL CFrame::AddMenuIcon(int nID_MenuItem, HICON hIcon)
\r
1876 // Create a new ImageList if required
\r
1877 if (NULL == m_himlMenu)
\r
1879 if (m_himlMenu) ImageList_Destroy(m_himlMenu);
\r
1880 m_himlMenu = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 1, 0);
\r
1881 m_vMenuIcons.clear();
\r
1884 if (ImageList_AddIcon(m_himlMenu, hIcon) != -1)
\r
1886 m_vMenuIcons.push_back(nID_MenuItem);
\r
1888 // Recreate the Disabled imagelist
\r
1889 if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
\r
1890 m_himlMenuDis = NULL;
\r
1891 m_himlMenuDis = CreateDisabledImageList(m_himlMenu);
\r
1899 inline UINT CFrame::AddMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID)
\r
1900 // Adds the icons from a bitmap resouce to an internal ImageList for use with popup menu items.
\r
1901 // Note: If existing are a different size to the new ones, the old ones will be removed!
\r
1902 // The ToolBarDisabledID is ignored unless ToolBarID and ToolBarDisabledID bitmaps are the same size.
\r
1904 // Count the MenuData entries excluding seperators
\r
1906 for (UINT i = 0 ; i < MenuData.size(); ++i)
\r
1908 if (MenuData[i] != 0) // Don't count seperators
\r
1914 // Load the button images from Resouce ID
\r
1915 CBitmap Bitmap(ToolBarID);
\r
1917 if ((0 == iImages) || (!Bitmap))
\r
1918 return (UINT)m_vMenuIcons.size(); // No valid images, so nothing to do!
\r
1920 BITMAP bm = Bitmap.GetBitmapData();
\r
1921 int iImageWidth = bm.bmWidth / iImages;
\r
1922 int iImageHeight = bm.bmHeight;
\r
1924 // Create the ImageList if required
\r
1925 if (NULL == m_himlMenu)
\r
1927 m_himlMenu = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iImages, 0);
\r
1928 m_vMenuIcons.clear();
\r
1935 ImageList_GetIconSize(m_himlMenu, &Oldcx, &Oldcy);
\r
1936 if (iImageHeight != Oldcy)
\r
1938 TRACE(_T("Unable to add icons. The new icons are a different size to the old ones\n"));
\r
1939 return (UINT)m_vMenuIcons.size();
\r
1943 // Add the resource IDs to the m_vMenuIcons vector
\r
1944 for (UINT j = 0 ; j < MenuData.size(); ++j)
\r
1946 if (MenuData[j] != 0)
\r
1948 m_vMenuIcons.push_back(MenuData[j]);
\r
1952 // Add the images to the ImageList
\r
1953 ImageList_AddMasked(m_himlMenu, Bitmap, crMask);
\r
1955 // Create the Disabled imagelist
\r
1956 if (ToolBarDisabledID)
\r
1958 if (0 != m_himlMenuDis)
\r
1959 m_himlMenuDis = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iImages, 0);
\r
1961 CBitmap BitmapDisabled(ToolBarDisabledID);
\r
1962 BITMAP bmDis = BitmapDisabled.GetBitmapData();
\r
1964 int iImageWidthDis = bmDis.bmWidth / iImages;
\r
1965 int iImageHeightDis = bmDis.bmHeight;
\r
1967 // Normal and Disabled icons must be the same size
\r
1968 if ((iImageWidthDis == iImageWidth) && (iImageHeightDis == iImageHeight))
\r
1970 ImageList_AddMasked(m_himlMenu, BitmapDisabled, crMask);
\r
1974 ImageList_Destroy(m_himlMenuDis);
\r
1975 m_himlMenuDis = CreateDisabledImageList(m_himlMenu);
\r
1980 if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
\r
1981 m_himlMenuDis = CreateDisabledImageList(m_himlMenu);
\r
1984 // return the number of menu icons
\r
1985 return (UINT)m_vMenuIcons.size();
\r
1988 inline void CFrame::AddMenuBarBand()
\r
1990 // Adds a MenuBar to the rebar control
\r
1991 REBARBANDINFO rbbi = {0};
\r
1992 CSize sz = GetMenuBar().GetMaxSize();
\r
1994 // Calculate the MenuBar height from the menu font
\r
1996 CClientDC dcMenuBar(&GetMenuBar());
\r
1997 dcMenuBar.SelectObject(GetMenuBar().GetFont());
\r
1998 csMenuBar = dcMenuBar.GetTextExtentPoint32(_T("\tSomeText"), lstrlen(_T("\tSomeText")));
\r
1999 int MenuBar_Height = csMenuBar.cy + 6;
\r
2001 rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_SIZE | RBBIM_ID;
\r
2002 rbbi.cxMinChild = sz.cx;
\r
2004 rbbi.cyMinChild = MenuBar_Height;
\r
2005 rbbi.cyMaxChild = MenuBar_Height;
\r
2006 rbbi.fStyle = RBBS_BREAK | RBBS_VARIABLEHEIGHT | RBBS_GRIPPERALWAYS ;
\r
2007 rbbi.hwndChild = GetMenuBar();
\r
2008 rbbi.wID = IDW_MENUBAR;
\r
2010 // Note: rbbi.cbSize is set inside the InsertBand function
\r
2011 GetReBar().InsertBand(-1, rbbi);
\r
2012 SetMenuBarBandSize();
\r
2013 GetReBar().SetMenuBar(GetMenuBar());
\r
2015 if (GetReBar().GetReBarTheme().LockMenuBand)
\r
2016 GetReBar().ShowGripper(GetReBar().GetBand(GetMenuBar()), FALSE);
\r
2019 inline void CFrame::AddMRUEntry(LPCTSTR szMRUEntry)
\r
2021 // Erase possible duplicate entries from vector
\r
2022 RemoveMRUEntry(szMRUEntry);
\r
2024 // Insert the entry at the beginning of the vector
\r
2025 m_vMRUEntries.insert(m_vMRUEntries.begin(), szMRUEntry);
\r
2027 // Delete excessive MRU entries
\r
2028 if (m_vMRUEntries.size() > m_nMaxMRU)
\r
2029 m_vMRUEntries.erase(m_vMRUEntries.begin() + m_nMaxMRU, m_vMRUEntries.end());
\r
2034 inline void CFrame::AddToolBarBand(CToolBar& TB, DWORD dwStyle, UINT nID)
\r
2036 // Adds a ToolBar to the rebar control
\r
2038 // Create the ToolBar Window
\r
2039 TB.Create(&GetReBar());
\r
2041 // Fill the REBARBAND structure
\r
2042 REBARBANDINFO rbbi = {0};
\r
2043 CSize sz = TB.GetMaxSize();
\r
2045 rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_SIZE | RBBIM_ID;
\r
2046 rbbi.cyMinChild = sz.cy;
\r
2047 rbbi.cyMaxChild = sz.cy;
\r
2048 rbbi.cx = sz.cx +2;
\r
2049 rbbi.cxMinChild = sz.cx +2;
\r
2051 rbbi.fStyle = dwStyle;
\r
2052 rbbi.hwndChild = TB;
\r
2055 // Note: rbbi.cbSize is set inside the InsertBand function
\r
2056 GetReBar().InsertBand(-1, rbbi);
\r
2059 inline void CFrame::AddToolBarButton(UINT nID, BOOL bEnabled /* = TRUE*/, LPCTSTR szText)
\r
2060 // Adds Resource IDs to toolbar buttons.
\r
2061 // A resource ID of 0 is a separator
\r
2063 GetToolBar().AddButton(nID, bEnabled);
\r
2066 GetToolBar().SetButtonText(nID, szText);
\r
2068 if (!IsWindow()) TRACE(_T("Warning ... Resource IDs for toolbars should be added in SetupToolBar\n"));
\r
2071 inline void CFrame::AdjustFrameRect(RECT rcView) const
\r
2072 // Adjust the size of the frame to accommodate the View window's dimensions
\r
2074 // Adjust for the view styles
\r
2075 CRect rc = rcView;
\r
2076 DWORD dwStyle = (DWORD)GetView()->GetWindowLongPtr(GWL_STYLE);
\r
2077 DWORD dwExStyle = (DWORD)GetView()->GetWindowLongPtr(GWL_EXSTYLE);
\r
2078 AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
\r
2080 // Calculate the new frame height
\r
2081 CRect rcFrameBefore = GetWindowRect();
\r
2082 CRect rcViewBefore = GetViewRect();
\r
2083 int Height = rc.Height() + rcFrameBefore.Height() - rcViewBefore.Height();
\r
2085 // Adjust for the frame styles
\r
2086 dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
\r
2087 dwExStyle = (DWORD)GetWindowLongPtr(GWL_EXSTYLE);
\r
2088 AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
\r
2090 // Calculate final rect size, and reposition frame
\r
2091 SetWindowPos(NULL, 0, 0, rc.Width(), Height, SWP_NOMOVE);
\r
2094 inline void CFrame::CreateToolBar()
\r
2096 if (IsReBarSupported() && m_bUseReBar)
\r
2097 AddToolBarBand(GetToolBar(), RBBS_BREAK, IDW_TOOLBAR); // Create the toolbar inside rebar
\r
2099 GetToolBar().Create(this); // Create the toolbar without a rebar
\r
2103 if (IsReBarSupported() && m_bUseReBar)
\r
2105 if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().LockMenuBand)
\r
2107 // Hide gripper for single toolbar
\r
2108 if (GetReBar().GetBandCount() <= 2)
\r
2109 GetReBar().ShowGripper(GetReBar().GetBand(GetToolBar()), FALSE);
\r
2113 if (GetToolBar().GetToolBarData().size() > 0)
\r
2115 // Set the toolbar images (if not already set in SetupToolBar)
\r
2116 // A mask of 192,192,192 is compatible with AddBitmap (for Win95)
\r
2117 if (!GetToolBar().SendMessage(TB_GETIMAGELIST, 0L, 0L))
\r
2118 SetToolBarImages(RGB(192,192,192), IDW_MAIN, 0, 0);
\r
2120 // Add the icons for popup menu
\r
2121 AddMenuIcons(GetToolBar().GetToolBarData(), RGB(192, 192, 192), IDW_MAIN, 0);
\r
2125 TRACE(_T("Warning ... No resource IDs assigned to the toolbar\n"));
\r
2129 inline void CFrame::DrawMenuItem(LPDRAWITEMSTRUCT pdis)
\r
2131 MenuItemData* pmid = (MenuItemData*)pdis->itemData;
\r
2132 int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState);
\r
2133 MenuTheme tm = GetMenuTheme();
\r
2134 CDC DrawDC(pdis->hDC);
\r
2136 if (IsAeroThemed() && m_pMenuMetrics->IsThemeBackgroundPartiallyTransparent(MENU_POPUPITEM, iStateId))
\r
2138 m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPBACKGROUND, 0, &pdis->rcItem, NULL);
\r
2141 // Draw the gutter
\r
2142 CRect rcGutter = m_pMenuMetrics->GetGutterRect(pdis->rcItem);
\r
2143 if (IsAeroThemed())
\r
2144 m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPGUTTER, 0, &rcGutter, NULL);
\r
2146 DrawDC.GradientFill(tm.clrPressed1, tm.clrPressed2, rcGutter, TRUE);
\r
2148 if (pmid->mii.fType & MFT_SEPARATOR)
\r
2150 // Draw the separator
\r
2151 if (IsAeroThemed())
\r
2153 CRect rcSeparator = m_pMenuMetrics->GetSeperatorRect(pdis->rcItem);
\r
2154 m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPSEPARATOR, 0, &rcSeparator, NULL);
\r
2158 CRect rc = pdis->rcItem;
\r
2159 CRect rcSep = pdis->rcItem;
\r
2160 rcSep.left = m_pMenuMetrics->GetGutterRect(rc).Width() + 2;
\r
2161 DrawDC.SolidFill(RGB(255,255,255), rcSep);
\r
2162 rcSep.top += (rc.bottom - rc.top)/2;
\r
2163 DrawDC.DrawEdge(rcSep, EDGE_ETCHED, BF_TOP);
\r
2168 // Draw the item background
\r
2169 DrawMenuItemBkgnd(pdis);
\r
2171 // Draw Checkmark or icon
\r
2172 if (pmid->mii.fState & MFS_CHECKED)
\r
2173 DrawMenuItemCheckmark(pdis);
\r
2175 DrawMenuItemIcon(pdis);
\r
2178 DrawMenuItemText(pdis);
\r
2181 if (IsAeroThemed())
\r
2183 // Draw the Submenu arrow
\r
2184 if (pmid->mii.hSubMenu)
\r
2186 CRect rcSubMenu = pdis->rcItem;
\r
2187 rcSubMenu.left = pdis->rcItem.right - m_pMenuMetrics->m_marItem.cxRightWidth - m_pMenuMetrics->m_marText.cxRightWidth;;
\r
2188 m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPSUBMENU, m_pMenuMetrics->ToCheckStateId(pmid->mii.fType, iStateId), &rcSubMenu, NULL);
\r
2191 // Suppress further drawing to prevent an incorrect Submenu arrow being drawn
\r
2192 CRect rc = pdis->rcItem;
\r
2193 ::ExcludeClipRect(pdis->hDC, rc.left, rc.top, rc.right, rc.bottom);
\r
2199 inline void CFrame::DrawMenuItemBkgnd(LPDRAWITEMSTRUCT pdis)
\r
2201 // Draw the item background
\r
2202 CRect rcSelection = m_pMenuMetrics->GetSelectionRect(pdis->rcItem);
\r
2203 if (IsAeroThemed())
\r
2205 int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState);
\r
2206 m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPITEM, iStateId, &rcSelection, NULL);
\r
2210 BOOL bDisabled = pdis->itemState & ODS_GRAYED;
\r
2211 BOOL bSelected = pdis->itemState & ODS_SELECTED;
\r
2212 CRect rcDraw = pdis->rcItem;
\r
2213 CDC* pDrawDC = FromHandle(pdis->hDC);
\r
2214 MenuTheme tm = GetMenuTheme();
\r
2216 if ((bSelected) && (!bDisabled))
\r
2218 // draw selected item background
\r
2219 pDrawDC->CreateSolidBrush(tm.clrHot1);
\r
2220 pDrawDC->CreatePen(PS_SOLID, 1, tm.clrOutline);
\r
2221 pDrawDC->Rectangle(rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom);
\r
2225 // draw non-selected item background
\r
2226 rcDraw.left = m_pMenuMetrics->GetGutterRect(pdis->rcItem).Width();
\r
2227 pDrawDC->SolidFill(RGB(255,255,255), rcDraw);
\r
2232 inline void CFrame::DrawMenuItemCheckmark(LPDRAWITEMSTRUCT pdis)
\r
2233 // Draws the checkmark or radiocheck transparently
\r
2235 CRect rc = pdis->rcItem;
\r
2236 UINT fType = ((MenuItemData*)pdis->itemData)->mii.fType;
\r
2237 MenuTheme tm = GetMenuTheme();
\r
2239 CDC* pDrawDC = FromHandle(pdis->hDC);
\r
2241 if (IsAeroThemed())
\r
2243 int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState);
\r
2244 MenuItemData* pmid = (MenuItemData*)pdis->itemData;
\r
2245 CRect rcCheckBackground = m_pMenuMetrics->GetCheckBackgroundRect(pdis->rcItem);
\r
2246 m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPCHECKBACKGROUND, m_pMenuMetrics->ToCheckBackgroundStateId(iStateId), &rcCheckBackground, NULL);
\r
2247 CRect rcCheck = m_pMenuMetrics->GetCheckRect(pdis->rcItem);
\r
2248 m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPCHECK, m_pMenuMetrics->ToCheckStateId(pmid->mii.fType, iStateId), &rcCheck, NULL);
\r
2252 // Draw the checkmark's background rectangle first
\r
2253 int Iconx = m_pMenuMetrics->m_sizeCheck.cx;
\r
2254 int Icony = m_pMenuMetrics->m_sizeCheck.cy;
\r
2255 int left = m_pMenuMetrics->m_marCheck.cxLeftWidth;
\r
2256 int top = rc.top + (rc.Height() - Icony)/2;
\r
2257 rcBk.SetRect(left, top, left + Iconx, top + Icony);
\r
2259 pDrawDC->CreateSolidBrush(tm.clrHot2);
\r
2260 pDrawDC->CreatePen(PS_SOLID, 1, tm.clrOutline);
\r
2262 // Draw the checkmark's background rectangle
\r
2263 pDrawDC->Rectangle(rcBk.left, rcBk.top, rcBk.right, rcBk.bottom);
\r
2265 CMemDC MemDC(FromHandle(pdis->hDC));
\r
2266 int cxCheck = ::GetSystemMetrics(SM_CXMENUCHECK);
\r
2267 int cyCheck = ::GetSystemMetrics(SM_CYMENUCHECK);
\r
2268 MemDC.CreateBitmap(cxCheck, cyCheck, 1, 1, NULL);
\r
2269 CRect rcCheck( 0, 0, cxCheck, cyCheck);
\r
2271 // Copy the check mark bitmap to hdcMem
\r
2272 if (MFT_RADIOCHECK == fType)
\r
2273 MemDC.DrawFrameControl(rcCheck, DFC_MENU, DFCS_MENUBULLET);
\r
2275 MemDC.DrawFrameControl(rcCheck, DFC_MENU, DFCS_MENUCHECK);
\r
2277 int xoffset = (rcBk.Width() - rcCheck.Width()-1)/2;
\r
2278 int yoffset = (rcBk.Height() - rcCheck.Height()-1)/2;
\r
2282 // Draw a white or black check mark as required
\r
2283 // Unfortunately MaskBlt isn't supported on Win95, 98 or ME, so we do it the hard way
\r
2284 CMemDC MaskDC(FromHandle(pdis->hDC));
\r
2285 MaskDC.CreateCompatibleBitmap(FromHandle(pdis->hDC), cxCheck, cyCheck);
\r
2286 MaskDC.BitBlt(0, 0, cxCheck, cyCheck, &MaskDC, 0, 0, WHITENESS);
\r
2288 if ((pdis->itemState & ODS_SELECTED)) // && (!tm.UseThemes))
\r
2290 // Draw a white checkmark
\r
2291 MemDC.BitBlt(0, 0, cxCheck, cyCheck, &MemDC, 0, 0, DSTINVERT);
\r
2292 MaskDC.BitBlt(0, 0, cxCheck, cyCheck, &MemDC, 0, 0, SRCAND);
\r
2293 pDrawDC->BitBlt(rcBk.left + xoffset, rcBk.top + yoffset, cxCheck, cyCheck, &MaskDC, 0, 0, SRCPAINT);
\r
2297 // Draw a black checkmark
\r
2298 int BullitOffset = ((MFT_RADIOCHECK == fType)/* && tm.UseThemes*/)? 1 : 0;
\r
2299 MaskDC.BitBlt( -BullitOffset, BullitOffset, cxCheck, cyCheck, &MemDC, 0, 0, SRCAND);
\r
2300 pDrawDC->BitBlt(rcBk.left + xoffset, rcBk.top + yoffset, cxCheck, cyCheck, &MaskDC, 0, 0, SRCAND);
\r
2305 inline void CFrame::DrawMenuItemIcon(LPDRAWITEMSTRUCT pdis)
\r
2311 int Iconx = m_pMenuMetrics->m_sizeCheck.cx;
\r
2312 int Icony = m_pMenuMetrics->m_sizeCheck.cy;
\r
2314 // get the drawing rectangle
\r
2315 CRect rc = pdis->rcItem;
\r
2316 int left = m_pMenuMetrics->m_marCheck.cxLeftWidth;
\r
2317 int top = rc.top + (rc.Height() - Icony)/2;
\r
2318 rc.SetRect(left, top, left + Iconx, top + Icony);
\r
2320 // get the icon's location in the imagelist
\r
2322 for (int i = 0 ; i < (int)m_vMenuIcons.size(); ++i)
\r
2324 if (pdis->itemID == m_vMenuIcons[i])
\r
2331 BOOL bDisabled = pdis->itemState & ODS_GRAYED;
\r
2332 if ((bDisabled) && (m_himlMenuDis))
\r
2333 ImageList_Draw(m_himlMenuDis, iImage, pdis->hDC, rc.left, rc.top, ILD_TRANSPARENT);
\r
2335 ImageList_Draw(m_himlMenu, iImage, pdis->hDC, rc.left, rc.top, ILD_TRANSPARENT);
\r
2339 inline void CFrame::DrawMenuItemText(LPDRAWITEMSTRUCT pdis)
\r
2341 LPCTSTR ItemText = ((MenuItemData*)pdis->itemData)->GetItemText();
\r
2342 BOOL bDisabled = pdis->itemState & ODS_GRAYED;
\r
2343 COLORREF colorText = GetSysColor(bDisabled ? COLOR_GRAYTEXT : COLOR_MENUTEXT);
\r
2345 // Calculate the text rect size
\r
2346 CRect rcText = m_pMenuMetrics->GetTextRect(pdis->rcItem);
\r
2348 // find the position of tab character
\r
2350 for(int i = 0; i < lstrlen(ItemText); ++i)
\r
2352 if(_T('\t') == ItemText[i])
\r
2359 // Draw the item text
\r
2360 if (IsAeroThemed())
\r
2362 ULONG uAccel = ((pdis->itemState & ODS_NOACCEL) ? DT_HIDEPREFIX : 0);
\r
2363 int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState);
\r
2365 // Draw the item text before the tab
\r
2366 m_pMenuMetrics->DrawThemeText(pdis->hDC, MENU_POPUPITEM, iStateId, T2W(ItemText), nTab, DT_SINGLELINE | DT_LEFT | DT_TOP | uAccel, 0, &rcText);
\r
2368 // Draw text after tab, right aligned
\r
2370 m_pMenuMetrics->DrawThemeText(pdis->hDC, MENU_POPUPITEM, iStateId, T2W(&ItemText[nTab + 1]), -1, DT_SINGLELINE | DT_RIGHT | DT_TOP | uAccel, 0, &rcText);
\r
2374 SetTextColor(pdis->hDC, colorText);
\r
2375 int iMode = SetBkMode(pdis->hDC, TRANSPARENT);
\r
2376 DrawText(pdis->hDC, ItemText, nTab, rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
\r
2378 // Draw text after tab, right aligned
\r
2380 DrawText(pdis->hDC, &ItemText[nTab + 1], -1, rcText, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);
\r
2382 SetBkMode(pdis->hDC, iMode);
\r
2386 inline int CFrame::GetMenuItemPos(HMENU hMenu, LPCTSTR szItem)
\r
2387 // Returns the position of the menu item, given it's name
\r
2389 int nMenuItemCount = GetMenuItemCount(hMenu);
\r
2390 MENUITEMINFO mii = {0};
\r
2391 mii.cbSize = GetSizeofMenuItemInfo();
\r
2393 for (int nItem = 0 ; nItem < nMenuItemCount; ++nItem)
\r
2395 std::vector<TCHAR> vTChar( MAX_MENU_STRING+1, _T('\0') );
\r
2396 TCHAR* szStr = &vTChar[0];
\r
2398 std::vector<TCHAR> vStripped( MAX_MENU_STRING+1, _T('\0') );
\r
2399 TCHAR* szStripped = &vStripped[0];
\r
2401 mii.fMask = MIIM_TYPE;
\r
2402 mii.fType = MFT_STRING;
\r
2403 mii.dwTypeData = szStr;
\r
2404 mii.cch = MAX_MENU_STRING;
\r
2406 // Fill the contents of szStr from the menu item
\r
2407 if (::GetMenuItemInfo(hMenu, nItem, TRUE, &mii) && (lstrlen(szStr) <= MAX_MENU_STRING))
\r
2409 // Strip out any & characters
\r
2411 for (int i = 0; i < lstrlen(szStr); ++i)
\r
2413 if (szStr[i] != _T('&'))
\r
2414 szStripped[j++] = szStr[i];
\r
2416 szStripped[j] = _T('\0'); // Append null tchar
\r
2418 // Compare the strings
\r
2419 if (0 == lstrcmp(szStripped, szItem))
\r
2427 inline CString CFrame::GetMRUEntry(UINT nIndex)
\r
2429 CString strPathName;
\r
2430 if (nIndex < m_vMRUEntries.size())
\r
2432 strPathName = m_vMRUEntries[nIndex];
\r
2434 // Now put the selected entry at Index 0
\r
2435 AddMRUEntry(strPathName);
\r
2437 return strPathName;
\r
2440 inline CRect CFrame::GetViewRect() const
\r
2442 // Get the frame's client area
\r
2443 CRect rcFrame = GetClientRect();
\r
2445 // Get the statusbar's window area
\r
2447 if (GetStatusBar().IsWindowVisible() || !IsWindowVisible())
\r
2448 rcStatus = GetStatusBar().GetWindowRect();
\r
2450 // Get the top rebar or toolbar's window area
\r
2452 if (IsReBarSupported() && m_bUseReBar)
\r
2453 rcTop = GetReBar().GetWindowRect();
\r
2455 if (GetToolBar().IsWindow() && GetToolBar().IsWindowVisible())
\r
2456 rcTop = GetToolBar().GetWindowRect();
\r
2458 // Return client size less the rebar and status windows
\r
2459 int top = rcFrame.top + rcTop.Height();
\r
2460 int left = rcFrame.left;
\r
2461 int right = rcFrame.right;
\r
2462 int bottom = rcFrame.Height() - (rcStatus.Height());
\r
2463 if ((bottom <= top) ||( right <= left))
\r
2464 top = left = right = bottom = 0;
\r
2466 CRect rcView(left, top, right, bottom);
\r
2470 inline CString CFrame::GetThemeName() const
\r
2472 // Returns the XP theme name
\r
2473 HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll"));
\r
2474 WCHAR ThemeName[31] = L"";
\r
2477 typedef HRESULT (__stdcall *PFNGETCURRENTTHEMENAME)(LPWSTR pszThemeFileName, int cchMaxNameChars,
\r
2478 LPWSTR pszColorBuff, int cchMaxColorChars, LPWSTR pszSizeBuff, int cchMaxSizeChars);
\r
2480 PFNGETCURRENTTHEMENAME pfn = (PFNGETCURRENTTHEMENAME)GetProcAddress(hMod, "GetCurrentThemeName");
\r
2481 (*pfn)(0, 0, ThemeName, 30, 0, 0);
\r
2483 ::FreeLibrary(hMod);
\r
2486 return CString(ThemeName);
\r
2489 inline void CFrame::LoadCommonControls()
\r
2495 // Load the Common Controls DLL
\r
2496 hComCtl = ::LoadLibrary(_T("COMCTL32.DLL"));
\r
2498 throw CWinException(_T("Failed to load COMCTL32.DLL"));
\r
2500 if (GetComCtlVersion() > 470)
\r
2502 // Declare a pointer to the InItCommonControlsEx function
\r
2503 typedef BOOL WINAPI INIT_EX(INITCOMMONCONTROLSEX*);
\r
2504 INIT_EX* pfnInit = (INIT_EX*)::GetProcAddress(hComCtl, "InitCommonControlsEx");
\r
2506 // Load the full set of common controls
\r
2507 INITCOMMONCONTROLSEX InitStruct = {0};
\r
2508 InitStruct.dwSize = sizeof(INITCOMMONCONTROLSEX);
\r
2509 InitStruct.dwICC = ICC_COOL_CLASSES|ICC_DATE_CLASSES|ICC_INTERNET_CLASSES|ICC_NATIVEFNTCTL_CLASS|
\r
2510 ICC_PAGESCROLLER_CLASS|ICC_USEREX_CLASSES|ICC_WIN95_CLASSES;
\r
2512 // Call InitCommonControlsEx
\r
2513 if(!((*pfnInit)(&InitStruct)))
\r
2514 throw CWinException(_T("InitCommonControlsEx failed"));
\r
2518 ::InitCommonControls();
\r
2521 ::FreeLibrary(hComCtl);
\r
2524 catch (const CWinException &e)
\r
2528 ::FreeLibrary(hComCtl);
\r
2534 inline BOOL CFrame::LoadRegistryMRUSettings(UINT nMaxMRU /*= 0*/)
\r
2536 // Load the MRU list from the registry
\r
2538 assert(!m_strKeyName.IsEmpty()); // KeyName must be set before calling LoadRegistryMRUSettings
\r
2540 BOOL bRet = FALSE;
\r
2544 m_nMaxMRU = MIN(nMaxMRU, 16);
\r
2545 std::vector<CString> vMRUEntries;
\r
2546 CString strKey = _T("Software\\") + m_strKeyName + _T("\\Recent Files");
\r
2548 if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey))
\r
2550 for (UINT i = 0; i < m_nMaxMRU; ++i)
\r
2552 DWORD dwType = REG_SZ;
\r
2553 DWORD dwBufferSize = 0;
\r
2554 TCHAR szSubKey[10] = _T("");
\r
2555 wsprintf(szSubKey, _T("File %d\0"), i+1);
\r
2557 if (ERROR_SUCCESS != RegQueryValueEx(hKey, szSubKey, NULL, &dwType, NULL, &dwBufferSize))
\r
2558 throw CWinException(_T("RegQueryValueEx failed\n"));
\r
2560 std::vector<TCHAR> PathName( dwBufferSize, _T('\0') );
\r
2561 TCHAR* pTCharArray = &PathName[0];
\r
2563 // load the entry from the registry
\r
2564 if (ERROR_SUCCESS != RegQueryValueEx(hKey, szSubKey, NULL, &dwType, (LPBYTE)pTCharArray, &dwBufferSize))
\r
2565 throw CWinException(_T("RegQueryValueEx failed\n"));
\r
2567 if ( lstrlen( pTCharArray ) )
\r
2568 vMRUEntries.push_back( pTCharArray );
\r
2571 // successfully loaded all MRU values, so store them
\r
2572 m_vMRUEntries = vMRUEntries;
\r
2573 RegCloseKey(hKey);
\r
2578 catch(const CWinException& e)
\r
2580 TRACE(_T("Failed to load MRU values from registry\n"));
\r
2584 RegCloseKey(hKey);
\r
2590 inline BOOL CFrame::LoadRegistrySettings(LPCTSTR szKeyName)
\r
2592 assert (NULL != szKeyName);
\r
2593 m_strKeyName = szKeyName;
\r
2595 CString strKey = _T("Software\\") + m_strKeyName + _T("\\Frame Settings");
\r
2597 BOOL bRet = FALSE;
\r
2601 if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey))
\r
2603 DWORD dwType = REG_BINARY;
\r
2604 DWORD BufferSize = sizeof(DWORD);
\r
2605 DWORD dwTop, dwLeft, dwWidth, dwHeight, dwStatusBar, dwToolBar;
\r
2606 if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Top"), NULL, &dwType, (LPBYTE)&dwTop, &BufferSize))
\r
2607 throw CWinException(_T("RegQueryValueEx Failed"));
\r
2608 if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Left"), NULL, &dwType, (LPBYTE)&dwLeft, &BufferSize))
\r
2609 throw CWinException(_T("RegQueryValueEx Failed"));
\r
2610 if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Width"), NULL, &dwType, (LPBYTE)&dwWidth, &BufferSize))
\r
2611 throw CWinException(_T("RegQueryValueEx Failed"));
\r
2612 if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Height"), NULL, &dwType, (LPBYTE)&dwHeight, &BufferSize))
\r
2613 throw CWinException(_T("RegQueryValueEx Failed"));
\r
2614 if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("StatusBar"), NULL, &dwType, (LPBYTE)&dwStatusBar, &BufferSize))
\r
2615 throw CWinException(_T("RegQueryValueEx Failed"));
\r
2616 if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("ToolBar"), NULL, &dwType, (LPBYTE)&dwToolBar, &BufferSize))
\r
2617 throw CWinException(_T("RegQueryValueEx Failed"));
\r
2619 m_rcPosition.top = dwTop;
\r
2620 m_rcPosition.left = dwLeft;
\r
2621 m_rcPosition.bottom = m_rcPosition.top + dwHeight;
\r
2622 m_rcPosition.right = m_rcPosition.left + dwWidth;
\r
2623 m_bShowStatusBar = dwStatusBar & 1;
\r
2624 m_bShowToolBar = dwToolBar & 1;
\r
2626 RegCloseKey(hKey);
\r
2631 catch (const CWinException& e)
\r
2633 TRACE(_T("Failed to load values from registry, using defaults!\n"));
\r
2637 RegCloseKey(hKey);
\r
2643 inline void CFrame::MeasureMenuItem(MEASUREITEMSTRUCT *pmis)
\r
2648 MenuItemData* pmid = (MenuItemData*)pmis->itemData;
\r
2649 assert(::IsMenu(pmid->hMenu)); // Does itemData contain a valid MenuItemData struct?
\r
2651 // Add icon/check width
\r
2652 cxTotal += m_pMenuMetrics->m_sizeCheck.cx + m_pMenuMetrics->m_marCheckBackground.Width() + m_pMenuMetrics->m_marCheck.Width();
\r
2654 if (pmid->mii.fType & MFT_SEPARATOR)
\r
2656 // separator height
\r
2657 cyMax = m_pMenuMetrics->m_sizeSeparator.cy + m_pMenuMetrics->m_marItem.Height();
\r
2661 // Add check background horizontal padding.
\r
2662 cxTotal += m_pMenuMetrics->m_marCheckBackground.cxLeftWidth + m_pMenuMetrics->m_marCheckBackground.cxRightWidth;
\r
2664 // Add selection margin padding.
\r
2665 cxTotal += m_pMenuMetrics->m_marItem.cxLeftWidth + m_pMenuMetrics->m_marItem.cxRightWidth;
\r
2667 // Account for text size
\r
2668 CSize sizeText = m_pMenuMetrics->GetTextSize(pmid);
\r
2669 cxTotal += sizeText.cx;
\r
2670 cyMax = MAX(cyMax, sizeText.cy);
\r
2672 // Account for icon or check height
\r
2673 cyMax = MAX(cyMax, m_pMenuMetrics->m_sizeCheck.cy + m_pMenuMetrics->m_marCheckBackground.Height() + m_pMenuMetrics->m_marCheck.Height());
\r
2676 // Return the composite sizes.
\r
2677 pmis->itemWidth = cxTotal;
\r
2678 pmis->itemHeight = cyMax;
\r
2681 inline void CFrame::OnActivate(WPARAM wParam, LPARAM lParam)
\r
2683 // Do default processing first
\r
2684 DefWindowProc(WM_ACTIVATE, wParam, lParam);
\r
2686 if (LOWORD(wParam) == WA_INACTIVE)
\r
2688 // Save the hwnd of the window which currently has focus
\r
2689 // (this must be CFrame window itself or a child window
\r
2690 if (!IsIconic()) m_hOldFocus = ::GetFocus();
\r
2692 // Send a notification to the view window
\r
2693 int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
\r
2695 nhdr.hwndFrom = m_hOldFocus;
\r
2696 nhdr.idFrom = idCtrl;
\r
2697 nhdr.code = UWM_FRAMELOSTFOCUS;
\r
2698 if (GetView()->IsWindow())
\r
2699 GetView()->SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);
\r
2703 // Now set the focus to the appropriate child window
\r
2704 if (m_hOldFocus) ::SetFocus(m_hOldFocus);
\r
2706 // Send a notification to the view window
\r
2707 int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
\r
2709 nhdr.hwndFrom = m_hOldFocus;
\r
2710 nhdr.idFrom = idCtrl;
\r
2711 nhdr.code = UWM_FRAMEGOTFOCUS;
\r
2712 if (GetView()->IsWindow())
\r
2713 GetView()->SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);
\r
2717 inline void CFrame::OnClose()
\r
2719 // Called in response to a WM_CLOSE message for the frame.
\r
2720 ShowWindow(SW_HIDE);
\r
2721 SaveRegistrySettings();
\r
2723 GetMenuBar().Destroy();
\r
2724 GetToolBar().Destroy();
\r
2725 GetReBar().Destroy();
\r
2726 GetStatusBar().Destroy();
\r
2727 GetView()->Destroy();
\r
2730 inline void CFrame::OnCreate()
\r
2732 // This is called when the frame window is being created.
\r
2733 // Override this in CMainFrame if you wish to modify what happens here
\r
2736 SetIconLarge(IDW_MAIN);
\r
2737 SetIconSmall(IDW_MAIN);
\r
2739 // Set the keyboard accelerators
\r
2740 m_hAccel = LoadAccelerators(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_MAIN));
\r
2741 GetApp()->SetAccelerators(m_hAccel, this);
\r
2743 // Set the Caption
\r
2744 SetWindowText(LoadString(IDW_MAIN));
\r
2746 // Set the theme for the frame elements
\r
2749 // Create the rebar and menubar
\r
2750 if (IsReBarSupported() && m_bUseReBar)
\r
2752 // Create the rebar
\r
2753 GetReBar().Create(this);
\r
2755 // Create the menu inside rebar
\r
2756 GetMenuBar().Create(&GetReBar());
\r
2761 SetFrameMenu(IDW_MAIN);
\r
2762 m_pMenuMetrics = new CMenuMetrics(this);
\r
2766 // Create the ToolBar
\r
2767 if (m_bUseToolBar)
\r
2770 ShowToolBar(m_bShowToolBar);
\r
2774 GetFrameMenu().CheckMenuItem(IDW_VIEW_TOOLBAR, MF_UNCHECKED);
\r
2775 GetFrameMenu().EnableMenuItem(IDW_VIEW_TOOLBAR, MF_GRAYED);
\r
2778 // Create the status bar
\r
2779 GetStatusBar().Create(this);
\r
2780 GetStatusBar().SetFont(&m_fntStatusBar, FALSE);
\r
2781 ShowStatusBar(m_bShowStatusBar);
\r
2783 // Create the view window
\r
2784 assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
\r
2785 GetView()->Create(this);
\r
2787 // Disable XP themes for the menubar
\r
2788 if ( m_bUseThemes || (GetWinVersion() < 2600) ) // themes or WinVersion < Vista
\r
2789 GetMenuBar().SetWindowTheme(L" ", L" ");
\r
2791 // Start timer for Status updates
\r
2792 if (m_bShowIndicatorStatus || m_bShowMenuStatus)
\r
2793 SetTimer(ID_STATUS_TIMER, 200, NULL);
\r
2795 // Reposition the child windows
\r
2796 OnSysColorChange();
\r
2800 inline void CFrame::OnDestroy()
\r
2803 KillTimer(ID_STATUS_TIMER);
\r
2804 ::PostQuitMessage(0); // Terminates the application
\r
2807 inline LRESULT CFrame::OnDrawItem(WPARAM wParam, LPARAM lParam)
\r
2808 // OwnerDraw is used to render the popup menu items
\r
2810 LPDRAWITEMSTRUCT pdis = (LPDRAWITEMSTRUCT) lParam;
\r
2811 if (pdis->CtlType != ODT_MENU)
\r
2812 return CWnd::WndProcDefault(WM_DRAWITEM, wParam, lParam);
\r
2814 if (!IsRectEmpty(&pdis->rcItem))
\r
2815 DrawMenuItem(pdis);
\r
2820 inline void CFrame::OnExitMenuLoop()
\r
2824 for (UINT nItem = 0; nItem < m_vMenuItemData.size(); ++nItem)
\r
2826 // Undo OwnerDraw and put the text back
\r
2827 MENUITEMINFO mii = {0};
\r
2828 mii.cbSize = GetSizeofMenuItemInfo();
\r
2830 mii.fMask = MIIM_TYPE | MIIM_DATA;
\r
2831 mii.fType = m_vMenuItemData[nItem]->mii.fType;
\r
2832 mii.dwTypeData = m_vMenuItemData[nItem]->GetItemText();
\r
2833 mii.cch = lstrlen(m_vMenuItemData[nItem]->GetItemText());
\r
2834 mii.dwItemData = 0;
\r
2835 ::SetMenuItemInfo(m_vMenuItemData[nItem]->hMenu, m_vMenuItemData[nItem]->nPos, TRUE, &mii);
\r
2838 m_vMenuItemData.clear();
\r
2842 inline void CFrame::OnHelp()
\r
2844 // Ensure only one dialog displayed even for multiple hits of the F1 button
\r
2845 if (!m_AboutDialog.IsWindow())
\r
2847 // Store the window handle that currently has keyboard focus
\r
2848 HWND hPrevFocus = ::GetFocus();
\r
2849 if (hPrevFocus == GetMenuBar())
\r
2850 hPrevFocus = m_hWnd;
\r
2852 m_AboutDialog.SetDlgParent(this);
\r
2853 m_AboutDialog.DoModal();
\r
2855 ::SetFocus(hPrevFocus);
\r
2859 inline void CFrame::OnInitMenuPopup(WPARAM wParam, LPARAM lParam)
\r
2861 // The system menu shouldn't be owner drawn
\r
2862 if (HIWORD(lParam)) return;
\r
2866 CMenu* pMenu = FromHandle((HMENU)wParam);
\r
2868 for (UINT i = 0; i < pMenu->GetMenuItemCount(); ++i)
\r
2870 MenuItemData* pItem = new MenuItemData; // deleted in OnExitMenuLoop
\r
2871 m_vMenuItemData.push_back(ItemDataPtr(pItem)); // Store pItem in smart pointer for later automatic deletion
\r
2873 MENUITEMINFO mii = {0};
\r
2874 mii.cbSize = GetSizeofMenuItemInfo();
\r
2876 // Use old fashioned MIIM_TYPE instead of MIIM_FTYPE for MS VC6 compatibility
\r
2877 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU |MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
\r
2878 mii.dwTypeData = pItem->GetItemText(); // assign TCHAR pointer, text is assigned by GetMenuItemInfo
\r
2879 mii.cch = MAX_MENU_STRING -1;
\r
2881 // Send message for menu updates
\r
2882 UINT menuItem = pMenu->GetMenuItemID(i);
\r
2883 SendMessage(UWM_UPDATE_COMMAND, (WPARAM)menuItem, 0);
\r
2885 // Specify owner-draw for the menu item type
\r
2886 if (pMenu->GetMenuItemInfo(i, &mii, TRUE))
\r
2888 if (0 == mii.dwItemData)
\r
2890 pItem->hMenu = *pMenu;
\r
2893 mii.dwItemData = (DWORD_PTR)pItem;
\r
2894 mii.fType |= MFT_OWNERDRAW;
\r
2895 pMenu->SetMenuItemInfo(i, &mii, TRUE); // Store pItem in mii
\r
2902 inline LRESULT CFrame::OnMeasureItem(WPARAM wParam, LPARAM lParam)
\r
2903 // Called before the Popup menu is displayed, so that the MEASUREITEMSTRUCT
\r
2904 // values can be assigned with the menu item's dimensions.
\r
2906 LPMEASUREITEMSTRUCT pmis = (LPMEASUREITEMSTRUCT) lParam;
\r
2907 if (pmis->CtlType != ODT_MENU)
\r
2908 return CWnd::WndProcDefault(WM_MEASUREITEM, wParam, lParam);
\r
2910 MeasureMenuItem(pmis);
\r
2914 inline LRESULT CFrame::OnMenuChar(WPARAM wParam, LPARAM lParam)
\r
2916 if ((IsMenuBarUsed()) && (LOWORD(wParam)!= VK_SPACE))
\r
2918 // Activate MenuBar for key pressed with Alt key held down
\r
2919 GetMenuBar().OnMenuChar(wParam, lParam);
\r
2922 return CWnd::WndProcDefault(WM_MENUCHAR, wParam, lParam);
\r
2925 inline void CFrame::OnMenuSelect(WPARAM wParam, LPARAM lParam)
\r
2927 // Set the StatusBar text when we hover over a menu
\r
2928 // Only popup submenus have status strings
\r
2929 if (m_bShowMenuStatus)
\r
2931 int nID = LOWORD (wParam);
\r
2932 CMenu* pMenu = FromHandle((HMENU) lParam);
\r
2934 if ((pMenu != GetMenu()) && (nID != 0) && !(HIWORD(wParam) & MF_POPUP))
\r
2935 m_strStatusText = LoadString(nID);
\r
2937 m_strStatusText = _T("Ready");
\r
2943 inline LRESULT CFrame::OnNotify(WPARAM wParam, LPARAM lParam)
\r
2945 UNREFERENCED_PARAMETER(wParam);
\r
2947 switch (((LPNMHDR)lParam)->code)
\r
2949 case UWM_UNDOCKED:
\r
2952 case RBN_HEIGHTCHANGE:
\r
2956 // case RBN_LAYOUTCHANGED:
\r
2957 // if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
\r
2958 // GetReBar().MoveBandsLeft();
\r
2961 if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().ShortBands)
\r
2962 return 1L; // Supress maximise or minimise rebar band
\r
2965 // Display tooltips for the toolbar
\r
2966 case TTN_GETDISPINFO:
\r
2967 if (GetToolBar().IsWindow())
\r
2969 CToolBar* pToolBar = 0;
\r
2970 if (IsReBarUsed())
\r
2972 // Get the ToolBar's CWnd
\r
2973 CWnd* pWnd = FromHandle(GetReBar().HitTest(GetCursorPos()));
\r
2974 if (pWnd && (lstrcmp(pWnd->GetClassName(), _T("ToolbarWindow32")) == 0))
\r
2976 pToolBar = (CToolBar*)pWnd;
\r
2982 LPNMTTDISPINFO lpDispInfo = (LPNMTTDISPINFO)lParam;
\r
2983 int iIndex = pToolBar->HitTest();
\r
2986 int nID = pToolBar->GetCommandID(iIndex);
\r
2989 m_strTooltip = LoadString(nID);
\r
2990 lpDispInfo->lpszText = (LPTSTR)m_strTooltip.c_str();
\r
2993 m_strTooltip = _T("");
\r
2998 } // switch LPNMHDR
\r
3002 } // CFrame::Onotify(...)
\r
3004 inline void CFrame::OnSetFocus()
\r
3009 inline void CFrame::OnSysColorChange()
\r
3011 // Honour theme color changes
\r
3012 if (GetReBar().IsWindow())
\r
3014 for (int nBand = 0; nBand <= GetReBar().GetBandCount(); ++nBand)
\r
3016 GetReBar().SetBandColor(nBand, GetSysColor(COLOR_BTNTEXT), GetSysColor(COLOR_BTNFACE));
\r
3020 // Update the status bar font and text
\r
3021 NONCLIENTMETRICS nm = {0};
\r
3022 nm.cbSize = GetSizeofNonClientMetrics();
\r
3023 SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &nm, 0);
\r
3024 m_fntStatusBar.CreateFontIndirect(&nm.lfStatusFont);
\r
3025 GetStatusBar().SetFont(&m_fntStatusBar, TRUE);
\r
3029 if (GetMenuBar().IsWindow())
\r
3031 // Update the MenuBar font and button size
\r
3032 m_fntMenuBar.CreateFontIndirect(&nm.lfMenuFont);
\r
3033 GetMenuBar().SetFont(&m_fntMenuBar, TRUE);
\r
3034 GetMenuBar().SetMenu(GetFrameMenu());
\r
3036 // Update the MenuBar band size
\r
3037 int nBand = GetReBar().GetBand(GetMenuBar());
\r
3038 REBARBANDINFO rbbi = {0};
\r
3039 CClientDC dcMenuBar(&GetMenuBar());
\r
3040 dcMenuBar.SelectObject(GetMenuBar().GetFont());
\r
3041 CSize sizeMenuBar = dcMenuBar.GetTextExtentPoint32(_T("\tSomeText"), lstrlen(_T("\tSomeText")));
\r
3042 int MenuBar_Height = sizeMenuBar.cy + 6;
\r
3043 rbbi.fMask = RBBIM_CHILDSIZE;
\r
3044 rbbi.cyMinChild = MenuBar_Height;
\r
3045 rbbi.cyMaxChild = MenuBar_Height;
\r
3046 GetReBar().SetBandInfo(nBand, rbbi);
\r
3049 if (m_XPThemeName != GetThemeName())
\r
3051 m_pMenuMetrics->Initialize();
\r
3053 // Reposition and redraw everything
\r
3055 RedrawWindow(NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
\r
3057 // Forward the message to the view window
\r
3058 m_pView->PostMessage(WM_SYSCOLORCHANGE, 0L, 0L);
\r
3061 inline LRESULT CFrame::OnSysCommand(WPARAM wParam, LPARAM lParam)
\r
3063 if ((SC_KEYMENU == wParam) && (VK_SPACE != lParam) && IsMenuBarUsed())
\r
3065 GetMenuBar().OnSysCommand(wParam, lParam);
\r
3069 if (SC_MINIMIZE == wParam)
\r
3070 m_hOldFocus = ::GetFocus();
\r
3072 return CWnd::WndProcDefault(WM_SYSCOMMAND, wParam, lParam);
\r
3075 inline void CFrame::OnTimer(WPARAM wParam)
\r
3077 if (ID_STATUS_TIMER == wParam)
\r
3079 if (m_bShowMenuStatus)
\r
3081 // Get the toolbar the point is over
\r
3082 CToolBar* pToolBar = 0;
\r
3083 if (IsReBarUsed())
\r
3085 // Get the ToolBar's CWnd
\r
3086 CWnd* pWnd = FromHandle(GetReBar().HitTest(GetCursorPos()));
\r
3087 if (pWnd && (dynamic_cast<CToolBar*>(pWnd)) && !(dynamic_cast<CMenuBar*>(pWnd)))
\r
3088 pToolBar = (CToolBar*)pWnd;
\r
3092 CPoint pt = GetCursorPos();
\r
3093 CWnd* pWnd = WindowFromPoint(GetCursorPos());
\r
3094 if (pWnd && (dynamic_cast<CToolBar*>(pWnd)))
\r
3095 pToolBar = (CToolBar*)pWnd;
\r
3098 if ((pToolBar) && (WindowFromPoint(GetCursorPos()) == pToolBar))
\r
3100 // Which toolbar button is the mouse cursor hovering over?
\r
3101 int nButton = pToolBar->HitTest();
\r
3104 int nID = pToolBar->GetCommandID(nButton);
\r
3105 // Only update the statusbar if things have changed
\r
3106 if (nID != m_nOldID)
\r
3109 m_strStatusText = LoadString(nID);
\r
3111 m_strStatusText = _T("Ready");
\r
3113 if (GetStatusBar().IsWindow())
\r
3121 if (m_nOldID != -1)
\r
3123 m_strStatusText = _T("Ready");
\r
3130 if (m_bShowIndicatorStatus)
\r
3131 SetStatusIndicators();
\r
3135 inline void CFrame::OnViewStatusBar()
\r
3137 m_bShowStatusBar = !m_bShowStatusBar;
\r
3138 ShowStatusBar(m_bShowStatusBar);
\r
3141 inline void CFrame::OnViewToolBar()
\r
3143 m_bShowToolBar = !m_bShowToolBar;
\r
3144 ShowToolBar(m_bShowToolBar);
\r
3147 inline void CFrame::PreCreate(CREATESTRUCT& cs)
\r
3149 // Set the frame window styles
\r
3150 cs.style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
\r
3152 // Set the original window position
\r
3153 cs.x = m_rcPosition.left;
\r
3154 cs.y = m_rcPosition.top;
\r
3155 cs.cx = m_rcPosition.Width();
\r
3156 cs.cy = m_rcPosition.Height();
\r
3159 inline void CFrame::PreRegisterClass(WNDCLASS &wc)
\r
3161 // Set the Window Class
\r
3162 wc.lpszClassName = _T("Win32++ Frame");
\r
3165 inline void CFrame::RecalcLayout()
\r
3167 CWnd* pView = GetView();
\r
3168 if ((!pView) || (!pView->GetHwnd()))
\r
3171 // Resize the status bar
\r
3172 if (GetStatusBar().IsWindow() && m_bShowStatusBar)
\r
3174 GetStatusBar().SetWindowPos(NULL, 0, 0, 0, 0, SWP_SHOWWINDOW);
\r
3175 GetStatusBar().Invalidate();
\r
3179 // Resize the rebar or toolbar
\r
3180 if (IsReBarUsed())
\r
3182 GetReBar().SendMessage(WM_SIZE, 0L, 0L);
\r
3183 GetReBar().Invalidate();
\r
3185 else if (m_bUseToolBar && m_bShowToolBar)
\r
3186 GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);
\r
3188 // Resize the View window
\r
3189 CRect rClient = GetViewRect();
\r
3190 if ((rClient.bottom - rClient.top) >= 0)
\r
3192 int x = rClient.left;
\r
3193 int y = rClient.top;
\r
3194 int cx = rClient.Width();
\r
3195 int cy = rClient.Height();
\r
3197 pView->SetWindowPos( NULL, x, y, cx, cy, SWP_SHOWWINDOW|SWP_ASYNCWINDOWPOS );
\r
3200 // Adjust rebar bands
\r
3201 if (IsReBarUsed())
\r
3203 if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
\r
3204 GetReBar().MoveBandsLeft();
\r
3206 if (IsMenuBarUsed())
\r
3207 SetMenuBarBandSize();
\r
3211 inline void CFrame::RemoveMRUEntry(LPCTSTR szMRUEntry)
\r
3213 std::vector<CString>::iterator it;
\r
3214 for (it = m_vMRUEntries.begin(); it != m_vMRUEntries.end(); ++it)
\r
3216 if ((*it) == szMRUEntry)
\r
3218 m_vMRUEntries.erase(it);
\r
3226 inline BOOL CFrame::SaveRegistrySettings()
\r
3228 // Store the window position in the registry
\r
3229 if (!m_strKeyName.IsEmpty())
\r
3231 CString strKeyName = _T("Software\\") + m_strKeyName + _T("\\Frame Settings");
\r
3236 if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
\r
3237 throw CWinException(_T("RegCreateKeyEx failed"));
\r
3239 WINDOWPLACEMENT Wndpl = {0};
\r
3240 Wndpl.length = sizeof(WINDOWPLACEMENT);
\r
3242 if (GetWindowPlacement(Wndpl))
\r
3244 // Get the Frame's window position
\r
3245 CRect rc = Wndpl.rcNormalPosition;
\r
3246 DWORD dwTop = MAX(rc.top, 0);
\r
3247 DWORD dwLeft = MAX(rc.left, 0);
\r
3248 DWORD dwWidth = MAX(rc.Width(), 100);
\r
3249 DWORD dwHeight = MAX(rc.Height(), 50);
\r
3251 if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Top"), 0, REG_DWORD, (LPBYTE)&dwTop, sizeof(DWORD)))
\r
3252 throw CWinException(_T("RegSetValueEx failed"));
\r
3253 if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Left"), 0, REG_DWORD, (LPBYTE)&dwLeft, sizeof(DWORD)))
\r
3254 throw CWinException(_T("RegSetValueEx failed"));
\r
3255 if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Width"), 0, REG_DWORD, (LPBYTE)&dwWidth, sizeof(DWORD)))
\r
3256 throw CWinException(_T("RegSetValueEx failed"));
\r
3257 if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Height"), 0, REG_DWORD, (LPBYTE)&dwHeight, sizeof(DWORD)))
\r
3258 throw CWinException(_T("RegSetValueEx failed"));
\r
3261 // Store the ToolBar and statusbar states
\r
3262 DWORD dwShowToolBar = m_bShowToolBar;
\r
3263 DWORD dwShowStatusBar = m_bShowStatusBar;
\r
3265 if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("ToolBar"), 0, REG_DWORD, (LPBYTE)&dwShowToolBar, sizeof(DWORD)))
\r
3266 throw CWinException(_T("RegSetValueEx failed"));
\r
3267 if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("StatusBar"), 0, REG_DWORD, (LPBYTE)&dwShowStatusBar, sizeof(DWORD)))
\r
3268 throw CWinException(_T("RegSetValueEx failed"));
\r
3270 RegCloseKey(hKey);
\r
3273 catch (const CWinException& e)
\r
3275 TRACE(_T("Failed to save registry settings\n"));
\r
3279 // Roll back the registry changes by deleting this subkey
\r
3280 RegDeleteKey(HKEY_CURRENT_USER ,strKeyName);
\r
3281 RegCloseKey(hKey);
\r
3288 // Store the MRU entries in the registry
\r
3289 if (m_nMaxMRU > 0)
\r
3291 CString strKeyName = _T("Software\\") + m_strKeyName + _T("\\Recent Files");
\r
3296 if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
\r
3297 throw CWinException(_T("RegCreateKeyEx failed"));
\r
3299 for (UINT i = 0; i < m_nMaxMRU; ++i)
\r
3301 TCHAR szSubKey[10];
\r
3302 wsprintf(szSubKey, _T("File %d\0"), i+1);
\r
3303 CString strPathName;
\r
3304 if (i < m_vMRUEntries.size())
\r
3305 strPathName = m_vMRUEntries[i];
\r
3307 if (ERROR_SUCCESS != RegSetValueEx(hKey, szSubKey, 0, REG_SZ, (LPBYTE)strPathName.c_str(), (1 + strPathName.GetLength() )*sizeof(TCHAR)))
\r
3308 throw CWinException(_T("RegSetValueEx failed"));
\r
3311 RegCloseKey(hKey);
\r
3314 catch (const CWinException& e)
\r
3316 TRACE(_T("Failed to save registry MRU settings\n"));
\r
3320 // Roll back the registry changes by deleting this subkey
\r
3321 RegDeleteKey(HKEY_CURRENT_USER ,strKeyName);
\r
3322 RegCloseKey(hKey);
\r
3334 inline void CFrame::SetFrameMenu(INT ID_MENU)
\r
3336 // Sets the frame's menu from a Resouce ID.
\r
3337 // A resource ID of 0 removes the menu from the frame.
\r
3341 // Sets the frame's menu from a resource ID.
\r
3342 hMenu = ::LoadMenu(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(ID_MENU));
\r
3346 SetFrameMenu(hMenu);
\r
3349 inline void CFrame::SetFrameMenu(HMENU hMenu)
\r
3351 // Sets the frame's menu from a HMENU.
\r
3352 m_Menu.Attach(hMenu);
\r
3354 if (IsMenuBarUsed())
\r
3356 GetMenuBar().SetMenu(GetFrameMenu());
\r
3357 BOOL bShow = (hMenu != NULL); // boolean expression
\r
3364 inline UINT CFrame::SetMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID)
\r
3366 // Remove any existing menu icons
\r
3367 if (m_himlMenu) ImageList_Destroy(m_himlMenu);
\r
3368 if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
\r
3369 m_himlMenu = NULL;
\r
3370 m_himlMenuDis = NULL;
\r
3371 m_vMenuIcons.clear();
\r
3373 // Exit if no ToolBarID is specified
\r
3374 if (ToolBarID == 0) return 0;
\r
3376 // Add the menu icons from the bitmap IDs
\r
3377 return AddMenuIcons(MenuData, crMask, ToolBarID, ToolBarDisabledID);
\r
3380 inline void CFrame::SetMenuBarBandSize()
\r
3382 // Sets the minimum width of the MenuBar band to the width of the rebar
\r
3383 // This prevents other bands from moving to this MenuBar's row.
\r
3385 CRect rcClient = GetClientRect();
\r
3386 CReBar& RB = GetReBar();
\r
3387 int nBand = RB.GetBand(GetMenuBar());
\r
3388 CRect rcBorder = RB.GetBandBorders(nBand);
\r
3390 REBARBANDINFO rbbi = {0};
\r
3391 rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_SIZE;
\r
3392 RB.GetBandInfo(nBand, rbbi);
\r
3395 if ((GetReBar().GetReBarTheme().UseThemes) && (GetReBar().GetReBarTheme().LockMenuBand))
\r
3396 Width = rcClient.Width() - rcBorder.Width() - 2;
\r
3398 Width = GetMenuBar().GetMaxSize().cx;
\r
3400 rbbi.cxMinChild = Width;
\r
3403 RB.SetBandInfo(nBand, rbbi);
\r
3406 inline void CFrame::SetMenuTheme(MenuTheme& Theme)
\r
3408 m_ThemeMenu.UseThemes = Theme.UseThemes;
\r
3409 m_ThemeMenu.clrHot1 = Theme.clrHot1;
\r
3410 m_ThemeMenu.clrHot2 = Theme.clrHot2;
\r
3411 m_ThemeMenu.clrPressed1 = Theme.clrPressed1;
\r
3412 m_ThemeMenu.clrPressed2 = Theme.clrPressed2;
\r
3413 m_ThemeMenu.clrOutline = Theme.clrOutline;
\r
3415 GetMenuBar().SetMenuBarTheme(Theme); // Sets the theme for MenuBar buttons
\r
3419 inline void CFrame::SetStatusIndicators()
\r
3421 if (::IsWindow(GetStatusBar()))
\r
3423 LPCTSTR Status1 = (::GetKeyState(VK_CAPITAL) & 0x0001)? _T("\tCAP") : _T("");
\r
3424 LPCTSTR Status2 = (::GetKeyState(VK_NUMLOCK) & 0x0001)? _T("\tNUM") : _T("");
\r
3425 LPCTSTR Status3 = (::GetKeyState(VK_SCROLL) & 0x0001)? _T("\tSCRL"): _T("");
\r
3427 // Only update indictors if the text has changed
\r
3428 if (Status1 != m_OldStatus[0]) GetStatusBar().SetPartText(1, (Status1));
\r
3429 if (Status2 != m_OldStatus[1]) GetStatusBar().SetPartText(2, (Status2));
\r
3430 if (Status3 != m_OldStatus[2]) GetStatusBar().SetPartText(3, (Status3));
\r
3432 m_OldStatus[0] = Status1;
\r
3433 m_OldStatus[1] = Status2;
\r
3434 m_OldStatus[2] = Status3;
\r
3438 inline void CFrame::SetStatusText()
\r
3440 if (::IsWindow(GetStatusBar()))
\r
3442 // Calculate the width of the text indicators
\r
3443 CClientDC dcStatus(&GetStatusBar());
\r
3444 CSize csCAP = dcStatus.GetTextExtentPoint32(_T("\tCAP"), lstrlen(_T("\tCAP")));
\r
3445 CSize csNUM = dcStatus.GetTextExtentPoint32(_T("\tNUM"), lstrlen(_T("\tNUM")));
\r
3446 CSize csSCRL = dcStatus.GetTextExtentPoint32(_T("\tSCRL "), lstrlen(_T("\tSCRL ")));
\r
3448 // Get the coordinates of the parent window's client area.
\r
3449 CRect rcClient = GetClientRect();
\r
3450 int width = MAX(300, rcClient.right);
\r
3452 if (m_bShowIndicatorStatus)
\r
3455 GetStatusBar().SetPartWidth(0, width - (csCAP.cx+csNUM.cx+csSCRL.cx+20));
\r
3456 GetStatusBar().SetPartWidth(1, csCAP.cx);
\r
3457 GetStatusBar().SetPartWidth(2, csNUM.cx);
\r
3458 GetStatusBar().SetPartWidth(3, csSCRL.cx);
\r
3460 SetStatusIndicators();
\r
3463 // Place text in the 1st pane
\r
3464 GetStatusBar().SetPartText(0, m_strStatusText);
\r
3468 inline void CFrame::SetTheme()
\r
3470 // Note: To modify theme colors, override this function in CMainframe,
\r
3471 // and make any modifications there.
\r
3473 // Avoid themes if using less than 16 bit colors
\r
3474 CClientDC DesktopDC(NULL);
\r
3475 if (DesktopDC.GetDeviceCaps(BITSPIXEL) < 16)
\r
3476 m_bUseThemes = FALSE;
\r
3483 // Retrieve the XP theme name
\r
3484 m_XPThemeName = GetThemeName();
\r
3486 enum Themetype{ Modern, Grey, Blue, Silver, Olive };
\r
3489 if (GetWinVersion() < 2600) // Not for Vista and above
\r
3491 if (m_XPThemeName == _T("NormalColor"))
\r
3493 if (m_XPThemeName == _T("Metallic"))
\r
3495 if (m_XPThemeName == _T("HomeStead"))
\r
3505 ToolBarTheme tt = {T, RGB(180, 250, 255), RGB(140, 190, 255), RGB(150, 220, 255), RGB(80, 100, 255), RGB(127, 127, 255)};
\r
3506 ReBarTheme tr = {T, RGB(225, 230, 255), RGB(240, 242, 250), RGB(248, 248, 248), RGB(180, 200, 230), F, T, T, T, T, F};
\r
3507 MenuTheme tm = {T, RGB(180, 250, 255), RGB(140, 190, 255), RGB(240, 250, 255), RGB(120, 170, 220), RGB(127, 127, 255)};
\r
3509 GetToolBar().SetToolBarTheme(tt);
\r
3510 SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
\r
3512 GetReBar().SetReBarTheme(tr);
\r
3516 case Grey: // A color scheme suitable for 16 bit colors. Suitable for Windows older than XP.
\r
3518 ToolBarTheme tt = {T, RGB(182, 189, 210), RGB(182, 189, 210), RGB(133, 146, 181), RGB(133, 146, 181), RGB(10, 36, 106)};
\r
3519 ReBarTheme tr = {T, RGB(212, 208, 200), RGB(212, 208, 200), RGB(230, 226, 222), RGB(220, 218, 208), F, T, T, T, T, F};
\r
3520 MenuTheme tm = {T, RGB(182, 189, 210), RGB( 182, 189, 210), RGB(200, 196, 190), RGB(200, 196, 190), RGB(100, 100, 100)};
\r
3522 GetToolBar().SetToolBarTheme(tt);
\r
3523 SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
\r
3525 GetReBar().SetReBarTheme(tr);
\r
3530 // Used for XP default (blue) color scheme
\r
3531 ToolBarTheme tt = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(255, 140, 40), RGB(255, 180, 80), RGB(192, 128, 255)};
\r
3532 ReBarTheme tr = {T, RGB(150,190,245), RGB(196,215,250), RGB(220,230,250), RGB( 70,130,220), F, T, T, T, T, F};
\r
3533 MenuTheme tm = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(220,230,250), RGB(150,190,245), RGB(128, 128, 200)};
\r
3535 GetToolBar().SetToolBarTheme(tt);
\r
3536 SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
\r
3538 GetReBar().SetReBarTheme(tr);
\r
3544 // Used for XP Silver color scheme
\r
3545 ToolBarTheme tt = {T, RGB(192, 210, 238), RGB(192, 210, 238), RGB(152, 181, 226), RGB(152, 181, 226), RGB(49, 106, 197)};
\r
3546 ReBarTheme tr = {T, RGB(225, 220, 240), RGB(240, 240, 245), RGB(245, 240, 255), RGB(160, 155, 180), F, T, T, T, T, F};
\r
3547 MenuTheme tm = {T, RGB(196, 215, 250), RGB( 120, 180, 220), RGB(240, 240, 245), RGB(170, 165, 185), RGB(128, 128, 150)};
\r
3549 GetToolBar().SetToolBarTheme(tt);
\r
3550 SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
\r
3552 GetReBar().SetReBarTheme(tr);
\r
3558 // Used for XP Olive color scheme
\r
3559 ReBarTheme tr = {T, RGB(215, 216, 182), RGB(242, 242, 230), RGB(249, 255, 227), RGB(178, 191, 145), F, T, T, T, T, F};
\r
3560 ToolBarTheme tt = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(255, 140, 40), RGB(255, 180, 80), RGB(200, 128, 128)};
\r
3561 MenuTheme tm = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(249, 255, 227), RGB(178, 191, 145), RGB(128, 128, 128)};
\r
3563 GetToolBar().SetToolBarTheme(tt);
\r
3564 SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
\r
3566 GetReBar().SetReBarTheme(tr);
\r
3573 // Use a classic style by default
\r
3574 ReBarTheme tr = {T, 0, 0, 0, 0, F, T, T, F, F, F};
\r
3575 GetReBar().SetReBarTheme(tr);
\r
3581 inline void CFrame::SetToolBarImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID)
\r
3582 // Either sets the imagelist or adds/replaces bitmap depending on ComCtl32.dll version
\r
3583 // Assumes the width of the button image = bitmap_size / buttons
\r
3584 // Assumes buttons have been already been added via AdddToolBarButton
\r
3585 // The colour mask is ignored for 32bit bitmaps, but is required for 24bit bitmaps
\r
3586 // The colour mask is often grey RGB(192,192,192) or magenta (255,0,255)
\r
3587 // The color mask is ignored for 32bit bitmap resources
\r
3588 // The Hot and disabled bitmap resources can be 0
\r
3590 GetToolBar().SetImages(crMask, ToolBarID, ToolBarHotID, ToolBarDisabledID);
\r
3593 inline void CFrame::SetupToolBar()
\r
3595 // Use this function to set the Resource IDs for the toolbar(s).
\r
3597 /* // Set the Resource IDs for the toolbar buttons
\r
3598 AddToolBarButton( IDM_FILE_NEW );
\r
3599 AddToolBarButton( IDM_FILE_OPEN );
\r
3600 AddToolBarButton( IDM_FILE_SAVE );
\r
3601 AddToolBarButton( 0 ); // Separator
\r
3602 AddToolBarButton( IDM_EDIT_CUT );
\r
3603 AddToolBarButton( IDM_EDIT_COPY );
\r
3604 AddToolBarButton( IDM_EDIT_PASTE );
\r
3605 AddToolBarButton( 0 ); // Separator
\r
3606 AddToolBarButton( IDM_FILE_PRINT );
\r
3607 AddToolBarButton( 0 ); // Separator
\r
3608 AddToolBarButton( IDM_HELP_ABOUT );
\r
3612 inline void CFrame::SetView(CWnd& wndView)
\r
3613 // Sets or changes the View window displayed within the frame
\r
3615 if (m_pView != &wndView)
\r
3617 // Destroy the existing view window (if any)
\r
3618 if (m_pView) m_pView->Destroy();
\r
3620 // Assign the view window
\r
3621 m_pView = &wndView;
\r
3625 // The frame is already created, so create and position the new view too
\r
3626 assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
\r
3627 GetView()->Create(this);
\r
3633 inline void CFrame::ShowMenu(BOOL bShow)
\r
3637 if (IsReBarUsed())
\r
3638 GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetMenuBar()), TRUE);
\r
3644 if (IsReBarUsed())
\r
3645 GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetMenuBar()), FALSE);
\r
3650 if (GetReBar().IsWindow())
\r
3652 if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
\r
3653 GetReBar().MoveBandsLeft();
\r
3656 // Reposition the Windows
\r
3662 inline void CFrame::ShowStatusBar(BOOL bShow)
\r
3666 m_Menu.CheckMenuItem(IDW_VIEW_STATUSBAR, MF_CHECKED);
\r
3667 GetStatusBar().ShowWindow(SW_SHOW);
\r
3668 m_bShowStatusBar = TRUE;
\r
3672 m_Menu.CheckMenuItem(IDW_VIEW_STATUSBAR, MF_UNCHECKED);
\r
3673 GetStatusBar().ShowWindow(SW_HIDE);
\r
3674 m_bShowStatusBar = FALSE;
\r
3677 // Reposition the Windows
\r
3681 inline void CFrame::ShowToolBar(BOOL bShow)
\r
3685 m_Menu.CheckMenuItem(IDW_VIEW_TOOLBAR, MF_CHECKED);
\r
3686 if (IsReBarUsed())
\r
3687 GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetToolBar()), TRUE);
\r
3689 GetToolBar().ShowWindow(SW_SHOW);
\r
3690 m_bShowToolBar = TRUE;
\r
3694 m_Menu.CheckMenuItem(IDW_VIEW_TOOLBAR, MF_UNCHECKED);
\r
3695 if (IsReBarUsed())
\r
3696 GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetToolBar()), FALSE);
\r
3698 GetToolBar().ShowWindow(SW_HIDE);
\r
3699 m_bShowToolBar = FALSE;
\r
3702 if (GetReBar().IsWindow())
\r
3704 if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
\r
3705 GetReBar().MoveBandsLeft();
\r
3708 // Reposition the Windows
\r
3712 inline void CFrame::UpdateMRUMenu()
\r
3714 if (0 >= m_nMaxMRU) return;
\r
3716 // Set the text for the MRU Menu
\r
3717 CString strMRUArray[16];
\r
3718 UINT MaxMRUArrayIndex = 0;
\r
3719 if (m_vMRUEntries.size() > 0)
\r
3721 for (UINT n = 0; ((n < m_vMRUEntries.size()) && (n <= m_nMaxMRU)); ++n)
\r
3723 strMRUArray[n] = m_vMRUEntries[n];
\r
3724 if (strMRUArray[n].GetLength() > MAX_MENU_STRING - 10)
\r
3726 // Truncate the string if its too long
\r
3727 strMRUArray[n].Delete(0, strMRUArray[n].GetLength() - MAX_MENU_STRING +10);
\r
3728 strMRUArray[n] = _T("... ") + strMRUArray[n];
\r
3731 // Prefix the string with its number
\r
3733 wsprintf(tVal, _T("%d "), n+1);
\r
3734 strMRUArray[n] = tVal + strMRUArray[n];
\r
3735 MaxMRUArrayIndex = n;
\r
3740 strMRUArray[0] = _T("Recent Files");
\r
3743 // Set MRU menu items
\r
3744 MENUITEMINFO mii = {0};
\r
3745 mii.cbSize = GetSizeofMenuItemInfo();
\r
3747 int nFileItem = 0; // We place the MRU items under the left most menu item
\r
3748 CMenu* pFileMenu = GetFrameMenu().GetSubMenu(nFileItem);
\r
3752 // Remove all but the first MRU Menu entry
\r
3753 for (UINT u = IDW_FILE_MRU_FILE2; u <= IDW_FILE_MRU_FILE1 +16; ++u)
\r
3755 pFileMenu->DeleteMenu(u, MF_BYCOMMAND);
\r
3758 int MaxMRUIndex = (int)MIN(MaxMRUArrayIndex, m_nMaxMRU);
\r
3760 for (int index = MaxMRUIndex; index >= 0; --index)
\r
3762 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
\r
3763 mii.fState = (0 == m_vMRUEntries.size())? MFS_GRAYED : 0;
\r
3764 mii.fType = MFT_STRING;
\r
3765 mii.wID = IDW_FILE_MRU_FILE1 + index;
\r
3766 mii.dwTypeData = (LPTSTR)strMRUArray[index].c_str();
\r
3769 if (index == MaxMRUIndex)
\r
3770 // Replace the last MRU entry first
\r
3771 bResult = pFileMenu->SetMenuItemInfo(IDW_FILE_MRU_FILE1, &mii, FALSE);
\r
3773 // Insert the other MRU entries next
\r
3774 bResult = pFileMenu->InsertMenuItem(IDW_FILE_MRU_FILE1 + index + 1, &mii, FALSE);
\r
3778 TRACE(_T("Failed to set MRU menu item\n"));
\r
3787 inline LRESULT CFrame::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
3792 OnActivate(wParam, lParam);
\r
3800 case WM_ERASEBKGND:
\r
3806 return OnMenuChar(wParam, lParam);
\r
3807 case WM_MENUSELECT:
\r
3808 OnMenuSelect(wParam, lParam);
\r
3816 case WM_SYSCOLORCHANGE: // Changing themes trigger this
\r
3817 OnSysColorChange();
\r
3819 case WM_SYSCOMMAND:
\r
3820 return OnSysCommand(wParam, lParam);
\r
3824 case WM_DRAWITEM: // Owner draw menu items
\r
3825 return OnDrawItem(wParam, lParam);
\r
3826 case WM_INITMENUPOPUP:
\r
3827 OnInitMenuPopup(wParam, lParam);
\r
3829 case WM_MEASUREITEM:
\r
3830 return OnMeasureItem(wParam, lParam);
\r
3831 case WM_EXITMENULOOP:
\r
3834 case UWM_GETMENUTHEME:
\r
3836 MenuTheme& tm = GetMenuTheme();
\r
3837 return (LRESULT)&tm;
\r
3839 case UWM_GETREBARTHEME:
\r
3841 ReBarTheme& rm = GetReBarTheme();
\r
3842 return (LRESULT)&rm;
\r
3844 case UWM_GETTOOLBARTHEME:
\r
3846 ToolBarTheme& tt = GetToolBarTheme();
\r
3847 return (LRESULT)&tt;
\r
3851 return CWnd::WndProcDefault(uMsg, wParam, lParam);
\r
3852 } // LRESULT CFrame::WndProcDefault(...)
\r
3855 } // namespace Win32xx
\r
3857 #endif // _WIN32XX_FRAME_H_
\r