bcgmenubar.cpp

来自「用bcg库编写的java IDE 源码」· C++ 代码 · 共 1,479 行 · 第 1/3 页

CPP
1,479
字号
//*******************************************************************************
// 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.
// 
// Stas Levin <stas@iet.co.il>
//*******************************************************************************

// 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;

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_bActualMaximizeMode = 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;
	m_bMenuBar = 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_KILLFOCUS()
	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)
{
	if (GetFocus () == this)
	{
		GetParentFrame()->SetFocus ();
	}

	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 ||
		(bMax && IsCustomizeMode ()))
	{
		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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?