www.pudn.com > editpad_src > bcgtoolbarmenubutton.cpp, change:1999-11-25,size:32840b
//*******************************************************************************
// 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>
//*******************************************************************************
// BCGToolbarMenuButton.cpp: implementation of the CBCGToolbarMenuButton class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "bcgbarres.h"
#include "BCGToolbarMenuButton.h"
#include "BCGMenuBar.h"
#include "BCGPopupMenuBar.h"
#include "BCGCommandManager.h"
#include "globals.h"
#include "BCGKeyboardManager.h"
#include "BCGFrameWnd.h"
#include "BCGMDIFrameWnd.h"
#include "BCGOleIPFrameWnd.h"
#include "MenuImages.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
static const int SEPARATOR_SIZE = 2;
static const int IMAGE_MARGIN = 2;
IMPLEMENT_SERIAL(CBCGToolbarMenuButton, CBCGToolbarButton, VERSIONABLE_SCHEMA | 1)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CBCGToolbarMenuButton::CBCGToolbarMenuButton()
{
Initialize ();
}
//*****************************************************************************************
CBCGToolbarMenuButton::CBCGToolbarMenuButton (UINT uiID, HMENU hMenu,
int iImage, LPCTSTR lpszText, BOOL bUserButton)
{
Initialize ();
m_nID = uiID;
m_bUserButton = bUserButton;
SetImage (iImage);
m_strText = (lpszText == NULL) ? _T("") : lpszText;
CreateFromMenu (hMenu);
}
//*****************************************************************************************
void CBCGToolbarMenuButton::Initialize ()
{
m_bDrawDownArrow = FALSE;
m_bMenuMode = FALSE;
m_pPopupMenu = NULL;
m_pWndParent = NULL;
m_bDefault = FALSE;
m_bClickedOnMenu = FALSE;
m_bHorz = TRUE;
}
//*****************************************************************************************
CBCGToolbarMenuButton::CBCGToolbarMenuButton (const CBCGToolbarMenuButton& src)
{
m_nID = src.m_nID;
m_nStyle = src.m_nStyle;
m_bUserButton = src.m_bUserButton;
SetImage (src.GetImage ());
m_strText = src.m_strText;
m_bDragFromCollection = FALSE;
m_bText = src.m_bText;
m_bImage = src.m_bImage;
m_bDrawDownArrow = src.m_bDrawDownArrow;
m_bMenuMode = src.m_bMenuMode;
m_bDefault = src.m_bDefault;
HMENU hmenu = src.CreateMenu ();
ASSERT (hmenu != NULL);
CreateFromMenu (hmenu);
::DestroyMenu (hmenu);
m_rect.SetRectEmpty ();
m_pPopupMenu = NULL;
m_pWndParent = NULL;
m_bClickedOnMenu = FALSE;
m_bHorz = TRUE;
}
//*****************************************************************************************
CBCGToolbarMenuButton::~CBCGToolbarMenuButton()
{
if (m_pPopupMenu != NULL)
{
m_pPopupMenu->m_pParentBtn = NULL;
}
while (!m_listCommands.IsEmpty ())
{
delete m_listCommands.RemoveHead ();
}
}
//////////////////////////////////////////////////////////////////////
// Overrides:
void CBCGToolbarMenuButton::CopyFrom (const CBCGToolbarButton& s)
{
CBCGToolbarButton::CopyFrom (s);
const CBCGToolbarMenuButton& src = (const CBCGToolbarMenuButton&) s;
m_bDefault = src.m_bDefault;
while (!m_listCommands.IsEmpty ())
{
delete m_listCommands.RemoveHead ();
}
for (POSITION pos = src.m_listCommands.GetHeadPosition (); pos != NULL;)
{
CBCGToolbarMenuButton* pItem = (CBCGToolbarMenuButton*) src.m_listCommands.GetNext (pos);
ASSERT (pItem != NULL);
ASSERT_KINDOF (CBCGToolbarMenuButton, pItem);
CRuntimeClass* pSrcClass = pItem->GetRuntimeClass ();
ASSERT (pSrcClass != NULL);
CBCGToolbarMenuButton* pNewItem = (CBCGToolbarMenuButton*) pSrcClass->CreateObject ();
ASSERT (pNewItem != NULL);
ASSERT_KINDOF (CBCGToolbarMenuButton, pNewItem);
pNewItem->CopyFrom (*pItem);
m_listCommands.AddTail (pNewItem);
}
// m_nID = 0; ?????
}
//*****************************************************************************************
void CBCGToolbarMenuButton::Serialize (CArchive& ar)
{
CBCGToolbarButton::Serialize (ar);
if (ar.IsLoading ())
{
while (!m_listCommands.IsEmpty ())
{
delete m_listCommands.RemoveHead ();
}
}
m_listCommands.Serialize (ar);
}
//*****************************************************************************************
void CBCGToolbarMenuButton::OnDraw (CDC* pDC, const CRect& rect, CBCGToolBarImages* pImages,
BOOL bHorz, BOOL bCustomizeMode, BOOL bHighlight,
BOOL bDrawBorder, BOOL bGrayDisabledButtons)
{
if (m_bMenuMode)
{
DrawMenuItem (pDC, rect, pImages, bCustomizeMode, bHighlight, bGrayDisabledButtons);
return;
}
CSize sizeImage = CMenuImages::Size ();
//---------------
// Interior grey:
//---------------
pDC->FillRect (rect, &globalData.brBtnFace);
if (!bCustomizeMode && !bHighlight &&
(m_nStyle & (TBBS_CHECKED | TBBS_INDETERMINATE)))
{
CRect rectDither = rect;
rectDither.InflateRect (-afxData.cxBorder2, -afxData.cyBorder2);
CBCGToolBarImages::FillDitheredRect (pDC, rectDither);
}
CRect rectParent = rect;
CRect rectArrow = rect;
if (m_bDrawDownArrow)
{
if (bHorz)
{
rectParent.right -= sizeImage.cx + SEPARATOR_SIZE;
rectArrow.left = rectParent.right - 1; // By Sven Ritter
}
else
{
rectParent.bottom -= sizeImage.cy + SEPARATOR_SIZE;
rectArrow.top = rectParent.bottom - 1; // By Sven Ritter
}
}
UINT uiStyle = m_nStyle;
if (m_bClickedOnMenu && m_nID != 0 && m_nID != (UINT) -1)
{
m_nStyle &= ~TBBS_PRESSED;
}
else if (m_pPopupMenu != NULL)
{
m_nStyle |= TBBS_PRESSED;
}
CBCGToolbarButton::OnDraw (pDC, rectParent, pImages, bHorz,
bCustomizeMode, bHighlight, bDrawBorder, bGrayDisabledButtons);
if (m_bDrawDownArrow)
{
if (m_nStyle & (TBBS_PRESSED | TBBS_CHECKED))
{
rectArrow.OffsetRect (1, 1);
}
if ((bHighlight || (m_nStyle & TBBS_PRESSED) ||
m_pPopupMenu != NULL) &&
m_nID != 0 && m_nID != (UINT) -1)
{
//----------------
// Draw separator:
//----------------
CRect rectSeparator = rectArrow;
if (bHorz)
{
rectSeparator.right = rectSeparator.left + SEPARATOR_SIZE;
}
else
{
rectSeparator.bottom = rectSeparator.top + SEPARATOR_SIZE;
}
pDC->Draw3dRect (rectSeparator, ::GetSysColor (COLOR_3DSHADOW),
::GetSysColor (COLOR_3DHILIGHT));
}
BOOL bDisabled = (bCustomizeMode && !IsEditable ()) ||
(!bCustomizeMode && (m_nStyle & TBBS_DISABLED));
int iImage;
if (bHorz)
{
iImage = (bDisabled) ? CMenuImages::IdArowDownDsbl : CMenuImages::IdArowDown;
}
else
{
iImage = (bDisabled) ? CMenuImages::IdArowLeftDsbl : CMenuImages::IdArowLeft;
}
if (m_pPopupMenu != NULL &&
(m_nStyle & (TBBS_PRESSED | TBBS_CHECKED)) == 0)
{
rectArrow.OffsetRect (1, 1);
}
CPoint pointImage (
rectArrow.left + (rectArrow.Width () - sizeImage.cx) / 2,
rectArrow.top + (rectArrow.Height () - sizeImage.cy) / 2);
CMenuImages::Draw (pDC, (CMenuImages::IMAGES_IDS) iImage, pointImage);
}
if (!bCustomizeMode)
{
if ((m_nStyle & (TBBS_PRESSED | TBBS_CHECKED)) ||
m_pPopupMenu != NULL)
{
//-----------------------
// Pressed in or checked:
//-----------------------
if (m_bClickedOnMenu && m_nID != 0 && m_nID != (UINT) -1)
{
pDC->Draw3dRect (&rectParent,
globalData.clrBtnHilite,
globalData.clrBtnShadow);
rectArrow.right --;
rectArrow.bottom --;
pDC->Draw3dRect (&rectArrow,
globalData.clrBtnShadow,
globalData.clrBtnHilite);
}
else
{
pDC->Draw3dRect (&rect,
globalData.clrBtnShadow,
globalData.clrBtnHilite);
}
}
else if (bHighlight && !(m_nStyle & TBBS_DISABLED) &&
!(m_nStyle & (TBBS_CHECKED | TBBS_INDETERMINATE)))
{
pDC->Draw3dRect (&rect, globalData.clrBtnHilite,
globalData.clrBtnShadow);
}
}
m_nStyle = uiStyle;
}
//*****************************************************************************************
SIZE CBCGToolbarMenuButton::OnCalculateSize (CDC* pDC, const CSize& sizeDefault, BOOL bHorz)
{
m_bHorz = bHorz;
int iArrowSize = 0;
if (m_bDrawDownArrow || m_bMenuMode)
{
iArrowSize = (bHorz) ?
CMenuImages::Size ().cx + SEPARATOR_SIZE - TEXT_MARGIN :
CMenuImages::Size ().cy + SEPARATOR_SIZE - TEXT_MARGIN;
}
//--------------------
// Change accelerator:
//--------------------
if (g_pKeyboardManager != NULL &&
m_bMenuMode &&
(m_nID 0xF000 || m_nID >= 0xF1F0)) // Not system.
{
//-----------------------------------
// Remove standard aceleration label:
//-----------------------------------
int iTabOffset = m_strText.Find (_T('\t'));
if (iTabOffset >= 0)
{
m_strText = m_strText.Left (iTabOffset);
}
//---------------------------------
// Add an actual accelartion label:
//---------------------------------
CString strAccel;
CFrameWnd* pParent = m_pWndParent == NULL ?
DYNAMIC_DOWNCAST (CFrameWnd, AfxGetMainWnd ()) :
m_pWndParent->GetTopLevelFrame ();
if (pParent != NULL &&
(CBCGKeyboardManager::FindDefaultAccelerator (
m_nID, strAccel, pParent) ||
CBCGKeyboardManager::FindDefaultAccelerator (
m_nID, strAccel, pParent->GetActiveFrame ())))
{
m_strText += _T('\t');
m_strText += strAccel;
}
}
CSize size = CBCGToolbarButton::OnCalculateSize (pDC, sizeDefault, bHorz);
if (bHorz)
{
size.cx += iArrowSize;
}
else
{
size.cy += iArrowSize;
}
if (m_bMenuMode)
{
size.cx += sizeDefault.cx + 2 * TEXT_MARGIN;
}
CBCGPopupMenuBar* pParentMenu =
DYNAMIC_DOWNCAST (CBCGPopupMenuBar, m_pWndParent);
if (pParentMenu != NULL)
{
size.cy = pParentMenu->GetRowHeight ();
}
return size;
}
//*****************************************************************************************
BOOL CBCGToolbarMenuButton::OnClick (CWnd* pWnd, BOOL bDelay)
{
ASSERT_VALID (pWnd);
m_bClickedOnMenu = FALSE;
if (m_bDrawDownArrow && !bDelay && !m_bMenuMode)
{
if (m_nID == 0 || m_nID == (UINT) -1)
{
m_bClickedOnMenu = TRUE;
}
else
{
CPoint ptMouse;
::GetCursorPos (&ptMouse);
pWnd->ScreenToClient (&ptMouse);
CRect rectArrow = m_rect;
if (m_bHorz)
{
rectArrow.left = rectArrow.right -
CMenuImages::Size ().cx - SEPARATOR_SIZE;
}
else
{
rectArrow.top = rectArrow.bottom -
CMenuImages::Size ().cy - SEPARATOR_SIZE;
}
m_bClickedOnMenu = rectArrow.PtInRect (ptMouse);
if (!m_bClickedOnMenu)
{
return FALSE;
}
}
}
if (!m_bClickedOnMenu && m_nID > 0 && m_nID != (UINT) -1 && !m_bDrawDownArrow)
{
return FALSE;
}
CBCGMenuBar* pMenuBar = DYNAMIC_DOWNCAST (CBCGMenuBar, m_pWndParent);
if (m_pPopupMenu != NULL)
{
//-----------------------------------------------------
// Second click to the popup menu item closes the menu:
//-----------------------------------------------------
ASSERT_VALID(m_pPopupMenu);
m_pPopupMenu->m_bAutoDestroyParent = FALSE;
m_pPopupMenu->DestroyWindow ();
m_pPopupMenu = NULL;
if (pMenuBar != NULL)
{
pMenuBar->SetHot (NULL);
}
}
else
{
CBCGPopupMenuBar* pParentMenu =
DYNAMIC_DOWNCAST (CBCGPopupMenuBar, m_pWndParent);
if (bDelay && pParentMenu != NULL && !CBCGToolBar::IsCustomizeMode ())
{
pParentMenu->StartPopupMenuTimer (this);
}
else
{
//------------------------------------
// Fixed by Sven Ritter (SpeedProject)
//------------------------------------
if (pMenuBar != NULL)
{
CBCGToolbarMenuButton* pCurrPopupMenuButton =
pMenuBar->GetDroppedDownMenu();
if (pCurrPopupMenuButton != NULL)
{
pCurrPopupMenuButton->OnCancelMode ();
}
}
// *** End *************************
if (!OpenPopupMenu (pWnd))
{
return FALSE;
}
}
if (pMenuBar != NULL)
{
pMenuBar->SetHot (this);
}
}
if (m_pWndParent != NULL)
{
m_pWndParent->InvalidateRect (m_rect);
}
return TRUE;
}
//****************************************************************************************
void CBCGToolbarMenuButton::OnChangeParentWnd (CWnd* pWndParent)
{
if (pWndParent != NULL)
{
if (pWndParent->IsKindOf (RUNTIME_CLASS (CBCGMenuBar)))
{
m_bDrawDownArrow = FALSE;
m_bText = TRUE;
m_bImage = FALSE;
}
else
{
m_bDrawDownArrow = (m_nID == 0 || !m_listCommands.IsEmpty ());
}
if (pWndParent->IsKindOf (RUNTIME_CLASS (CBCGPopupMenuBar)))
{
m_bMenuMode = TRUE;
m_bText = TRUE;
m_bImage = FALSE;
m_bDrawDownArrow = (m_nID == 0 || !m_listCommands.IsEmpty ());
}
else
{
m_bMenuMode = FALSE;
}
}
m_pWndParent = pWndParent;
}
//****************************************************************************************
void CBCGToolbarMenuButton::CreateFromMenu (HMENU hMenu)
{
while (!m_listCommands.IsEmpty ())
{
delete m_listCommands.RemoveHead ();
}
CMenu* pMenu = CMenu::FromHandle (hMenu);
if (pMenu == NULL)
{
return;
}
UINT uiDefaultCmd = ::GetMenuDefaultItem (hMenu, FALSE, GMDI_USEDISABLED);
int iCount = (int) pMenu->GetMenuItemCount ();
for (int i = 0; i iCount; i ++)
{
CBCGToolbarMenuButton* pItem = new CBCGToolbarMenuButton;
ASSERT_VALID (pItem);
pItem->m_nID = pMenu->GetMenuItemID (i);
pMenu->GetMenuString (i, pItem->m_strText, MF_BYPOSITION);
if (pItem->m_nID == -1) // Sub-menu...
{
CMenu* pSubMenu = pMenu->GetSubMenu (i);
pItem->CreateFromMenu (pSubMenu->GetSafeHmenu ());
}
else if (pItem->m_nID == uiDefaultCmd)
{
pItem->m_bDefault = TRUE;
}
/// By Guy Hachlili - support for the menu with breaks:
if (pMenu->GetMenuState (i, MF_BYPOSITION) & MF_MENUBREAK)
{
pItem->m_nStyle |= TBBS_BREAK;
}
/////////////////////////////
m_listCommands.AddTail (pItem);
}
}
//****************************************************************************************
HMENU CBCGToolbarMenuButton::CreateMenu () const
{
if (m_listCommands.IsEmpty () && m_nID != (UINT) -1)
{
return NULL;
}
CMenu menu;
if (!menu.CreatePopupMenu ())
{
TRACE(_T("CBCGToolbarMenuButton::CreateMenu (): Can't create popup menu!\n"));
return NULL;
}
BOOL bRes = TRUE;
DWORD dwLastError = 0;
UINT uiDefaultCmd = (UINT) -1;
int i = 0;
for (POSITION pos = m_listCommands.GetHeadPosition (); pos != NULL; i ++)
{
CBCGToolbarMenuButton* pItem = (CBCGToolbarMenuButton*) m_listCommands.GetNext (pos);
ASSERT (pItem != NULL);
ASSERT_KINDOF (CBCGToolbarButton, pItem);
UINT uiStyle = MF_STRING;
/// By Guy Hachlili - support for the menu with breaks:
if (pItem->m_nStyle & TBBS_BREAK)
{
uiStyle |= MF_MENUBREAK;
}
///////////////////////////////////////////////////////
switch (pItem->m_nID)
{
case 0: // Separator
bRes = menu.AppendMenu (MF_SEPARATOR);
if (!bRes)
{
dwLastError = GetLastError ();
}
break;
case -1: // Sub-menu
{
HMENU hSubMenu = pItem->CreateMenu ();
ASSERT (hSubMenu != NULL);
bRes = menu.AppendMenu (uiStyle | MF_POPUP,
(UINT) hSubMenu, pItem->m_strText);
if (!bRes)
{
dwLastError = GetLastError ();
}
//--------------------------------------------------------
// This is incompatibility between Windows 95 and
// NT API! (IMHO). CMenu::AppendMenu with MF_POPUP flag
// COPIES sub-menu resource under the Win NT and
// MOVES sub-menu under Win 95/98 and 2000!
//--------------------------------------------------------
if (globalData.bIsWindowsNT4)
{
::DestroyMenu (hSubMenu);
}
}
break;
default:
if (pItem->m_bDefault)
{
uiDefaultCmd = pItem->m_nID;
}
bRes = menu.AppendMenu (uiStyle, pItem->m_nID, pItem->m_strText);
if (!bRes)
{
dwLastError = GetLastError ();
}
}
if (!bRes)
{
TRACE(_T("CBCGToolbarMenuButton::CreateMenu (): Can't add menu item: %d\n Last error = %x\n"), pItem->m_nID, dwLastError);
return NULL;
}
}
HMENU hMenu = menu.Detach ();
if (uiDefaultCmd != (UINT)-1)
{
::SetMenuDefaultItem (hMenu, uiDefaultCmd, FALSE);
}
return hMenu;
}
//*****************************************************************************************
void CBCGToolbarMenuButton::DrawMenuItem (CDC* pDC, const CRect& rect, CBCGToolBarImages* pImages,
BOOL bCustomizeMode, BOOL bHighlight, BOOL bGrayDisabledButtons)
{
ASSERT_VALID (pDC);
ASSERT_VALID (this);
CSize sizeImage = CMenuImages::Size ();
BOOL bDisabled = (bCustomizeMode && !IsEditable ()) ||
(!bCustomizeMode && (m_nStyle & TBBS_DISABLED));
if (m_pPopupMenu != NULL)
{
bHighlight = TRUE;
}
CFont* pOldFont = NULL;
CBCGPopupMenuBar* pParentMenu =
DYNAMIC_DOWNCAST (CBCGPopupMenuBar, m_pWndParent);
if (m_nID != 0 && m_nID != (UINT) -1 &&
pParentMenu != NULL && pParentMenu->GetDefaultMenuId () == m_nID)
{
pOldFont = (CFont*) pDC->SelectObject (&globalData.fontBold);
}
CRect rectImage;
rectImage = rect;
rectImage.left += IMAGE_MARGIN;
rectImage.right = rectImage.left + CBCGToolBar::GetMenuImageSize ().cx + IMAGE_MARGIN;
CRect rectFrameBtn = rectImage;
rectFrameBtn.InflateRect (1, -1);
BOOL bIsRarelyUsed = (CBCGMenuBar::IsRecentlyUsedMenus () &&
CBCGToolBar::IsCommandRarelyUsed (m_nID));
if (bIsRarelyUsed)
{
bIsRarelyUsed = FALSE;
CBCGPopupMenuBar* pParentMenuBar =
DYNAMIC_DOWNCAST (CBCGPopupMenuBar, m_pWndParent);
if (pParentMenuBar != NULL)
{
CBCGPopupMenu* pParentMenu = DYNAMIC_DOWNCAST (CBCGPopupMenu,
pParentMenuBar->GetParent ());
if (pParentMenu != NULL && pParentMenu->HideRarelyUsedCommands ())
{
bIsRarelyUsed = TRUE;
}
}
}
BOOL bLightImage = FALSE;
if (bIsRarelyUsed)
{
bLightImage = TRUE;
if (bHighlight && (m_nStyle & (TBBS_CHECKED | TBBS_INDETERMINATE)))
{
bLightImage = FALSE;
}
if (GetImage () 0 && !(m_nStyle & (TBBS_CHECKED | TBBS_INDETERMINATE)))
{
bLightImage = FALSE;
}
}
else if (m_nStyle & (TBBS_CHECKED | TBBS_INDETERMINATE))
{
bLightImage = !bHighlight;
}
//---------------------
// Fill "checked" area:
//---------------------
if (bLightImage)
{
CBCGToolBarImages::FillDitheredRect (pDC, rectFrameBtn);
}
//----------------
// Draw the image:
//----------------
if (!IsDrawImage ()) // Try to find a matched image
{
BOOL bImageSave = m_bImage;
BOOL bUserButton = m_bUserButton;
BOOL bSuccess = TRUE;
m_bImage = TRUE; // Always try to draw image!
m_bUserButton = TRUE;
if (GetImage () 0)
{
m_bUserButton = FALSE;
if (GetImage () 0)
{
bSuccess = FALSE;
}
}
if (!bSuccess)
{
m_bImage = bImageSave;
m_bUserButton = bUserButton;
}
}
BOOL bImageIsReady = FALSE;
CRgn rgnClip;
rgnClip.CreateRectRgnIndirect (&rectImage);
if (IsDrawImage () && pImages != NULL)
{
pDC->SelectObject (&rgnClip);
CPoint ptImageOffset (
(rectImage.Width () - CBCGToolBar::GetMenuImageSize ().cx) / 2,
(rectImage.Height () - CBCGToolBar::GetMenuImageSize ().cy) / 2);
BOOL bPressed = FALSE;
if ((m_nStyle & TBBS_CHECKED) && !bCustomizeMode)
{
ptImageOffset.x ++;
ptImageOffset.y ++;
bPressed = TRUE;
}
if ((m_nStyle & TBBS_PRESSED) || !(m_nStyle & TBBS_DISABLED) ||
bCustomizeMode)
{
pImages->Draw (pDC,
rectImage.left + ptImageOffset.x, rectImage.top + ptImageOffset.y,
GetImage ());
if (bCustomizeMode || m_nStyle & TBBS_PRESSED)
{
bImageIsReady = TRUE;
}
}
if (!bImageIsReady)
{
pImages->Draw (pDC,
rectImage.left + ptImageOffset.x, rectImage.top + ptImageOffset.y,
GetImage (), bLightImage, bDisabled && bGrayDisabledButtons);
bImageIsReady = TRUE;
}
}
else
{
CFrameWnd* pParentFrame = m_pWndParent == NULL ?
DYNAMIC_DOWNCAST (CFrameWnd, AfxGetMainWnd ()) :
m_pWndParent->GetTopLevelFrame ();
//------------------------------------
// Get chance to user draw menu image:
//------------------------------------
CBCGMDIFrameWnd* pMainFrame = DYNAMIC_DOWNCAST (CBCGMDIFrameWnd, pParentFrame);
if (pMainFrame != NULL)
{
bImageIsReady = pMainFrame->OnDrawMenuImage (pDC, this, rectImage);
}
else // Maybe, SDI frame...
{
CBCGFrameWnd* pFrame = DYNAMIC_DOWNCAST (CBCGFrameWnd, pParentFrame);
if (pFrame != NULL)
{
bImageIsReady = pFrame->OnDrawMenuImage (pDC, this, rectImage);
}
else // Maybe, OLE frame...
{
CBCGOleIPFrameWnd* pOleFrame =
DYNAMIC_DOWNCAST (CBCGOleIPFrameWnd, pParentFrame);
if (pOleFrame != NULL)
{
bImageIsReady = pOleFrame->OnDrawMenuImage (pDC, this, rectImage);
}
}
}
}
pDC->SelectClipRgn (NULL);
rectImage.right ++;
if (m_nStyle & TBBS_CHECKED && !bImageIsReady)
{
if (!bLightImage && bIsRarelyUsed)
{
pDC->FillRect (rectImage, &globalData.brBtnFace);
}
CRect rectCheck = rectImage;
rectCheck.DeflateRect (0, 1);
CPoint pointCheck (
rectCheck.left + (rectCheck.Width () - sizeImage.cx) / 2,
rectCheck.top + (rectCheck.Height () - sizeImage.cy) / 2);
int iImage = (m_nStyle & TBBS_DISABLED) ? CMenuImages::IdCheckDsbl : CMenuImages::IdCheck;
CMenuImages::Draw (pDC, (CMenuImages::IMAGES_IDS) iImage, pointCheck);
pDC->Draw3dRect (rectFrameBtn, globalData.clrBtnShadow, globalData.clrBtnHilite);
}
else if (bImageIsReady && bHighlight && !(m_nStyle & TBBS_CHECKED))
{
pDC->Draw3dRect (rectFrameBtn, globalData.clrBtnHilite, globalData.clrBtnShadow);
}
else if (bImageIsReady && (m_nStyle & TBBS_CHECKED))
{
pDC->Draw3dRect (rectFrameBtn, globalData.clrBtnShadow, globalData.clrBtnHilite);
}
int iSystemImageId = -1;
//-------------------------------
// Try to draw system menu icons:
//-------------------------------
if (!bImageIsReady)
{
switch (m_nID)
{
case SC_MINIMIZE:
iSystemImageId = bDisabled ? CMenuImages::IdMinimizeDsbl : CMenuImages::IdMinimize;
break;
case SC_RESTORE:
iSystemImageId = bDisabled ? CMenuImages::IdRestoreDsbl : CMenuImages::IdRestore;
break;
case SC_CLOSE:
iSystemImageId = bDisabled ? CMenuImages::IdCloseDsbl : CMenuImages::IdClose;
break;
case SC_MAXIMIZE:
iSystemImageId = bDisabled ? CMenuImages::IdMaximizeDsbl : CMenuImages::IdMaximize;
break;
}
if (iSystemImageId != -1)
{
CRect rectSysImage = rectImage;
rectSysImage.DeflateRect (IMAGE_MARGIN, IMAGE_MARGIN);
CPoint pointSysImage (
rectSysImage.left + (rectSysImage.Width () - sizeImage.cx) / 2,
rectSysImage.top + (rectSysImage.Height () - sizeImage.cy) / 2);
CMenuImages::Draw (pDC, (CMenuImages::IMAGES_IDS) iSystemImageId, pointSysImage);
if (bHighlight)
{
pDC->Draw3dRect (&rectSysImage, globalData.clrBtnHilite, globalData.clrBtnShadow);
}
}
}
//-------------------------------
// Fill text area if highlighted:
//-------------------------------
CRect rectText = rect;
rectText.left = rectFrameBtn.right + IMAGE_MARGIN;
COLORREF clrText;
if (bHighlight && !bCustomizeMode)
{
CRect rectFill = rectFrameBtn;
if ((m_nStyle & (TBBS_CHECKED) || bImageIsReady) ||
iSystemImageId != -1)
{
rectFill.left = rectText.left - 1;
}
rectFill.right = rect.right - 1;
pDC->FillRect (&rectFill, &globalData.brHilite);
clrText = bDisabled ?
globalData.clrBtnFace :
globalData.clrTextHilite;
}
else
{
clrText = bDisabled ?
globalData.clrGrayedText :
globalData.clrBtnText;
}
//-------------------------
// Find acceleration label:
//-------------------------
CString strText = m_strText;
CString strAccel;
int iTabOffset = m_strText.Find (_T('\t'));
if (iTabOffset >= 0)
{
strText = strText.Left (iTabOffset);
strAccel = m_strText.Mid (iTabOffset + 1);
}
//-----------
// Draw text:
//-----------
rectText.left += TEXT_MARGIN;
if (!m_bWholeText)
{
CString strEllipses (_T("..."));
while (strText.GetLength () > 0 &&
pDC->GetTextExtent (strText + strEllipses).cx > rectText.Width ())
{
strText = strText.Left (strText.GetLength () - 1);
}
strText += strEllipses;
}
if (bDisabled && !bHighlight)
{
pDC->SetTextColor (globalData.clrBtnHilite);
CRect rectShft = rectText;
rectShft.OffsetRect (1, 1);
pDC->DrawText (strText, &rectShft, DT_SINGLELINE | DT_VCENTER);
}
pDC->SetTextColor (clrText);
pDC->DrawText (strText, &rectText, DT_SINGLELINE | DT_VCENTER);
//------------------------
// Draw accelerator label:
//------------------------
if (!strAccel.IsEmpty ())
{
CRect rectAccel = rectText;
rectAccel.right -= TEXT_MARGIN + sizeImage.cx;
if (bDisabled && !bHighlight)
{
pDC->SetTextColor (globalData.clrBtnHilite);
CRect rectAccelShft = rectAccel;
rectAccelShft.OffsetRect (1, 1);
pDC->DrawText (strAccel, &rectAccelShft, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);
}
pDC->SetTextColor (clrText);
pDC->DrawText (strAccel, &rectAccel, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);
}
//--------------------------------------------
// Draw triangle image for the cascade menues:
//--------------------------------------------
if (m_nID == (UINT) -1 || m_bDrawDownArrow)
{
CRect rectTriangle = rect;
rectTriangle.left = rectTriangle.right - sizeImage.cx;
CPoint pointTriangle (
rectTriangle.left + (rectTriangle.Width () - sizeImage.cx) / 2,
rectTriangle.top + (rectTriangle.Height () - sizeImage.cy) / 2);
int iImage = (bHighlight && !bCustomizeMode) ?
(bDisabled ? CMenuImages::IdArowLeftWhiteDsbl : CMenuImages::IdArowLeftWhite) :
(bDisabled ? CMenuImages::IdArowLeftDsbl : CMenuImages::IdArowLeft);
CMenuImages::Draw (pDC, (CMenuImages::IMAGES_IDS) iImage, pointTriangle);
}
if (pOldFont != NULL)
{
pDC->SelectObject (pOldFont);
}
}
//****************************************************************************************
void CBCGToolbarMenuButton::OnCancelMode ()
{
if (m_pPopupMenu != NULL && ::IsWindow (m_pPopupMenu->m_hWnd))
{
m_pPopupMenu->SaveState ();
m_pPopupMenu->m_bAutoDestroyParent = FALSE;
// m_pPopupMenu->DestroyWindow ();
m_pPopupMenu->CloseMenu ();
}
m_pPopupMenu = NULL;
if (m_pWndParent != NULL && ::IsWindow (m_pWndParent->m_hWnd))
{
m_pWndParent->InvalidateRect (m_rect);
m_pWndParent->UpdateWindow ();
}
}
//****************************************************************************************
BOOL CBCGToolbarMenuButton::OpenPopupMenu (CWnd* pWnd)
{
if (m_pPopupMenu != NULL)
{
return FALSE;
}
if (pWnd == NULL)
{
pWnd = m_pWndParent;
}
ASSERT (pWnd != NULL);
//---------------------------------------------------------------
// Define a new menu position. Place the menu in the right side
// of the current menu in the poup menu case or under the current
// item by default:
//---------------------------------------------------------------
CPoint point;
CBCGPopupMenuBar* pParentMenu =
DYNAMIC_DOWNCAST (CBCGPopupMenuBar, m_pWndParent);
CBCGMenuBar* pParentMenuBar =
DYNAMIC_DOWNCAST (CBCGMenuBar, m_pWndParent);
if (pParentMenu != NULL)
{
point = CPoint (0, m_rect.top - 2);
pWnd->ClientToScreen (&point);
CRect rectParent;
pParentMenu->GetWindowRect (rectParent);
point.x = rectParent.right + 1;
}
else if (pParentMenuBar != NULL &&
(pParentMenuBar->m_dwStyle & CBRS_ORIENT_HORZ) == 0)
{
//------------------------------------------------
// Parent menu bar is docked vertical, place menu
// in the left or right side of the parent frame:
//------------------------------------------------
point = CPoint (m_rect.right + 1, m_rect.top);
pWnd->ClientToScreen (&point);
}
else
{
point = CPoint (m_rect.left - 1, m_rect.bottom);
pWnd->ClientToScreen (&point);
}
HMENU hMenu = CreateMenu ();
if (hMenu == NULL && !IsEmptyMenuAllowed ())
{
return FALSE;
}
m_pPopupMenu = CreatePopupMenu ();
if (m_pPopupMenu == NULL)
{
return FALSE;
}
m_pPopupMenu->m_pParentBtn = this;
if (!m_pPopupMenu->Create (pWnd, point.x, point.y, hMenu))
{
m_pPopupMenu = NULL;
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CBCGToolbarMenuButton diagnostics
#ifdef _DEBUG
void CBCGToolbarMenuButton::AssertValid() const
{
CObject::AssertValid();
}
//******************************************************************************************
void CBCGToolbarMenuButton::Dump(CDumpContext& dc) const
{
CObject::Dump (dc);
CString strId;
strId.Format (_T("%x"), m_nID);
dc < "[" < m_strText < " >>>>> ]";
dc.SetDepth (dc.GetDepth () + 1);
dc < "{\n";
for (POSITION pos = m_listCommands.GetHeadPosition (); pos != NULL;)
{
CBCGToolbarButton* pButton = (CBCGToolbarButton*) m_listCommands.GetNext (pos);
ASSERT_VALID (pButton);
pButton->Dump (dc);
dc < "\n";
}
dc < "}\n";
dc.SetDepth (dc.GetDepth () - 1);
dc < "\n";
}
#endif
//******************************************************************************************
int CBCGToolbarMenuButton::OnDrawOnCustomizeList (
CDC* pDC, const CRect& rect, BOOL bSelected)
{
CBCGToolbarButton::OnDrawOnCustomizeList (pDC, rect, bSelected);
if (m_nID == 0 || !m_listCommands.IsEmpty ()) // Popup menu
{
CRect rectTriangle = rect;
rectTriangle.left = rectTriangle.right - CMenuImages::Size ().cx;
CPoint pointTriangle (
rectTriangle.left + (rectTriangle.Width () - CMenuImages::Size ().cx) / 2,
rectTriangle.top + (rectTriangle.Height () - CMenuImages::Size ().cy) / 2);
int iImage = (bSelected) ? CMenuImages::IdArowLeftWhite : CMenuImages::IdArowLeft;
CMenuImages::Draw (pDC, (CMenuImages::IMAGES_IDS) iImage, pointTriangle);
CRect rectLine = rect;
rectLine.right = rectTriangle.left - 1;
rectLine.left = rectLine.right - 2;
rectLine.DeflateRect (0, 2);
pDC->Draw3dRect (&rectLine, globalData.clrBtnShadow, globalData.clrBtnHilite);
}
return rect.Width ();
}
//*******************************************************************************************
BOOL CBCGToolbarMenuButton::OnBeforeDrag () const
{
if (m_pPopupMenu != NULL) // Is dropped down
{
m_pPopupMenu->CollapseSubmenus ();
}
return CBCGToolbarButton::OnBeforeDrag ();
}
//*******************************************************************************************
void CBCGToolbarMenuButton::GetTextHorzOffsets (int& xOffsetLeft, int& xOffsetRight)
{
xOffsetLeft = CBCGToolBar::GetMenuImageSize ().cx / 2 + TEXT_MARGIN;
xOffsetRight = CMenuImages::Size ().cx;
}
//*******************************************************************************************
void CBCGToolbarMenuButton::SaveBarState ()
{
if (m_pWndParent == NULL)
{
return;
}
CBCGPopupMenu* pParentMenu =
DYNAMIC_DOWNCAST (CBCGPopupMenu, m_pWndParent->GetParent ());
if (pParentMenu == NULL)
{
return;
}
ASSERT_VALID (pParentMenu);
CBCGPopupMenu* pTopLevelMenu = pParentMenu;
while ((pParentMenu = DYNAMIC_DOWNCAST (CBCGPopupMenu, pParentMenu->GetParent ()))
!= NULL)
{
pTopLevelMenu = pParentMenu;
}
ASSERT_VALID (pTopLevelMenu);
pTopLevelMenu->SaveState ();
}
//*************************************************************************************************
void CBCGToolbarMenuButton::GetImageRect (CRect& rectImage)
{
ASSERT_VALID (this);
rectImage = m_rect;
rectImage.left += IMAGE_MARGIN;
rectImage.right = rectImage.left +
CBCGToolBar::GetMenuImageSize ().cx + IMAGE_MARGIN;
}