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 + -
显示快捷键?