diff options
Diffstat (limited to 'mmc_updater/depends/win32cpp/frame.h')
| -rw-r--r-- | mmc_updater/depends/win32cpp/frame.h | 3303 |
1 files changed, 3303 insertions, 0 deletions
diff --git a/mmc_updater/depends/win32cpp/frame.h b/mmc_updater/depends/win32cpp/frame.h new file mode 100644 index 00000000..1f439fd7 --- /dev/null +++ b/mmc_updater/depends/win32cpp/frame.h @@ -0,0 +1,3303 @@ +// Win32++ Version 7.2 +// Released: 5th AUgust 2011 +// +// David Nash +// email: dnash@bigpond.net.au +// url: https://sourceforge.net/projects/win32-framework +// +// +// Copyright (c) 2005-2011 David Nash +// +// Permission is hereby granted, free of charge, to +// any person obtaining a copy of this software and +// associated documentation files (the "Software"), +// to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, +// merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom +// the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice +// shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +// OR OTHER DEALINGS IN THE SOFTWARE. +// +//////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////// +// frame.h +// Declaration of the CFrame and CMenuBar classes + +// The classes declared in this file support SDI (Single Document Interface) +// frames on Win32/Win64 operating systems (not Windows CE). For Windows CE, +// use wceframe.h instead. SDI frames are a simple frame which supports a +// single view window. Refer to mdi.h for frames that support several +// child windows. + +// CFrame also includes each of the following classes as members: +// * CReBar for managing the frame's rebar control. +// * CMenuBar for managing the menu inside the rebar. +// * CToolBar for managing the frame's toolbar. +// * CStatusBar for managing the frame's status bar. +// In each case these members are exposed by a GetXXX function, allowing +// them to be accessed or sent messages. + +// CFrame is responsible for creating a "frame" window. This window has a +// menu and and several child windows, including a toolbar (usualy hosted +// within a rebar), a status bar, and a view positioned over the frame +// window's non-client area. The "view" window is a seperate CWnd object +// assigned to the frame with the SetView function. + +// When compiling an application with these classes, it will need to be linked +// with Comctl32.lib. + +// To create a SDI frame application, inherit a CMainFrame class from CFrame. +// Use the Frame sample application as the starting point for your own frame +// applications. +// Refer to the Notepad and Scribble samples for examples on how to use these +// classes to create a frame application. + + +#ifndef _WIN32XX_FRAME_H_ +#define _WIN32XX_FRAME_H_ + +#include "wincore.h" +#include "dialog.h" +#include "gdi.h" +#include "statusbar.h" +#include "toolbar.h" +#include "rebar.h" +#include "default_resource.h" + +#ifndef RBN_MINMAX + #define RBN_MINMAX (RBN_FIRST - 21) +#endif + + +namespace Win32xx +{ + + //////////////////////////////////////////////// + // Declarations for structures for themes + // + struct MenuTheme + { + BOOL UseThemes; // TRUE if themes are used + COLORREF clrHot1; // Colour 1 for top menu. Color of selected menu item + COLORREF clrHot2; // Colour 2 for top menu. Color of checkbox + COLORREF clrPressed1; // Colour 1 for pressed top menu and side bar + COLORREF clrPressed2; // Colour 2 for pressed top menu and side bar + COLORREF clrOutline; // Colour for border outline + }; + + + // Forward declaration of CFrame. Its defined later. + class CFrame; + + + //////////////////////////////////// + // Declaration of the CMenuBar class + // + class CMenuBar : public CToolBar + { + friend class CFrame; + + public: + CMenuBar(); + virtual ~CMenuBar(); + virtual void SetMenu(HMENU hMenu); + virtual void SetMenuBarTheme(MenuTheme& Theme); + + HMENU GetMenu() const {return m_hTopMenu;} + MenuTheme& GetMenuBarTheme() {return m_ThemeMenu;} + + protected: + //Overridables + virtual void OnCreate(); + virtual LRESULT OnCustomDraw(NMHDR* pNMHDR); + virtual void OnKeyDown(WPARAM wParam, LPARAM lParam); + virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam); + virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam); + virtual void OnMenuChar(WPARAM wParam, LPARAM lParam); + virtual BOOL OnMenuInput(UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual void OnMouseLeave(); + virtual void OnMouseMove(WPARAM wParam, LPARAM lParam); + virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam); + virtual void OnSysCommand(WPARAM wParam, LPARAM lParam); + virtual void OnWindowPosChanged(); + virtual void PreCreate(CREATESTRUCT &cs); + virtual void PreRegisterClass(WNDCLASS &wc); + virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam); + + private: + CMenuBar(const CMenuBar&); // Disable copy construction + CMenuBar& operator = (const CMenuBar&); // Disable assignment operator + void DoAltKey(WORD KeyCode); + void DoPopupMenu(); + void DrawAllMDIButtons(CDC& DrawDC); + void DrawMDIButton(CDC& DrawDC, int iButton, UINT uState); + void ExitMenu(); + HWND GetActiveMDIChild(); + void GrabFocus(); + BOOL IsMDIChildMaxed() const; + BOOL IsMDIFrame() const; + void ReleaseFocus(); + void SetHotItem(int nHot); + static LRESULT CALLBACK StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam); + + enum MDIButtonType + { + MDI_MIN = 0, + MDI_RESTORE = 1, + MDI_CLOSE = 2, + }; + + BOOL m_bExitAfter; // Exit after Popup menu ends + BOOL m_bKeyMode; // keyboard navigation mode + BOOL m_bMenuActive; // popup menu active + BOOL m_bSelPopup; // a popup (cascade) menu is selected + HMENU m_hPopupMenu; // handle to the popup menu + HMENU m_hSelMenu; // handle to the casceded popup menu + HMENU m_hTopMenu; // handle to the top level menu + HWND m_hPrevFocus; // handle to window which had focus + CRect m_MDIRect[3]; // array of CRect for MDI buttons + int m_nHotItem; // hot item + int m_nMDIButton; // the MDI button (MDIButtonType) pressed + CPoint m_OldMousePos; // old Mouse position + MenuTheme m_ThemeMenu; // Theme structure + CFrame* m_pFrame; // Pointer to the frame + + }; // class CMenuBar + + + + ////////////////////////////////// + // Declaration of the CFrame class + // + class CFrame : public CWnd + { + friend class CMenuBar; + + struct ItemData + // Each Dropdown menu item has this data + { + HMENU hMenu; + UINT nPos; + UINT fType; + std::vector<TCHAR> vItemText; + HMENU hSubMenu; + + ItemData() : hMenu(0), nPos(0), fType(0), hSubMenu(0) { vItemText.assign(MAX_MENU_STRING, _T('\0')); } + LPTSTR GetItemText() {return &vItemText[0];} + }; + + typedef Shared_Ptr<ItemData> ItemDataPtr; + + public: + CFrame(); + virtual ~CFrame(); + + // Override these functions as required + virtual void AdjustFrameRect(RECT rcView) const; + virtual CRect GetViewRect() const; + virtual BOOL IsMDIFrame() const { return FALSE; } + virtual void SetStatusIndicators(); + virtual void SetStatusText(); + virtual void RecalcLayout(); + virtual MenuTheme& GetMenuTheme() const { return (MenuTheme&) m_ThemeMenu; } + virtual ReBarTheme& GetReBarTheme() const { return (ReBarTheme&)GetReBar().GetReBarTheme(); } + virtual ToolBarTheme& GetToolBarTheme() const { return (ToolBarTheme&)GetToolBar().GetToolBarTheme(); } + + // Virtual Attributes + // If you need to modify the default behaviour of the menubar, rebar, + // statusbar or toolbar, inherit from those classes, and override + // the following attribute functions. + virtual CMenuBar& GetMenuBar() const { return (CMenuBar&)m_MenuBar; } + virtual CReBar& GetReBar() const { return (CReBar&)m_ReBar; } + virtual CStatusBar& GetStatusBar() const { return (CStatusBar&)m_StatusBar; } + virtual CToolBar& GetToolBar() const { return (CToolBar&)m_ToolBar; } + + // These functions aren't virtual, and shouldn't be overridden + HACCEL GetFrameAccel() const { return m_hAccel; } + CMenu& GetFrameMenu() const { return (CMenu&)m_Menu; } + std::vector<tString> GetMRUEntries() const { return m_vMRUEntries; } + tString GetRegistryKeyName() const { return m_tsKeyName; } + CWnd* GetView() const { return m_pView; } + tString GetMRUEntry(UINT nIndex); + void SetFrameMenu(INT ID_MENU); + void SetFrameMenu(HMENU hMenu); + void SetMenuTheme(MenuTheme& Theme); + void SetView(CWnd& wndView); + BOOL IsMenuBarUsed() const { return (GetMenuBar() != 0); } + BOOL IsReBarSupported() const { return (GetComCtlVersion() >= 470); } + BOOL IsReBarUsed() const { return (GetReBar() != 0); } + + protected: + // Override these functions as required + virtual BOOL AddMenuIcon(int nID_MenuItem, HICON hIcon, int cx = 16, int cy = 16); + virtual UINT AddMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID); + virtual void AddMenuBarBand(); + virtual void AddMRUEntry(LPCTSTR szMRUEntry); + virtual void AddToolBarBand(CToolBar& TB, DWORD dwStyle, UINT nID); + virtual void AddToolBarButton(UINT nID, BOOL bEnabled = TRUE, LPCTSTR szText = 0); + virtual void CreateToolBar(); + virtual void DrawCheckmark(LPDRAWITEMSTRUCT pdis, CDC& DrawDC); + virtual void DrawMenuIcon(LPDRAWITEMSTRUCT pdis, CDC& DrawDC, BOOL bDisabled); + virtual void DrawMenuText(CDC& DrawDC, LPCTSTR ItemText, CRect& rc, COLORREF colorText); + virtual int GetMenuItemPos(HMENU hMenu, LPCTSTR szItem); + virtual BOOL LoadRegistrySettings(LPCTSTR szKeyName); + virtual BOOL LoadRegistryMRUSettings(UINT nMaxMRU = 0); + virtual void OnActivate(WPARAM wParam, LPARAM lParam); + virtual void OnClose(); + virtual void OnCreate(); + virtual void OnDestroy(); + virtual LRESULT OnDrawItem(WPARAM wParam, LPARAM lParam); + virtual void OnExitMenuLoop(); + virtual void OnHelp(); + virtual void OnInitMenuPopup(WPARAM wParam, LPARAM lParam); + virtual LRESULT OnMeasureItem(WPARAM wParam, LPARAM lParam); + virtual LRESULT OnMenuChar(WPARAM wParam, LPARAM lParam); + virtual void OnMenuSelect(WPARAM wParam, LPARAM lParam); + virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam); + virtual void OnSetFocus(); + virtual void OnSysColorChange(); + virtual LRESULT OnSysCommand(WPARAM wParam, LPARAM lParam); + virtual void OnTimer(WPARAM wParam); + virtual void OnViewStatusBar(); + virtual void OnViewToolBar(); + virtual void PreCreate(CREATESTRUCT& cs); + virtual void PreRegisterClass(WNDCLASS &wc); + virtual void RemoveMRUEntry(LPCTSTR szMRUEntry); + virtual BOOL SaveRegistrySettings(); + virtual void SetMenuBarBandSize(); + virtual UINT SetMenuIcons(const std::vector<UINT>& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID); + virtual void SetupToolBar(); + virtual void SetTheme(); + virtual void SetToolBarImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID); + virtual void ShowMenu(BOOL bShow); + virtual void ShowStatusBar(BOOL bShow); + virtual void ShowToolBar(BOOL bShow); + virtual void UpdateMRUMenu(); + virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam); + + enum Constants + { + ID_STATUS_TIMER = 1, + POST_TEXT_GAP = 16, // for owner draw menu item + }; + + tString m_tsStatusText; // TCHAR std::string for status text + BOOL m_bShowIndicatorStatus; // set to TRUE to see indicators in status bar + BOOL m_bShowMenuStatus; // set to TRUE to see menu and toolbar updates in status bar + BOOL m_bUseReBar; // set to TRUE if ReBars are to be used + BOOL m_bUseThemes; // set to TRUE if themes are to be used + BOOL m_bUpdateTheme; // set to TRUE to run SetThemes when theme changes + BOOL m_bUseToolBar; // set to TRUE if the toolbar is used + BOOL m_bUseCustomDraw; // set to TRUE to perform custom drawing on menu items + BOOL m_bShowStatusBar; // A flag to indicate if the StatusBar should be displayed + BOOL m_bShowToolBar; // A flag to indicate if the ToolBar should be displayed + MenuTheme m_ThemeMenu; // Theme structure for popup menus + HIMAGELIST m_himlMenu; // Imagelist of menu icons + HIMAGELIST m_himlMenuDis; // Imagelist of disabled menu icons + + private: + CFrame(const CFrame&); // Disable copy construction + CFrame& operator = (const CFrame&); // Disable assignment operator + void LoadCommonControls(); + + std::vector<ItemDataPtr> m_vMenuItemData;// vector of ItemData pointers + std::vector<UINT> m_vMenuIcons; // vector of menu icon resource IDs + std::vector<tString> m_vMRUEntries; // Vector of tStrings for MRU entires + CDialog m_AboutDialog; // Help about dialog + CMenuBar m_MenuBar; // CMenuBar object + CReBar m_ReBar; // CReBar object + CStatusBar m_StatusBar; // CStatusBar object + CToolBar m_ToolBar; // CToolBar object + CMenu m_Menu; // handle to the frame menu + HACCEL m_hAccel; // handle to the frame's accelerator table + CWnd* m_pView; // pointer to the View CWnd object + LPCTSTR m_OldStatus[3]; // Array of TCHAR pointers; + tString m_tsKeyName; // TCHAR std::string for Registry key name + tString m_tsTooltip; // TCHAR std::string for tool tips + UINT m_nMaxMRU; // maximum number of MRU entries + CRect m_rcPosition; // CRect of the starting window position + HWND m_hOldFocus; // The window which had focus prior to the app'a deactivation + int m_nOldID; // The previous ToolBar ID displayed in the statusbar + + }; // class CFrame + +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +namespace Win32xx +{ + + ///////////////////////////////////// + // Definitions for the CMenuBar class + // + inline CMenuBar::CMenuBar() + { + m_bExitAfter = FALSE; + m_hTopMenu = NULL; + m_nHotItem = -1; + m_bSelPopup = FALSE; + m_hSelMenu = NULL; + m_bMenuActive = FALSE; + m_bKeyMode = FALSE; + m_hPrevFocus = NULL; + m_nMDIButton = 0; + m_hPopupMenu = 0; + + ZeroMemory(&m_ThemeMenu, sizeof(MenuTheme)); + } + + inline CMenuBar::~CMenuBar() + { + } + + inline void CMenuBar::DoAltKey(WORD KeyCode) + { + //Handle key pressed with Alt held down + UINT ID; + if (SendMessage(TB_MAPACCELERATOR, KeyCode, (LPARAM) &ID)) + { + GrabFocus(); + m_bKeyMode = TRUE; + SetHotItem(ID); + m_bMenuActive = TRUE; + PostMessage(UWM_POPUPMENU, 0L, 0L); + } + else + ::MessageBeep(MB_OK); + } + + inline void CMenuBar::DoPopupMenu() + { + if (m_bKeyMode) + // Simulate a down arrow key press + PostMessage(WM_KEYDOWN, VK_DOWN, 0L); + + m_bKeyMode = FALSE; + m_bExitAfter = FALSE; + m_OldMousePos = GetCursorPos(); + + HWND hMaxMDIChild = NULL; + if (IsMDIChildMaxed()) + hMaxMDIChild = GetActiveMDIChild(); + + // Load the submenu + int nMaxedOffset = IsMDIChildMaxed()? 1:0; + m_hPopupMenu = ::GetSubMenu(m_hTopMenu, m_nHotItem - nMaxedOffset); + if (IsMDIChildMaxed() && (0 == m_nHotItem) ) + m_hPopupMenu = ::GetSystemMenu(hMaxMDIChild, FALSE); + + // Retrieve the bounding rectangle for the toolbar button + CRect rc = GetItemRect(m_nHotItem); + + // convert rectangle to desktop coordinates + ClientToScreen(rc); + + // Position popup above toolbar if it won't fit below + TPMPARAMS tpm; + tpm.cbSize = sizeof(TPMPARAMS); + tpm.rcExclude = rc; + + // Set the hot button + SendMessage(TB_SETHOTITEM, m_nHotItem, 0L); + SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(TRUE, 0)); + + m_bSelPopup = FALSE; + m_hSelMenu = NULL; + m_bMenuActive = TRUE; + + // We hook mouse input to process mouse and keyboard input during + // the popup menu. Messages are sent to StaticMsgHook. + + // Remove any remaining hook first + TLSData* pTLSData = (TLSData*)::TlsGetValue(GetApp()->GetTlsIndex()); + pTLSData->pMenuBar = this; + if (pTLSData->hHook != NULL) + ::UnhookWindowsHookEx(pTLSData->hHook); + + // Hook messages about to be processed by the shortcut menu + pTLSData->hHook = ::SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)StaticMsgHook, NULL, ::GetCurrentThreadId()); + + // Display the shortcut menu + BOOL bRightToLeft = FALSE; + +#if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500) + bRightToLeft = ((GetAncestor()->GetWindowLongPtr(GWL_EXSTYLE)) & WS_EX_LAYOUTRTL); +#endif + + int xPos = bRightToLeft? rc.right : rc.left; + UINT nID = ::TrackPopupMenuEx(m_hPopupMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL, + xPos, rc.bottom, m_hWnd, &tpm); + + // We get here once the TrackPopupMenuEx has ended + m_bMenuActive = FALSE; + + // Remove the message hook + ::UnhookWindowsHookEx(pTLSData->hHook); + pTLSData->hHook = NULL; + + // Process MDI Child system menu + if (IsMDIChildMaxed()) + { + if (::GetSystemMenu(hMaxMDIChild, FALSE) == m_hPopupMenu ) + { + if (nID) + ::SendMessage(hMaxMDIChild, WM_SYSCOMMAND, nID, 0L); + } + } + + // Resestablish Focus + if (m_bKeyMode) + GrabFocus(); + } + + inline void CMenuBar::DrawAllMDIButtons(CDC& DrawDC) + { + if (!IsMDIFrame()) + return; + + if (IsMDIChildMaxed()) + { + int cx = GetSystemMetrics(SM_CXSMICON); + int cy = GetSystemMetrics(SM_CYSMICON); + CRect rc = GetClientRect(); + int gap = 4; + rc.right -= gap; + + // Assign values to each element of the CRect array + for (int i = 0 ; i < 3 ; ++i) + { + int left = rc.right - (i+1)*cx - gap*(i+1); + int top = rc.bottom/2 - cy/2; + int right = rc.right - i*cx - gap*(i+1); + int bottom = rc.bottom/2 + cy/2; + ::SetRect(&m_MDIRect[2 - i], left, top, right, bottom); + } + + // Hide the MDI button if it won't fit + for (int k = 0 ; k <= 2 ; ++k) + { + + if (m_MDIRect[k].left < GetMaxSize().cx) + { + ::SetRectEmpty(&m_MDIRect[k]); + } + } + + DrawMDIButton(DrawDC, MDI_MIN, 0); + DrawMDIButton(DrawDC, MDI_RESTORE, 0); + DrawMDIButton(DrawDC, MDI_CLOSE, 0); + } + } + + inline void CMenuBar::DrawMDIButton(CDC& DrawDC, int iButton, UINT uState) + { + if (!IsRectEmpty(&m_MDIRect[iButton])) + { + switch (uState) + { + case 0: + { + // Draw a grey outline + DrawDC.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE)); + DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom); + DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom); + DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top); + DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top); + DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom); + } + break; + case 1: + { + // Draw outline, white at top, black on bottom + DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); + DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom); + DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom); + DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top); + DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255)); + DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top); + DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom); + } + + break; + case 2: + { + // Draw outline, black on top, white on bottom + DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255)); + DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom); + DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom); + DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top); + DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); + DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top); + DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom); + } + break; + } + + DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0)); + + switch (iButton) + { + case MDI_MIN: + // Manually Draw Minimise button + DrawDC.MoveTo(m_MDIRect[0].left + 4, m_MDIRect[0].bottom -4); + DrawDC.LineTo(m_MDIRect[0].right - 4, m_MDIRect[0].bottom - 4); + + DrawDC.MoveTo(m_MDIRect[0].left + 4, m_MDIRect[0].bottom -5); + DrawDC.LineTo(m_MDIRect[0].right - 4, m_MDIRect[0].bottom - 5); + break; + case MDI_RESTORE: + // Manually Draw Restore Button + DrawDC.MoveTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 7); + DrawDC.LineTo(m_MDIRect[1].left + 3, m_MDIRect[1].bottom -4); + DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].bottom -4); + DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].top + 7); + DrawDC.LineTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 7); + + DrawDC.MoveTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 8); + DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].top + 8); + + DrawDC.MoveTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 7); + DrawDC.LineTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 4); + DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].top + 4); + DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].bottom -6); + DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].bottom -6); + + DrawDC.MoveTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 5); + DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].top + 5); + break; + case MDI_CLOSE: + // Manually Draw Close Button + DrawDC.MoveTo(m_MDIRect[2].left + 4, m_MDIRect[2].top +5); + DrawDC.LineTo(m_MDIRect[2].right - 4, m_MDIRect[2].bottom -3); + + DrawDC.MoveTo(m_MDIRect[2].left + 5, m_MDIRect[2].top +5); + DrawDC.LineTo(m_MDIRect[2].right - 4, m_MDIRect[2].bottom -4); + + DrawDC.MoveTo(m_MDIRect[2].left + 4, m_MDIRect[2].top +6); + DrawDC.LineTo(m_MDIRect[2].right - 5, m_MDIRect[2].bottom -3); + + DrawDC.MoveTo(m_MDIRect[2].right -5, m_MDIRect[2].top +5); + DrawDC.LineTo(m_MDIRect[2].left + 3, m_MDIRect[2].bottom -3); + + DrawDC.MoveTo(m_MDIRect[2].right -5, m_MDIRect[2].top +6); + DrawDC.LineTo(m_MDIRect[2].left + 4, m_MDIRect[2].bottom -3); + + DrawDC.MoveTo(m_MDIRect[2].right -6, m_MDIRect[2].top +5); + DrawDC.LineTo(m_MDIRect[2].left + 3, m_MDIRect[2].bottom -4); + break; + } + } + } + + inline void CMenuBar::ExitMenu() + { + ReleaseFocus(); + m_bKeyMode = FALSE; + m_bMenuActive = FALSE; + SendMessage(TB_PRESSBUTTON, m_nHotItem, (LPARAM) MAKELONG (FALSE, 0)); + SetHotItem(-1); + + CPoint pt = GetCursorPos(); + ScreenToClient(pt); + + // Update mouse mouse position for hot tracking + SendMessage(WM_MOUSEMOVE, 0L, MAKELONG(pt.x, pt.y)); + } + + inline HWND CMenuBar::GetActiveMDIChild() + { + HWND hwndMDIChild = NULL; + if (IsMDIFrame()) + { + hwndMDIChild = (HWND)::SendMessage(m_pFrame->GetView()->GetHwnd(), WM_MDIGETACTIVE, 0L, 0L); + } + + return hwndMDIChild; + } + + inline void CMenuBar::GrabFocus() + { + if (::GetFocus() != m_hWnd) + m_hPrevFocus = ::SetFocus(m_hWnd); + ::SetCapture(m_hWnd); + ::SetCursor(::LoadCursor(NULL, IDC_ARROW)); + } + + inline BOOL CMenuBar::IsMDIChildMaxed() const + { + BOOL bMaxed = FALSE; + + if (IsMDIFrame() && m_pFrame->GetView()->IsWindow()) + { + m_pFrame->GetView()->SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMaxed); + } + + return bMaxed; + } + + inline BOOL CMenuBar::IsMDIFrame() const + { + return (m_pFrame->IsMDIFrame()); + } + + inline void CMenuBar::OnMenuChar(WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(lParam); + + if (!m_bMenuActive) + DoAltKey(LOWORD(wParam)); + } + + inline void CMenuBar::OnCreate() + { + // We must send this message before sending the TB_ADDBITMAP or TB_ADDBUTTONS message + SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0L); + + m_pFrame = (CFrame*)GetAncestor(); + assert(m_pFrame); + } + + inline LRESULT CMenuBar::OnCustomDraw(NMHDR* pNMHDR) + // CustomDraw is used to render the MenuBar's toolbar buttons + { + if (m_ThemeMenu.UseThemes) + { + LPNMTBCUSTOMDRAW lpNMCustomDraw = (LPNMTBCUSTOMDRAW)pNMHDR; + + switch (lpNMCustomDraw->nmcd.dwDrawStage) + { + // Begin paint cycle + case CDDS_PREPAINT: + // Send NM_CUSTOMDRAW item draw, and post-paint notification messages. + return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT ; + + // An item is about to be drawn + case CDDS_ITEMPREPAINT: + { + CDC* pDrawDC = FromHandle(lpNMCustomDraw->nmcd.hdc); + CRect rcRect = lpNMCustomDraw->nmcd.rc; + int nState = lpNMCustomDraw->nmcd.uItemState; + DWORD dwItem = (DWORD)lpNMCustomDraw->nmcd.dwItemSpec; + + // Leave a pixel gap above and below the drawn rectangle + if (IsAeroThemed()) + rcRect.InflateRect(0, -2); + else + rcRect.InflateRect(0, -1); + + if (IsMDIChildMaxed() && (0 == dwItem)) + // Draw over MDI Max button + { + HICON hIcon = (HICON)::SendMessage(GetActiveMDIChild(), WM_GETICON, ICON_SMALL, 0L); + if (NULL == hIcon) + hIcon = ::LoadIcon(NULL, IDI_APPLICATION); + + int cx = ::GetSystemMetrics (SM_CXSMICON); + int cy = ::GetSystemMetrics (SM_CYSMICON); + int y = 1 + (GetWindowRect().Height() - cy)/2; + int x = (rcRect.Width() - cx)/2; + pDrawDC->DrawIconEx(x, y, hIcon, cx, cy, 0, NULL, DI_NORMAL); + + pDrawDC->Detach(); // Optional, deletes GDI objects sooner + return CDRF_SKIPDEFAULT; // No further drawing + } + + else if (nState & (CDIS_HOT | CDIS_SELECTED)) + { + if ((nState & CDIS_SELECTED) || (GetButtonState(dwItem) & TBSTATE_PRESSED)) + { + pDrawDC->GradientFill(m_ThemeMenu.clrPressed1, m_ThemeMenu.clrPressed2, rcRect, FALSE); + } + else if (nState & CDIS_HOT) + { + pDrawDC->GradientFill(m_ThemeMenu.clrHot1, m_ThemeMenu.clrHot2, rcRect, FALSE); + } + + // Draw border + pDrawDC->CreatePen(PS_SOLID, 1, m_ThemeMenu.clrOutline); + pDrawDC->MoveTo(rcRect.left, rcRect.bottom); + pDrawDC->LineTo(rcRect.left, rcRect.top); + pDrawDC->LineTo(rcRect.right-1, rcRect.top); + pDrawDC->LineTo(rcRect.right-1, rcRect.bottom); + pDrawDC->MoveTo(rcRect.right-1, rcRect.bottom); + pDrawDC->LineTo(rcRect.left, rcRect.bottom); + + TCHAR str[80] = _T(""); + int nLength = (int)SendMessage(TB_GETBUTTONTEXT, lpNMCustomDraw->nmcd.dwItemSpec, 0L); + if ((nLength > 0) && (nLength < 80)) + SendMessage(TB_GETBUTTONTEXT, lpNMCustomDraw->nmcd.dwItemSpec, (LPARAM)str); + + // Draw highlight text + pDrawDC->SelectObject(GetFont()); + rcRect.bottom += 1; + int iMode = pDrawDC->SetBkMode(TRANSPARENT); + pDrawDC->DrawText(str, lstrlen(str), rcRect, DT_VCENTER | DT_CENTER | DT_SINGLELINE); + + pDrawDC->SetBkMode(iMode); + pDrawDC->Detach(); // Optional, deletes GDI objects sooner + return CDRF_SKIPDEFAULT; // No further drawing + } + } + return CDRF_DODEFAULT ; // Do default drawing + + // Painting cycle has completed + case CDDS_POSTPAINT: + // Draw MDI Minimise, Restore and Close buttons + { + CDC* pDrawDC = FromHandle(lpNMCustomDraw->nmcd.hdc); + DrawAllMDIButtons(*pDrawDC); + pDrawDC->Detach(); // Optional, deletes GDI objects sooner + } + break; + } + } + return 0L; + } + + inline void CMenuBar::OnKeyDown(WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(lParam); + + switch (wParam) + { + case VK_ESCAPE: + ExitMenu(); + break; + + case VK_SPACE: + ExitMenu(); + // Bring up the system menu + GetAncestor()->PostMessage(WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE); + break; + + // Handle VK_DOWN,VK_UP and VK_RETURN together + case VK_DOWN: + case VK_UP: + case VK_RETURN: + // Always use PostMessage for USER_POPUPMENU (not SendMessage) + PostMessage(UWM_POPUPMENU, 0L, 0L); + break; + + case VK_LEFT: + // Move left to next topmenu item + (m_nHotItem > 0)? SetHotItem(m_nHotItem -1) : SetHotItem(GetButtonCount()-1); + break; + + case VK_RIGHT: + // Move right to next topmenu item + (m_nHotItem < GetButtonCount() -1)? SetHotItem(m_nHotItem +1) : SetHotItem(0); + break; + + default: + // Handle Accelerator keys with Alt toggled down + if (m_bKeyMode) + { + UINT ID; + if (SendMessage(TB_MAPACCELERATOR, wParam, (LPARAM) &ID)) + { + m_nHotItem = ID; + PostMessage(UWM_POPUPMENU, 0L, 0L); + } + else + ::MessageBeep(MB_OK); + } + break; + } // switch (wParam) + } + + inline void CMenuBar::OnLButtonDown(WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(wParam); + + GrabFocus(); + m_nMDIButton = 0; + CPoint pt; + + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + + if (IsMDIFrame()) + { + if (IsMDIChildMaxed()) + { + CClientDC MenuBarDC(this); + m_nMDIButton = -1; + + if (m_MDIRect[0].PtInRect(pt)) m_nMDIButton = 0; + if (m_MDIRect[1].PtInRect(pt)) m_nMDIButton = 1; + if (m_MDIRect[2].PtInRect(pt)) m_nMDIButton = 2; + + if (m_nMDIButton >= 0) + { + DrawMDIButton(MenuBarDC, MDI_MIN, (0 == m_nMDIButton)? 2 : 0); + DrawMDIButton(MenuBarDC, MDI_RESTORE, (1 == m_nMDIButton)? 2 : 0); + DrawMDIButton(MenuBarDC, MDI_CLOSE, (2 == m_nMDIButton)? 2 : 0); + } + + // Bring up the MDI Child window's system menu when the icon is pressed + if (0 == HitTest()) + { + m_nHotItem = 0; + PostMessage(UWM_POPUPMENU, 0L, 0L); + } + } + } + } + + inline void CMenuBar::OnLButtonUp(WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(wParam); + CPoint pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + + if (IsMDIFrame()) + { + HWND MDIClient = m_pFrame->GetView()->GetHwnd(); + HWND MDIChild = GetActiveMDIChild(); + + if (IsMDIChildMaxed()) + { + CPoint pt = GetCursorPos(); + ScreenToClient(pt); + + // Process the MDI button action when the left mouse button is up + if (m_MDIRect[0].PtInRect(pt)) + { + if (MDI_MIN == m_nMDIButton) + ::ShowWindow(MDIChild, SW_MINIMIZE); + } + + if (m_MDIRect[1].PtInRect(pt)) + { + if (MDI_RESTORE == m_nMDIButton) + ::PostMessage(MDIClient, WM_MDIRESTORE, (WPARAM)MDIChild, 0L); + } + + if (m_MDIRect[2].PtInRect(pt)) + { + if (MDI_CLOSE == m_nMDIButton) + ::PostMessage(MDIChild, WM_CLOSE, 0L, 0L); + } + } + } + m_nMDIButton = 0; + ExitMenu(); + } + + inline BOOL CMenuBar::OnMenuInput(UINT uMsg, WPARAM wParam, LPARAM lParam) + // When a popup menu is active, StaticMsgHook directs all menu messages here + { + switch(uMsg) + { + case WM_KEYDOWN: + m_bExitAfter = FALSE; + { + switch (wParam) + { + case VK_ESCAPE: + // Use default processing if inside a Sub Menu + if ((m_hSelMenu) &&(m_hSelMenu != m_hPopupMenu)) + return FALSE; + + m_bMenuActive = FALSE; + m_bKeyMode = TRUE; + SendMessage(WM_CANCELMODE, 0L, 0L); + SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0)); + SendMessage(TB_SETHOTITEM, m_nHotItem, 0L); + break; + + case VK_LEFT: + // Use default processing if inside a Sub Menu + if ((m_hSelMenu) &&(m_hSelMenu != m_hPopupMenu)) + return FALSE; + + SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0)); + + // Move left to next topmenu item + (m_nHotItem > 0)? --m_nHotItem : m_nHotItem = GetButtonCount()-1; + SendMessage(WM_CANCELMODE, 0L, 0L); + + // Always use PostMessage for USER_POPUPMENU (not SendMessage) + PostMessage(UWM_POPUPMENU, 0L, 0L); + PostMessage(WM_KEYDOWN, VK_DOWN, 0L); + break; + + case VK_RIGHT: + // Use default processing to open Sub Menu + if (m_bSelPopup) + return FALSE; + + SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0)); + + // Move right to next topmenu item + (m_nHotItem < GetButtonCount()-1)? ++m_nHotItem : m_nHotItem = 0; + SendMessage(WM_CANCELMODE, 0L, 0L); + + // Always use PostMessage for USER_POPUPMENU (not SendMessage) + PostMessage(UWM_POPUPMENU, 0L, 0L); + PostMessage(WM_KEYDOWN, VK_DOWN, 0L); + break; + + case VK_RETURN: + m_bExitAfter = TRUE; + break; + + } // switch (wParam) + + } // case WM_KEYDOWN + + return FALSE; + + case WM_CHAR: + m_bExitAfter = TRUE; + return FALSE; + + case WM_LBUTTONDOWN: + { + m_bExitAfter = TRUE; + if (HitTest() >= 0) + { + // Cancel popup when we hit a button a second time + SendMessage(WM_CANCELMODE, 0L, 0L); + return TRUE; + } + } + return FALSE; + + case WM_LBUTTONDBLCLK: + // Perform default action for DblClick on MDI Maxed icon + if (IsMDIChildMaxed() && (0 == HitTest())) + { + CWnd* pMDIChild = FromHandle(GetActiveMDIChild()); + CMenu* pChildMenu = pMDIChild->GetSystemMenu(FALSE); + + UINT nID = pChildMenu->GetDefaultItem(FALSE, 0); + if (nID) + pMDIChild->PostMessage(WM_SYSCOMMAND, nID, 0L); + } + + m_bExitAfter = TRUE; + return FALSE; + + case WM_MENUSELECT: + { + // store info about selected item + m_hSelMenu = (HMENU)lParam; + m_bSelPopup = ((HIWORD(wParam) & MF_POPUP) != 0); + + // Reflect message back to the frame window + GetAncestor()->SendMessage(WM_MENUSELECT, wParam, lParam); + } + return TRUE; + + case WM_MOUSEMOVE: + { + CPoint pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + + // Skip if mouse hasn't moved + if ((pt.x == m_OldMousePos.x) && (pt.y == m_OldMousePos.y)) + return FALSE; + + m_OldMousePos.x = pt.x; + m_OldMousePos.y = pt.y; + ScreenToClient(pt); + + // Reflect messages back to the MenuBar for hot tracking + SendMessage(WM_MOUSEMOVE, 0L, MAKELPARAM(pt.x, pt.y)); + } + break; + + } + return FALSE; + } + + inline void CMenuBar::OnMouseLeave() + { + if (IsMDIFrame()) + { + if (IsMDIChildMaxed()) + { + CClientDC MenuBarDC(this); + + DrawMDIButton(MenuBarDC, MDI_MIN, 0); + DrawMDIButton(MenuBarDC, MDI_RESTORE, 0); + DrawMDIButton(MenuBarDC, MDI_CLOSE, 0); + } + } + } + + inline void CMenuBar::OnMouseMove(WPARAM wParam, LPARAM lParam) + { + CPoint pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + + if (IsMDIFrame()) + { + if (IsMDIChildMaxed()) + { + CClientDC MenuBarDC(this); + int MDIButton = -1; + if (m_MDIRect[0].PtInRect(pt)) MDIButton = 0; + if (m_MDIRect[1].PtInRect(pt)) MDIButton = 1; + if (m_MDIRect[2].PtInRect(pt)) MDIButton = 2; + + if (MK_LBUTTON == wParam) // mouse moved with left mouse button is held down + { + // toggle the MDI button image pressed/unpressed as required + if (MDIButton >= 0) + { + DrawMDIButton(MenuBarDC, MDI_MIN, ((0 == MDIButton) && (0 == m_nMDIButton))? 2 : 0); + DrawMDIButton(MenuBarDC, MDI_RESTORE, ((1 == MDIButton) && (1 == m_nMDIButton))? 2 : 0); + DrawMDIButton(MenuBarDC, MDI_CLOSE, ((2 == MDIButton) && (2 == m_nMDIButton))? 2 : 0); + } + else + { + DrawMDIButton(MenuBarDC, MDI_MIN, 0); + DrawMDIButton(MenuBarDC, MDI_RESTORE, 0); + DrawMDIButton(MenuBarDC, MDI_CLOSE, 0); + } + } + else // mouse moved without left mouse button held down |
