www.pudn.com > vc开发的精美界面.zip > BCGMenuBar.cpp
//******************************************************************************* // COPYRIGHT NOTES // --------------- // This source code is a part of BCGControlBar library. // You may use, compile or redistribute it as part of your application // for free. You cannot redistribute it as a part of a software development // library without the agreement of the author. If the sources are // distributed along with the application, you should leave the original // copyright notes in the source code without any changes. // This code can be used WITHOUT ANY WARRANTIES on your own risk. // // For the latest updates to this library, check my site: // http://welcome.to/bcgsoft // // Stas Levin//******************************************************************************* // BCGMenuBar.cpp : implementation file // #include "stdafx.h" #include "globals.h" #include "BCGMenuBar.h" #include "BCGToolbarButton.h" #include "BCGToolbarMenuButton.h" #include "BCGToolbarSystemMenuButton.h" #include "BCGToolbarMenuButtonsButton.h" #include "BCGPopupMenu.h" #include "MenuHash.h" #include "bcgbarres.h" #include "bcglocalres.h" #include "BCGMDIFrameWnd.h" #include "BCGFrameWnd.h" #include "BCGOleIPFrameWnd.h" #include "BCGMultiDocTemplate.h" #include "BCGDockBar.h" #include "RegPath.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_SERIAL(CBCGMenuBar, CBCGToolBar, VERSIONABLE_SCHEMA | 1) HHOOK CBCGMenuBar::m_hookMouseDrag = NULL; CBCGMenuBar* CBCGMenuBar::m_pDraggedMenuBar = NULL; BOOL CBCGMenuBar::m_bShowAllCommands = FALSE; BOOL CBCGMenuBar::m_bRecentlyUsedMenus = TRUE; BOOL CBCGMenuBar::m_bShowAllMenusDelay = TRUE; BOOL CBCGMenuBar::m_bMenuShadows = TRUE; BOOL CBCGMenuBar::m_bHighlightDisabledItems = FALSE; static const UINT uiShowAllItemsTimerId = 1; static const int iShowAllItemsTimerFreq = 5000; // 5 sec static const CString strMenuProfile = _T("BCGMenuBar"); ///////////////////////////////////////////////////////////////////////////// // CBCGMenuBar CBCGMenuBar::CBCGMenuBar() { m_bMaximizeMode = FALSE; m_hMenu = NULL; m_hDefaultMenu = NULL; m_hSysMenu = NULL; m_hSysIcon = NULL; m_uiDefMenuResId = 0; m_nSystemButtonsNum = 0; m_nSystemButtonsNumSaved = 0; m_bHaveButtons = FALSE; m_szSystemButton = CSize (0, 0); m_bAutoDocMenus = TRUE; } CBCGMenuBar::~CBCGMenuBar() { SetDragMode (FALSE); ::DestroyMenu (m_hMenu); } BEGIN_MESSAGE_MAP(CBCGMenuBar, CBCGToolBar) //{{AFX_MSG_MAP(CBCGMenuBar) ON_WM_CREATE() ON_WM_LBUTTONDOWN() ON_WM_SETFOCUS() ON_WM_WINDOWPOSCHANGED() ON_WM_TIMER() ON_WM_LBUTTONDBLCLK() ON_WM_SETTINGCHANGE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CBCGMenuBar message handlers void CBCGMenuBar::CreateFromMenu (HMENU hMenu, BOOL bDefaultMenu, BOOL bForceUpdate) { if (GetFocus () == this) { GetParentFrame()->SetFocus (); } if (m_hMenu != hMenu || IsCustomizeMode () || bForceUpdate) { g_menuHash.SaveMenuBar (m_hMenu, this); BOOL bMaximizeMode = m_bMaximizeMode; m_bMaximizeMode = FALSE; m_hMenu = hMenu; if (bDefaultMenu) { m_hDefaultMenu = hMenu; } if (!g_menuHash.LoadMenuBar (hMenu, this)) { CMenu* pMenu = CMenu::FromHandle (hMenu); if (pMenu == NULL) { return; } RemoveAllButtons (); int iCount = (int) pMenu->GetMenuItemCount (); for (int i = 0; i < iCount; i ++) { UINT uiID = pMenu->GetMenuItemID (i); CString strText; pMenu->GetMenuString (i, strText, MF_BYPOSITION); switch (uiID) { case -1: // Pop-up menu { CMenu* pPopupMenu = pMenu->GetSubMenu (i); ASSERT (pPopupMenu != NULL); CBCGToolbarMenuButton button ( 0, pPopupMenu->GetSafeHmenu (), -1, strText); button.m_bText = TRUE; button.m_bImage = FALSE; InsertButton (button); } break; case 0: // Separator InsertSeparator (); break; default: // Regular command { CBCGToolbarButton button (uiID, -1, strText); button.m_bText = TRUE; button.m_bImage = FALSE; InsertButton (button); } break; } } } if (bMaximizeMode) { CMDIFrameWnd* pParentFrame = DYNAMIC_DOWNCAST (CMDIFrameWnd, m_pParentWnd); if (pParentFrame != NULL) { SetMaximizeMode (TRUE, pParentFrame->MDIGetActive ()); } } if (GetSafeHwnd () != NULL) { AdjustLayout (); } RebuildAccelerationKeys (); } } //*************************************************************************************** CSize CBCGMenuBar::CalcDynamicLayout (int nLength, DWORD dwMode) { return CalcLayout(dwMode, nLength); } //********************************************************************************** CSize CBCGMenuBar::CalcLayout(DWORD dwMode, int nLength) { OnChangeHot (-1); //------------------------------------------ // Is menu bar have the buttons with images? //------------------------------------------ m_bHaveButtons = FALSE; for (POSITION pos = m_Buttons.GetHeadPosition (); pos != NULL;) { CBCGToolbarButton* pButton = (CBCGToolbarButton*) m_Buttons.GetNext (pos); ASSERT_VALID (pButton); if (!pButton->IsKindOf (RUNTIME_CLASS (CBCGToolbarMenuButtonsButton)) && !pButton->IsKindOf (RUNTIME_CLASS (CBCGToolbarSystemMenuButton)) && pButton->m_bImage && pButton->IsDrawImage ()) { m_bHaveButtons = TRUE; break; } } if (m_pDockContext != NULL && m_pDockContext->m_bDragging) { SetDragMode (TRUE); } if ((dwMode == (LM_HORZ | LM_MRUWIDTH)) || (m_pDockContext != NULL && !m_pDockContext->m_bDragging && IsFloating ())) { return CBCGToolBar::CalcLayout (dwMode, nLength); } BOOL bVert = (dwMode & LM_VERTDOCK) || ((dwMode & LM_HORZ) == 0); CRect rect; rect.SetRectEmpty (); if (m_pDockBar != NULL) { rect = ((CBCGDockBar*) m_pDockBar)->m_rectLayout; } if (rect.IsRectEmpty ()) { CWnd* pFrame = GetOwner (); pFrame->GetClientRect(&rect); } CSize size; CRect rectClient; rectClient.SetRectEmpty(); CalcInsideRect (rectClient, (dwMode & LM_HORZ)); if (!bVert) { WrapToolBar (rect.Width ()); //------------------------------------- // Calculate size again after wrapping: //------------------------------------- size = CalcSize (FALSE); size.cx = rect.Width () - rectClient.Width() / 2; size.cy -= rectClient.Height(); } else { //------------------------------------- // Calculate size again after wrapping: //------------------------------------- size = CalcSize (TRUE); size.cy = rect.Height () - rectClient.Height() / 2; size.cx -= rectClient.Width(); } //-------------------------------------------------- // Something may changed, rebuild acceleration keys: //-------------------------------------------------- RebuildAccelerationKeys (); return size; } //*************************************************************************************** void CBCGMenuBar::SetMaximizeMode (BOOL bMax, CWnd* pWnd) { if (m_bMaximizeMode == bMax) { return; } if (bMax) { if (pWnd == NULL) { bMax = FALSE; } else { // get the sys menu. m_hSysMenu = pWnd->GetSystemMenu (FALSE)->GetSafeHmenu (); // If we have a system menu, then add a system menu button. if (m_hSysMenu != NULL) { m_hSysIcon = pWnd->GetIcon (FALSE); if (m_hSysIcon == NULL) { m_hSysIcon = (HICON) GetClassLong (*pWnd, GCL_HICONSM); } InsertButton (CBCGToolbarSystemMenuButton (m_hSysMenu, m_hSysIcon), 0); } LONG style = ::GetWindowLong(*pWnd, GWL_STYLE); // Assume no buttons. m_nSystemButtonsNum = 0; // Add a minimize box if required. if (style & WS_MINIMIZEBOX) { InsertButton (CBCGToolbarMenuButtonsButton (SC_MINIMIZE)); m_nSystemButtonsNum++; } // Add a restore box if required. if (style & WS_MAXIMIZEBOX) { InsertButton (CBCGToolbarMenuButtonsButton (SC_RESTORE)); m_nSystemButtonsNum++; } // Add a close box if required. if (m_hSysMenu != NULL) { //-------------------------------------------------------------- // Jan Vasina: check if the maximized window has its system menu // with the close button enabled: //-------------------------------------------------------------- CBCGToolbarMenuButtonsButton closeButton (SC_CLOSE); MENUITEMINFO menuInfo; ZeroMemory(&menuInfo,sizeof(MENUITEMINFO)); menuInfo.cbSize = sizeof(MENUITEMINFO); menuInfo.fMask = MIIM_STATE; ::GetMenuItemInfo(m_hSysMenu, SC_CLOSE, FALSE, &menuInfo); if ((menuInfo.fState & MFS_GRAYED) || (menuInfo.fState & MFS_DISABLED)) { closeButton.m_nStyle |= TBBS_DISABLED; } InsertButton (closeButton); m_nSystemButtonsNum++; } } } else { m_nSystemButtonsNumSaved = m_nSystemButtonsNum; // By Jon Wang // Remove first button if a system menu was added. if (m_hSysMenu != NULL) { RemoveButton (0); } for (int i = 0; i < m_nSystemButtonsNum; i ++) { CBCGToolbarMenuButtonsButton* pButton = (CBCGToolbarMenuButtonsButton*) m_Buttons.RemoveTail (); ASSERT_KINDOF (CBCGToolbarMenuButtonsButton, pButton); delete pButton; } // Now we habe no system buttons on the menu. m_nSystemButtonsNum = 0; } m_bMaximizeMode = bMax; AdjustLayout (); } //*************************************************************************************** void CBCGMenuBar::RestoreMaximizeMode () { if (m_bMaximizeMode) { return; } CBCGToolbarSystemMenuButton button (m_hSysMenu, m_hSysIcon); InsertButton (button, 0); InsertButton (CBCGToolbarMenuButtonsButton (SC_MINIMIZE)); InsertButton (CBCGToolbarMenuButtonsButton (SC_RESTORE)); InsertButton (CBCGToolbarMenuButtonsButton (SC_CLOSE)); m_bMaximizeMode = TRUE; m_nSystemButtonsNum = m_nSystemButtonsNumSaved; GetParentFrame ()->RecalcLayout (); Invalidate (); UpdateWindow (); } //*************************************************************************************** void CBCGMenuBar::AdjustLocations () { CBCGToolBar::AdjustLocations (); if (!m_bMaximizeMode) { return; } CRect rectClient; GetClientRect (&rectClient); BOOL bHorz = m_dwStyle & CBRS_ORIENT_HORZ ? TRUE : FALSE; int iButtonWidth = m_szSystemButton.cx; int iButtonHeight = m_szSystemButton.cy; POSITION pos = m_Buttons.GetTailPosition (); CRect rect = rectClient; rectClient.SetRectEmpty (); CalcInsideRect (rectClient, bHorz); if (!bHorz) { rect.bottom += rectClient.Height (); } rect.left = rect.right - iButtonWidth; rect.top = rect.bottom - iButtonHeight; for (int i = 0; i < m_nSystemButtonsNum; i ++) { ASSERT (pos != NULL); CBCGToolbarMenuButtonsButton* pButton = (CBCGToolbarMenuButtonsButton*) m_Buttons.GetPrev (pos); ASSERT_KINDOF (CBCGToolbarMenuButtonsButton, pButton); pButton->SetRect (rect); if (bHorz) { rect.OffsetRect (-iButtonWidth - 1, 0); } else { rect.OffsetRect (0, -iButtonHeight - 1); } } } //*************************************************************************************** BOOL CBCGMenuBar::OnSendCommand (const CBCGToolbarButton* pButton) { CBCGToolbarMenuButtonsButton* pSysButton = DYNAMIC_DOWNCAST (CBCGToolbarMenuButtonsButton, pButton); if (pSysButton == NULL) { return FALSE; } if (pSysButton->m_uiSystemCommand != SC_CLOSE && pSysButton->m_uiSystemCommand != SC_MINIMIZE && pSysButton->m_uiSystemCommand != SC_RESTORE) { ASSERT (FALSE); return TRUE; } CMDIFrameWnd* pParentFrame = DYNAMIC_DOWNCAST (CMDIFrameWnd, m_pParentWnd); if (pParentFrame == NULL) { MessageBeep ((UINT) -1); return TRUE; } CMDIChildWnd* pChild = pParentFrame->MDIGetActive (); ASSERT_VALID (pChild); pChild->SendMessage (WM_SYSCOMMAND, pSysButton->m_uiSystemCommand); return TRUE; } //************************************************************************************* int CBCGMenuBar::OnToolHitTest(CPoint point, TOOLINFO* pTI) const { ASSERT_VALID(this); int nHit = ((CBCGMenuBar*)this)->HitTest(point); if (nHit != -1) { CBCGToolbarButton* pButton = GetButton (nHit); if (pButton == NULL || pButton->IsKindOf (RUNTIME_CLASS (CBCGToolbarMenuButton))) { //----------------------------------- // Don't show tooltips on menu items! //----------------------------------- return -1; } } return CBCGToolBar::OnToolHitTest (point, pTI); } //************************************************************************************* int CBCGMenuBar::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CBCGToolBar::OnCreate(lpCreateStruct) == -1) return -1; //------------------------------------ // Attach menubar to the parent frame: //------------------------------------ //---------------------- // First, try MDI frame: //---------------------- CBCGMDIFrameWnd* pWndParentMDIFrame = DYNAMIC_DOWNCAST (CBCGMDIFrameWnd, m_pParentWnd); if (pWndParentMDIFrame != NULL) { pWndParentMDIFrame->m_Impl.SetMenuBar (this); } else { CBCGFrameWnd* pWndParentFrame = DYNAMIC_DOWNCAST (CBCGFrameWnd, m_pParentWnd); if (pWndParentFrame != NULL) { pWndParentFrame->m_Impl.SetMenuBar (this); } else { CBCGOleIPFrameWnd* pOleFrame = DYNAMIC_DOWNCAST (CBCGOleIPFrameWnd, GetParentFrame ()); if (pOleFrame != NULL) { pOleFrame->m_Impl.SetMenuBar (this); } } } //---------------------------- // Set default menu bar title: //---------------------------- CBCGLocalResource locaRes; CString strTitle; strTitle.LoadString (IDS_BCGBARRES_MENU_BAR_TITLE); SetWindowText (strTitle); //------------------------------------------------------------- // Force the menu bar to be hiden whren the in-place editing is // is activated (server application shows its own menu): //------------------------------------------------------------- SetBarStyle (GetBarStyle() | CBRS_HIDE_INPLACE); //------------------------------ // Calculate system button size: //------------------------------ CalcSysButtonSize (); return 0; } //************************************************************************************* BOOL CBCGMenuBar::LoadState (LPCTSTR lpszProfileName, int nIndex, UINT /*uiID*/) { ASSERT (m_hDefaultMenu != NULL); CString strProfileName = ::BCGGetRegPath (strMenuProfile, lpszProfileName); //------------------------------------------------------------ // Save current maximize mode (system buttons are not saved!): //------------------------------------------------------------ BOOL bMaximizeMode = m_bMaximizeMode; SetMaximizeMode (FALSE); CDocManager* pDocManager = AfxGetApp ()->m_pDocManager; if (m_bAutoDocMenus && pDocManager != NULL) { //--------------------------------------- // Walk all templates in the application: //--------------------------------------- for (POSITION pos = pDocManager->GetFirstDocTemplatePosition (); pos != NULL;) { CBCGMultiDocTemplate* pTemplate = (CBCGMultiDocTemplate*) pDocManager->GetNextDocTemplate (pos); ASSERT_VALID (pTemplate); ASSERT_KINDOF (CDocTemplate, pTemplate); //----------------------------------------------------- // We are interessing CMultiDocTemplate objects with // the sahred menu only.... //----------------------------------------------------- if (!pTemplate->IsKindOf (RUNTIME_CLASS (CMultiDocTemplate)) || pTemplate->m_hMenuShared == NULL) { continue; } UINT uiMenuResId = pTemplate->GetResId (); ASSERT (uiMenuResId != 0); //--------------------------------------------------------------- // Load menubar from registry and associate it with the // template shared menu: //--------------------------------------------------------------- if (CBCGToolBar::LoadState (strProfileName, nIndex, uiMenuResId)) { g_menuHash.SaveMenuBar (pTemplate->m_hMenuShared, this); } } } //---------------------- // Load defualt menubar: //---------------------- if (CBCGToolBar::LoadState (strProfileName, nIndex, 0)) { g_menuHash.SaveMenuBar (m_hDefaultMenu, this); } //---------------------- // Restore current menu: //---------------------- if (bMaximizeMode) { RestoreMaximizeMode (); } if (m_hMenu != NULL && g_menuHash.LoadMenuBar (m_hMenu, this)) { GetParentFrame ()->RecalcLayout (); Invalidate (); UpdateWindow (); } RebuildAccelerationKeys (); return TRUE; } //************************************************************************************* BOOL CBCGMenuBar::SaveState (LPCTSTR lpszProfileName, int nIndex, UINT /*uiID*/) { ASSERT (m_hDefaultMenu != NULL); CString strProfileName = ::BCGGetRegPath (strMenuProfile, lpszProfileName); g_menuHash.SaveMenuBar (m_hMenu, this); //------------------------------------------------------------ // Save current maximize mode (system buttons are not saved!): //------------------------------------------------------------ BOOL bMaximizeMode = m_bMaximizeMode; SetMaximizeMode (FALSE); CDocManager* pDocManager = AfxGetApp ()->m_pDocManager; if (m_bAutoDocMenus && pDocManager != NULL) { //--------------------------------------- // Walk all templates in the application: //--------------------------------------- for (POSITION pos = pDocManager->GetFirstDocTemplatePosition (); pos != NULL;) { CBCGMultiDocTemplate* pTemplate = (CBCGMultiDocTemplate*) pDocManager->GetNextDocTemplate (pos); ASSERT_VALID (pTemplate); ASSERT_KINDOF (CDocTemplate, pTemplate); //----------------------------------------------------- // We are interessing CMultiDocTemplate objects with // the sahred menu only.... //----------------------------------------------------- if (!pTemplate->IsKindOf (RUNTIME_CLASS (CMultiDocTemplate)) || pTemplate->m_hMenuShared == NULL) { continue; } UINT uiMenuResId = pTemplate->GetResId (); ASSERT (uiMenuResId != 0); //---------------------------------------------------------- // Load menubar associated with the template shared menu and // save it in the registry: //---------------------------------------------------------- if (g_menuHash.LoadMenuBar (pTemplate->m_hMenuShared, this)) { CBCGToolBar::SaveState (strProfileName, nIndex, uiMenuResId); } } } //------------------- // Save default menu: //------------------- if (g_menuHash.LoadMenuBar (m_hDefaultMenu, this)) { CBCGToolBar::SaveState (strProfileName, nIndex, 0); } //---------------------- // Restore current menu: //---------------------- if (m_hMenu != NULL && g_menuHash.LoadMenuBar (m_hMenu, this)) { GetParentFrame ()->RecalcLayout (); Invalidate (); UpdateWindow (); } if (bMaximizeMode) { RestoreMaximizeMode (); } return TRUE; } //***************************************************************************************** void CBCGMenuBar::OnLButtonDown(UINT nFlags, CPoint point) { int iHit = HitTest (point); //-------------------------------------------------------- // Disable control bar dragging if any menues are dropped! //-------------------------------------------------------- if (iHit < 0 && // Click outside of buttons GetDroppedDownMenu () != NULL) { // Do nothing } else { CBCGToolBar::OnLButtonDown(nFlags, point); } } //**************************************************************************************** BOOL CBCGMenuBar::RestoreOriginalstate () { ASSERT (m_hMenu != NULL); HMENU hMenuCurr = m_hMenu; g_menuHash.SaveMenuBar (m_hMenu, this); BOOL bCurrMenuIsRestored = FALSE; //------------------------------------------------------------ // Save current maximize mode (system buttons are not saved!): //------------------------------------------------------------ BOOL bMaximizeMode = m_bMaximizeMode; SetMaximizeMode (FALSE); CDocManager* pDocManager = AfxGetApp ()->m_pDocManager; if (pDocManager != NULL) { //--------------------------------------- // Walk all templates in the application: //--------------------------------------- for (POSITION pos = pDocManager->GetFirstDocTemplatePosition (); pos != NULL;) { CBCGMultiDocTemplate* pTemplate = (CBCGMultiDocTemplate*) pDocManager->GetNextDocTemplate (pos); ASSERT_VALID (pTemplate); ASSERT_KINDOF (CDocTemplate, pTemplate); //----------------------------------------------------- // We are interessing CMultiDocTemplate objects with // the shared menu only.... //----------------------------------------------------- if (!pTemplate->IsKindOf (RUNTIME_CLASS (CMultiDocTemplate)) || pTemplate->m_hMenuShared == NULL) { continue; } UINT uiMenuResId = pTemplate->GetResId (); ASSERT (uiMenuResId != 0); //------------------------------------- // Restore original menu from resource: //------------------------------------- HINSTANCE hInst = AfxFindResourceHandle ( MAKEINTRESOURCE (uiMenuResId), RT_MENU); BOOL bCurr = (hMenuCurr == pTemplate->m_hMenuShared); pTemplate->m_hMenuShared = ::LoadMenu (hInst, MAKEINTRESOURCE (uiMenuResId)); CreateFromMenu (pTemplate->m_hMenuShared, FALSE); g_menuHash.SaveMenuBar (pTemplate->m_hMenuShared, this); if (bCurr) { hMenuCurr = pTemplate->m_hMenuShared; bCurrMenuIsRestored = TRUE; } } } //---------------------- // Load defualt menubar: //---------------------- if (m_uiDefMenuResId != 0) { HINSTANCE hInst = AfxFindResourceHandle ( MAKEINTRESOURCE (m_uiDefMenuResId), RT_MENU); m_hDefaultMenu = ::LoadMenu (hInst, MAKEINTRESOURCE (m_uiDefMenuResId)); OnDefaultMenuLoaded(m_hDefaultMenu); CreateFromMenu (m_hDefaultMenu, TRUE); g_menuHash.SaveMenuBar (m_hDefaultMenu, this); if (!bCurrMenuIsRestored) { hMenuCurr = m_hDefaultMenu; } } //---------------------- // Restore current menu: //---------------------- if (g_menuHash.LoadMenuBar (hMenuCurr, this)) { m_hMenu = hMenuCurr; if (!bMaximizeMode) { GetParentFrame ()->RecalcLayout (); Invalidate (); UpdateWindow (); } } if (bMaximizeMode) { RestoreMaximizeMode (); } return TRUE; } //******************************************************************************************** void CBCGMenuBar::SetDefaultMenuResId (UINT uiResId) { m_uiDefMenuResId = uiResId; } //****************************************************************** BOOL CBCGMenuBar::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_KEYDOWN) { //----------------------------------------------------------- // Fisrt, try to move keyboard control to the drop-down menu: //----------------------------------------------------------- CBCGToolbarMenuButton* pMenuButon = GetDroppedDownMenu (); if (pMenuButon != NULL) { return CControlBar::PreTranslateMessage(pMsg); } int iTotalItems = GetCount (); if (m_bMaximizeMode) { iTotalItems -= m_nSystemButtonsNum; } if (m_iHighlighted >= 0 && m_iHighlighted < iTotalItems) { int iButton = m_iHighlighted; switch (pMsg->wParam) { case VK_ESCAPE: { Deactivate (); RestoreFocus (); m_bShowAllCommands = FALSE; } break; case VK_RIGHT: if (++ m_iHighlighted >= iTotalItems) { m_iHighlighted = 0; } InvalidateButton (iButton); InvalidateButton (m_iHighlighted); UpdateWindow (); break; case VK_LEFT: if (-- m_iHighlighted < 0) { m_iHighlighted = iTotalItems - 1; } InvalidateButton (iButton); InvalidateButton (m_iHighlighted); UpdateWindow (); break; case VK_DOWN: DropDownMenu (GetButton (m_iHighlighted)); return TRUE; case VK_RETURN: if (!DropDownMenu (GetButton (m_iHighlighted))) { ProcessCommand (GetButton (m_iHighlighted)); } return TRUE; default: if (TranslateChar ((int) pMsg->wParam)) { return TRUE; } } } } return CBCGToolBar::PreTranslateMessage(pMsg); } //************************************************************************************** void CBCGMenuBar::OnSetFocus(CWnd* pOldWnd) { CBCGToolBar::OnSetFocus(pOldWnd); if (GetDroppedDownMenu () == NULL) { GetOwner()->SendMessage (WM_SETMESSAGESTRING, AFX_IDS_IDLEMESSAGE); int iFirstItem = (m_bMaximizeMode) ? 1 : 0; if (m_iHighlighted < 0 && iFirstItem < GetCount ()) { m_iHighlighted = iFirstItem; InvalidateButton (iFirstItem); } } } //************************************************************************************** BOOL CBCGMenuBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID) { m_pParentWnd = pParentWnd; return CBCGToolBar::Create (pParentWnd, dwStyle, nID); } //*************************************************************************************** BOOL CBCGMenuBar::CreateEx(CWnd* pParentWnd, DWORD dwCtrlStyle, DWORD dwStyle, CRect rcBorders, UINT nID) { m_pParentWnd = pParentWnd; return CBCGToolBar::CreateEx (pParentWnd, dwCtrlStyle, dwStyle, rcBorders, nID); } //*************************************************************************************** LRESULT CALLBACK CBCGMenuBar::BCGMenuBarMouseProc (int nCode, WPARAM wParam, LPARAM lParam) { MOUSEHOOKSTRUCT* lpMS = (MOUSEHOOKSTRUCT*) lParam; ASSERT (lpMS != NULL); if (wParam == WM_LBUTTONUP || wParam == WM_NCLBUTTONUP) { if (m_pDraggedMenuBar != NULL && m_pDraggedMenuBar->m_pDockContext != NULL && m_pDraggedMenuBar->m_pDockContext->m_bDragging) { //------------------------------------------------------------------------ // End of dragging. Don't allow the menubar to be docked on the right side // of any control bars! //------------------------------------------------------------------------ m_pDraggedMenuBar->m_pDockContext->m_rectDragVert.top = 0; m_pDraggedMenuBar->m_pDockContext->m_rectDragHorz.left = 0; m_pDraggedMenuBar->SetDragMode (FALSE); } } return CallNextHookEx (m_hookMouseDrag, nCode, wParam, lParam); } //************************************************************************************************ void CBCGMenuBar::SetDragMode (BOOL bOn) { if (bOn) { if (m_hookMouseDrag == NULL) // Not installed yet, set it now! { m_hookMouseDrag = ::SetWindowsHookEx (WH_MOUSE, BCGMenuBarMouseProc, 0, GetCurrentThreadId ()); if (m_hookMouseDrag == NULL) { TRACE (_T("CBCGMenuBar: Can't set mouse hook!\n")); return; } } m_pDraggedMenuBar = this; } else { if (m_hookMouseDrag != NULL) { ::UnhookWindowsHookEx (m_hookMouseDrag); m_hookMouseDrag = NULL; } m_pDraggedMenuBar = NULL; } } //************************************************************************************************ void CBCGMenuBar::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) { CBCGToolBar::OnWindowPosChanged(lpwndpos); SetDragMode (FALSE); } //***************************************************************************************** CSize CBCGMenuBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz) { if (m_Buttons.IsEmpty ()) { return GetButtonSize (); } DWORD dwMode = bStretch ? LM_STRETCH : 0; dwMode |= bHorz ? LM_HORZ : 0; return CalcLayout (dwMode); } //***************************************************************************************** BOOL CBCGMenuBar::OnSetDefaultButtonText (CBCGToolbarButton* pButton) { ASSERT_VALID (pButton); CString strText; if (FindMenuItemText (m_hMenu, pButton->m_nID, strText)) { pButton->m_strText = strText; return TRUE; } return CBCGToolBar::OnSetDefaultButtonText (pButton); } //**************************************************************************************** BOOL CBCGMenuBar::FindMenuItemText (HMENU hMenu, const UINT nItemID, CString& strOutText) { if (hMenu == NULL || nItemID == 0 || nItemID == (UINT) -1) { return FALSE; } CMenu* pMenu = CMenu::FromHandle (hMenu); if (pMenu == NULL) { return FALSE; } int iCount = (int) pMenu->GetMenuItemCount (); for (int i = 0; i < iCount; i ++) { UINT uiID = pMenu->GetMenuItemID (i); if (uiID == nItemID) // Found! { pMenu->GetMenuString (i, strOutText, MF_BYPOSITION); return TRUE; } else if (uiID == -1) // Pop-up menu { CMenu* pPopupMenu = pMenu->GetSubMenu (i); ASSERT (pPopupMenu != NULL); if (FindMenuItemText (pPopupMenu->GetSafeHmenu (), nItemID, strOutText)) { return TRUE; } } } return FALSE; } //****************************************************************************************** int CBCGMenuBar::FindDropIndex (const CPoint point, CRect& rectDrag) const { int iIndex = CBCGToolBar::FindDropIndex (point, rectDrag); if (m_bMaximizeMode && iIndex >= 0) { //-------------------------------------- // Maybe drag left from the system icon? //-------------------------------------- if (iIndex == 0) { return -1; } //----------------------------------------- // Maybe drag right of the system buttons? //----------------------------------------- if (iIndex > GetCount () - m_nSystemButtonsNum) { iIndex = GetCount () - m_nSystemButtonsNum; if (m_nSystemButtonsNum > 0) { //---------------------------------------------------------- // Put drag rectangle right of the last "non-system" button: //---------------------------------------------------------- CBCGToolbarButton* pLastButton = GetButton (iIndex - 1); ASSERT_VALID (pLastButton); CRect rectBtn = pLastButton->Rect (); CPoint ptDrag (rectBtn.right, rectBtn.top + rectBtn.Height () / 2); VERIFY (CBCGToolBar::FindDropIndex (ptDrag, rectDrag) == iIndex); } } } return iIndex; } //**************************************************************************************** void CBCGMenuBar::OnChangeHot (int iHot) { CBCGToolBar::OnChangeHot (iHot); KillTimer (uiShowAllItemsTimerId); if (GetDroppedDownMenu () == NULL) { m_bShowAllCommands = FALSE; } else { SetTimer (uiShowAllItemsTimerId, iShowAllItemsTimerFreq, NULL); } } //**************************************************************************************** void CBCGMenuBar::SetShowAllCommands (BOOL bShowAllCommands) { m_bShowAllCommands = bShowAllCommands; } //*************************************************************************************** CBCGToolbarButton* CBCGMenuBar::GetMenuItem (int iItem) const { if (m_bMaximizeMode) { iItem --; // Ignore system-menu button } return GetButton (iItem); } //*************************************************************************************** CBCGToolbarSystemMenuButton* CBCGMenuBar::GetSystemMenu () const { if (!m_bMaximizeMode) { return NULL; } ASSERT (!m_Buttons.IsEmpty ()); return DYNAMIC_DOWNCAST (CBCGToolbarSystemMenuButton, m_Buttons.GetHead ()); } //*************************************************************************************** CBCGToolbarMenuButtonsButton* CBCGMenuBar::GetSystemButton (UINT uiBtn, BOOL bByCommand) const { if (!m_bMaximizeMode) { return NULL; } if (bByCommand) { for (POSITION pos = m_Buttons.GetTailPosition (); pos != NULL;) { CBCGToolbarMenuButtonsButton* pButton = DYNAMIC_DOWNCAST (CBCGToolbarMenuButtonsButton, m_Buttons.GetPrev (pos)); if (pButton == NULL) { break; } if (pButton->m_nID == uiBtn) { return pButton; } } return NULL; } // else - by index: if ((int) uiBtn < 0 || (int) uiBtn >= m_nSystemButtonsNum) { ASSERT (FALSE); return NULL; } int iIndex = m_Buttons.GetCount () - m_nSystemButtonsNum + uiBtn; CBCGToolbarMenuButtonsButton* pButton = DYNAMIC_DOWNCAST (CBCGToolbarMenuButtonsButton, GetButton (iIndex)); ASSERT_VALID (pButton); return pButton; } //************************************************************************************ BOOL CBCGMenuBar::SetMenuFont (LPLOGFONT lpLogFont, BOOL bHorz) { if (!globalData.SetMenuFont (lpLogFont, bHorz)) { return FALSE; } //------------------------------------------- // Recalculate all toolbars and menus layout: //------------------------------------------- extern CObList gAllToolbars; for (POSITION pos = gAllToolbars.GetHeadPosition (); pos != NULL;) { CBCGToolBar* pToolBar = (CBCGToolBar*) gAllToolbars.GetNext (pos); ASSERT (pToolBar != NULL); if (CWnd::FromHandlePermanent (pToolBar->m_hWnd) != NULL) { ASSERT_VALID(pToolBar); pToolBar->AdjustLayout (); } } return TRUE; } //************************************************************************************ inline const CFont& CBCGMenuBar::GetMenuFont (BOOL bHorz) { return bHorz ? globalData.fontRegular : globalData.fontVert; } //************************************************************************************ void CBCGMenuBar::OnTimer(UINT nIDEvent) { if (nIDEvent == uiShowAllItemsTimerId) { CPoint ptCursor; ::GetCursorPos (&ptCursor); ScreenToClient (&ptCursor); //-------------------------------------------------------------- // Check that the popup-menu is still exist and mouse cursor is // within the menu button: //-------------------------------------------------------------- CBCGToolbarMenuButton* pMenuButon = GetDroppedDownMenu (); if (pMenuButon != NULL && pMenuButon->m_pPopupMenu != NULL && pMenuButon->m_rect.PtInRect (ptCursor) && !pMenuButon->m_pPopupMenu->AreAllCommandsShown ()) { pMenuButon->m_pPopupMenu->ShowAllCommands (); } KillTimer (uiShowAllItemsTimerId); } CBCGToolBar::OnTimer(nIDEvent); } //******************************************************************************************* void CBCGMenuBar::OnLButtonDblClk(UINT nFlags, CPoint point) { CBCGToolBar::OnLButtonDblClk(nFlags, point); if (IsShowAllCommands () || IsCustomizeMode ()) { return; } int iButton = HitTest(point); if (iButton < 0) { return; } CBCGToolbarMenuButton* pMenuButton = DYNAMIC_DOWNCAST (CBCGToolbarMenuButton, GetButton(iButton)); if (pMenuButton == NULL) { return; } ////////////////////////////////////////////// // Add by Yuhu.Wang on 99/11/04 // Special deal to system menu button //-------------------------------------------- if(pMenuButton->IsKindOf (RUNTIME_CLASS (CBCGToolbarSystemMenuButton))) { return; } //-------------------------------------------- ////////////////////////////////////////////// m_bShowAllCommands = TRUE; pMenuButton->OnCancelMode (); if (pMenuButton->OnClick (this, FALSE)) { OnChangeHot (iButton); InvalidateButton (iButton); UpdateWindow(); // immediate feedback } } //*********************************************************************************** void CBCGMenuBar::CalcSysButtonSize () { CWindowDC dc (NULL); CDC dcMem; dcMem.CreateCompatibleDC (NULL); // Assume display! int iButtonWidth = ::GetSystemMetrics (SM_CXSIZE); int iButtonHeight = ::GetSystemMetrics (SM_CYSIZE); CBitmap bmpMem; bmpMem.CreateCompatibleBitmap (&dc, iButtonWidth, iButtonHeight); CBitmap* pBmpOriginal = dcMem.SelectObject (&bmpMem); CRect rectBtn (0, 0, iButtonWidth, iButtonHeight); dcMem.DrawFrameControl (rectBtn, DFC_CAPTION, DFCS_ADJUSTRECT); m_szSystemButton = rectBtn.Size (); dcMem.SelectObject (pBmpOriginal); } //********************************************************************************* void CBCGMenuBar::OnSettingChange(UINT uFlags, LPCTSTR lpszSection) { CBCGToolBar::OnSettingChange(uFlags, lpszSection); CalcSysButtonSize (); Invalidate (); UpdateWindow (); }