Merge branch 'master' of git.ucc.asn.au:/matches/honours
[matches/honours.git] / research / transmission_spectroscopy / TOF / Win32++ / include / frame.h
1 // Win32++   Version 7.3\r
2 // Released: 30th November 2011\r
3 //\r
4 //      David Nash\r
5 //      email: [email protected]\r
6 //      url: https://sourceforge.net/projects/win32-framework\r
7 //\r
8 //\r
9 // Copyright (c) 2005-2011  David Nash\r
10 //\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
20 //\r
21 // The above copyright notice and this permission notice\r
22 // shall be included in all copies or substantial portions\r
23 // of the Software.\r
24 //\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
34 //\r
35 ////////////////////////////////////////////////////////\r
36 \r
37 \r
38 ////////////////////////////////////////////////////////\r
39 // frame.h\r
40 //  Declaration of the CFrame and CMenuBar classes\r
41 \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
46 // child windows.\r
47 \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
55 \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
61 \r
62 // When compiling an application with these classes, it will need to be linked\r
63 // with Comctl32.lib.\r
64 \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
67 // applications.\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
70 \r
71 \r
72 #ifndef _WIN32XX_FRAME_H_\r
73 #define _WIN32XX_FRAME_H_\r
74 \r
75 #include "wincore.h"\r
76 #include "dialog.h"\r
77 #include "gdi.h"\r
78 #include "statusbar.h"\r
79 #include "toolbar.h"\r
80 #include "rebar.h"\r
81 #include "default_resource.h"\r
82 \r
83 #ifndef RBN_MINMAX\r
84   #define RBN_MINMAX (RBN_FIRST - 21)\r
85 #endif\r
86 #ifndef TMT_BORDERSIZE\r
87   #define TMT_BORDERSIZE        2403\r
88 #endif\r
89 #ifndef TMT_CONTENTMARGINS\r
90   #define TMT_CONTENTMARGINS    3602\r
91 #endif\r
92 #ifndef VSCLASS_MENU\r
93   #define VSCLASS_MENU  L"MENU"\r
94 #endif\r
95 #ifndef ODS_NOACCEL\r
96   #define ODS_NOACCEL 0x0100\r
97 #endif\r
98 #ifndef ODS_HOTLIGHT\r
99   #define ODS_HOTLIGHT 0x0040\r
100 #endif\r
101 #ifndef ODS_INACTIVE\r
102   #define ODS_INACTIVE 0x0080\r
103 #endif\r
104 #ifndef DT_HIDEPREFIX\r
105   #define DT_HIDEPREFIX 0x00100000\r
106 #endif\r
107 \r
108 \r
109 \r
110 namespace Win32xx\r
111 {\r
112 \r
113         ////////////////////////////////////////////////\r
114         // Declarations for structures for themes\r
115         //\r
116         struct MenuTheme\r
117         {\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
124         };\r
125 \r
126         // define some structs and enums from uxtheme.h and vssym32.h\r
127         typedef struct _MARGINS\r
128         {\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
134 \r
135         class CMargins : public MARGINS\r
136         {\r
137         public:\r
138                 CMargins(int cxLeft, int cxRight, int cyTop, int cyBottom)\r
139                 {\r
140                         cxLeftWidth    = cxLeft;        cxRightWidth   = cxRight;\r
141                         cyTopHeight    = cyTop;         cyBottomHeight = cyBottom;\r
142                 }\r
143                 CMargins()\r
144                 {\r
145                         cxLeftWidth    = 0;                     cxRightWidth   = 0;\r
146                         cyTopHeight    = 0;                     cyBottomHeight = 0;\r
147                 }\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
151                 {\r
152                         cxLeftWidth    = cxLeft;        cxRightWidth   = cxRight;\r
153                         cyTopHeight    = cyTop;         cyBottomHeight = cyBottom;\r
154                 }\r
155         };\r
156 \r
157         enum THEMESIZE\r
158         {\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
162         };\r
163 \r
164         enum POPUPCHECKSTATES\r
165         {\r
166                 MC_CHECKMARKNORMAL = 1,\r
167                 MC_CHECKMARKDISABLED = 2,\r
168                 MC_BULLETNORMAL = 3,\r
169                 MC_BULLETDISABLED = 4,\r
170         };\r
171 \r
172         enum POPUPCHECKBACKGROUNDSTATES\r
173         {\r
174                 MCB_DISABLED = 1,\r
175                 MCB_NORMAL = 2,\r
176                 MCB_BITMAP = 3,\r
177         };\r
178 \r
179         enum POPUPITEMSTATES\r
180         {\r
181                 MPI_NORMAL = 1,\r
182                 MPI_HOT = 2,\r
183                 MPI_DISABLED = 3,\r
184                 MPI_DISABLEDHOT = 4,\r
185         };\r
186 \r
187         enum POPUPSUBMENUSTATES\r
188         {\r
189                 MSM_NORMAL = 1,\r
190                 MSM_DISABLED = 2,\r
191         };\r
192 \r
193         enum MENUPARTS\r
194         {\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
202                 MENU_BARITEM = 8,\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
215         };\r
216 \r
217 \r
218         // Forward declaration of CFrame. Its defined later.\r
219         class CFrame;\r
220 \r
221         struct MenuItemData\r
222         // Each Dropdown menu item has this data\r
223         {\r
224                 HMENU hMenu;\r
225                 MENUITEMINFO mii;\r
226                 UINT  nPos;\r
227                 std::vector<TCHAR> vItemText;\r
228 \r
229                 MenuItemData() : hMenu(0), nPos(0) { vItemText.assign(MAX_MENU_STRING, _T('\0')); }\r
230                 LPTSTR GetItemText() {return &vItemText[0];}\r
231         };\r
232 \r
233 \r
234         ////////////////////////////////////\r
235         // Declaration of the CMenuBar class\r
236         //\r
237         class CMenuBar : public CToolBar\r
238         {\r
239                 friend class CFrame;\r
240 \r
241         public:\r
242                 CMenuBar();\r
243                 virtual ~CMenuBar();\r
244                 virtual void SetMenu(HMENU hMenu);\r
245                 virtual void SetMenuBarTheme(MenuTheme& Theme);\r
246 \r
247                 HMENU GetMenu() const {return m_hTopMenu;}\r
248                 MenuTheme& GetMenuBarTheme() {return m_ThemeMenu;}\r
249 \r
250         protected:\r
251         //Overridables\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
267 \r
268         private:\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
275                 void ExitMenu();\r
276                 HWND GetActiveMDIChild();\r
277                 void GrabFocus();\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
283 \r
284                 enum MDIButtonType\r
285                 {\r
286                         MDI_MIN = 0,\r
287                         MDI_RESTORE = 1,\r
288                         MDI_CLOSE = 2,\r
289                 };\r
290 \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
305 \r
306         };  // class CMenuBar\r
307 \r
308 \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
315         class CMenuMetrics\r
316         {\r
317         public:\r
318                 CMenuMetrics(CFrame* pFrame);\r
319                 ~CMenuMetrics();\r
320 \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
328                 void  Initialize();\r
329                 int   ToItemStateId(UINT uItemState);\r
330                 int   ToCheckBackgroundStateId(int iStateId);\r
331                 int   ToCheckStateId(UINT fType, int iStateId);\r
332 \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
343 \r
344                 HANDLE  m_hTheme;              // Theme handle\r
345                 CFrame* m_pFrame;              // Pointer to the frame window\r
346 \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
351 \r
352                 CSize   m_sizeCheck;           // Check size metric\r
353                 CSize   m_sizeSeparator;       // Separator size metric\r
354 \r
355         private:\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
365 \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
376         };\r
377 \r
378 \r
379         //////////////////////////////////\r
380         // Declaration of the CFrame class\r
381         //\r
382         class CFrame : public CWnd\r
383         {\r
384                 friend class CMenuBar;\r
385                 typedef Shared_Ptr<MenuItemData> ItemDataPtr;\r
386 \r
387         public:\r
388                 CFrame();\r
389                 virtual ~CFrame();\r
390 \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
402 \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
411 \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
426 \r
427         protected:\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
477 \r
478                 enum Constants\r
479                 {\r
480                         ID_STATUS_TIMER = 1,\r
481                 };\r
482 \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
495 \r
496         private:\r
497                 CFrame(const CFrame&);                          // Disable copy construction\r
498                 CFrame& operator = (const CFrame&); // Disable assignment operator\r
499                 void LoadCommonControls();\r
500 \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
522 \r
523         };  // class CFrame\r
524 \r
525 }\r
526 \r
527 \r
528 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
529 \r
530 \r
531 namespace Win32xx\r
532 {\r
533 \r
534         /////////////////////////////////////\r
535         // Definitions for the CMenuBar class\r
536         //\r
537         inline CMenuBar::CMenuBar()\r
538         {\r
539                 m_bExitAfter    = FALSE;\r
540                 m_hTopMenu              = NULL;\r
541                 m_nHotItem              = -1;\r
542                 m_bSelPopup             = FALSE;\r
543                 m_hSelMenu              = NULL;\r
544                 m_bMenuActive   = FALSE;\r
545                 m_bKeyMode              = FALSE;\r
546                 m_hPrevFocus    = NULL;\r
547                 m_nMDIButton    = 0;\r
548                 m_hPopupMenu    = 0;\r
549 \r
550                 ZeroMemory(&m_ThemeMenu, sizeof(MenuTheme));\r
551         }\r
552 \r
553         inline CMenuBar::~CMenuBar()\r
554         {\r
555         }\r
556 \r
557         inline void CMenuBar::DoAltKey(WORD KeyCode)\r
558         {\r
559                 //Handle key pressed with Alt held down\r
560                 UINT ID;\r
561                 if (SendMessage(TB_MAPACCELERATOR, KeyCode, (LPARAM) &ID))\r
562                 {\r
563                         GrabFocus();\r
564                         m_bKeyMode = TRUE;\r
565                         SetHotItem(ID);\r
566                         m_bMenuActive = TRUE;\r
567                         PostMessage(UWM_POPUPMENU, 0L, 0L);\r
568                 }\r
569                 else\r
570                         ::MessageBeep(MB_OK);\r
571         }\r
572 \r
573         inline void CMenuBar::DoPopupMenu()\r
574         {\r
575                 if (m_bKeyMode)\r
576                         // Simulate a down arrow key press\r
577                         PostMessage(WM_KEYDOWN, VK_DOWN, 0L);\r
578 \r
579                 m_bKeyMode = FALSE;\r
580                 m_bExitAfter = FALSE;\r
581                 m_OldMousePos = GetCursorPos();\r
582 \r
583                 HWND hMaxMDIChild = NULL;\r
584                 if (IsMDIChildMaxed())\r
585                         hMaxMDIChild = GetActiveMDIChild();\r
586 \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
592 \r
593         // Retrieve the bounding rectangle for the toolbar button\r
594                 CRect rc = GetItemRect(m_nHotItem);\r
595 \r
596                 // convert rectangle to desktop coordinates\r
597                 ClientToScreen(rc);\r
598 \r
599                 // Position popup above toolbar if it won't fit below\r
600                 TPMPARAMS tpm;\r
601                 tpm.cbSize = sizeof(TPMPARAMS);\r
602                 tpm.rcExclude = rc;\r
603 \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
607 \r
608                 m_bSelPopup = FALSE;\r
609                 m_hSelMenu = NULL;\r
610                 m_bMenuActive = TRUE;\r
611 \r
612                 // We hook mouse input to process mouse and keyboard input during\r
613                 //  the popup menu. Messages are sent to StaticMsgHook.\r
614 \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
620 \r
621                 // Hook messages about to be processed by the shortcut menu\r
622                 pTLSData->hHook = ::SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)StaticMsgHook, NULL, ::GetCurrentThreadId());\r
623 \r
624                 // Display the shortcut menu\r
625                 BOOL bRightToLeft = FALSE;\r
626 \r
627 #if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)\r
628                 bRightToLeft = ((GetAncestor()->GetWindowLongPtr(GWL_EXSTYLE)) & WS_EX_LAYOUTRTL);\r
629 #endif\r
630 \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
634 \r
635                 // We get here once the TrackPopupMenuEx has ended\r
636                 m_bMenuActive = FALSE;\r
637 \r
638                 // Remove the message hook\r
639                 ::UnhookWindowsHookEx(pTLSData->hHook);\r
640                 pTLSData->hHook = NULL;\r
641 \r
642                 // Process MDI Child system menu\r
643                 if (IsMDIChildMaxed())\r
644                 {\r
645                         if (::GetSystemMenu(hMaxMDIChild, FALSE) == m_hPopupMenu )\r
646                         {\r
647                                 if (nID)\r
648                                         ::SendMessage(hMaxMDIChild, WM_SYSCOMMAND, nID, 0L);\r
649                         }\r
650                 }\r
651 \r
652                 // Resestablish Focus\r
653                 if (m_bKeyMode)\r
654                         GrabFocus();\r
655         }\r
656 \r
657         inline void CMenuBar::DrawAllMDIButtons(CDC& DrawDC)\r
658         {\r
659                 if (!IsMDIFrame())\r
660                         return;\r
661 \r
662                 if (IsMDIChildMaxed())\r
663                 {\r
664                         int cx = GetSystemMetrics(SM_CXSMICON);\r
665                         int cy = GetSystemMetrics(SM_CYSMICON);\r
666                         CRect rc = GetClientRect();\r
667                         int gap = 4;\r
668                         rc.right -= gap;\r
669 \r
670                         // Assign values to each element of the CRect array\r
671                         for (int i = 0 ; i < 3 ; ++i)\r
672                         {\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
678                         }\r
679 \r
680                         // Hide the MDI button if it won't fit\r
681                         for (int k = 0 ; k <= 2 ; ++k)\r
682                         {\r
683 \r
684                                 if (m_MDIRect[k].left < GetMaxSize().cx)\r
685                                 {\r
686                                         ::SetRectEmpty(&m_MDIRect[k]);\r
687                                 }\r
688                         }\r
689 \r
690                         DrawMDIButton(DrawDC, MDI_MIN, 0);\r
691                         DrawMDIButton(DrawDC, MDI_RESTORE, 0);\r
692                         DrawMDIButton(DrawDC, MDI_CLOSE, 0);\r
693                 }\r
694         }\r
695 \r
696         inline void CMenuBar::DrawMDIButton(CDC& DrawDC, int iButton, UINT uState)\r
697         {\r
698                 if (!IsRectEmpty(&m_MDIRect[iButton]))\r
699                 {\r
700                         switch (uState)\r
701                         {\r
702                         case 0:\r
703                                 {\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
711                                 }\r
712                                 break;\r
713                         case 1:\r
714                                 {\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
723                                 }\r
724 \r
725                                 break;\r
726                         case 2:\r
727                                 {\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
736                                 }\r
737                                 break;\r
738                         }\r
739 \r
740                         DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));\r
741 \r
742                         switch (iButton)\r
743                         {\r
744                         case MDI_MIN:\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
748 \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
751                                 break;\r
752                         case MDI_RESTORE:\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
759 \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
762 \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
768 \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
771                                 break;\r
772                         case MDI_CLOSE:\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
776 \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
779 \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
782 \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
785 \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
788 \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
791                                 break;\r
792                         }\r
793                 }\r
794         }\r
795 \r
796         inline void CMenuBar::ExitMenu()\r
797         {\r
798                 ReleaseFocus();\r
799                 m_bKeyMode = FALSE;\r
800                 m_bMenuActive = FALSE;\r
801                 SendMessage(TB_PRESSBUTTON, m_nHotItem, (LPARAM) MAKELONG (FALSE, 0));\r
802                 SetHotItem(-1);\r
803 \r
804                 CPoint pt = GetCursorPos();\r
805                 ScreenToClient(pt);\r
806 \r
807                 // Update mouse mouse position for hot tracking\r
808                 SendMessage(WM_MOUSEMOVE, 0L, MAKELONG(pt.x, pt.y));\r
809         }\r
810 \r
811         inline HWND CMenuBar::GetActiveMDIChild()\r
812         {\r
813                 HWND hwndMDIChild = NULL;\r
814                 if (IsMDIFrame())\r
815                 {\r
816                         hwndMDIChild = (HWND)::SendMessage(m_pFrame->GetView()->GetHwnd(), WM_MDIGETACTIVE, 0L, 0L);\r
817                 }\r
818 \r
819                 return hwndMDIChild;\r
820         }\r
821 \r
822         inline void CMenuBar::GrabFocus()\r
823         {\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
828         }\r
829 \r
830         inline BOOL CMenuBar::IsMDIChildMaxed() const\r
831         {\r
832                 BOOL bMaxed = FALSE;\r
833 \r
834                 if (IsMDIFrame() && m_pFrame->GetView()->IsWindow())\r
835                 {\r
836                         m_pFrame->GetView()->SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMaxed);\r
837                 }\r
838 \r
839                 return bMaxed;\r
840         }\r
841 \r
842         inline BOOL CMenuBar::IsMDIFrame() const\r
843         {\r
844                 return (m_pFrame->IsMDIFrame());\r
845         }\r
846 \r
847         inline void CMenuBar::OnMenuChar(WPARAM wParam, LPARAM lParam)\r
848         {\r
849                 UNREFERENCED_PARAMETER(lParam);\r
850 \r
851                 if (!m_bMenuActive)\r
852                         DoAltKey(LOWORD(wParam));\r
853         }\r
854 \r
855         inline void CMenuBar::OnCreate()\r
856         {\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
859 \r
860                 m_pFrame = (CFrame*)GetAncestor();\r
861                 assert(m_pFrame);\r
862         }\r
863 \r
864         inline LRESULT CMenuBar::OnCustomDraw(NMHDR* pNMHDR)\r
865         // CustomDraw is used to render the MenuBar's toolbar buttons\r
866         {\r
867                 if (m_ThemeMenu.UseThemes)\r
868                 {\r
869                         LPNMTBCUSTOMDRAW lpNMCustomDraw = (LPNMTBCUSTOMDRAW)pNMHDR;\r
870 \r
871                         switch (lpNMCustomDraw->nmcd.dwDrawStage)\r
872                         {\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
877 \r
878                         // An item is about to be drawn\r
879                         case CDDS_ITEMPREPAINT:\r
880                                 {\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
885 \r
886                                         // Leave a pixel gap above and below the drawn rectangle\r
887                                         if (IsAeroThemed())\r
888                                                 rcRect.InflateRect(0, -2);\r
889                                         else\r
890                                                 rcRect.InflateRect(0, -1);\r
891 \r
892                                         if (IsMDIChildMaxed() && (0 == dwItem))\r
893                                         // Draw over MDI Max button\r
894                                         {\r
895                                                 HICON hIcon = (HICON)::SendMessage(GetActiveMDIChild(), WM_GETICON, ICON_SMALL, 0L);\r
896                                                 if (NULL == hIcon)\r
897                                                         hIcon = ::LoadIcon(NULL, IDI_APPLICATION);\r
898 \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
904 \r
905                                                 DrawDC.Detach();\r
906                                                 return CDRF_SKIPDEFAULT;  // No further drawing\r
907                                         }\r
908 \r
909                                         else if (nState & (CDIS_HOT | CDIS_SELECTED))\r
910                                         {\r
911                                                 if ((nState & CDIS_SELECTED) || (GetButtonState(dwItem) & TBSTATE_PRESSED))\r
912                                                 {\r
913                                                         DrawDC.GradientFill(m_ThemeMenu.clrPressed1, m_ThemeMenu.clrPressed2, rcRect, FALSE);\r
914                                                 }\r
915                                                 else if (nState & CDIS_HOT)\r
916                                                 {\r
917                                                         DrawDC.GradientFill(m_ThemeMenu.clrHot1, m_ThemeMenu.clrHot2, rcRect, FALSE);\r
918                                                 }\r
919 \r
920                                                 // Draw border\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
928 \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
933 \r
934                                                 // Draw highlight text\r
935                                                 CFont* pFont = GetFont();\r
936                                                 ::SelectObject(DrawDC, pFont->GetHandle());\r
937 \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
941 \r
942                                                 DrawDC.SetBkMode(iMode);\r
943                                                 DrawDC.Detach();\r
944                                                 return CDRF_SKIPDEFAULT;  // No further drawing\r
945                                         }\r
946                                         DrawDC.Detach();\r
947                                 }\r
948                                 return CDRF_DODEFAULT ;   // Do default drawing\r
949 \r
950                         // Painting cycle has completed\r
951                         case CDDS_POSTPAINT:\r
952                                 // Draw MDI Minimise, Restore and Close buttons\r
953                                 {\r
954                                         CDC DrawDC(lpNMCustomDraw->nmcd.hdc);\r
955                                         DrawAllMDIButtons(DrawDC);\r
956                                         DrawDC.Detach();\r
957                                 }\r
958                                 break;\r
959                         }\r
960                 }\r
961                 return 0L;\r
962         }\r
963 \r
964         inline void CMenuBar::OnKeyDown(WPARAM wParam, LPARAM lParam)\r
965         {\r
966                 UNREFERENCED_PARAMETER(lParam);\r
967 \r
968                 switch (wParam)\r
969                 {\r
970                 case VK_ESCAPE:\r
971                         ExitMenu();\r
972                         break;\r
973 \r
974                 case VK_SPACE:\r
975                         ExitMenu();\r
976                         // Bring up the system menu\r
977                         GetAncestor()->PostMessage(WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE);\r
978                         break;\r
979 \r
980                 // Handle VK_DOWN,VK_UP and VK_RETURN together\r
981                 case VK_DOWN:\r
982                 case VK_UP:\r
983                 case VK_RETURN:\r
984                         // Always use PostMessage for USER_POPUPMENU (not SendMessage)\r
985                         PostMessage(UWM_POPUPMENU, 0L, 0L);\r
986                         break;\r
987 \r
988                 case VK_LEFT:\r
989                         // Move left to next topmenu item\r
990                         (m_nHotItem > 0)? SetHotItem(m_nHotItem -1) : SetHotItem(GetButtonCount()-1);\r
991                         break;\r
992 \r
993                 case VK_RIGHT:\r
994                         // Move right to next topmenu item\r
995                         (m_nHotItem < GetButtonCount() -1)? SetHotItem(m_nHotItem +1) : SetHotItem(0);\r
996                         break;\r
997 \r
998                 default:\r
999                         // Handle Accelerator keys with Alt toggled down\r
1000                         if (m_bKeyMode)\r
1001                         {\r
1002                                 UINT ID;\r
1003                                 if (SendMessage(TB_MAPACCELERATOR, wParam, (LPARAM) &ID))\r
1004                                 {\r
1005                                         m_nHotItem = ID;\r
1006                                         PostMessage(UWM_POPUPMENU, 0L, 0L);\r
1007                                 }\r
1008                                 else\r
1009                                         ::MessageBeep(MB_OK);\r
1010                         }\r
1011                         break;\r
1012                 } // switch (wParam)\r
1013         }\r
1014 \r
1015         inline void CMenuBar::OnLButtonDown(WPARAM wParam, LPARAM lParam)\r
1016         {\r
1017                 UNREFERENCED_PARAMETER(wParam);\r
1018 \r
1019                 GrabFocus();\r
1020                 m_nMDIButton = 0;\r
1021                 CPoint pt;\r
1022 \r
1023                 pt.x = GET_X_LPARAM(lParam);\r
1024                 pt.y = GET_Y_LPARAM(lParam);\r
1025 \r
1026                 if (IsMDIFrame())\r
1027                 {\r
1028                         if (IsMDIChildMaxed())\r
1029                         {\r
1030                                 CClientDC MenuBarDC(this);\r
1031                                 m_nMDIButton = -1;\r
1032 \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
1036 \r
1037                                 if (m_nMDIButton >= 0)\r
1038                                 {\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
1042                                 }\r
1043 \r
1044                                 // Bring up the MDI Child window's system menu when the icon is pressed\r
1045                                 if (0 == HitTest())\r
1046                                 {\r
1047                                         m_nHotItem = 0;\r
1048                                         PostMessage(UWM_POPUPMENU, 0L, 0L);\r
1049                                 }\r
1050                         }\r
1051                 }\r
1052         }\r
1053 \r
1054         inline void CMenuBar::OnLButtonUp(WPARAM wParam, LPARAM lParam)\r
1055         {\r
1056                 UNREFERENCED_PARAMETER(wParam);\r
1057                 CPoint pt;\r
1058                 pt.x = GET_X_LPARAM(lParam);\r
1059                 pt.y = GET_Y_LPARAM(lParam);\r
1060 \r
1061                 if (IsMDIFrame())\r
1062                 {\r
1063                         HWND MDIClient = m_pFrame->GetView()->GetHwnd();\r
1064                         HWND MDIChild = GetActiveMDIChild();\r
1065 \r
1066                         if (IsMDIChildMaxed())\r
1067                         {\r
1068                                 CPoint pt = GetCursorPos();\r
1069                                 ScreenToClient(pt);\r
1070 \r
1071                                 // Process the MDI button action when the left mouse button is up\r
1072                                 if (m_MDIRect[0].PtInRect(pt))\r
1073                                 {\r
1074                                         if (MDI_MIN == m_nMDIButton)\r
1075                                                 ::ShowWindow(MDIChild, SW_MINIMIZE);\r
1076                                 }\r
1077 \r
1078                                 if (m_MDIRect[1].PtInRect(pt))\r
1079                                 {\r
1080                                         if (MDI_RESTORE == m_nMDIButton)\r
1081                                         ::PostMessage(MDIClient, WM_MDIRESTORE, (WPARAM)MDIChild, 0L);\r
1082                                 }\r
1083 \r
1084                                 if (m_MDIRect[2].PtInRect(pt))\r
1085                                 {\r
1086                                         if (MDI_CLOSE == m_nMDIButton)\r
1087                                                 ::PostMessage(MDIChild, WM_CLOSE, 0L, 0L);\r
1088                                 }\r
1089                         }\r
1090                 }\r
1091                 m_nMDIButton = 0;\r
1092                 ExitMenu();\r
1093         }\r
1094 \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
1097         {\r
1098                 switch(uMsg)\r
1099                 {\r
1100                 case WM_KEYDOWN:\r
1101                         m_bExitAfter = FALSE;\r
1102                         {\r
1103                                 switch (wParam)\r
1104                                 {\r
1105                                 case VK_ESCAPE:\r
1106                                         // Use default processing if inside a Sub Menu\r
1107                                         if ((m_hSelMenu) &&(m_hSelMenu != m_hPopupMenu))\r
1108                                                 return FALSE;\r
1109 \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
1115                                         break;\r
1116 \r
1117                                 case VK_LEFT:\r
1118                                         // Use default processing if inside a Sub Menu\r
1119                                     if ((m_hSelMenu) &&(m_hSelMenu != m_hPopupMenu))\r
1120                                                 return FALSE;\r
1121 \r
1122                                         SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));\r
1123 \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
1127 \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
1131                                         break;\r
1132 \r
1133                                 case VK_RIGHT:\r
1134                                         // Use default processing to open Sub Menu\r
1135                                         if (m_bSelPopup)\r
1136                                                 return FALSE;\r
1137 \r
1138                                         SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));\r
1139 \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
1143 \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
1147                                         break;\r
1148 \r
1149                                 case VK_RETURN:\r
1150                                         m_bExitAfter = TRUE;\r
1151                                         break;\r
1152 \r
1153                                 } // switch (wParam)\r
1154 \r
1155                         } // case WM_KEYDOWN\r
1156 \r
1157                         return FALSE;\r
1158 \r
1159                 case WM_CHAR:\r
1160                         m_bExitAfter = TRUE;\r
1161                         return FALSE;\r
1162 \r
1163                 case WM_LBUTTONDOWN:\r
1164                         {\r
1165                                 m_bExitAfter = TRUE;\r
1166                                 if (HitTest() >= 0)\r
1167                                 {\r
1168                                         // Cancel popup when we hit a button a second time\r
1169                                         SendMessage(WM_CANCELMODE, 0L, 0L);\r
1170                                         return TRUE;\r
1171                                 }\r
1172                         }\r
1173                         return FALSE;\r
1174 \r
1175                 case WM_LBUTTONDBLCLK:\r
1176                         // Perform default action for DblClick on MDI Maxed icon\r
1177                         if (IsMDIChildMaxed() && (0 == HitTest()))\r
1178                         {\r
1179                                 CWnd* pMDIChild = FromHandle(GetActiveMDIChild());\r
1180                                 CMenu* pChildMenu = pMDIChild->GetSystemMenu(FALSE);\r
1181 \r
1182                                 UINT nID = pChildMenu->GetDefaultItem(FALSE, 0);\r
1183                                 if (nID)\r
1184                                         pMDIChild->PostMessage(WM_SYSCOMMAND, nID, 0L);\r
1185                         }\r
1186 \r
1187                         m_bExitAfter = TRUE;\r
1188                         return FALSE;\r
1189 \r
1190                 case WM_MENUSELECT:\r
1191                         {\r
1192                                 // store info about selected item\r
1193                                 m_hSelMenu = (HMENU)lParam;\r
1194                                 m_bSelPopup = ((HIWORD(wParam) & MF_POPUP) != 0);\r
1195 \r
1196                                 // Reflect message back to the frame window\r
1197                                 GetAncestor()->SendMessage(WM_MENUSELECT, wParam, lParam);\r
1198                         }\r
1199                         return TRUE;\r
1200 \r
1201                 case WM_MOUSEMOVE:\r
1202                         {\r
1203                                 CPoint pt;\r
1204                                 pt.x = GET_X_LPARAM(lParam);\r
1205                                 pt.y = GET_Y_LPARAM(lParam);\r
1206 \r
1207                                 // Skip if mouse hasn't moved\r
1208                                 if ((pt.x == m_OldMousePos.x) && (pt.y == m_OldMousePos.y))\r
1209                                         return FALSE;\r
1210 \r
1211                                 m_OldMousePos.x = pt.x;\r
1212                                 m_OldMousePos.y = pt.y;\r
1213                                 ScreenToClient(pt);\r
1214 \r
1215                                 // Reflect messages back to the MenuBar for hot tracking\r
1216                                 SendMessage(WM_MOUSEMOVE, 0L, MAKELPARAM(pt.x, pt.y));\r
1217                         }\r
1218                         break;\r
1219 \r
1220                 }\r
1221                 return FALSE;\r
1222         }\r
1223 \r
1224         inline void CMenuBar::OnMouseLeave()\r
1225         {\r
1226                 if (IsMDIFrame())\r
1227                 {\r
1228                         if (IsMDIChildMaxed())\r
1229                         {\r
1230                                 CClientDC MenuBarDC(this);\r
1231 \r
1232                                 DrawMDIButton(MenuBarDC, MDI_MIN,     0);\r
1233                                 DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);\r
1234                                 DrawMDIButton(MenuBarDC, MDI_CLOSE,   0);\r
1235                         }\r
1236                 }\r
1237         }\r
1238 \r
1239         inline void CMenuBar::OnMouseMove(WPARAM wParam, LPARAM lParam)\r
1240         {\r
1241                 CPoint pt;\r
1242                 pt.x = GET_X_LPARAM(lParam);\r
1243                 pt.y = GET_Y_LPARAM(lParam);\r
1244 \r
1245                 if (IsMDIFrame())\r
1246                 {\r
1247                         if (IsMDIChildMaxed())\r
1248                         {\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
1254 \r
1255                                 if (MK_LBUTTON == wParam)  // mouse moved with left mouse button is held down\r
1256                                 {\r
1257                                         // toggle the MDI button image pressed/unpressed as required\r
1258                                         if (MDIButton >= 0)\r
1259                                         {\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
1263                                         }\r
1264                                         else\r
1265                                         {\r
1266                                                 DrawMDIButton(MenuBarDC, MDI_MIN,     0);\r
1267                                                 DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);\r
1268                                                 DrawMDIButton(MenuBarDC, MDI_CLOSE,   0);\r
1269                                         }\r
1270                                 }\r
1271                                 else    // mouse moved without left mouse button held down\r
1272                                 {\r
1273                                         if (MDIButton >= 0)\r
1274                                         {\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
1278                                         }\r
1279                                         else\r
1280                                         {\r
1281                                                 DrawMDIButton(MenuBarDC, MDI_MIN,     0);\r
1282                                                 DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);\r
1283                                                 DrawMDIButton(MenuBarDC, MDI_CLOSE,   0);\r
1284                                         }\r
1285                                 }\r
1286                         }\r
1287                 }\r
1288         }\r
1289 \r
1290         inline LRESULT CMenuBar::OnNotifyReflect(WPARAM wParam, LPARAM lParam)\r
1291         {\r
1292                 UNREFERENCED_PARAMETER(wParam);\r
1293 \r
1294                 switch (((LPNMHDR)lParam)->code)\r
1295                 {\r
1296                 case NM_CUSTOMDRAW:\r
1297                         {\r
1298                                 return OnCustomDraw((LPNMHDR) lParam);\r
1299                         }\r
1300 \r
1301                 case TBN_DROPDOWN:\r
1302                         // Always use PostMessage for USER_POPUPMENU (not SendMessage)\r
1303                         PostMessage(UWM_POPUPMENU, 0L, 0L);\r
1304                         break;\r
1305 \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
1309                         {\r
1310                                 CPoint pt = GetCursorPos();\r
1311                                 if (this == WindowFromPoint(pt))        // MenuBar window must be on top\r
1312                                 {\r
1313                                         DWORD flag = ((LPNMTBHOTITEM)lParam)->dwFlags;\r
1314                                         if ((flag & HICF_MOUSE) && !(flag & HICF_LEAVING))\r
1315                                         {\r
1316                                                 int nButton = HitTest();\r
1317                                                 if ((m_bMenuActive) && (nButton != m_nHotItem))\r
1318                                                 {\r
1319                                                         SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));\r
1320                                                         m_nHotItem = nButton;\r
1321                                                         SendMessage(WM_CANCELMODE, 0L, 0L);\r
1322 \r
1323                                                         //Always use PostMessage for USER_POPUPMENU (not SendMessage)\r
1324                                                         PostMessage(UWM_POPUPMENU, 0L, 0L);\r
1325                                                 }\r
1326                                                 m_nHotItem = nButton;\r
1327                                         }\r
1328 \r
1329                                         // Handle escape from popup menu\r
1330                                         if ((flag & HICF_LEAVING) && m_bKeyMode)\r
1331                                         {\r
1332                                                 m_nHotItem = ((LPNMTBHOTITEM)lParam)->idOld;\r
1333                                                 PostMessage(TB_SETHOTITEM, m_nHotItem, 0L);\r
1334                                         }\r
1335 \r
1336                                 }\r
1337                                 break;\r
1338                         } //case TBN_HOTITEMCHANGE:\r
1339 \r
1340                 } // switch(((LPNMHDR)lParam)->code)\r
1341                 return 0L;\r
1342         } // CMenuBar::OnNotify(...)\r
1343 \r
1344         inline void CMenuBar::OnWindowPosChanged()\r
1345         {\r
1346                 InvalidateRect(&m_MDIRect[0], TRUE);\r
1347                 InvalidateRect(&m_MDIRect[1], TRUE);\r
1348                 InvalidateRect(&m_MDIRect[2], TRUE);\r
1349                 {\r
1350                         CClientDC MenuBarDC(this);\r
1351                         DrawAllMDIButtons(MenuBarDC);\r
1352                 }\r
1353         }\r
1354 \r
1355         inline void CMenuBar::PreCreate(CREATESTRUCT &cs)\r
1356         {\r
1357                 cs.style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS | TBSTYLE_LIST | TBSTYLE_FLAT | CCS_NODIVIDER | CCS_NORESIZE;\r
1358         }\r
1359 \r
1360         inline void CMenuBar::PreRegisterClass(WNDCLASS &wc)\r
1361         {\r
1362                 // Set the Window Class\r
1363                 wc.lpszClassName =  TOOLBARCLASSNAME;\r
1364         }\r
1365 \r
1366         inline void CMenuBar::ReleaseFocus()\r
1367         {\r
1368                 if (m_hPrevFocus)\r
1369                         ::SetFocus(m_hPrevFocus);\r
1370 \r
1371                 m_hPrevFocus = NULL;\r
1372                 ::ReleaseCapture();\r
1373         }\r
1374 \r
1375         inline void CMenuBar::SetHotItem(int nHot)\r
1376         {\r
1377                 m_nHotItem = nHot;\r
1378                 SendMessage(TB_SETHOTITEM, m_nHotItem, 0L);\r
1379         }\r
1380 \r
1381         inline void CMenuBar::SetMenu(HMENU hMenu)\r
1382         {\r
1383                 assert(::IsWindow(m_hWnd));\r
1384 \r
1385                 m_hTopMenu = hMenu;\r
1386                 int nMaxedOffset = (IsMDIChildMaxed()? 1:0);\r
1387 \r
1388                 // Remove any existing buttons\r
1389                 while (SendMessage(TB_BUTTONCOUNT,  0L, 0L) > 0)\r
1390                 {\r
1391                         if(!SendMessage(TB_DELETEBUTTON, 0L, 0L))\r
1392                                 break;\r
1393                 }\r
1394 \r
1395                 // Set the Bitmap size to zero\r
1396                 SendMessage(TB_SETBITMAPSIZE, 0L, MAKELPARAM(0, 0));\r
1397 \r
1398                 if (IsMDIChildMaxed())\r
1399                 {\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
1408                 }\r
1409 \r
1410                 for (int i = 0 ; i < ::GetMenuItemCount(hMenu); ++i)\r
1411                 {\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
1419 \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
1425                 }\r
1426         }\r
1427 \r
1428         inline void CMenuBar::SetMenuBarTheme(MenuTheme& Theme)\r
1429         {\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
1436 \r
1437                 if (IsWindow())\r
1438                         Invalidate();\r
1439         }\r
1440 \r
1441         inline LRESULT CALLBACK CMenuBar::StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam)\r
1442         {\r
1443                 assert(GetApp());\r
1444                 MSG* pMsg = (MSG*)lParam;\r
1445                 TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());\r
1446                 assert(pTLSData);\r
1447                 CMenuBar* pMenuBar = (CMenuBar*)pTLSData->pMenuBar;\r
1448 \r
1449                 if (pMenuBar && (MSGF_MENU == nCode))\r
1450                 {\r
1451                         // process menu message\r
1452                         if (pMenuBar->OnMenuInput(pMsg->message, pMsg->wParam, pMsg->lParam))\r
1453                         {\r
1454                                 return TRUE;\r
1455                         }\r
1456                 }\r
1457 \r
1458                 return CallNextHookEx(pTLSData->hHook, nCode, wParam, lParam);\r
1459         }\r
1460 \r
1461         inline void CMenuBar::OnSysCommand(WPARAM wParam, LPARAM lParam)\r
1462         {\r
1463                 if (SC_KEYMENU == wParam)\r
1464                 {\r
1465                         if (0 == lParam)\r
1466                         {\r
1467                                 // Alt/F10 key toggled\r
1468                                 GrabFocus();\r
1469                                 m_bKeyMode = TRUE;\r
1470                                 int nMaxedOffset = (IsMDIChildMaxed()? 1:0);\r
1471                                 SetHotItem(nMaxedOffset);\r
1472                         }\r
1473                         else\r
1474                                 // Handle key pressed with Alt held down\r
1475                                 DoAltKey((WORD)lParam);\r
1476                 }\r
1477         }\r
1478 \r
1479         inline LRESULT CMenuBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
1480         {\r
1481                 switch (uMsg)\r
1482                 {\r
1483                 case WM_CHAR:\r
1484                         return 0L;  // Discard these messages\r
1485                 case WM_DRAWITEM:\r
1486                         m_pFrame->OnDrawItem(wParam, lParam);\r
1487                         return TRUE; // handled\r
1488                 case WM_EXITMENULOOP:\r
1489                         if (m_bExitAfter)\r
1490                                 ExitMenu();\r
1491                         m_pFrame->OnExitMenuLoop();\r
1492                         break;\r
1493                 case WM_INITMENUPOPUP:\r
1494                         m_pFrame->OnInitMenuPopup(wParam, lParam);\r
1495                         break;\r
1496                 case WM_KEYDOWN:\r
1497                         OnKeyDown(wParam, lParam);\r
1498                         return 0L;      // Discard these messages\r
1499                 case WM_KILLFOCUS:\r
1500                         ExitMenu();\r
1501                         return 0L;\r
1502                 case WM_LBUTTONDOWN:\r
1503                         // Do default processing first\r
1504                         CallWindowProc(GetPrevWindowProc(), uMsg, wParam, lParam);\r
1505 \r
1506                         OnLButtonDown(wParam, lParam);\r
1507                         return 0L;\r
1508                 case WM_LBUTTONUP:\r
1509                         OnLButtonUp(wParam, lParam);\r
1510                         break;\r
1511                 case WM_MEASUREITEM:\r
1512                         m_pFrame->OnMeasureItem(wParam, lParam);\r
1513                         return TRUE; // handled\r
1514                 case WM_MOUSELEAVE:\r
1515                         OnMouseLeave();\r
1516                         break;\r
1517                 case WM_MOUSEMOVE:\r
1518                         OnMouseMove(wParam, lParam);\r
1519                         break;\r
1520                 case UWM_POPUPMENU:\r
1521                         DoPopupMenu();\r
1522                         return 0L;\r
1523                 case WM_SYSKEYDOWN:\r
1524                         if ((VK_MENU == wParam) || (VK_F10 == wParam))\r
1525                                 return 0L;\r
1526                         break;\r
1527                 case WM_SYSKEYUP:\r
1528                         if ((VK_MENU == wParam) || (VK_F10 == wParam))\r
1529                         {\r
1530                                 ExitMenu();\r
1531                                 return 0L;\r
1532                         }\r
1533                         break;\r
1534                 case UWM_GETMENUTHEME:\r
1535                         {\r
1536                                 MenuTheme& tm = GetMenuBarTheme();\r
1537                                 return (LRESULT)&tm;\r
1538                         }\r
1539                 case WM_WINDOWPOSCHANGED:\r
1540                         OnWindowPosChanged();\r
1541                         break;\r
1542                 case WM_WINDOWPOSCHANGING:\r
1543                         // Bypass CToolBar::WndProcDefault for this message\r
1544                         return CWnd::WndProcDefault(uMsg, wParam, lParam);\r
1545 \r
1546                 } // switch (uMsg)\r
1547 \r
1548                 return CToolBar::WndProcDefault(uMsg, wParam, lParam);\r
1549         } // LRESULT CMenuBar::WndProcDefault(...)\r
1550 \r
1551 \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
1555         {\r
1556                 assert(pFrame);\r
1557                 m_pFrame = pFrame;\r
1558 \r
1559                 Initialize();\r
1560         }\r
1561 \r
1562         inline void CMenuMetrics::Initialize()\r
1563         {\r
1564                 assert(m_pFrame);\r
1565 \r
1566                 HMODULE hModule = ::LoadLibrary(_T("UXTHEME.DLL"));\r
1567                 if (hModule)\r
1568                 {\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
1579                 }\r
1580 \r
1581                 if (m_hTheme)\r
1582                 {\r
1583                         CloseThemeData();\r
1584                         m_hTheme = 0;\r
1585                 }\r
1586 \r
1587                 m_hTheme = OpenThemeData(*m_pFrame, VSCLASS_MENU);\r
1588 \r
1589                 if (m_hTheme)\r
1590                 {\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
1600 \r
1601                         // Popup text margins\r
1602                         m_marText = m_marItem;\r
1603                         m_marText.cxRightWidth = iBorderSize;\r
1604                         m_marText.cxLeftWidth = iBgBorderSize;\r
1605                 }\r
1606                 else\r
1607                 {\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
1614                 }\r
1615         }\r
1616 \r
1617         inline CMenuMetrics::~CMenuMetrics()\r
1618         {\r
1619                 if (m_hTheme)           CloseThemeData();\r
1620         }\r
1621 \r
1622         inline HRESULT CMenuMetrics::CloseThemeData()\r
1623         {\r
1624                 if (m_pfnCloseThemeData)\r
1625                         return (*m_pfnCloseThemeData)(m_hTheme);\r
1626 \r
1627                 return E_NOTIMPL;\r
1628         }\r
1629 \r
1630         inline HRESULT CMenuMetrics::DrawThemeBackground(HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect)\r
1631         {\r
1632                 if (m_pfnDrawThemeBackground)\r
1633                         return (*m_pfnDrawThemeBackground)(m_hTheme, hdc, iPartId, iStateId, pRect, pClipRect);\r
1634 \r
1635                 return E_NOTIMPL;\r
1636         }\r
1637 \r
1638         inline HRESULT CMenuMetrics::DrawThemeText(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect)\r
1639         {\r
1640                 if (m_pfnDrawThemeText)\r
1641                         return (*m_pfnDrawThemeText)(m_hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, pRect);\r
1642 \r
1643                 return E_NOTIMPL;\r
1644         }\r
1645 \r
1646         inline HRESULT CMenuMetrics::GetThemePartSize(HDC hdc, int iPartId, int iStateId, LPCRECT prc, THEMESIZE eSize, SIZE* psz)\r
1647         {\r
1648                 if (m_pfnGetThemePartSize)\r
1649                         return (*m_pfnGetThemePartSize)(m_hTheme, hdc, iPartId, iStateId, prc, eSize, psz);\r
1650 \r
1651                 return E_NOTIMPL;\r
1652         }\r
1653 \r
1654         inline HRESULT CMenuMetrics::GetThemeInt(int iPartId, int iStateId, int iPropId, int* piVal)\r
1655         {\r
1656                 if (m_pfnGetThemeInt)\r
1657                         return (*m_pfnGetThemeInt)(m_hTheme, iPartId, iStateId, iPropId, piVal);\r
1658 \r
1659                 return E_NOTIMPL;\r
1660         }\r
1661 \r
1662         inline HRESULT CMenuMetrics::GetThemeMargins(HDC hdc, int iPartId, int iStateId, int iPropId, LPRECT prc, MARGINS* pMargins)\r
1663         {\r
1664                 if (m_pfnGetThemeMargins)\r
1665                         return (*m_pfnGetThemeMargins)(m_hTheme, hdc, iPartId, iStateId, iPropId, prc, pMargins);\r
1666 \r
1667                 return E_NOTIMPL;\r
1668         }\r
1669 \r
1670         inline HRESULT CMenuMetrics::GetThemeTextExtent(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect)\r
1671         {\r
1672                 if (m_pfnGetThemeTextExtent)\r
1673                         return (*m_pfnGetThemeTextExtent)(m_hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, pBoundingRect, pExtentRect);\r
1674 \r
1675                 return E_NOTIMPL;\r
1676         }\r
1677 \r
1678         inline BOOL CMenuMetrics::IsThemeBackgroundPartiallyTransparent(int iPartId, int iStateId)\r
1679         {\r
1680                 if (m_pfnIsThemeBGPartTransparent)\r
1681                         return (*m_pfnIsThemeBGPartTransparent)(m_hTheme, iPartId, iStateId);\r
1682 \r
1683                 return E_NOTIMPL;\r
1684         }\r
1685 \r
1686         inline HANDLE CMenuMetrics::OpenThemeData(HWND hwnd, LPCWSTR pszClassList)\r
1687         {\r
1688                 if (m_pfnOpenThemeData)\r
1689                         return (*m_pfnOpenThemeData)(hwnd, pszClassList);\r
1690 \r
1691                 return NULL;\r
1692         }\r
1693 \r
1694         inline CRect CMenuMetrics::GetCheckBackgroundRect(CRect rcItem)\r
1695         {\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
1700 \r
1701                 return CRect(x, y, x + cx, y + cy);\r
1702         }\r
1703 \r
1704         inline CRect CMenuMetrics::GetGutterRect(CRect rcItem)\r
1705         {\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
1710 \r
1711                 return CRect(x, y, x + cx, y + cy);\r
1712         }\r
1713 \r
1714         inline CRect CMenuMetrics::GetCheckRect(CRect rcItem)\r
1715         {\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
1718 \r
1719                 return CRect(x, y, x + m_sizeCheck.cx, y + m_sizeCheck.cy);\r
1720         }\r
1721 \r
1722         inline CRect CMenuMetrics::GetSelectionRect(CRect rcItem)\r
1723         {\r
1724                 int x = rcItem.left + m_marItem.cxLeftWidth;\r
1725                 int y = rcItem.top;\r
1726 \r
1727                 return CRect(x, y, rcItem.right - m_marItem.cxRightWidth, y + rcItem.Height());\r
1728         }\r
1729 \r
1730         inline CRect CMenuMetrics::GetSeperatorRect(CRect rcItem)\r
1731         {\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
1736 \r
1737                 return CRect(left, top, right, bottom);\r
1738         }\r
1739 \r
1740         inline CSize CMenuMetrics::GetTextSize(MenuItemData* pmd)\r
1741         {\r
1742                 CSize sizeText;\r
1743                 assert(m_pFrame);\r
1744                 CClientDC DesktopDC(NULL);\r
1745                 LPCTSTR szItemText = pmd->GetItemText();\r
1746 \r
1747                 if (IsAeroThemed())\r
1748                 {\r
1749                         CRect rcText;\r
1750                         GetThemeTextExtent(DesktopDC, MENU_POPUPITEM, 0, T2W(szItemText), lstrlen(szItemText),\r
1751                                                    DT_LEFT | DT_SINGLELINE, NULL, &rcText);\r
1752 \r
1753                         sizeText.SetSize(rcText.right + m_marText.Width(), rcText.bottom + m_marText.Height());\r
1754                 }\r
1755                 else\r
1756                 {\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
1761 \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
1765 \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
1772                 }\r
1773 \r
1774                 if (_tcschr(szItemText, _T('\t')))\r
1775                         sizeText.cx += 8;       // Add POST_TEXT_GAP if the text includes a tab\r
1776 \r
1777                 return sizeText;\r
1778         }\r
1779 \r
1780         inline CRect CMenuMetrics::GetTextRect(CRect rcItem)\r
1781         {\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
1786 \r
1787                 return CRect(left, top, right, bottom);\r
1788         }\r
1789 \r
1790         inline int CMenuMetrics::ToItemStateId(UINT uItemState)\r
1791         {\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
1795 \r
1796                 if (fDisabled)\r
1797                         iState = (fHot ? MPI_DISABLEDHOT : MPI_DISABLED);\r
1798                 else if (fHot)\r
1799                         iState = MPI_HOT;\r
1800                 else\r
1801                         iState= MPI_NORMAL;\r
1802 \r
1803                 return iState;\r
1804         }\r
1805 \r
1806         inline int CMenuMetrics::ToCheckBackgroundStateId(int iStateId)\r
1807         {\r
1808                 POPUPCHECKBACKGROUNDSTATES iStateIdCheckBackground;\r
1809 \r
1810                 // Determine the check background state.\r
1811                 if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT)\r
1812                         iStateIdCheckBackground = MCB_DISABLED;\r
1813                 else\r
1814                         iStateIdCheckBackground = MCB_NORMAL;\r
1815 \r
1816                 return iStateIdCheckBackground;\r
1817         }\r
1818 \r
1819         inline int CMenuMetrics::ToCheckStateId(UINT fType, int iStateId)\r
1820         {\r
1821                 POPUPCHECKSTATES iStateIdCheck;\r
1822 \r
1823                 if (fType & MFT_RADIOCHECK)\r
1824                 {\r
1825                         if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT)\r
1826                                 iStateIdCheck = MC_BULLETDISABLED;\r
1827                         else\r
1828                                 iStateIdCheck = MC_BULLETNORMAL;\r
1829                 }\r
1830                 else\r
1831                 {\r
1832                         if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT)\r
1833                                 iStateIdCheck = MC_CHECKMARKDISABLED;\r
1834                         else\r
1835                                 iStateIdCheck = MC_CHECKMARKNORMAL;\r
1836                 }\r
1837 \r
1838                 return iStateIdCheck;\r
1839         }\r
1840 \r
1841 \r
1842         ///////////////////////////////////\r
1843         // Definitions for the CFrame class\r
1844         //\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
1848         {\r
1849                 ZeroMemory(&m_ThemeMenu, sizeof(m_ThemeMenu));\r
1850 \r
1851                 // Do either InitCommonControls or InitCommonControlsEx\r
1852                 LoadCommonControls();\r
1853 \r
1854                 // By default, we use the rebar if we can\r
1855                 if (GetComCtlVersion() > 470)\r
1856                         m_bUseReBar = TRUE;\r
1857 \r
1858                 for (int i = 0 ; i < 3 ; ++i)\r
1859                         m_OldStatus[i] = _T('\0');\r
1860 \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
1866         }\r
1867 \r
1868         inline CFrame::~CFrame()\r
1869         {\r
1870                 if (m_himlMenu)         ImageList_Destroy(m_himlMenu);\r
1871                 if (m_himlMenuDis)      ImageList_Destroy(m_himlMenuDis);\r
1872         }\r
1873 \r
1874         inline BOOL CFrame::AddMenuIcon(int nID_MenuItem, HICON hIcon)\r
1875         {\r
1876                 // Create a new ImageList if required\r
1877                 if (NULL == m_himlMenu)\r
1878                 {\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
1882                 }\r
1883 \r
1884                 if (ImageList_AddIcon(m_himlMenu, hIcon) != -1)\r
1885                 {\r
1886                         m_vMenuIcons.push_back(nID_MenuItem);\r
1887 \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
1892 \r
1893                         return TRUE;\r
1894                 }\r
1895 \r
1896                 return FALSE;\r
1897         }\r
1898 \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
1903         {\r
1904                 // Count the MenuData entries excluding seperators\r
1905                 int iImages = 0;\r
1906                 for (UINT i = 0 ; i < MenuData.size(); ++i)\r
1907                 {\r
1908                         if (MenuData[i] != 0)   // Don't count seperators\r
1909                         {\r
1910                                 ++iImages;\r
1911                         }\r
1912                 }\r
1913 \r
1914                 // Load the button images from Resouce ID\r
1915                 CBitmap Bitmap(ToolBarID);\r
1916 \r
1917                 if ((0 == iImages) || (!Bitmap))\r
1918                         return (UINT)m_vMenuIcons.size();       // No valid images, so nothing to do!\r
1919 \r
1920                 BITMAP bm = Bitmap.GetBitmapData();\r
1921                 int iImageWidth  = bm.bmWidth / iImages;\r
1922                 int iImageHeight = bm.bmHeight;\r
1923 \r
1924                 // Create the ImageList if required\r
1925                 if (NULL == m_himlMenu)\r
1926                 {\r
1927                         m_himlMenu = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iImages, 0);\r
1928                         m_vMenuIcons.clear();\r
1929                 }\r
1930                 else\r
1931                 {\r
1932                         int Oldcx;\r
1933                         int Oldcy;\r
1934 \r
1935                         ImageList_GetIconSize(m_himlMenu, &Oldcx, &Oldcy);\r
1936                         if (iImageHeight != Oldcy)\r
1937                         {\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
1940                         }\r
1941                 }\r
1942 \r
1943                 // Add the resource IDs to the m_vMenuIcons vector\r
1944                 for (UINT j = 0 ; j < MenuData.size(); ++j)\r
1945                 {\r
1946                         if (MenuData[j] != 0)\r
1947                         {\r
1948                                 m_vMenuIcons.push_back(MenuData[j]);\r
1949                         }\r
1950                 }\r
1951 \r
1952                 // Add the images to the ImageList\r
1953                 ImageList_AddMasked(m_himlMenu, Bitmap, crMask);\r
1954 \r
1955                 // Create the Disabled imagelist\r
1956                 if (ToolBarDisabledID)\r
1957                 {\r
1958                         if (0 != m_himlMenuDis)\r
1959                                 m_himlMenuDis = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iImages, 0);\r
1960 \r
1961                         CBitmap BitmapDisabled(ToolBarDisabledID);\r
1962                         BITMAP bmDis = BitmapDisabled.GetBitmapData();\r
1963 \r
1964                         int iImageWidthDis  = bmDis.bmWidth / iImages;\r
1965                         int iImageHeightDis = bmDis.bmHeight;\r
1966 \r
1967                         // Normal and Disabled icons must be the same size\r
1968                         if ((iImageWidthDis == iImageWidth) && (iImageHeightDis == iImageHeight))\r
1969                         {\r
1970                                 ImageList_AddMasked(m_himlMenu, BitmapDisabled, crMask);\r
1971                         }\r
1972                         else\r
1973                         {\r
1974                                 ImageList_Destroy(m_himlMenuDis);\r
1975                                 m_himlMenuDis = CreateDisabledImageList(m_himlMenu);\r
1976                         }\r
1977                 }\r
1978                 else\r
1979                 {\r
1980                         if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);\r
1981                         m_himlMenuDis = CreateDisabledImageList(m_himlMenu);\r
1982                 }\r
1983 \r
1984                 // return the number of menu icons\r
1985                 return (UINT)m_vMenuIcons.size();\r
1986         }\r
1987 \r
1988         inline void CFrame::AddMenuBarBand()\r
1989         {\r
1990                 // Adds a MenuBar to the rebar control\r
1991                 REBARBANDINFO rbbi = {0};\r
1992                 CSize sz = GetMenuBar().GetMaxSize();\r
1993 \r
1994                 // Calculate the MenuBar height from the menu font\r
1995                 CSize csMenuBar;\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
2000 \r
2001                 rbbi.fMask      = RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_SIZE | RBBIM_ID;\r
2002                 rbbi.cxMinChild = sz.cx;\r
2003                 rbbi.cx         = 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
2009 \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
2014 \r
2015                 if (GetReBar().GetReBarTheme().LockMenuBand)\r
2016                         GetReBar().ShowGripper(GetReBar().GetBand(GetMenuBar()), FALSE);\r
2017         }\r
2018 \r
2019         inline void CFrame::AddMRUEntry(LPCTSTR szMRUEntry)\r
2020         {\r
2021                 // Erase possible duplicate entries from vector\r
2022                 RemoveMRUEntry(szMRUEntry);\r
2023 \r
2024                 // Insert the entry at the beginning of the vector\r
2025                 m_vMRUEntries.insert(m_vMRUEntries.begin(), szMRUEntry);\r
2026 \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
2030 \r
2031                 UpdateMRUMenu();\r
2032         }\r
2033 \r
2034         inline void CFrame::AddToolBarBand(CToolBar& TB, DWORD dwStyle, UINT nID)\r
2035         {\r
2036                 // Adds a ToolBar to the rebar control\r
2037 \r
2038                 // Create the ToolBar Window\r
2039                 TB.Create(&GetReBar());\r
2040 \r
2041                 // Fill the REBARBAND structure\r
2042                 REBARBANDINFO rbbi = {0};\r
2043                 CSize sz = TB.GetMaxSize();\r
2044 \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
2050 \r
2051                 rbbi.fStyle     = dwStyle;\r
2052                 rbbi.hwndChild  = TB;\r
2053                 rbbi.wID        = nID;\r
2054 \r
2055                 // Note: rbbi.cbSize is set inside the InsertBand function\r
2056                 GetReBar().InsertBand(-1, rbbi);\r
2057         }\r
2058 \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
2062         {\r
2063                 GetToolBar().AddButton(nID, bEnabled);\r
2064 \r
2065                 if(0 != szText)\r
2066                         GetToolBar().SetButtonText(nID, szText);\r
2067 \r
2068                 if (!IsWindow()) TRACE(_T("Warning ... Resource IDs for toolbars should be added in SetupToolBar\n"));\r
2069         }\r
2070 \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
2073         {\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
2079 \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
2084 \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
2089 \r
2090                 // Calculate final rect size, and reposition frame\r
2091                 SetWindowPos(NULL, 0, 0, rc.Width(), Height, SWP_NOMOVE);\r
2092         }\r
2093 \r
2094         inline void CFrame::CreateToolBar()\r
2095         {\r
2096                 if (IsReBarSupported() && m_bUseReBar)\r
2097                         AddToolBarBand(GetToolBar(), RBBS_BREAK, IDW_TOOLBAR);  // Create the toolbar inside rebar\r
2098                 else\r
2099                         GetToolBar().Create(this);      // Create the toolbar without a rebar\r
2100 \r
2101                 SetupToolBar();\r
2102 \r
2103                 if (IsReBarSupported() && m_bUseReBar)\r
2104                 {\r
2105                         if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().LockMenuBand)\r
2106                         {\r
2107                                 // Hide gripper for single toolbar\r
2108                                 if (GetReBar().GetBandCount() <= 2)\r
2109                                         GetReBar().ShowGripper(GetReBar().GetBand(GetToolBar()), FALSE);\r
2110                         }\r
2111                 }\r
2112 \r
2113                 if (GetToolBar().GetToolBarData().size() > 0)\r
2114                 {\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
2119 \r
2120                         // Add the icons for popup menu\r
2121                         AddMenuIcons(GetToolBar().GetToolBarData(), RGB(192, 192, 192), IDW_MAIN, 0);\r
2122                 }\r
2123                 else\r
2124                 {\r
2125                         TRACE(_T("Warning ... No resource IDs assigned to the toolbar\n"));\r
2126                 }\r
2127         }\r
2128 \r
2129         inline void CFrame::DrawMenuItem(LPDRAWITEMSTRUCT pdis)\r
2130         {\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
2135 \r
2136                 if (IsAeroThemed() && m_pMenuMetrics->IsThemeBackgroundPartiallyTransparent(MENU_POPUPITEM, iStateId))\r
2137                 {\r
2138                         m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPBACKGROUND, 0, &pdis->rcItem, NULL);\r
2139                 }\r
2140 \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
2145                 else\r
2146                         DrawDC.GradientFill(tm.clrPressed1, tm.clrPressed2, rcGutter, TRUE);\r
2147 \r
2148                 if (pmid->mii.fType & MFT_SEPARATOR)\r
2149                 {\r
2150                         // Draw the separator\r
2151                         if (IsAeroThemed())\r
2152                         {\r
2153                                 CRect rcSeparator = m_pMenuMetrics->GetSeperatorRect(pdis->rcItem);\r
2154                                 m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPSEPARATOR, 0, &rcSeparator, NULL);\r
2155                         }\r
2156                         else\r
2157                         {\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
2164                         }\r
2165                 }\r
2166                 else\r
2167                 {\r
2168                         // Draw the item background\r
2169                         DrawMenuItemBkgnd(pdis);\r
2170 \r
2171                         // Draw Checkmark or icon\r
2172                         if (pmid->mii.fState & MFS_CHECKED)\r
2173                                 DrawMenuItemCheckmark(pdis);\r
2174                         else\r
2175                                 DrawMenuItemIcon(pdis);\r
2176 \r
2177                         // Draw the text.\r
2178                         DrawMenuItemText(pdis);\r
2179                 }\r
2180 \r
2181                 if (IsAeroThemed())\r
2182                 {\r
2183                         // Draw the Submenu arrow\r
2184                         if (pmid->mii.hSubMenu)\r
2185                         {\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
2189                         }\r
2190 \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
2194                 }\r
2195 \r
2196                 DrawDC.Detach();\r
2197         }\r
2198 \r
2199         inline void CFrame::DrawMenuItemBkgnd(LPDRAWITEMSTRUCT pdis)\r
2200         {\r
2201                 // Draw the item background\r
2202                 CRect rcSelection = m_pMenuMetrics->GetSelectionRect(pdis->rcItem);\r
2203                 if (IsAeroThemed())\r
2204                 {\r
2205                         int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState);\r
2206                         m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPITEM, iStateId, &rcSelection, NULL);\r
2207                 }\r
2208                 else\r
2209                 {\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
2215 \r
2216                         if ((bSelected) && (!bDisabled))\r
2217                         {\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
2222                         }\r
2223                         else\r
2224                         {\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
2228                         }\r
2229                 }\r
2230         }\r
2231 \r
2232         inline void CFrame::DrawMenuItemCheckmark(LPDRAWITEMSTRUCT pdis)\r
2233         // Draws the checkmark or radiocheck transparently\r
2234         {\r
2235                 CRect rc = pdis->rcItem;\r
2236                 UINT fType = ((MenuItemData*)pdis->itemData)->mii.fType;\r
2237                 MenuTheme tm = GetMenuTheme();\r
2238                 CRect rcBk;\r
2239                 CDC* pDrawDC = FromHandle(pdis->hDC);\r
2240 \r
2241                 if (IsAeroThemed())\r
2242                 {\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
2249                 }\r
2250                 else\r
2251                 {\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
2258 \r
2259                         pDrawDC->CreateSolidBrush(tm.clrHot2);\r
2260                         pDrawDC->CreatePen(PS_SOLID, 1, tm.clrOutline);\r
2261 \r
2262                         // Draw the checkmark's background rectangle\r
2263                         pDrawDC->Rectangle(rcBk.left, rcBk.top, rcBk.right, rcBk.bottom);\r
2264 \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
2270 \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
2274                         else\r
2275                                 MemDC.DrawFrameControl(rcCheck, DFC_MENU, DFCS_MENUCHECK);\r
2276 \r
2277                         int xoffset = (rcBk.Width() - rcCheck.Width()-1)/2;\r
2278                         int yoffset = (rcBk.Height() - rcCheck.Height()-1)/2;\r
2279 \r
2280                         xoffset += 2;\r
2281 \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
2287 \r
2288                         if ((pdis->itemState & ODS_SELECTED))  // && (!tm.UseThemes))\r
2289                         {\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
2294                         }\r
2295                         else\r
2296                         {\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
2301                         }\r
2302                 }\r
2303         }\r
2304 \r
2305         inline void CFrame::DrawMenuItemIcon(LPDRAWITEMSTRUCT pdis)\r
2306         {\r
2307                 if (!m_himlMenu)\r
2308                         return;\r
2309 \r
2310                 // Get icon size\r
2311                 int Iconx = m_pMenuMetrics->m_sizeCheck.cx;\r
2312                 int Icony = m_pMenuMetrics->m_sizeCheck.cy;\r
2313 \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
2319 \r
2320                 // get the icon's location in the imagelist\r
2321                 int iImage = -1;\r
2322                 for (int i = 0 ; i < (int)m_vMenuIcons.size(); ++i)\r
2323                 {\r
2324                         if (pdis->itemID == m_vMenuIcons[i])\r
2325                                 iImage = i;\r
2326                 }\r
2327 \r
2328                 // draw the image\r
2329                 if (iImage >= 0 )\r
2330                 {\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
2334                         else\r
2335                                 ImageList_Draw(m_himlMenu, iImage, pdis->hDC, rc.left, rc.top, ILD_TRANSPARENT);\r
2336                 }\r
2337         }\r
2338 \r
2339         inline void CFrame::DrawMenuItemText(LPDRAWITEMSTRUCT pdis)\r
2340         {\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
2344 \r
2345                 // Calculate the text rect size\r
2346                 CRect rcText = m_pMenuMetrics->GetTextRect(pdis->rcItem);\r
2347 \r
2348                 // find the position of tab character\r
2349                 int nTab = -1;\r
2350                 for(int i = 0; i < lstrlen(ItemText); ++i)\r
2351                 {\r
2352                         if(_T('\t') == ItemText[i])\r
2353                         {\r
2354                                 nTab = i;\r
2355                                 break;\r
2356                         }\r
2357                 }\r
2358 \r
2359                 // Draw the item text\r
2360                 if (IsAeroThemed())\r
2361                 {\r
2362                         ULONG uAccel = ((pdis->itemState & ODS_NOACCEL) ? DT_HIDEPREFIX : 0);\r
2363                         int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState);\r
2364 \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
2367 \r
2368                         // Draw text after tab, right aligned\r
2369                         if(nTab != -1)\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
2371                 }\r
2372                 else\r
2373                 {\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
2377 \r
2378                         // Draw text after tab, right aligned\r
2379                         if(nTab != -1)\r
2380                                 DrawText(pdis->hDC, &ItemText[nTab + 1], -1, rcText, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);\r
2381 \r
2382                         SetBkMode(pdis->hDC, iMode);\r
2383                 }\r
2384         }\r
2385 \r
2386         inline int CFrame::GetMenuItemPos(HMENU hMenu, LPCTSTR szItem)\r
2387         // Returns the position of the menu item, given it's name\r
2388         {\r
2389                 int nMenuItemCount = GetMenuItemCount(hMenu);\r
2390                 MENUITEMINFO mii = {0};\r
2391                 mii.cbSize = GetSizeofMenuItemInfo();\r
2392 \r
2393                 for (int nItem = 0 ; nItem < nMenuItemCount; ++nItem)\r
2394                 {\r
2395                         std::vector<TCHAR> vTChar( MAX_MENU_STRING+1, _T('\0') );\r
2396                         TCHAR* szStr = &vTChar[0];\r
2397 \r
2398                         std::vector<TCHAR> vStripped( MAX_MENU_STRING+1, _T('\0') );\r
2399                         TCHAR* szStripped = &vStripped[0];\r
2400 \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
2405 \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
2408                         {\r
2409                                 // Strip out any & characters\r
2410                                 int j = 0;\r
2411                                 for (int i = 0; i < lstrlen(szStr); ++i)\r
2412                                 {\r
2413                                         if (szStr[i] != _T('&'))\r
2414                                                 szStripped[j++] = szStr[i];\r
2415                                 }\r
2416                                 szStripped[j] = _T('\0');       // Append null tchar\r
2417 \r
2418                                 // Compare the strings\r
2419                                 if (0 == lstrcmp(szStripped, szItem))\r
2420                                         return nItem;\r
2421                         }\r
2422                 }\r
2423 \r
2424                 return -1;\r
2425         }\r
2426 \r
2427         inline CString CFrame::GetMRUEntry(UINT nIndex)\r
2428         {\r
2429                 CString strPathName;\r
2430                 if (nIndex < m_vMRUEntries.size())\r
2431                 {\r
2432                         strPathName = m_vMRUEntries[nIndex];\r
2433 \r
2434                         // Now put the selected entry at Index 0\r
2435                         AddMRUEntry(strPathName);\r
2436                 }\r
2437                 return strPathName;\r
2438         }\r
2439 \r
2440         inline CRect CFrame::GetViewRect() const\r
2441         {\r
2442                 // Get the frame's client area\r
2443                 CRect rcFrame = GetClientRect();\r
2444 \r
2445                 // Get the statusbar's window area\r
2446                 CRect rcStatus;\r
2447                 if (GetStatusBar().IsWindowVisible() || !IsWindowVisible())\r
2448                         rcStatus = GetStatusBar().GetWindowRect();\r
2449 \r
2450                 // Get the top rebar or toolbar's window area\r
2451                 CRect rcTop;\r
2452                 if (IsReBarSupported() && m_bUseReBar)\r
2453                         rcTop = GetReBar().GetWindowRect();\r
2454                 else\r
2455                         if (GetToolBar().IsWindow() && GetToolBar().IsWindowVisible())\r
2456                                 rcTop = GetToolBar().GetWindowRect();\r
2457 \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
2465 \r
2466                 CRect rcView(left, top, right, bottom);\r
2467                 return rcView;\r
2468         }\r
2469 \r
2470         inline CString CFrame::GetThemeName() const\r
2471         {\r
2472                 // Returns the XP theme name\r
2473                 HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll"));\r
2474                 WCHAR ThemeName[31] = L"";\r
2475                 if(hMod)\r
2476                 {\r
2477                         typedef HRESULT (__stdcall *PFNGETCURRENTTHEMENAME)(LPWSTR pszThemeFileName, int cchMaxNameChars,\r
2478                                 LPWSTR pszColorBuff, int cchMaxColorChars, LPWSTR pszSizeBuff, int cchMaxSizeChars);\r
2479 \r
2480                         PFNGETCURRENTTHEMENAME pfn = (PFNGETCURRENTTHEMENAME)GetProcAddress(hMod, "GetCurrentThemeName");\r
2481                         (*pfn)(0, 0, ThemeName, 30, 0, 0);\r
2482 \r
2483                         ::FreeLibrary(hMod);\r
2484                 }\r
2485 \r
2486                 return CString(ThemeName);\r
2487         }\r
2488 \r
2489         inline void CFrame::LoadCommonControls()\r
2490         {\r
2491                 HMODULE hComCtl;\r
2492 \r
2493                 try\r
2494                 {\r
2495                         // Load the Common Controls DLL\r
2496                         hComCtl = ::LoadLibrary(_T("COMCTL32.DLL"));\r
2497                         if (!hComCtl)\r
2498                                 throw CWinException(_T("Failed to load COMCTL32.DLL"));\r
2499 \r
2500                         if (GetComCtlVersion() > 470)\r
2501                         {\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
2505 \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
2511 \r
2512                                 // Call InitCommonControlsEx\r
2513                                 if(!((*pfnInit)(&InitStruct)))\r
2514                                         throw CWinException(_T("InitCommonControlsEx failed"));\r
2515                         }\r
2516                         else\r
2517                         {\r
2518                                 ::InitCommonControls();\r
2519                         }\r
2520 \r
2521                         ::FreeLibrary(hComCtl);\r
2522                 }\r
2523 \r
2524                 catch (const CWinException &e)\r
2525                 {\r
2526                         e.what();\r
2527                         if (hComCtl)\r
2528                                 ::FreeLibrary(hComCtl);\r
2529 \r
2530                         throw;\r
2531                 }\r
2532         }\r
2533 \r
2534         inline BOOL CFrame::LoadRegistryMRUSettings(UINT nMaxMRU /*= 0*/)\r
2535         {\r
2536                 // Load the MRU list from the registry\r
2537 \r
2538                 assert(!m_strKeyName.IsEmpty()); // KeyName must be set before calling LoadRegistryMRUSettings\r
2539                 HKEY hKey = NULL;\r
2540                 BOOL bRet = FALSE;\r
2541 \r
2542                 try\r
2543                 {\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
2547 \r
2548                         if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey))\r
2549                         {\r
2550                                 for (UINT i = 0; i < m_nMaxMRU; ++i)\r
2551                                 {\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
2556 \r
2557                                         if (ERROR_SUCCESS != RegQueryValueEx(hKey, szSubKey, NULL, &dwType, NULL, &dwBufferSize))\r
2558                                                 throw CWinException(_T("RegQueryValueEx failed\n"));\r
2559 \r
2560                                         std::vector<TCHAR> PathName( dwBufferSize, _T('\0') );\r
2561                                         TCHAR* pTCharArray = &PathName[0];\r
2562 \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
2566 \r
2567                                         if ( lstrlen( pTCharArray ) )\r
2568                                                 vMRUEntries.push_back( pTCharArray );\r
2569                                 }\r
2570 \r
2571                                 // successfully loaded all MRU values, so store them\r
2572                                 m_vMRUEntries = vMRUEntries;\r
2573                                 RegCloseKey(hKey);\r
2574                                 bRet = TRUE;\r
2575                         }\r
2576                 }\r
2577 \r
2578                 catch(const CWinException& e)\r
2579                 {\r
2580                         TRACE(_T("Failed to load MRU values from registry\n"));\r
2581                         e.what();\r
2582 \r
2583                         if (hKey)\r
2584                                 RegCloseKey(hKey);\r
2585                 }\r
2586 \r
2587                 return bRet;\r
2588         }\r
2589 \r
2590         inline BOOL CFrame::LoadRegistrySettings(LPCTSTR szKeyName)\r
2591         {\r
2592                 assert (NULL != szKeyName);\r
2593                 m_strKeyName = szKeyName;\r
2594 \r
2595                 CString strKey = _T("Software\\") + m_strKeyName + _T("\\Frame Settings");\r
2596                 HKEY hKey = 0;\r
2597                 BOOL bRet = FALSE;\r
2598 \r
2599                 try\r
2600                 {\r
2601                         if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey))\r
2602                         {\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
2618 \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
2625 \r
2626                                 RegCloseKey(hKey);\r
2627                                 bRet = TRUE;\r
2628                         }\r
2629                 }\r
2630 \r
2631                 catch (const CWinException& e)\r
2632                 {\r
2633                         TRACE(_T("Failed to load values from registry, using defaults!\n"));\r
2634                         e.what();\r
2635 \r
2636                         if (hKey)\r
2637                                 RegCloseKey(hKey);\r
2638                 }\r
2639 \r
2640                 return bRet;\r
2641         }\r
2642 \r
2643         inline void CFrame::MeasureMenuItem(MEASUREITEMSTRUCT *pmis)\r
2644         {\r
2645                 int cxTotal = 0;\r
2646                 int cyMax = 0;\r
2647 \r
2648                 MenuItemData* pmid = (MenuItemData*)pmis->itemData;\r
2649                 assert(::IsMenu(pmid->hMenu));  // Does itemData contain a valid MenuItemData struct?\r
2650 \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
2653 \r
2654                 if (pmid->mii.fType & MFT_SEPARATOR)\r
2655                 {\r
2656                         // separator height\r
2657                         cyMax = m_pMenuMetrics->m_sizeSeparator.cy + m_pMenuMetrics->m_marItem.Height();\r
2658                 }\r
2659                 else\r
2660                 {\r
2661                         // Add check background horizontal padding.\r
2662                         cxTotal += m_pMenuMetrics->m_marCheckBackground.cxLeftWidth + m_pMenuMetrics->m_marCheckBackground.cxRightWidth;\r
2663 \r
2664                         // Add selection margin padding.\r
2665                         cxTotal += m_pMenuMetrics->m_marItem.cxLeftWidth + m_pMenuMetrics->m_marItem.cxRightWidth;\r
2666 \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
2671 \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
2674                 }\r
2675 \r
2676                 // Return the composite sizes.\r
2677                 pmis->itemWidth = cxTotal;\r
2678                 pmis->itemHeight = cyMax;\r
2679         }\r
2680 \r
2681         inline void CFrame::OnActivate(WPARAM wParam, LPARAM lParam)\r
2682         {\r
2683                 // Do default processing first\r
2684                 DefWindowProc(WM_ACTIVATE, wParam, lParam);\r
2685 \r
2686                 if (LOWORD(wParam) == WA_INACTIVE)\r
2687                 {\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
2691 \r
2692                         // Send a notification to the view window\r
2693                         int idCtrl = ::GetDlgCtrlID(m_hOldFocus);\r
2694                         NMHDR nhdr={0};\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
2700                 }\r
2701                 else\r
2702                 {\r
2703                         // Now set the focus to the appropriate child window\r
2704                         if (m_hOldFocus) ::SetFocus(m_hOldFocus);\r
2705 \r
2706                         // Send a notification to the view window\r
2707                         int idCtrl = ::GetDlgCtrlID(m_hOldFocus);\r
2708                         NMHDR nhdr={0};\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
2714                 }\r
2715         }\r
2716 \r
2717         inline void CFrame::OnClose()\r
2718         {\r
2719                 // Called in response to a WM_CLOSE message for the frame.\r
2720                 ShowWindow(SW_HIDE);\r
2721                 SaveRegistrySettings();\r
2722 \r
2723                 GetMenuBar().Destroy();\r
2724                 GetToolBar().Destroy();\r
2725                 GetReBar().Destroy();\r
2726                 GetStatusBar().Destroy();\r
2727                 GetView()->Destroy();\r
2728         }\r
2729 \r
2730         inline void CFrame::OnCreate()\r
2731         {\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
2734 \r
2735                 // Set the icon\r
2736                 SetIconLarge(IDW_MAIN);\r
2737                 SetIconSmall(IDW_MAIN);\r
2738 \r
2739                 // Set the keyboard accelerators\r
2740                 m_hAccel = LoadAccelerators(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_MAIN));\r
2741                 GetApp()->SetAccelerators(m_hAccel, this);\r
2742 \r
2743                 // Set the Caption\r
2744                 SetWindowText(LoadString(IDW_MAIN));\r
2745 \r
2746                 // Set the theme for the frame elements\r
2747                 SetTheme();\r
2748 \r
2749                 // Create the rebar and menubar\r
2750                 if (IsReBarSupported() && m_bUseReBar)\r
2751                 {\r
2752                         // Create the rebar\r
2753                         GetReBar().Create(this);\r
2754 \r
2755                         // Create the menu inside rebar\r
2756                         GetMenuBar().Create(&GetReBar());\r
2757                         AddMenuBarBand();\r
2758                 }\r
2759 \r
2760                 // Setup the menu\r
2761                 SetFrameMenu(IDW_MAIN);\r
2762                 m_pMenuMetrics = new CMenuMetrics(this);\r
2763 \r
2764                 UpdateMRUMenu();\r
2765 \r
2766                 // Create the ToolBar\r
2767                 if (m_bUseToolBar)\r
2768                 {\r
2769                         CreateToolBar();\r
2770                         ShowToolBar(m_bShowToolBar);\r
2771                 }\r
2772                 else\r
2773                 {\r
2774                         GetFrameMenu().CheckMenuItem(IDW_VIEW_TOOLBAR, MF_UNCHECKED);\r
2775                         GetFrameMenu().EnableMenuItem(IDW_VIEW_TOOLBAR, MF_GRAYED);\r
2776                 }\r
2777 \r
2778                 // Create the status bar\r
2779                 GetStatusBar().Create(this);\r
2780                 GetStatusBar().SetFont(&m_fntStatusBar, FALSE);\r
2781                 ShowStatusBar(m_bShowStatusBar);\r
2782 \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
2786 \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
2790 \r
2791                 // Start timer for Status updates\r
2792                 if (m_bShowIndicatorStatus || m_bShowMenuStatus)\r
2793                         SetTimer(ID_STATUS_TIMER, 200, NULL);\r
2794 \r
2795                 // Reposition the child windows\r
2796                 OnSysColorChange();\r
2797                 RecalcLayout();\r
2798         }\r
2799 \r
2800         inline void CFrame::OnDestroy()\r
2801         {\r
2802                 SetMenu(NULL);\r
2803                 KillTimer(ID_STATUS_TIMER);\r
2804                 ::PostQuitMessage(0);   // Terminates the application\r
2805         }\r
2806 \r
2807         inline LRESULT CFrame::OnDrawItem(WPARAM wParam, LPARAM lParam)\r
2808         // OwnerDraw is used to render the popup menu items\r
2809         {\r
2810                 LPDRAWITEMSTRUCT pdis = (LPDRAWITEMSTRUCT) lParam;\r
2811                 if (pdis->CtlType != ODT_MENU)\r
2812                         return CWnd::WndProcDefault(WM_DRAWITEM, wParam, lParam);\r
2813 \r
2814                 if (!IsRectEmpty(&pdis->rcItem))\r
2815                         DrawMenuItem(pdis);\r
2816 \r
2817                 return TRUE;\r
2818         }\r
2819 \r
2820         inline void CFrame::OnExitMenuLoop()\r
2821         {\r
2822                 if (m_bUseThemes)\r
2823                 {\r
2824                         for (UINT nItem = 0; nItem < m_vMenuItemData.size(); ++nItem)\r
2825                         {\r
2826                                 // Undo OwnerDraw and put the text back\r
2827                                 MENUITEMINFO mii = {0};\r
2828                                 mii.cbSize = GetSizeofMenuItemInfo();\r
2829 \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
2836                         }\r
2837 \r
2838                         m_vMenuItemData.clear();\r
2839                 }\r
2840         }\r
2841 \r
2842         inline void CFrame::OnHelp()\r
2843         {\r
2844                 // Ensure only one dialog displayed even for multiple hits of the F1 button\r
2845                 if (!m_AboutDialog.IsWindow())\r
2846                 {\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
2851 \r
2852                         m_AboutDialog.SetDlgParent(this);\r
2853                         m_AboutDialog.DoModal();\r
2854 \r
2855                         ::SetFocus(hPrevFocus);\r
2856                 }\r
2857         }\r
2858 \r
2859         inline void CFrame::OnInitMenuPopup(WPARAM wParam, LPARAM lParam)\r
2860         {\r
2861                 // The system menu shouldn't be owner drawn\r
2862                 if (HIWORD(lParam)) return;\r
2863 \r
2864                 if (m_bUseThemes)\r
2865                 {\r
2866                         CMenu* pMenu = FromHandle((HMENU)wParam);\r
2867 \r
2868                         for (UINT i = 0; i < pMenu->GetMenuItemCount(); ++i)\r
2869                         {\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
2872 \r
2873                                 MENUITEMINFO mii = {0};\r
2874                                 mii.cbSize = GetSizeofMenuItemInfo();\r
2875 \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
2880 \r
2881                                 // Send message for menu updates\r
2882                                 UINT menuItem = pMenu->GetMenuItemID(i);\r
2883                                 SendMessage(UWM_UPDATE_COMMAND, (WPARAM)menuItem, 0);\r
2884 \r
2885                                 // Specify owner-draw for the menu item type\r
2886                                 if (pMenu->GetMenuItemInfo(i, &mii, TRUE))\r
2887                                 {\r
2888                                         if (0 == mii.dwItemData)\r
2889                                         {\r
2890                                                 pItem->hMenu = *pMenu;\r
2891                                                 pItem->nPos = i;\r
2892                                                 pItem->mii = mii;\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
2896                                         }\r
2897                                 }\r
2898                         }\r
2899                 }\r
2900         }\r
2901 \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
2905         {\r
2906                 LPMEASUREITEMSTRUCT pmis = (LPMEASUREITEMSTRUCT) lParam;\r
2907                 if (pmis->CtlType != ODT_MENU)\r
2908                         return CWnd::WndProcDefault(WM_MEASUREITEM, wParam, lParam);\r
2909 \r
2910                 MeasureMenuItem(pmis);\r
2911                 return TRUE;\r
2912         }\r
2913 \r
2914         inline LRESULT CFrame::OnMenuChar(WPARAM wParam, LPARAM lParam)\r
2915         {\r
2916                 if ((IsMenuBarUsed()) && (LOWORD(wParam)!= VK_SPACE))\r
2917                 {\r
2918                         // Activate MenuBar for key pressed with Alt key held down\r
2919                         GetMenuBar().OnMenuChar(wParam, lParam);\r
2920                         return -1L;\r
2921                 }\r
2922                 return CWnd::WndProcDefault(WM_MENUCHAR, wParam, lParam);\r
2923         }\r
2924 \r
2925         inline void CFrame::OnMenuSelect(WPARAM wParam, LPARAM lParam)\r
2926         {\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
2930                 {\r
2931                         int nID = LOWORD (wParam);\r
2932                         CMenu* pMenu = FromHandle((HMENU) lParam);\r
2933 \r
2934                         if ((pMenu != GetMenu()) && (nID != 0) && !(HIWORD(wParam) & MF_POPUP))\r
2935                                 m_strStatusText = LoadString(nID);\r
2936                         else\r
2937                                 m_strStatusText = _T("Ready");\r
2938 \r
2939                         SetStatusText();\r
2940                 }\r
2941         }\r
2942 \r
2943         inline LRESULT CFrame::OnNotify(WPARAM wParam, LPARAM lParam)\r
2944         {\r
2945                 UNREFERENCED_PARAMETER(wParam);\r
2946 \r
2947                 switch (((LPNMHDR)lParam)->code)\r
2948                 {\r
2949                 case UWM_UNDOCKED:\r
2950                         m_hOldFocus = 0;\r
2951                         break;\r
2952                 case RBN_HEIGHTCHANGE:\r
2953                         RecalcLayout();\r
2954                         Invalidate();\r
2955                         break;\r
2956         //      case RBN_LAYOUTCHANGED:\r
2957         //              if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)\r
2958         //                      GetReBar().MoveBandsLeft();\r
2959         //              break;\r
2960                 case RBN_MINMAX:\r
2961                         if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().ShortBands)\r
2962                                 return 1L;      // Supress maximise or minimise rebar band\r
2963                         break;\r
2964 \r
2965                 // Display tooltips for the toolbar\r
2966                 case TTN_GETDISPINFO:\r
2967                         if (GetToolBar().IsWindow())\r
2968                         {\r
2969                                 CToolBar* pToolBar = 0;\r
2970                                 if (IsReBarUsed())\r
2971                                 {\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
2975                                         {\r
2976                                                 pToolBar = (CToolBar*)pWnd;\r
2977                                         }\r
2978                                 }\r
2979 \r
2980                                 if (pToolBar)\r
2981                                 {\r
2982                                         LPNMTTDISPINFO lpDispInfo = (LPNMTTDISPINFO)lParam;\r
2983                                         int iIndex =  pToolBar->HitTest();\r
2984                                         if (iIndex >= 0)\r
2985                                         {\r
2986                                                 int nID = pToolBar->GetCommandID(iIndex);\r
2987                                                 if (nID > 0)\r
2988                                                 {\r
2989                                                         m_strTooltip = LoadString(nID);\r
2990                                                         lpDispInfo->lpszText = (LPTSTR)m_strTooltip.c_str();\r
2991                                                 }\r
2992                                                 else\r
2993                                                         m_strTooltip = _T("");\r
2994                                         }\r
2995                                 }\r
2996                         }\r
2997                         break;\r
2998                 } // switch LPNMHDR\r
2999 \r
3000                 return 0L;\r
3001 \r
3002         } // CFrame::Onotify(...)\r
3003 \r
3004         inline void CFrame::OnSetFocus()\r
3005         {\r
3006                 SetStatusText();\r
3007         }\r
3008 \r
3009         inline void CFrame::OnSysColorChange()\r
3010         {\r
3011                 // Honour theme color changes\r
3012                 if (GetReBar().IsWindow())\r
3013                 {\r
3014                         for (int nBand = 0; nBand <= GetReBar().GetBandCount(); ++nBand)\r
3015                         {\r
3016                                 GetReBar().SetBandColor(nBand, GetSysColor(COLOR_BTNTEXT), GetSysColor(COLOR_BTNFACE));\r
3017                         }\r
3018                 }\r
3019 \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
3026                 SetStatusText();\r
3027 \r
3028 \r
3029                 if (GetMenuBar().IsWindow())\r
3030                 {\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
3035 \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
3047                 }\r
3048 \r
3049                 if (m_XPThemeName != GetThemeName())\r
3050                         SetTheme();\r
3051                 m_pMenuMetrics->Initialize();\r
3052 \r
3053                 // Reposition and redraw everything\r
3054                 RecalcLayout();\r
3055                 RedrawWindow(NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);\r
3056 \r
3057                 // Forward the message to the view window\r
3058                 m_pView->PostMessage(WM_SYSCOLORCHANGE, 0L, 0L);\r
3059         }\r
3060 \r
3061         inline LRESULT CFrame::OnSysCommand(WPARAM wParam, LPARAM lParam)\r
3062         {\r
3063                 if ((SC_KEYMENU == wParam) && (VK_SPACE != lParam) && IsMenuBarUsed())\r
3064                 {\r
3065                         GetMenuBar().OnSysCommand(wParam, lParam);\r
3066                         return 0L;\r
3067                 }\r
3068 \r
3069                 if (SC_MINIMIZE == wParam)\r
3070                         m_hOldFocus = ::GetFocus();\r
3071 \r
3072                 return CWnd::WndProcDefault(WM_SYSCOMMAND, wParam, lParam);\r
3073         }\r
3074 \r
3075         inline void CFrame::OnTimer(WPARAM wParam)\r
3076         {\r
3077                 if (ID_STATUS_TIMER == wParam)\r
3078                 {\r
3079                         if (m_bShowMenuStatus)\r
3080                         {\r
3081                                 // Get the toolbar the point is over\r
3082                                 CToolBar* pToolBar = 0;\r
3083                                 if (IsReBarUsed())\r
3084                                 {\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
3089                                 }\r
3090                                 else\r
3091                                 {\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
3096                                 }\r
3097 \r
3098                                 if ((pToolBar) && (WindowFromPoint(GetCursorPos()) == pToolBar))\r
3099                                 {\r
3100                                         // Which toolbar button is the mouse cursor hovering over?\r
3101                                         int nButton = pToolBar->HitTest();\r
3102                                         if (nButton >= 0)\r
3103                                         {\r
3104                                                 int nID = pToolBar->GetCommandID(nButton);\r
3105                                                 // Only update the statusbar if things have changed\r
3106                                                 if (nID != m_nOldID)\r
3107                                                 {\r
3108                                                         if (nID != 0)\r
3109                                                                 m_strStatusText = LoadString(nID);\r
3110                                                         else\r
3111                                                                 m_strStatusText = _T("Ready");\r
3112 \r
3113                                                         if (GetStatusBar().IsWindow())\r
3114                                                                 SetStatusText();\r
3115                                                 }\r
3116                                                 m_nOldID = nID;\r
3117                                         }\r
3118                                 }\r
3119                                 else\r
3120                                 {\r
3121                                         if (m_nOldID != -1)\r
3122                                         {\r
3123                                                 m_strStatusText = _T("Ready");\r
3124                                                 SetStatusText();\r
3125                                         }\r
3126                                         m_nOldID = -1;\r
3127                                 }\r
3128                         }\r
3129 \r
3130                         if (m_bShowIndicatorStatus)\r
3131                                 SetStatusIndicators();\r
3132                 }\r
3133         }\r
3134 \r
3135         inline void CFrame::OnViewStatusBar()\r
3136         {\r
3137                 m_bShowStatusBar = !m_bShowStatusBar;\r
3138                 ShowStatusBar(m_bShowStatusBar);\r
3139         }\r
3140 \r
3141         inline void CFrame::OnViewToolBar()\r
3142         {\r
3143                 m_bShowToolBar = !m_bShowToolBar;\r
3144                 ShowToolBar(m_bShowToolBar);\r
3145         }\r
3146 \r
3147         inline void CFrame::PreCreate(CREATESTRUCT& cs)\r
3148         {\r
3149                 // Set the frame window styles\r
3150                 cs.style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;\r
3151 \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
3157         }\r
3158 \r
3159         inline void CFrame::PreRegisterClass(WNDCLASS &wc)\r
3160         {\r
3161                 // Set the Window Class\r
3162                 wc.lpszClassName =  _T("Win32++ Frame");\r
3163         }\r
3164 \r
3165         inline void CFrame::RecalcLayout()\r
3166         {\r
3167                 CWnd* pView = GetView();\r
3168                 if ((!pView) || (!pView->GetHwnd()))\r
3169                         return;\r
3170 \r
3171                 // Resize the status bar\r
3172                 if (GetStatusBar().IsWindow() && m_bShowStatusBar)\r
3173                 {\r
3174                         GetStatusBar().SetWindowPos(NULL, 0, 0, 0, 0, SWP_SHOWWINDOW);\r
3175                         GetStatusBar().Invalidate();\r
3176                         SetStatusText();\r
3177                 }\r
3178 \r
3179                 // Resize the rebar or toolbar\r
3180                 if (IsReBarUsed())\r
3181                 {\r
3182                         GetReBar().SendMessage(WM_SIZE, 0L, 0L);\r
3183                         GetReBar().Invalidate();\r
3184                 }\r
3185                 else if (m_bUseToolBar && m_bShowToolBar)\r
3186                         GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);\r
3187 \r
3188                 // Resize the View window\r
3189                 CRect rClient = GetViewRect();\r
3190                 if ((rClient.bottom - rClient.top) >= 0)\r
3191                 {\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
3196 \r
3197                         pView->SetWindowPos( NULL, x, y, cx, cy, SWP_SHOWWINDOW|SWP_ASYNCWINDOWPOS );\r
3198                 }\r
3199 \r
3200                 // Adjust rebar bands\r
3201                 if (IsReBarUsed())\r
3202                 {\r
3203                         if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)\r
3204                                 GetReBar().MoveBandsLeft();\r
3205 \r
3206                         if (IsMenuBarUsed())\r
3207                                 SetMenuBarBandSize();\r
3208                 }\r
3209         }\r
3210 \r
3211         inline void CFrame::RemoveMRUEntry(LPCTSTR szMRUEntry)\r
3212         {\r
3213                 std::vector<CString>::iterator it;\r
3214                 for (it = m_vMRUEntries.begin(); it != m_vMRUEntries.end(); ++it)\r
3215                 {\r
3216                         if ((*it) == szMRUEntry)\r
3217                         {\r
3218                                 m_vMRUEntries.erase(it);\r
3219                                 break;\r
3220                         }\r
3221                 }\r
3222 \r
3223                 UpdateMRUMenu();\r
3224         }\r
3225 \r
3226         inline BOOL CFrame::SaveRegistrySettings()\r
3227         {\r
3228                 // Store the window position in the registry\r
3229                 if (!m_strKeyName.IsEmpty())\r
3230                 {\r
3231                         CString strKeyName = _T("Software\\") + m_strKeyName + _T("\\Frame Settings");\r
3232                         HKEY hKey = NULL;\r
3233 \r
3234                         try\r
3235                         {\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
3238 \r
3239                                 WINDOWPLACEMENT Wndpl = {0};\r
3240                                 Wndpl.length = sizeof(WINDOWPLACEMENT);\r
3241 \r
3242                                 if (GetWindowPlacement(Wndpl))\r
3243                                 {\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
3250 \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
3259                                 }\r
3260 \r
3261                                 // Store the ToolBar and statusbar states\r
3262                                 DWORD dwShowToolBar = m_bShowToolBar;\r
3263                                 DWORD dwShowStatusBar = m_bShowStatusBar;\r
3264 \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
3269 \r
3270                                 RegCloseKey(hKey);\r
3271                         }\r
3272 \r
3273                         catch (const CWinException& e)\r
3274                         {\r
3275                                 TRACE(_T("Failed to save registry settings\n"));\r
3276 \r
3277                                 if (hKey)\r
3278                                 {\r
3279                                         // Roll back the registry changes by deleting this subkey\r
3280                                         RegDeleteKey(HKEY_CURRENT_USER ,strKeyName);\r
3281                                         RegCloseKey(hKey);\r
3282                                 }\r
3283 \r
3284                                 e.what();\r
3285                                 return FALSE;\r
3286                         }\r
3287 \r
3288                         // Store the MRU entries in the registry\r
3289                         if (m_nMaxMRU > 0)\r
3290                         {\r
3291                                 CString strKeyName = _T("Software\\") + m_strKeyName + _T("\\Recent Files");\r
3292                                 HKEY hKey = NULL;\r
3293 \r
3294                                 try\r
3295                                 {\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
3298 \r
3299                                         for (UINT i = 0; i < m_nMaxMRU; ++i)\r
3300                                         {\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
3306 \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
3309                                         }\r
3310 \r
3311                                         RegCloseKey(hKey);\r
3312                                 }\r
3313 \r
3314                                 catch (const CWinException& e)\r
3315                                 {\r
3316                                         TRACE(_T("Failed to save registry MRU settings\n"));\r
3317 \r
3318                                         if (hKey)\r
3319                                         {\r
3320                                                 // Roll back the registry changes by deleting this subkey\r
3321                                                 RegDeleteKey(HKEY_CURRENT_USER ,strKeyName);\r
3322                                                 RegCloseKey(hKey);\r
3323                                         }\r
3324 \r
3325                                         e.what();\r
3326                                         return FALSE;\r
3327                                 }\r
3328                         }\r
3329                 }\r
3330 \r
3331                 return TRUE;\r
3332         }\r
3333 \r
3334         inline void CFrame::SetFrameMenu(INT ID_MENU)\r
3335         {\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
3338                 HMENU hMenu = 0;\r
3339                 if (ID_MENU != 0)\r
3340                 {\r
3341                 // Sets the frame's menu from a resource ID.\r
3342                         hMenu = ::LoadMenu(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(ID_MENU));\r
3343                         assert (hMenu);\r
3344                 }\r
3345 \r
3346                 SetFrameMenu(hMenu);\r
3347         }\r
3348 \r
3349         inline void CFrame::SetFrameMenu(HMENU hMenu)\r
3350         {\r
3351                 // Sets the frame's menu from a HMENU.\r
3352                 m_Menu.Attach(hMenu);\r
3353 \r
3354                 if (IsMenuBarUsed())\r
3355                 {\r
3356                         GetMenuBar().SetMenu(GetFrameMenu());\r
3357                         BOOL bShow = (hMenu != NULL);   // boolean expression\r
3358                         ShowMenu(bShow);\r
3359                 }\r
3360                 else\r
3361                         SetMenu(&m_Menu);\r
3362         }\r
3363 \r
3364         inline UINT CFrame::SetMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID)\r
3365         {\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
3372 \r
3373                 // Exit if no ToolBarID is specified\r
3374                 if (ToolBarID == 0) return 0;\r
3375 \r
3376                 // Add the menu icons from the bitmap IDs\r
3377                 return AddMenuIcons(MenuData, crMask, ToolBarID, ToolBarDisabledID);\r
3378         }\r
3379 \r
3380         inline void CFrame::SetMenuBarBandSize()\r
3381         {\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
3384 \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
3389 \r
3390                 REBARBANDINFO rbbi = {0};\r
3391                 rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_SIZE;\r
3392                 RB.GetBandInfo(nBand, rbbi);\r
3393 \r
3394                 int Width;\r
3395                 if ((GetReBar().GetReBarTheme().UseThemes) && (GetReBar().GetReBarTheme().LockMenuBand))\r
3396                         Width = rcClient.Width() - rcBorder.Width() - 2;\r
3397                 else\r
3398                         Width = GetMenuBar().GetMaxSize().cx;\r
3399 \r
3400                 rbbi.cxMinChild = Width;\r
3401                 rbbi.cx         = Width;\r
3402 \r
3403                 RB.SetBandInfo(nBand, rbbi);\r
3404         }\r
3405 \r
3406         inline void CFrame::SetMenuTheme(MenuTheme& Theme)\r
3407         {\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
3414 \r
3415                 GetMenuBar().SetMenuBarTheme(Theme); // Sets the theme for MenuBar buttons\r
3416                 Invalidate();\r
3417         }\r
3418 \r
3419         inline void CFrame::SetStatusIndicators()\r
3420         {\r
3421                 if (::IsWindow(GetStatusBar()))\r
3422                 {\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
3426 \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
3431 \r
3432                         m_OldStatus[0] = Status1;\r
3433                         m_OldStatus[1] = Status2;\r
3434                         m_OldStatus[2] = Status3;\r
3435                 }\r
3436         }\r
3437 \r
3438         inline void CFrame::SetStatusText()\r
3439         {\r
3440                 if (::IsWindow(GetStatusBar()))\r
3441                 {\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
3447 \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
3451 \r
3452                         if (m_bShowIndicatorStatus)\r
3453                         {\r
3454                                 // Create 4 panes\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
3459 \r
3460                                 SetStatusIndicators();\r
3461                         }\r
3462 \r
3463                         // Place text in the 1st pane\r
3464                         GetStatusBar().SetPartText(0, m_strStatusText);\r
3465                 }\r
3466         }\r
3467 \r
3468         inline void CFrame::SetTheme()\r
3469         {\r
3470                 // Note: To modify theme colors, override this function in CMainframe,\r
3471                 //        and make any modifications there.\r
3472 \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
3477 \r
3478                 BOOL T = TRUE;\r
3479                 BOOL F = FALSE;\r
3480 \r
3481                 if (m_bUseThemes)\r
3482                 {\r
3483                         // Retrieve the XP theme name\r
3484                         m_XPThemeName = GetThemeName();\r
3485 \r
3486                         enum Themetype{ Modern, Grey, Blue, Silver, Olive };\r
3487 \r
3488                         int Theme = Grey;\r
3489                         if (GetWinVersion() < 2600) // Not for Vista and above\r
3490                         {\r
3491                                 if (m_XPThemeName == _T("NormalColor"))\r
3492                                         Theme = Blue;\r
3493                                 if (m_XPThemeName == _T("Metallic"))\r
3494                                         Theme = Silver;\r
3495                                 if (m_XPThemeName == _T("HomeStead"))\r
3496                                         Theme = Olive;\r
3497                         }\r
3498                         else\r
3499                                 Theme = Modern;\r
3500 \r
3501                         switch (Theme)\r
3502                         {\r
3503                         case Modern:\r
3504                                 {\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
3508 \r
3509                                         GetToolBar().SetToolBarTheme(tt);\r
3510                                         SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar\r
3511 \r
3512                                         GetReBar().SetReBarTheme(tr);\r
3513                                 }\r
3514                                 break;\r
3515 \r
3516                         case Grey:      // A color scheme suitable for 16 bit colors. Suitable for Windows older than XP.\r
3517                                 {\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
3521 \r
3522                                         GetToolBar().SetToolBarTheme(tt);\r
3523                                         SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar\r
3524 \r
3525                                         GetReBar().SetReBarTheme(tr);\r
3526                                 }\r
3527                                 break;\r
3528                         case Blue:\r
3529                                 {\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
3534 \r
3535                                         GetToolBar().SetToolBarTheme(tt);\r
3536                                         SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar\r
3537 \r
3538                                         GetReBar().SetReBarTheme(tr);\r
3539                                 }\r
3540                                 break;\r
3541 \r
3542                         case Silver:\r
3543                                 {\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
3548 \r
3549                                         GetToolBar().SetToolBarTheme(tt);\r
3550                                         SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar\r
3551 \r
3552                                         GetReBar().SetReBarTheme(tr);\r
3553                                 }\r
3554                                 break;\r
3555 \r
3556                         case Olive:\r
3557                                 {\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
3562 \r
3563                                         GetToolBar().SetToolBarTheme(tt);\r
3564                                         SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar\r
3565 \r
3566                                         GetReBar().SetReBarTheme(tr);\r
3567                                 }\r
3568                                 break;\r
3569                         }\r
3570                 }\r
3571                 else\r
3572                 {\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
3576                 }\r
3577 \r
3578                 RecalcLayout();\r
3579         }\r
3580 \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
3589         {\r
3590                 GetToolBar().SetImages(crMask, ToolBarID, ToolBarHotID, ToolBarDisabledID);\r
3591         }\r
3592 \r
3593         inline void CFrame::SetupToolBar()\r
3594         {\r
3595                 // Use this function to set the Resource IDs for the toolbar(s).\r
3596 \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
3609 */\r
3610         }\r
3611 \r
3612         inline void CFrame::SetView(CWnd& wndView)\r
3613         // Sets or changes the View window displayed within the frame\r
3614         {\r
3615                 if (m_pView != &wndView)\r
3616                 {\r
3617                         // Destroy the existing view window (if any)\r
3618                         if (m_pView) m_pView->Destroy();\r
3619 \r
3620                         // Assign the view window\r
3621                         m_pView = &wndView;\r
3622 \r
3623                         if (m_hWnd)\r
3624                         {\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
3628                                 RecalcLayout();\r
3629                         }\r
3630                 }\r
3631         }\r
3632 \r
3633         inline void CFrame::ShowMenu(BOOL bShow)\r
3634         {\r
3635                 if (bShow)\r
3636                 {\r
3637                         if (IsReBarUsed())\r
3638                                 GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetMenuBar()), TRUE);\r
3639                         else\r
3640                                 SetMenu(&m_Menu);\r
3641                 }\r
3642                 else\r
3643                 {\r
3644                         if (IsReBarUsed())\r
3645                                 GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetMenuBar()), FALSE);\r
3646                         else\r
3647                                 SetMenu(NULL);\r
3648                 }\r
3649 \r
3650                 if (GetReBar().IsWindow())\r
3651                 {\r
3652                         if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)\r
3653                                 GetReBar().MoveBandsLeft();\r
3654                 }\r
3655 \r
3656                 // Reposition the Windows\r
3657                 RecalcLayout();\r
3658         }\r
3659 \r
3660 \r
3661 \r
3662         inline void CFrame::ShowStatusBar(BOOL bShow)\r
3663         {\r
3664                 if (bShow)\r
3665                 {\r
3666                         m_Menu.CheckMenuItem(IDW_VIEW_STATUSBAR, MF_CHECKED);\r
3667                         GetStatusBar().ShowWindow(SW_SHOW);\r
3668                         m_bShowStatusBar = TRUE;\r
3669                 }\r
3670                 else\r
3671                 {\r
3672                         m_Menu.CheckMenuItem(IDW_VIEW_STATUSBAR, MF_UNCHECKED);\r
3673                         GetStatusBar().ShowWindow(SW_HIDE);\r
3674                         m_bShowStatusBar = FALSE;\r
3675                 }\r
3676 \r
3677                 // Reposition the Windows\r
3678                 RecalcLayout();\r
3679         }\r
3680 \r
3681         inline void CFrame::ShowToolBar(BOOL bShow)\r
3682         {\r
3683                 if (bShow)\r
3684                 {\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
3688                         else\r
3689                                 GetToolBar().ShowWindow(SW_SHOW);\r
3690                         m_bShowToolBar = TRUE;\r
3691                 }\r
3692                 else\r
3693                 {\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
3697                         else\r
3698                                 GetToolBar().ShowWindow(SW_HIDE);\r
3699                         m_bShowToolBar = FALSE;\r
3700                 }\r
3701 \r
3702                 if (GetReBar().IsWindow())\r
3703                 {\r
3704                         if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)\r
3705                                 GetReBar().MoveBandsLeft();\r
3706                 }\r
3707 \r
3708                 // Reposition the Windows\r
3709                 RecalcLayout();\r
3710         }\r
3711 \r
3712         inline void CFrame::UpdateMRUMenu()\r
3713         {\r
3714                 if (0 >= m_nMaxMRU) return;\r
3715 \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
3720                 {\r
3721                         for (UINT n = 0; ((n < m_vMRUEntries.size()) && (n <= m_nMaxMRU)); ++n)\r
3722                         {\r
3723                                 strMRUArray[n] = m_vMRUEntries[n];\r
3724                                 if (strMRUArray[n].GetLength() > MAX_MENU_STRING - 10)\r
3725                                 {\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
3729                                 }\r
3730 \r
3731                                 // Prefix the string with its number\r
3732                                 TCHAR tVal[5];\r
3733                                 wsprintf(tVal, _T("%d "), n+1);\r
3734                                 strMRUArray[n] = tVal + strMRUArray[n];\r
3735                                 MaxMRUArrayIndex = n;\r
3736                         }\r
3737                 }\r
3738                 else\r
3739                 {\r
3740                         strMRUArray[0] = _T("Recent Files");\r
3741                 }\r
3742 \r
3743                 // Set MRU menu items\r
3744                 MENUITEMINFO mii = {0};\r
3745                 mii.cbSize = GetSizeofMenuItemInfo();\r
3746 \r
3747                 int nFileItem = 0;  // We place the MRU items under the left most menu item\r
3748                 CMenu* pFileMenu = GetFrameMenu().GetSubMenu(nFileItem);\r
3749 \r
3750                 if (pFileMenu)\r
3751                 {\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
3754                         {\r
3755                                 pFileMenu->DeleteMenu(u, MF_BYCOMMAND);\r
3756                         }\r
3757 \r
3758                         int MaxMRUIndex = (int)MIN(MaxMRUArrayIndex, m_nMaxMRU);\r
3759 \r
3760                         for (int index = MaxMRUIndex; index >= 0; --index)\r
3761                         {\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
3767 \r
3768                                 BOOL bResult;\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
3772                                 else\r
3773                                         // Insert the other MRU entries next\r
3774                                         bResult = pFileMenu->InsertMenuItem(IDW_FILE_MRU_FILE1 + index + 1, &mii, FALSE);\r
3775 \r
3776                                 if (!bResult)\r
3777                                 {\r
3778                                         TRACE(_T("Failed to set MRU menu item\n"));\r
3779                                         break;\r
3780                                 }\r
3781                         }\r
3782                 }\r
3783 \r
3784                 DrawMenuBar();\r
3785         }\r
3786 \r
3787         inline LRESULT CFrame::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
3788         {\r
3789                 switch (uMsg)\r
3790                 {\r
3791                 case WM_ACTIVATE:\r
3792                         OnActivate(wParam, lParam);\r
3793                         return 0L;\r
3794                 case WM_CLOSE:\r
3795                         OnClose();\r
3796                         break;\r
3797                 case WM_DESTROY:\r
3798                         OnDestroy();\r
3799                         return 0L;\r
3800                 case WM_ERASEBKGND:\r
3801                         return 0L;\r
3802                 case WM_HELP:\r
3803                         OnHelp();\r
3804                         return 0L;\r
3805                 case WM_MENUCHAR:\r
3806                         return OnMenuChar(wParam, lParam);\r
3807                 case WM_MENUSELECT:\r
3808                         OnMenuSelect(wParam, lParam);\r
3809                         return 0L;\r
3810                 case WM_SETFOCUS:\r
3811                         OnSetFocus();\r
3812                         break;\r
3813                 case WM_SIZE:\r
3814                         RecalcLayout();\r
3815                         return 0L;\r
3816                 case WM_SYSCOLORCHANGE:         // Changing themes trigger this\r
3817                         OnSysColorChange();\r
3818                         return 0L;\r
3819                 case WM_SYSCOMMAND:\r
3820                         return OnSysCommand(wParam, lParam);\r
3821                 case WM_TIMER:\r
3822                         OnTimer(wParam);\r
3823                         return 0L;\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
3828                         break;\r
3829                 case WM_MEASUREITEM:\r
3830                         return OnMeasureItem(wParam, lParam);\r
3831                 case WM_EXITMENULOOP:\r
3832                         OnExitMenuLoop();\r
3833                         break;\r
3834                 case UWM_GETMENUTHEME:\r
3835                         {\r
3836                                 MenuTheme& tm = GetMenuTheme();\r
3837                                 return (LRESULT)&tm;\r
3838                         }\r
3839                 case UWM_GETREBARTHEME:\r
3840                         {\r
3841                                 ReBarTheme& rm = GetReBarTheme();\r
3842                                 return (LRESULT)&rm;\r
3843                         }\r
3844                 case UWM_GETTOOLBARTHEME:\r
3845                         {\r
3846                                 ToolBarTheme& tt = GetToolBarTheme();\r
3847                                 return (LRESULT)&tt;\r
3848                         }\r
3849                 } // switch uMsg\r
3850 \r
3851                 return CWnd::WndProcDefault(uMsg, wParam, lParam);\r
3852         } // LRESULT CFrame::WndProcDefault(...)\r
3853 \r
3854 \r
3855 } // namespace Win32xx\r
3856 \r
3857 #endif // _WIN32XX_FRAME_H_\r

UCC git Repository :: git.ucc.asn.au