bcgpopupmenubar.cpp

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

CPP
1,423
字号
//*******************************************************************************
// 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>
//*******************************************************************************

// BCGPopupMenuBar.cpp : implementation file
//

#include "stdafx.h"
#include <afxpriv.h>

#pragma warning (disable : 4201)
	#include "mmsystem.h"
#pragma warning (default : 4201)

#include "BCGPopupMenuBar.h"
#include "BCGToolbarButton.h"
#include "BCGToolbarMenuButton.h"
#include "BCGPopupMenu.h"
#include "BCGCommandManager.h"
#include "globals.h"
#include "BCGToolbarMenuButton.h"
#include "bcgbarres.h"
#include "bcglocalres.h"
#include "BCGMenuBar.h"
#include "BCGToolbarComboBoxButton.h"
#include "registry.h"

#include "XPDrawLayer.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static const int iVertMargin = 1;
static const int iHorzMargin = 1;
static const int iSeparatorHeight = 2;
static const int iMinTabSpace = 10;
static const int iEmptyMenuWidth = 50;
static const int iEmptyMenuHeight = 20;

static const int uiPopupTimerEvent = 1;

UINT CBCGPopupMenuBar::m_uiPopupTimerDelay = (UINT) -1;

/////////////////////////////////////////////////////////////////////////////
// CBCGPopupMenuBar

IMPLEMENT_SERIAL(CBCGPopupMenuBar, CBCGToolBar, 1)

CBCGPopupMenuBar::CBCGPopupMenuBar() :
	m_uiDefaultMenuCmdId (0),
	m_pDelayedPopupMenuButton (NULL),
	m_bFirstClick (TRUE),
	m_iOffset (0),
	m_xSeparatorOffsetLeft (0),
	m_xSeparatorOffsetRight (0),
	m_iMaxWidth (-1),
	m_bAreAllCommandsShown (TRUE)
{
	m_bMenuMode = TRUE;
}

CBCGPopupMenuBar::~CBCGPopupMenuBar()
{
}


BEGIN_MESSAGE_MAP(CBCGPopupMenuBar, CBCGToolBar)
	//{{AFX_MSG_MAP(CBCGPopupMenuBar)
	ON_WM_NCPAINT()
	ON_WM_NCCALCSIZE()
	ON_WM_DESTROY()
	ON_WM_TIMER()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CBCGPopupMenuBar message handlers

BOOL CBCGPopupMenuBar::OnSendCommand (const CBCGToolbarButton* pButton)
{
	ASSERT_VALID (pButton);

	if ((pButton->m_nStyle & TBBS_DISABLED) != 0 ||
		pButton->m_nID < 0 || pButton->m_nID == (UINT)-1)
	{
		return FALSE;
	}

	CBCGToolbarMenuButton* pMenuButton = 
		DYNAMIC_DOWNCAST (CBCGToolbarMenuButton, pButton);
	if (pMenuButton != NULL && pMenuButton->m_pPopupMenu != NULL)
	{
		return FALSE;
	}

	InvokeMenuCommand (pButton->m_nID);
	return TRUE;
}
//**************************************************************************************
void CBCGPopupMenuBar::InvokeMenuCommand (UINT uiCmdId)
{
	ASSERT (uiCmdId != (UINT) -1);

	GetOwner()->SendMessage(WM_SETMESSAGESTRING, AFX_IDS_IDLEMESSAGE);

	//--------------------
	// Deactivate menubar:
	//--------------------
	CBCGPopupMenu* pParentMenu = DYNAMIC_DOWNCAST (CBCGPopupMenu, GetParent ());
	if (pParentMenu != NULL)
	{
		CBCGToolBar* pToolBar = pParentMenu->GetParentToolBar ();
		if (pToolBar != NULL)
		{
			pToolBar->Deactivate ();
		}
	}

	CFrameWnd* pParentFrame = GetParentFrame ();
	ASSERT_VALID (pParentFrame);

	if (uiCmdId != 0)
	{
		//----------------------------------
		// Play standard menu command sound!
		//----------------------------------
		PlaySound (_T("MenuCommand"), NULL, SND_ASYNC | SND_NODEFAULT);

		//----------------------------------
		// Send command to the parent frame:
		//----------------------------------
		AddCommandUsage (uiCmdId);
		GetOwner()->PostMessage (WM_COMMAND, uiCmdId);
	}

	pParentFrame->DestroyWindow ();
}
//***************************************************************
void CBCGPopupMenuBar::AdjustLocations ()
{
	if (GetSafeHwnd () == NULL ||
		!::IsWindow (m_hWnd))
	{
		return;
	}

	ASSERT_VALID(this);

	if (m_xSeparatorOffsetLeft == 0)
	{
		//-----------------------------------------------------------
		// To enable MS Office 2000 look, we'll draw the separators
		// bellow the menu text only (in the previous versions
		// separator has been drawn on the whole menu row). Ask
		// menu button about text area offsets:
		//-----------------------------------------------------------
		CBCGToolbarMenuButton::GetTextHorzOffsets (
			m_xSeparatorOffsetLeft,
			m_xSeparatorOffsetRight);
	}

	CRect rectClient;	// Client area rectangle
	GetClientRect (&rectClient);

	CClientDC dc (this);
	CFont* pOldFont = (CFont*) dc.SelectObject (&globalData.fontRegular);
	ASSERT (pOldFont != NULL);

	int y = rectClient.top + iVertMargin - m_iOffset * GetRowHeight ();

	/// By Guy Hachlili - support for the menu with breaks:
	int origy = y;
	int x = rectClient.left;
	int right = (m_arColumns.GetSize() == 0 ||
		CBCGToolBar::IsCustomizeMode ()) ?	
			rectClient.Width() :
			m_arColumns [0];
	int nColumn = 0;
	/////////

	CSize sizeMenuButton = GetMenuImageSize ();
	sizeMenuButton += CSize (2 * iHorzMargin, 2 * iVertMargin);

	sizeMenuButton.cy = max (sizeMenuButton.cy, 
							globalData.GetTextHeight ());

	for (POSITION pos = m_Buttons.GetHeadPosition (); pos != NULL;)
	{
		CBCGToolbarButton* pButton = (CBCGToolbarButton*) m_Buttons.GetNext (pos);
		ASSERT (pButton != NULL);

		/// By Guy Hachlili - support for the menu with breaks:
		if ((pButton->m_nStyle & TBBS_BREAK) && (y != origy) &&
			!CBCGToolBar::IsCustomizeMode ())
		{
			y = origy;
			nColumn ++;
			x = right + iHorzMargin;
			right = m_arColumns [nColumn];
		}
		////////////////////
		
		CRect rectButton;
		rectButton.top = y;

		if (pButton->m_nStyle & TBBS_SEPARATOR)
		{
			rectButton.left = x + m_xSeparatorOffsetLeft;
			rectButton.right = right + rectClient.left - m_xSeparatorOffsetRight;
			rectButton.bottom = rectButton.top + iSeparatorHeight;
		}
		else
		{
			CSize sizeButton = pButton->OnCalculateSize (&dc, 
									sizeMenuButton, TRUE);

			rectButton.left = x;
			rectButton.right = right + rectClient.left;
			rectButton.bottom = rectButton.top + sizeButton.cy;
		}

		pButton->SetRect (rectButton);
		y += rectButton.Height ();
	}

	dc.SelectObject (pOldFont);

	//--------------------------------------------------
	// Something may changed, rebuild acceleration keys:
	//--------------------------------------------------
	RebuildAccelerationKeys ();
}
//***************************************************************************************
void CBCGPopupMenuBar::DrawSeparator (CDC* pDC, const CRect& rect, BOOL /*bHorz*/)
{
    #define IMAGE_MARGIN	6
    int nOffSet = CBCGToolBar::GetMenuImageSize ().cx/2;

    //draw basic backgroung
	{
      CRect rcBk(rect);
	  rcBk.DeflateRect(nOffSet+1,0,-(nOffSet+IMAGE_MARGIN),0);
	  CBrush br;
      br.CreateSolidBrush(GuiDrawLayer::GetRGBMenuItemBackGrnd());
	  pDC->FillRect(rcBk,&br);
	  br.DeleteObject();
	}

	CRect rectSeparator = rect;
	rectSeparator.top += rectSeparator.Height () / 2;
	rectSeparator.bottom = rectSeparator.top + 1;

	rectSeparator.DeflateRect(nOffSet+IMAGE_MARGIN+1,0,-(nOffSet+IMAGE_MARGIN),0);
	/**
	pDC->Draw3dRect (rectSeparator, globalData.clrBtnShadow,
									globalData.clrBtnHilite);
    **/
	CBrush cbt;
	cbt.CreateSolidBrush(RGB(167, 167, 167));
	pDC->FillRect(rectSeparator,&cbt);
	cbt.DeleteObject();
}
//***************************************************************************************
CSize CBCGPopupMenuBar::CalcSize ()
{
	CSize size (0, 0);

	CClientDC dc (this);
	CFont* pOldFont = (CFont*) dc.SelectObject (&globalData.fontRegular);
	ASSERT (pOldFont != NULL);

	if (m_Buttons.IsEmpty ())
	{
		size = CSize (iEmptyMenuWidth, iEmptyMenuHeight);
	}
	else
	{
		//////// By Guy Hachlili - support for the menu with breaks:
		CSize column (0, 0);
		m_arColumns.RemoveAll ();
		//////////////////////////

		CSize sizeMenuButton = GetMenuImageSize ();
		sizeMenuButton += CSize (2 * iHorzMargin, 2 * iVertMargin);

		sizeMenuButton.cy = max (sizeMenuButton.cy, 
								globalData.GetTextHeight ());

		for (POSITION pos = m_Buttons.GetHeadPosition (); pos != NULL;)
		{
			CBCGToolbarButton* pButton = (CBCGToolbarButton*) m_Buttons.GetNext (pos);
			ASSERT (pButton != NULL);

			CSize sizeButton = pButton->OnCalculateSize (&dc, 
				sizeMenuButton, TRUE);

			//////// By Guy Hachlili - support for the menu with breaks:
			if ((pButton->m_nStyle & TBBS_BREAK) &&
				!CBCGToolBar::IsCustomizeMode ())
			{
				if ((column.cx != 0) && (column.cy != 0))
				{
					size.cy = max (column.cy, size.cy);
					size.cx += column.cx + iHorzMargin;
					m_arColumns.Add (size.cx);
				}
				column.cx = column.cy = 0;
			}
			///////////////////////////////

			int iHeight = sizeButton.cy;

			if (pButton->m_nStyle & TBBS_SEPARATOR)
			{
				iHeight = iSeparatorHeight;
			}
			else
			{
				if (pButton->IsDrawText () &&
					pButton->m_strText.Find (_T('\t')) > 0)
				{
					sizeButton.cx += iMinTabSpace;
				}

				pButton->m_bWholeText = 
					(m_iMaxWidth <= 0 || 
					sizeButton.cx <= m_iMaxWidth - 2 * iHorzMargin);

				column.cx = max (sizeButton.cx, column.cx);
			}

			column.cy += iHeight;
		}

		size.cy = max (column.cy, size.cy);
		size.cx += column.cx;
	}

	size.cy += 2 * iVertMargin;
	size.cx += 2 * iHorzMargin;

	if (m_iMaxWidth > 0 && size.cx > m_iMaxWidth)
	{
		size.cx = m_iMaxWidth;
	}

	m_arColumns.Add (size.cx);

	dc.SelectObject (pOldFont);
	return size;
}
//***************************************************************************************
void CBCGPopupMenuBar::OnNcPaint() 
{
	//--------------------------------------
	// Disable gripper and borders painting!
	//--------------------------------------
}
//***************************************************************************************
void CBCGPopupMenuBar::OnNcCalcSize(BOOL /*bCalcValidRects*/, NCCALCSIZE_PARAMS FAR* /*lpncsp*/) 
{
	//-----------------------------------------------
	// Don't leave space for the gripper and borders!
	//-----------------------------------------------
}
//****************************************************************************************
void CBCGPopupMenuBar::DrawDragMarker (CDC* pDC)
{
	CPen* pOldPen = (CPen*) pDC->SelectObject (&m_penDrag);

	for (int i = 0; i < 2; i ++)
	{
		pDC->MoveTo (m_rectDrag.left, m_rectDrag.top + m_rectDrag.Height () / 2 + i - 1);
		pDC->LineTo (m_rectDrag.right, m_rectDrag.top + m_rectDrag.Height () / 2 + i - 1);

		pDC->MoveTo (m_rectDrag.left + i, m_rectDrag.top + i);
		pDC->LineTo (m_rectDrag.left + i, m_rectDrag.bottom - i);

		pDC->MoveTo (m_rectDrag.right - i - 1, m_rectDrag.top + i);
		pDC->LineTo (m_rectDrag.right - i - 1, m_rectDrag.bottom - i);
	}

	pDC->SelectObject (pOldPen);
}
//********************************************************************************
int CBCGPopupMenuBar::FindDropIndex (const CPoint p, CRect& rectDrag) const
{
	const int iCursorSize = 6;

	GetClientRect (&rectDrag);

	if (m_Buttons.IsEmpty ())
	{
		rectDrag.bottom = rectDrag.top + iCursorSize;
		return 0;
	}

	CPoint point = p;
	if (point.y < 0)
	{
		point.y = 0;
	}

	int iDragButton = -1;
	int iIndex = 0;
	for (POSITION pos = m_Buttons.GetHeadPosition (); pos != NULL; iIndex ++)
	{
		CBCGToolbarButton* pButton = (CBCGToolbarButton*) m_Buttons.GetNext (pos);
		ASSERT (pButton != NULL);

		CRect rect = pButton->Rect ();
		if (point.y < rect.top)
		{
			iDragButton = iIndex;
			rectDrag.top = rect.top;
			break;
		}
		else if (point.y <= rect.bottom)
		{
			rectDrag = rect;
			if (point.y - rect.top > rect.bottom - point.y)
			{
				iDragButton = iIndex + 1;
				rectDrag.top = rectDrag.bottom;
			}
			else
			{
				iDragButton = iIndex;
				rectDrag.top = rect.top;
			}
			break;
		}
	}

	if (iDragButton == -1)
	{
		rectDrag.top = rectDrag.bottom - iCursorSize;
		iDragButton = iIndex;
	}

	rectDrag.bottom = rectDrag.top + iCursorSize;
	rectDrag.OffsetRect (0, -iCursorSize / 2);

	return iDragButton;
}
//***************************************************************************************
CBCGToolbarButton* CBCGPopupMenuBar::CreateDroppedButton (COleDataObject* pDataObject)
{
	CBCGToolbarButton* pButton = CBCGToolbarButton::CreateFromOleData (pDataObject);
	ASSERT (pButton != NULL);

	CBCGToolbarMenuButton* pMenuButton = 
		DYNAMIC_DOWNCAST (CBCGToolbarMenuButton, pButton);

	if (pMenuButton == NULL)
	{
		pMenuButton = new CBCGToolbarMenuButton (
			pButton->m_nID, NULL, pButton->GetImage (), pButton->m_strText,

⌨️ 快捷键说明

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