📄 bcgtoolbar.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.
//
// Stas Levin <stas@iet.co.il>
//*******************************************************************************
// bcgtoolbar.cpp : definition of CBCGToolBar
//
// This code is based on the Microsoft Visual C++ sample file
// TOOLBAR.C from the OLDBARS example
//
#include "stdafx.h"
#include "bcgbarres.h"
#include "BCGtoolbar.h"
#include "BCGMenuBar.h"
#include "BCGToolbarButton.h"
#include "BCGToolbarDropSource.h"
#include "ButtonAppearanceDlg.h"
#include "CBCGToolbarCustomize.h"
#include "bcglocalres.h"
#include "Registry.h"
#include "BCGMDIFrameWnd.h"
#include "BCGFrameWnd.h"
#include "BCGKeyboardManager.h"
#include "BCGToolbarMenuButton.h"
#include "BCGToolbarSystemMenuButton.h"
#include "BCGPopupMenu.h"
#include "CustomizeButton.h"
#include "BCGCommandManager.h"
#include "RegPath.h"
#include "trackmouse.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
#define TEXT_MARGIN 3
#define STRETCH_DELTA 6
#define BUTTON_MIN_WIDTH 5
#define LINE_OFFSET 5
#define REG_SECTION_FMT _T("%sBCGToolBar-%d")
#define REG_SECTION_FMT_EX _T("%sBCGToolBar-%d%x")
#define REG_PARAMS_FMT _T("%sBCGToolbarParameters")
#define REG_ENTRY_NAME _T("Name")
#define REG_ENTRY_BUTTONS _T("Buttons")
#define REG_ENTRY_TOOLTIPS _T("Tooltips")
#define REG_ENTRY_KEYS _T("ShortcutKeys")
#define REG_ENTRY_LARGE_ICONS _T("LargeIcons")
#define REG_ENTRY_ANIMATION _T("MenuAnimation")
#define REG_ENTRY_RU_MENUS _T("RecentlyUsedMenus")
#define REG_ENTRY_MENU_SHADOWS _T("MenuShadows")
#define REG_ENTRY_SHOW_ALL_MENUS_DELAY _T("ShowAllMenusAfterDelay")
#define REG_ENTRY_CMD_USAGE_COUNT _T("CommandsUsage")
#define REG_ENTRY_LOOK2000 _T("Look2000")
static const CString strToolbarProfile = _T("BCGToolBars");
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
/////////////////////////////////////////////////////////////////////////////
// CBCGToolBar notification messages:
UINT BCGM_TOOLBARMENU = ::RegisterWindowMessage (_T("BCGTOOLBAR_POPUPMENU"));
UINT BCGM_CUSTOMIZETOOLBAR = ::RegisterWindowMessage (_T("BCGTOOLBAR_CUSTOMIZE"));
UINT BCGM_CREATETOOLBAR = ::RegisterWindowMessage (_T("BCGTOOLBAR_CREATE"));
UINT BCGM_DELETETOOLBAR = ::RegisterWindowMessage (_T("BCGTOOLBAR_DELETE"));
UINT BCGM_CUSTOMIZEHELP = ::RegisterWindowMessage (_T("BCGTOOLBAR_CUSTOMIZEHELP"));
UINT BCGM_RESETTOOLBAR = ::RegisterWindowMessage (_T("BCGTOOLBAR_RESETTOOLBAR"));
UINT BCGM_SHOWREGULARMENU = ::RegisterWindowMessage (_T("BCGTOOLBAR_SHOWREGULARMENU"));
/////////////////////////////////////////////////////////////////////////////
// All CBCGToolBar collection:
CObList gAllToolbars;
BOOL CBCGToolBar::m_bCustomizeMode = FALSE;
BOOL CBCGToolBar::m_bAltCustomizeMode = FALSE;
BOOL CBCGToolBar::m_bShowTooltips = TRUE;
BOOL CBCGToolBar::m_bShowShortcutKeys = TRUE;
BOOL CBCGToolBar::m_bLargeIcons = FALSE;
CBCGToolbarDropSource CBCGToolBar::m_DropSource;
CBCGToolBarImages CBCGToolBar::m_Images;
CBCGToolBarImages CBCGToolBar::m_ColdImages;
CBCGToolBarImages CBCGToolBar::m_MenuImages;
CBCGToolBarImages CBCGToolBar::m_DisabledImages;
CBCGToolBarImages CBCGToolBar::m_DisabledMenuImages;
CBCGToolBarImages* CBCGToolBar::m_pUserImages = NULL;
CSize CBCGToolBar::m_sizeButton = CSize (23, 22);
CSize CBCGToolBar::m_sizeImage = CSize (16, 15);
CSize CBCGToolBar::m_sizeCurButton = CSize (23, 22);
CSize CBCGToolBar::m_sizeCurImage = CSize (16, 15);
CSize CBCGToolBar::m_sizeMenuImage = CSize (-1, -1);
CSize CBCGToolBar::m_sizeMenuButton = CSize (-1, -1);
CMap<UINT, UINT, int, int> CBCGToolBar::m_DefaultImages;
COLORREF CBCGToolBar::m_clrTextHot = (COLORREF) -1;
extern CBCGToolbarCustomize* g_pWndCustomize;
HHOOK CBCGToolBar::m_hookMouseHelp = NULL;
CBCGToolBar* CBCGToolBar::m_pLastHookedToolbar = NULL;
CList<UINT, UINT> CBCGToolBar::m_lstUnpermittedCommands;
CList<UINT, UINT> CBCGToolBar::m_lstBasicCommands;
CCmdUsageCount CBCGToolBar::m_UsageCount;
BOOL CBCGToolBar::m_bAltCustomization = FALSE;
BOOL CBCGToolBar::m_bLook2000 = FALSE;
static inline BOOL IsSystemCommand (UINT uiCmd)
{
return (uiCmd >= 0xF000 && uiCmd < 0xF1F0);
}
/////////////////////////////////////////////////////////////////////////////
// CBCGToolBar
IMPLEMENT_SERIAL(CBCGToolBar, CControlBar, VERSIONABLE_SCHEMA | 1)
#pragma warning (disable : 4355)
CBCGToolBar::CBCGToolBar() :
m_bMenuMode (FALSE),
m_Impl (this)
{
m_iButtonCapture = -1; // nothing captured
m_iHighlighted = -1;
m_iSelected = -1;
m_iHot = -1;
m_iDragIndex = -1;
m_rectDrag.SetRectEmpty ();
m_pDragButton = NULL;
m_ptStartDrag = CPoint (-1, -1);
m_bIsDragCopy = FALSE;
m_bMasked = FALSE;
m_bPermament = FALSE;
m_pCustomizeBtn = NULL;
//---------------------
// UISG standard sizes:
//---------------------
m_cyTopBorder = m_cyBottomBorder = 1; // 1 pixel for top/bottom gaps
m_sizeCurButtonLocked = CSize (23, 22);
m_sizeCurImageLocked = CSize (16, 15);
m_sizeButtonLocked = CSize (23, 22);
m_sizeImageLocked = CSize (16, 15);
m_bStretchButton = FALSE;
m_rectTrack.SetRectEmpty ();
m_iImagesOffset = 0;
m_uiOriginalResID = 0;
m_bTracked = FALSE;
m_ptLastMouse = CPoint (-1, -1);
m_pWndLastCapture = NULL;
m_hwndLastFocus = NULL;
m_bLocked = FALSE;
m_bShowHotBorder = TRUE;
m_bGrayDisabledButtons = TRUE;
m_bLargeIconsAreEnbaled = TRUE;
m_iRebarPaneWidth = -1;
m_bTextLabels = FALSE;
m_bDrawTextLabels = FALSE;
m_nMaxBtnHeight = 0;
}
#pragma warning (default : 4355)
//******************************************************************************************
CBCGToolBar::~CBCGToolBar()
{
RemoveAllButtons ();
}
//******************************************************************************************
BOOL CBCGToolBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)
{
return CBCGToolBar::CreateEx (pParentWnd, TBSTYLE_FLAT,
dwStyle,
CRect(1, 1, 1, 1),
nID);
}
//******************************************************************************************
BOOL CBCGToolBar::CreateEx (CWnd* pParentWnd,
DWORD dwCtrlStyle,
DWORD dwStyle,
CRect rcBorders,
UINT nID)
{
dwStyle |= CBRS_GRIPPER;
if (pParentWnd != NULL)
{
ASSERT_VALID(pParentWnd); // must have a parent
}
if (rcBorders.left < 1)
{
rcBorders.left = 1; // Otherwise, I have a problem woith a "double" grippers
}
if (rcBorders.top < 1)
{
rcBorders.top = 1; // Otherwise, I have a problem woith a "double" grippers
}
SetBorders (rcBorders);
//----------------
// Save the style:
//----------------
m_dwStyle = (dwStyle & CBRS_ALL);
if (nID == AFX_IDW_TOOLBAR)
{
m_dwStyle |= CBRS_HIDE_INPLACE;
}
dwStyle &= ~CBRS_ALL;
dwStyle |= CCS_NOPARENTALIGN|CCS_NOMOVEY|CCS_NODIVIDER|CCS_NORESIZE;
dwStyle |= dwCtrlStyle;
//----------------------------
// Initialize common controls:
//----------------------------
VERIFY (AfxDeferRegisterClass (AFX_WNDCOMMCTLS_REG));
//-----------------
// Create the HWND:
//-----------------
CRect rect;
rect.SetRectEmpty();
//-----------------------------
// Register a new window class:
//-----------------------------
HINSTANCE hInst = AfxGetInstanceHandle();
UINT uiClassStyle = CS_DBLCLKS;
HCURSOR hCursor = ::LoadCursor (NULL, IDC_ARROW);
HBRUSH hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
CString strClassName;
strClassName.Format (_T("BCGToolBar:%x:%x:%x:%x"),
(UINT)hInst, uiClassStyle, (UINT)hCursor, (UINT)hbrBackground);
//---------------------------------
// See if the class already exists:
//---------------------------------
WNDCLASS wndcls;
if (::GetClassInfo (hInst, strClassName, &wndcls))
{
//-----------------------------------------------
// Already registered, assert everything is good:
//-----------------------------------------------
ASSERT (wndcls.style == uiClassStyle);
}
else
{
//-------------------------------------------
// Otherwise we need to register a new class:
//-------------------------------------------
wndcls.style = uiClassStyle;
wndcls.lpfnWndProc = ::DefWindowProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = hInst;
wndcls.hIcon = NULL;
wndcls.hCursor = hCursor;
wndcls.hbrBackground = hbrBackground;
wndcls.lpszMenuName = NULL;
wndcls.lpszClassName = strClassName;
if (!AfxRegisterClass (&wndcls))
{
AfxThrowResourceException();
}
}
if (!CControlBar::Create (strClassName, NULL, dwStyle, rect, pParentWnd, nID))
{
return FALSE;
}
return TRUE;
}
//******************************************************************************************
void CBCGToolBar::SetSizes (SIZE sizeButton, SIZE sizeImage)
{
ASSERT(sizeButton.cx > 0 && sizeButton.cy > 0);
//-----------------------------------------------------------------
// Button must be big enough to hold image + 3 pixels on each side:
//-----------------------------------------------------------------
ASSERT(sizeButton.cx >= sizeImage.cx + 6);
ASSERT(sizeButton.cy >= sizeImage.cy + 6);
m_sizeButton = sizeButton;
m_sizeImage = sizeImage;
m_sizeCurButton = sizeButton;
m_sizeCurImage = sizeImage;
m_Images.SetImageSize (m_sizeImage);
m_ColdImages.SetImageSize (m_sizeImage);
m_DisabledImages.SetImageSize (m_sizeImage);
if (m_bLargeIcons)
{
m_sizeCurButton.cx *= 2;
m_sizeCurButton.cy *= 2;
m_sizeCurImage.cx *= 2;
m_sizeCurImage.cy *= 2;
}
if (m_pUserImages != NULL)
{
m_pUserImages->SetImageSize (m_sizeImage);
}
}
//******************************************************************************************
void CBCGToolBar::SetLockedSizes (SIZE sizeButton, SIZE sizeImage)
{
ASSERT(sizeButton.cx > 0 && sizeButton.cy > 0);
//-----------------------------------------------------------------
// Button must be big enough to hold image + 3 pixels on each side:
//-----------------------------------------------------------------
ASSERT(sizeButton.cx >= sizeImage.cx + 6);
ASSERT(sizeButton.cy >= sizeImage.cy + 6);
m_sizeButtonLocked = sizeButton;
m_sizeImageLocked = sizeImage;
m_sizeCurButtonLocked = sizeButton;
m_sizeCurImageLocked = sizeImage;
m_ImagesLocked.SetImageSize (m_sizeImageLocked);
m_ColdImagesLocked.SetImageSize (m_sizeImageLocked);
m_DisabledImagesLocked.SetImageSize (m_sizeImageLocked);
if (m_bLargeIcons)
{
m_sizeCurButtonLocked.cx *= 2;
m_sizeCurButtonLocked.cy *= 2;
m_sizeCurImageLocked.cx *= 2;
m_sizeCurImageLocked.cy *= 2;
}
}
//******************************************************************************************
void CBCGToolBar::SetHeight(int cyHeight)
{
ASSERT_VALID (this);
int nHeight = cyHeight;
if (m_dwStyle & CBRS_BORDER_TOP)
{
cyHeight -= afxData.cyBorder2;
}
if (m_dwStyle & CBRS_BORDER_BOTTOM)
{
cyHeight -= afxData.cyBorder2;
}
m_cyBottomBorder = (cyHeight - GetRowHeight ()) / 2;
//-------------------------------------------------------
// If there is an extra pixel, m_cyTopBorder will get it:
//-------------------------------------------------------
m_cyTopBorder = cyHeight - GetRowHeight () - m_cyBottomBorder;
if (m_cyTopBorder < 0)
{
TRACE(_T("Warning: CBCGToolBar::SetHeight(%d) is smaller than button.\n"),
nHeight);
m_cyBottomBorder += m_cyTopBorder;
m_cyTopBorder = 0; // will clip at bottom
}
if (GetSafeHwnd () != NULL)
{
Invalidate ();
}
}
//******************************************************************************************
BOOL CBCGToolBar::SetUserImages (CBCGToolBarImages* pUserImages)
{
ASSERT (pUserImages != NULL);
if (!pUserImages->IsValid ())
{
ASSERT (FALSE);
return FALSE;
}
if (m_sizeImage != pUserImages->GetImageSize ())
{
ASSERT (FALSE);
return FALSE;
}
m_pUserImages = pUserImages;
return TRUE;
}
//******************************************************************************************
BOOL CBCGToolBar::SetButtons(const UINT* lpIDArray, int nIDCount)
{
ASSERT_VALID(this);
ASSERT(nIDCount >= 1); // must be at least one of them
ASSERT(lpIDArray == NULL ||
AfxIsValidAddress(lpIDArray, sizeof(UINT) * nIDCount, FALSE));
//-----------------------
// Save customize button:
//-----------------------
CCustomizeButton* pCustomizeBtn = NULL;
if (m_pCustomizeBtn != NULL)
{
ASSERT_VALID (m_pCustomizeBtn);
ASSERT (m_pCustomizeBtn == m_Buttons.GetTail ()); // Should be last
pCustomizeBtn = new CCustomizeButton;
pCustomizeBtn->CopyFrom (*m_pCustomizeBtn);
}
RemoveAllButtons ();
if (lpIDArray == NULL)
{
while (nIDCount-- > 0)
{
InsertSeparator ();
}
return TRUE;
}
int iImage = m_iImagesOffset;
//--------------------------------
// Go through them adding buttons:
//--------------------------------
for (int i = 0; i < nIDCount; i ++)
{
int iCmd = *lpIDArray ++;
if (iCmd == 0) // Separator
{
InsertSeparator ();
}
else
{
if (InsertButton (CBCGToolbarButton (iCmd, iImage, NULL, FALSE,
m_bLocked)) >= 0 && !m_bLocked)
{
m_DefaultImages.SetAt (iCmd, iImage);
}
iImage ++;
}
}
//--------------------------
// Restore customize button:
//--------------------------
if (pCustomizeBtn != NULL)
{
InsertButton (pCustomizeBtn);
m_pCustomizeBtn = pCustomizeBtn;
}
if (GetSafeHwnd () != NULL)
{
//------------------------------------
// Allow to produce some user actions:
//------------------------------------
OnReset ();
CWnd* pParentFrame = (m_pDockSite == NULL) ?
GetParent () : m_pDockSite;
if (pParentFrame != NULL)
{
pParentFrame->SendMessage (BCGM_RESETTOOLBAR, (WPARAM) m_uiOriginalResID);
}
}
return TRUE;
}
//******************************************************************************************
BOOL CBCGToolBar::LoadBitmap (UINT uiResID, UINT uiColdResID, UINT uiMenuResID,
BOOL bLocked,
UINT uiDisabledResID, UINT uiMenuDisabledResID)
{
m_bLocked = bLocked;
if (m_bLocked)
{
//------------------------------------------
// Don't add bitmap to the shared resources!
//------------------------------------------
if (!m_ImagesLocked.Load (uiResID, AfxGetResourceHandle (), TRUE))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -