📄 stdtoolbarctrl.h
字号:
#pragma once
#include <utility>
/////////////////////////////////////////////////////////////////////////////
// Standard Tool Bars
// Note. I can't understand the relation between TBBUTTON::iString and TBBUTTONINFO::pszText.
// I guess the tool bar control's implementation is broken.
// If bellow IE5.01, there is no way to hide toolbar's text and
// once you call CToolBarCtrl::AddStrings or set text to button, you can't avoid to show button' text.
// In fact, if you set iString with -1, you can hide text, but I'm afraid and did'nt do that.
// I have to set iString valid and moreover set text with SetButtonInfo.
// cuz while customizing buttons a valid iString is required to TBBUTTON
// Standard ToolBar Styles:
#define STD_TBSTYLE_SMALLICON 0x00000001L
#define STD_TBSTYLE_LARGEICON 0x00000002L
#define STD_TBSTYLE_ICONS STD_TBSTYLE_SMALLICON | STD_TBSTYLE_LARGEICON
#define STD_TBSTYLE_HIDELABEL 0x00000004L
#define STD_TBSTYLE_SHOWLABEL 0x00000008L
#define STD_TBSTYLE_SHOWLABELRIGHT 0x00000010L
#define STD_TBSTYLE_LABELS STD_TBSTYLE_HIDELABEL | STD_TBSTYLE_SHOWLABEL | STD_TBSTYLE_SHOWLABELRIGHT
#define STD_TBSTYLE_DEFAULT STD_TBSTYLE_LARGEICON | STD_TBSTYLE_SHOWLABEL
#define STD_TBSTYLE_ALL STD_TBSTYLE_ICONS | STD_TBSTYLE_LABELS
#define BTNS_STD_LIST 0x00010000L
// Standard ToolBar Button:
typedef struct _STD_TBBUTTON {
int idCommand;
DWORD fsStyle; // BTNS_
} STD_TBBUTTON, NEAR* PSTD_TBBUTTON, FAR* LPSTD_TBBUTTON;
typedef const STD_TBBUTTON FAR* LPCSTD_TBBUTTON;
/////////////////////////////////////////////////////////////////////////////
// Forward declarations
template <class T, class TBase = CStdToolBarCtrlBase, class TWinTraits = CControlWinTraits> class CStdToolBarCtrlImpl;
class CStdToolBarCtrl;
template <class T>
class CCustomizableStdToolBarHandler;
class CStdToolBarAdditionalCustomizeDlg;
// for debug
#ifdef _DEBUG
const bool _Mtl_StdToolBarCtrl_traceOn = true;
#define stbTRACE if (_Mtl_StdToolBarCtrl_traceOn) ATLTRACE
#else
#define stbTRACE
#endif
/////////////////////////////////////////////////////////////////////////////
// CStdToolBarCtrlBase - base class for the Standard Tool Bar implementation
class CStdToolBarCtrlBase : public CToolBarCtrl
{
public:
enum { s_kcxSeparator = 8 };
static bool _StdToolBar_HideLabel(HWND hWndToolBar)
{
CToolBarCtrl toolbar(hWndToolBar);
_CLockRedraw lock(hWndToolBar);
toolbar.ModifyStyle(0, TBSTYLE_LIST);
// If IE < 5.01, there is no methods to hide button's texts.
if (!_check_flag(TBSTYLE_EX_MIXEDBUTTONS, toolbar.GetExtendedStyle()))
return false;
for (int i = 0; i < toolbar.GetButtonCount(); ++i) {
// get button ID
TBBUTTON tbb;
toolbar.GetButton(i, &tbb);
int nCmdID = tbb.idCommand;
BYTE fsStyle = tbb.fsStyle;
// separator or not
if (fsStyle & BTNS_SEP)
continue;
fsStyle &= ~BTNS_AUTOSIZE; // if no label, no need to do it
fsStyle &= ~BTNS_SHOWTEXT;
CVersional<TBBUTTONINFO> bi;
bi.dwMask = TBIF_STYLE;
bi.fsStyle = fsStyle;
toolbar.SetButtonInfo(nCmdID, &bi);
}
toolbar.AutoSize();
return true;
}
static bool _StdToolBar_ShowLabel(HWND hWndToolBar,
const STD_TBBUTTON* ptbbFirst, const STD_TBBUTTON* ptbbLast)
{
CToolBarCtrl toolbar(hWndToolBar);
_CLockRedraw lock(hWndToolBar);
toolbar.ModifyStyle(TBSTYLE_LIST, 0);
StdToolBar_AddStrings(hWndToolBar, ptbbFirst, ptbbLast);// add it now!
for (int i = 0; i < toolbar.GetButtonCount(); ++i) {
// get button ID and Style
TBBUTTON tbb;
toolbar.GetButton(i, &tbb);
int nCmdID = tbb.idCommand;
BYTE fsStyle = tbb.fsStyle;
// separator or not
if (fsStyle & BTNS_SEP)
continue;
// update info
CVersional<TBBUTTONINFO> bi;
bi.dwMask = TBIF_STYLE;
fsStyle |= BTNS_AUTOSIZE; // fixed button size (IE5 style) or not
fsStyle |= BTNS_SHOWTEXT;
bi.fsStyle = fsStyle;
toolbar.SetButtonInfo(nCmdID, &bi);
}
// StdToolBar_AddStrings(hWndToolBar, ptbbFirst, ptbbLast);// add it now!
toolbar.AutoSize();
return true;
}
static bool _StdToolBar_ShowLabelRight(HWND hWndToolBar,
const STD_TBBUTTON* ptbbFirst, const STD_TBBUTTON* ptbbLast)
{
CToolBarCtrl toolbar(hWndToolBar);
_CLockRedraw lock(hWndToolBar);
toolbar.ModifyStyle(0, TBSTYLE_LIST);
StdToolBar_AddStrings(hWndToolBar, ptbbFirst, ptbbLast);
CSimpleArray<int> arrShowRightID;
for ( ; ptbbFirst != ptbbLast; ++ptbbFirst) {
if (ptbbFirst->fsStyle & BTNS_STD_LIST) {
int nCmdID = ptbbFirst->idCommand;
arrShowRightID.Add(nCmdID);
}
}
for (int i = 0; i < toolbar.GetButtonCount(); ++i) {
// get button ID and Style
TBBUTTON tbb;
toolbar.GetButton(i, &tbb);
int nCmdID = tbb.idCommand;
BYTE fsStyle = tbb.fsStyle;
// separator or not
if (fsStyle & BTNS_SEP)
continue;
// update info
CVersional<TBBUTTONINFO> bi;
bi.dwMask = TBIF_STYLE;
fsStyle |= BTNS_AUTOSIZE;
if (arrShowRightID.Find(nCmdID) != -1)
fsStyle |= BTNS_SHOWTEXT;
else
fsStyle &= ~BTNS_SHOWTEXT;
bi.fsStyle = fsStyle;
toolbar.SetButtonInfo(nCmdID, &bi);
}
toolbar.AutoSize();
return true;
}
static bool StdToolBar_AddStrings(HWND hWndToolBar, const STD_TBBUTTON* ptbbFirst, const STD_TBBUTTON* ptbbLast)
{
LPTSTR lpsz = _MakeStrings(ptbbFirst, ptbbLast);
if (lpsz == NULL)
return false;
CToolBarCtrl toolbar(hWndToolBar);
toolbar.AddStrings(lpsz);
delete [] lpsz;
//toolbar.AddStrings(_T("NS\0"));
return true;
}
static LPTSTR _MakeStrings(const STD_TBBUTTON* ptbbFirst, const STD_TBBUTTON* ptbbLast)
{
int nLen = 0;
CSimpleArray<CString> arrText;
for ( ; ptbbFirst != ptbbLast; ++ptbbFirst) {
CString strText;
if (_check_flag(BTNS_SEP, ptbbFirst->fsStyle))
continue;
if (_LoadToolTipText(ptbbFirst->idCommand, strText)) {
nLen += strText.GetLength() + 1;
arrText.Add(strText);
}
}
if (nLen == 0)
return NULL;
nLen += 1;
LPTSTR lpsz = new TCHAR[nLen];
::memset(lpsz, 0, nLen);
LPTSTR lpszRunner = lpsz;
for (int i = 0; i < arrText.GetSize(); ++i) {
::lstrcpy(lpszRunner, arrText[i]);
lpszRunner += arrText[i].GetLength() + 1;
}
return lpsz;
}
static bool _LoadToolTipText(int nCmdID, CString& strText)
{
TCHAR szBuff[256];
TCHAR szText[256];
szBuff[0] = 0;
int nRet = ::LoadString(_Module.GetResourceInstance(), nCmdID, szBuff, 256);
for (int i = 0; i < nRet; i++)
{
if (szBuff[i] == _T('\n'))
{
lstrcpyn(szText, &szBuff[i + 1], 256);
strText = szText;
return true;
}
}
return false;
}
static UINT _HwndToId(HWND hWndReBar, HWND hWndBand)
{
CReBarCtrl rebar(hWndReBar);
REBARBANDINFO rbbi;
rbbi.cbSize = sizeof(REBARBANDINFO);
for (UINT i = 0; i < rebar.GetBandCount(); ++i) {
rbbi.fMask = RBBIM_CHILD | RBBIM_ID;
rebar.GetBandInfo(i, &rbbi);
if (rbbi.hwndChild == hWndBand) {
return rbbi.wID;
}
}
return 0;
}
static int _HwndToIndex(HWND hWndReBar, HWND hWndBand)
{
CReBarCtrl rebar(hWndReBar);
UINT nID = _HwndToId(hWndReBar, hWndBand);
if (nID == 0)
return -1;
return rebar.IdToIndex(nID);
}
static bool _UpdateBandInfo(HWND hWndToolBar)
{
CToolBarCtrl toolbar(hWndToolBar);
CReBarCtrl rebar = toolbar.GetParent();
int nCount = rebar.GetBandCount();
if(nCount <= 0) // probably not a rebar
return false;
int nBtnCount = toolbar.GetButtonCount();
CRect rcRight;
if (!toolbar.GetItemRect(nBtnCount - 1, &rcRight))
return false;
CRect rcLeft;
if (!toolbar.GetItemRect(0, &rcLeft))
return false;
REBARBANDINFO rbbi;
rbbi.cbSize = sizeof(REBARBANDINFO);
rbbi.fMask = RBBIM_IDEALSIZE | RBBIM_CHILDSIZE;
rbbi.cxMinChild = rcLeft.right;
rbbi.cyMinChild = rcLeft.Height();
rbbi.cxIdeal = rcRight.right;
int nIndex = _HwndToIndex(rebar, hWndToolBar);
return (rebar.SetBandInfo(nIndex, &rbbi) == TRUE);
}
/*
static TBBUTTON* _MakeTBBtns(CSimpleArray<STD_TBBUTTON>& arrStdBtn, int* pFirstIndex, int* pLastIndex)
{
int nCount = pLastIndex - pFirstIndex;
if (nCount == 0)
return NULL;
TBBUTTON* pTBBtn = new TBBUTTON[nCount];
for (int j = 0; pFirstIndex != pLastIndex; ++pFirstIndex, ++j) {
ATLASSERT(j < nCount);
if (*pFirstIndex == -1)
pTBBtn[j] = _GetSeparatorTBBtn();
else
pTBBtn[j] = _GetTBBtn(arrStdBtn[*pFirstIndex], *pFirstIndex);
}
return pTBBtn;
}
*/
static TBBUTTON* _MakeFullTBBtns(const STD_TBBUTTON* ptbbFirst, const STD_TBBUTTON* ptbbLast, bool bValidateString)
{
int nCount = ptbbLast - ptbbFirst;
if (nCount == 0)
return NULL;
TBBUTTON* pTBBtn = new TBBUTTON[nCount];
int nBmp = 0;
int j = 0;
for ( ; ptbbFirst != ptbbLast; ++ptbbFirst) {
ATLASSERT(j < nCount);
pTBBtn[j].iBitmap = nBmp;
pTBBtn[j].idCommand = ptbbFirst->idCommand;
pTBBtn[j].fsState = TBSTATE_ENABLED;
pTBBtn[j].fsStyle = ptbbFirst->fsStyle & ~BTNS_STD_LIST;
pTBBtn[j].dwData = 0;
// Note. If invalid index, no text.
pTBBtn[j].iString = bValidateString ? nBmp : 0;
++nBmp;
++j;
}
return pTBBtn;
}
static TBBUTTON _GetSeparatorTBBtn()
{
TBBUTTON tbBtn;
tbBtn.iBitmap = s_kcxSeparator;
tbBtn.idCommand = 0;
tbBtn.fsState = 0;
tbBtn.fsStyle = TBSTYLE_SEP;
tbBtn.dwData = 0;
tbBtn.iString = 0;
return tbBtn;
}
static TBBUTTON _GetTBBtn(const STD_TBBUTTON& stb, int iBitmap)
{
TBBUTTON tbBtn;
tbBtn.iBitmap = iBitmap;
tbBtn.idCommand = stb.idCommand;
tbBtn.fsState = TBSTATE_ENABLED;
tbBtn.dwData = 0;
tbBtn.fsStyle = stb.fsStyle & ~BTNS_STD_LIST;
tbBtn.iString = iBitmap;
return tbBtn;
}
// Locking redraw
struct _CLockRedraw
{
CWindow m_wnd;
_CLockRedraw(HWND hWnd) : m_wnd(hWnd)
{
if (m_wnd.m_hWnd) {
m_wnd.SetRedraw(FALSE);
}
}
~_CLockRedraw()
{
if (m_wnd.m_hWnd) {
m_wnd.SetRedraw(TRUE);
m_wnd.Invalidate();
m_wnd.UpdateWindow();
}
}
};
};
/////////////////////////////////////////////////////////////////////////////
// CStdToolBarCtrlImpl - ATL implementation of Standard Tool Bars
template <class T, class TBase = CStdToolBarCtrlBase, class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CStdToolBarCtrlImpl :
public CWindowImpl< T, TBase, TWinTraits >,
public CCustomizableStdToolBarHandler<T>
{
public:
DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
// Data members
DWORD m_dwStdToolBarStyle;
CSimpleArray<STD_TBBUTTON> m_arrStdBtn;
CSimpleArray<int> m_arrBmpDefaultIndex;
std::pair<int, int> m_bmpIDSmall;
CSize m_sizeSmall;
std::pair<int, int> m_bmpIDLarge;
CSize m_sizeLarge;
COLORREF m_clrMask;
UINT m_nFlags;
// Ctor/Dtor
CStdToolBarCtrlImpl()
: m_dwStdToolBarStyle(0)
{
}
bool StdToolBar_Init(STD_TBBUTTON* ptbbFirst, STD_TBBUTTON* ptbbLast,
int *pBmpFirst, int* pBmpLast,
const std::pair<int, int>& bmpIDSmall, const std::pair<int, int>& bmpIDLarge = std::make_pair(0, 0),
CSize sizeSmall = CSize(16, 16), CSize sizeLarge = CSize(20, 20),
COLORREF clrMask = RGB(255, 0, 255), UINT nFlags = ILC_COLOR8)
{
for ( ; ptbbFirst != ptbbLast; ++ptbbFirst) {
ATLASSERT(_check_flag(BTNS_SEP, ptbbFirst->fsStyle) == false);
m_arrStdBtn.Add(*ptbbFirst);
}
for ( ; pBmpFirst != pBmpLast; ++pBmpFirst) {
m_arrBmpDefaultIndex.Add(*pBmpFirst);
}
m_bmpIDSmall = bmpIDSmall;
m_sizeSmall = sizeSmall;
m_bmpIDLarge = bmpIDLarge;
m_sizeLarge = sizeLarge;
m_clrMask = clrMask;
m_nFlags = nFlags;
return true;
}
bool StdToolBar_InitButtons(int* pFirstIndex, int* pLastIndex)
{
// clean up previous toolbar buttons
while (DeleteButton(0))
;
for ( ; pFirstIndex != pLastIndex; ++pFirstIndex)
{
if (*pFirstIndex == -1) // separator
{
TBBUTTON tbBtn = _GetSeparatorTBBtn();
MTLVERIFY(InsertButton(GetButtonCount(), &tbBtn));
}
else if (0 <= *pFirstIndex && *pFirstIndex < m_arrStdBtn.GetSize())
{
TBBUTTON tbBtn = _GetTBBtn(m_arrStdBtn[*pFirstIndex], *pFirstIndex);
tbBtn.fsStyle |= BTNS_AUTOSIZE;// default
MTLVERIFY(InsertButton(GetButtonCount(), &tbBtn));
}
}
return true;
}
void StdToolBar_Term()
{
StdToolBar_DestroyImageList();
USES_PT;
pT->StdToolBar_WriteProfile();
}
HWND StdToolBar_Create(HWND hWndParent,
DWORD dwStyle = ATL_SIMPLE_TOOLBAR_PANE_STYLE,
DWORD dwExtendedStyle = TBSTYLE_EX_DRAWDDARROWS | TBSTYLE_EX_MIXEDBUTTONS,
UINT nID = ATL_IDW_TOOLBAR)
{
m_hWnd = Create(hWndParent, rcDefault, NULL, dwStyle, 0, nID);
ATLASSERT(::IsWindow(m_hWnd));
SetExtendedStyle(dwExtendedStyle); // before adding buttons!
SetButtonStructSize(sizeof(TBBUTTON));
USES_PT;
pT->StdToolBar_GetProfile();
return m_hWnd;
}
// Attributes
int StdToolBar_GetIconCount()
{
return m_arrStdBtn.GetSize();
}
// Overridables
LRESULT StdToolBar_OnDropDown(int nCmdID)
{
return TBDDRET_DEFAULT;
}
void StdToolBar_GetProfile()
{
StdToolBar_InitButtons(_begin(m_arrBmpDefaultIndex), _end(m_arrBmpDefaultIndex));
}
void StdToolBar_WriteProfile()
{
}
// Methods
bool StdToolBar_Reset()
{
StdToolBar_InitButtons(_begin(m_arrBmpDefaultIndex), _end(m_arrBmpDefaultIndex));
return StdToolBar_ModifyStyle(STD_TBSTYLE_ALL, STD_TBSTYLE_DEFAULT);
}
bool StdToolBar_ModifyStyle(DWORD dwRemove, DWORD dwAdd)
{
DWORD dwStyleOld = m_dwStdToolBarStyle;
m_dwStdToolBarStyle = (m_dwStdToolBarStyle & ~dwRemove) | dwAdd;
if (dwStyleOld != m_dwStdToolBarStyle) {
StdToolBar_UpdateImageList();
StdToolBar_UpdateStyle();
_UpdateBandInfo(m_hWnd);
}
return true;
}
void StdToolBar_SetStyle(DWORD dwStyle, bool bForceUpdateStyle = false)
{
DWORD dwStyleOld = m_dwStdToolBarStyle;
m_dwStdToolBarStyle = dwStyle;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -