⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stdtoolbarctrl.h

📁 一个使用wtl写的完整的多窗口浏览器
💻 H
📖 第 1 页 / 共 2 页
字号:
#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 + -