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

📄 tabctrl.h

📁 一个使用wtl写的完整的多窗口浏览器
💻 H
📖 第 1 页 / 共 3 页
字号:
#pragma once
////////////////////////////////////////////////////////////////////////////
// MTL Version 0.10
// Copyright (C) 2001 MB<mb2@geocities.co.jp>
// All rights unreserved.
//
// This file is a part of Mb Template Library.
// The code and information is *NOT* provided "as-is" without
// warranty of any kind, either expressed or implied.
//
// TabCtrl.h: Last updated: February 12, 2001
/////////////////////////////////////////////////////////////////////////////
#include <vector>

namespace MTL
{

// for debug
#ifdef _DEBUG
	const bool _Mtl_TabCtrl2_traceOn = false;
	#define TCTRACE if (_Mtl_TabCtrl2_traceOn) ATLTRACE
#else
	#define TCTRACE
#endif

#define TOOLTIP_RELAY_EVENT(tip) \
	if(uMsg == WM_LBUTTONDOWN || uMsg == WM_MOUSEMOVE || uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONDOWN || \
	   uMsg == WM_MBUTTONDOWN || uMsg == WM_RBUTTONUP || uMsg == WM_MBUTTONUP) \
	{ \
		bHandled = FALSE; \
		MSG msg = { m_hWnd, uMsg, wParam, lParam }; \
		if (tip.IsWindow()) \
			tip.RelayEvent(&msg); \
	}

/////////////////////////////////////////////////////////////////////////////
// Tab Bars

// Window Styles:
#define TAB2WS_TOP				CCS_TOP
#define TAB2WS_BOTTOM			CCS_BOTTOM
#define TAB2WS_NORESIZE			CCS_NORESIZE
#define TAB2WS_NOPARENTALIGN	CCS_NOPARENTALIGN
#define TAB2WS_NODIVIDER		CCS_NODIVIDER

// Extended styles
#define TAB2_EX_TRANSPARENT		0x00000001L	// not supported yet
#define TAB2_EX_SHAREIMGLIST	0x00000002L
#define TAB2_EX_MULTILINE		0x00000004L
#define TAB2_EX_FIXEDSIZE		0x00000008L
#define TAB2_EX_SUPPORTREBAR	0x00000010L
#define TAB2_EX_SCROLLOPPOSITE	0x00000020L
#define TAB2_EX_ANCHORCOLOR		0x00000040L

// standard command bar styles
#define MTL_SIMPLE_TAB2_PANE_STYLE \
	(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | TAB2WS_NODIVIDER | TAB2WS_NORESIZE | TAB2WS_NOPARENTALIGN)

/////////////////////////////////////////////////////////////////////////////
// Forward declarations

template <class T, class TBase = CTabCtrl2Base, class TWinTraits = CControlWinTraits> class CCommandBarCtrlImpl;
class CTabCtrl2;

/////////////////////////////////////////////////////////////////////////////
// CTabButton

// CTabButton state flags
#define TCISTATE_HIDDEN		0x01
  // standard text state
#define TCISTATE_ENABLED	0x02
#define TCISTATE_INACTIVE	0x04
  // select or not
#define TCISTATE_SELECTED	0x08	// ordianry selected
#define TCISTATE_MSELECTED	0x10	// multi-selected
  // event state
#define TCISTATE_PRESSED	0x20	// mouse pressed
#define TCISTATE_HOT		0x40	// mouse above item
#define TCISTATE_MOUSEAWAYCAPTURED 0x80// mouse away but captured

class CTabCtrlItem
{
public:
// Data members
	BYTE m_fsState;
	CString m_strItem;	// string on button
	CRect m_rcItem;
	int m_nImgIndex;	// image list index
	DWORD m_dwUser;		// user's data

// Constants
	enum { s_kcxIconGap = 2 };
		
// Constructor/destructor
	CTabCtrlItem(const CString& strBtn = CString(), int nImgIndex = -1,
				 DWORD dwUser = 0, BYTE fsState = TCISTATE_ENABLED)
		: m_fsState(fsState), m_strItem(strBtn), m_nImgIndex(nImgIndex), m_dwUser(dwUser)
	{
		m_rcItem.SetRectEmpty();
	}
	
// Attributes
	bool ModifyState(BYTE fsRemove, BYTE fsAdd)
	{
		BYTE fsStateOld = m_fsState;
		m_fsState = (m_fsState & ~fsRemove) | fsAdd;

		if ((fsStateOld & TCISTATE_SELECTED || fsStateOld & TCISTATE_MSELECTED) &&
			(fsRemove == TCISTATE_HOT || fsAdd == TCISTATE_HOT))// selected, no need to update
			return false;
		else
			return m_fsState != fsStateOld;
	}	

// Methods
	void Update(CDCHandle dc, HIMAGELIST hImgList, bool bAnchorColor)
	{
//		TCTRACE(_T("CTabCtrlItem::Update\n"));
		if (m_fsState & TCISTATE_HIDDEN)
			return;

		int cxIcon = 0, cyIcon = 0;
		int cxIconOffset = 0;
		if (m_nImgIndex != -1) {
			::ImageList_GetIconSize(hImgList, &cxIcon, &cyIcon);
			cxIconOffset += cxIcon + s_kcxIconGap*2;
		}

		bool bHot = (m_fsState & TCISTATE_HOT) != 0;
		bool bPressed = (m_fsState & TCISTATE_PRESSED) != 0;
	
		CPoint ptOffset(0, 0);
		if (m_fsState & TCISTATE_SELECTED) {		// now selected
			if (bHot && bPressed) {
				COLORREF crTxt = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE));
				COLORREF crBk = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT));
				CBrush hbr(CDCHandle::GetHalftoneBrush());
				dc.SetBrushOrg(m_rcItem.left, m_rcItem.top);
				dc.FillRect(m_rcItem, hbr);
				dc.SetTextColor(crTxt);
				dc.SetBkColor(crBk);
				dc.DrawEdge(m_rcItem, BDR_RAISEDINNER, BF_RECT);
			}
			else {// ignored hot
				TCTRACE(_T(" draw selected(checked) button\n"));
				COLORREF crTxt = dc.SetTextColor(::GetSysColor(COLOR_BTNFACE));
				COLORREF crBk = dc.SetBkColor(::GetSysColor(COLOR_BTNHILIGHT));
				CBrush hbr(CDCHandle::GetHalftoneBrush());
				dc.SetBrushOrg(m_rcItem.left, m_rcItem.top);
				dc.FillRect(m_rcItem, hbr);
				dc.SetTextColor(crTxt);
				dc.SetBkColor(crBk);
				dc.DrawEdge(m_rcItem, EDGE_SUNKEN, BF_RECT);
			}

			ptOffset += CPoint(2, 2);
		}
		else if (m_fsState & TCISTATE_MSELECTED) {	// multi-selected
			if (bHot && bPressed) {
				dc.DrawEdge(m_rcItem, BDR_RAISEDINNER, BF_RECT);
			}
			else {
				dc.DrawEdge(m_rcItem, EDGE_SUNKEN, BF_RECT);
			}
			ptOffset += CPoint(2, 2);
		}
		else {										// not selected
			if (bHot && bPressed) {
				dc.DrawEdge(m_rcItem, BDR_RAISEDINNER, BF_RECT);// hot
				ptOffset += CPoint(2, 2);						// sunk a little
			}
			else if (bHot && !bPressed) {
				dc.DrawEdge(m_rcItem, BDR_RAISEDINNER, BF_RECT);// hot
			}
		}

		_DrawText(dc, ptOffset + CPoint(cxIconOffset, 0), bAnchorColor);

		if (m_nImgIndex != -1) {
			::ImageList_Draw(hImgList, m_nImgIndex, dc, m_rcItem.left + ptOffset.x + s_kcxIconGap,
				m_rcItem.top  + (m_rcItem.Height() - cyIcon) / 2 + ptOffset.y / 2, ILD_TRANSPARENT);
		}
	}
	
// Implementation
	void _DrawText(CDCHandle dc, CPoint ptOffset, bool bAnchorColor)
	{
		COLORREF clr;
		if (!(m_fsState & TCISTATE_ENABLED))
			clr = ::GetSysColor(COLOR_3DSHADOW);
		else if (m_fsState & TCISTATE_INACTIVE)
			clr = bAnchorColor ? RGB(0, 0, 255) : ::GetSysColor(COLOR_BTNTEXT);
		else
			clr = bAnchorColor ? RGB(128, 0, 128) : ::GetSysColor(COLOR_BTNTEXT);
			
		COLORREF clrOld = dc.SetTextColor(clr);

		CRect rcBtn(m_rcItem.left + ptOffset.x, m_rcItem.top + ptOffset.y, m_rcItem.right, m_rcItem.bottom);
		rcBtn.DeflateRect(2, 0);

		UINT uFortmat;
		int nWidth = MtlComputeWidthOfText(m_strItem, dc.GetCurrentFont());
		if (nWidth > rcBtn.Width())
			uFortmat = DT_LEFT | DT_END_ELLIPSIS;
		else
			uFortmat = DT_CENTER | DT_NOCLIP;
		
		if (!(m_fsState & TCISTATE_ENABLED)) {
			// disabled - draw shadow text shifted down and right 1 pixel (unles selected)
			CRect rcDisabled = rcBtn + CPoint(1, 1);
			COLORREF clrOld2 = dc.SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
			dc.DrawText(m_strItem, -1, rcDisabled, DT_SINGLELINE | uFortmat | DT_VCENTER | DT_NOPREFIX);
			dc.SetTextColor(clrOld2);
		}

		dc.DrawText(m_strItem, -1, rcBtn, DT_SINGLELINE | uFortmat | DT_VCENTER | DT_NOPREFIX);
		dc.SetTextColor(clrOld);
	}
	
	void DrawHot(CDCHandle dc)
	{
		dc.DrawEdge(m_rcItem, BDR_RAISEDINNER, BF_RECT);
	}

	void DrawPressed(CDCHandle dc)
	{
		dc.DrawEdge(m_rcItem, EDGE_SUNKEN, BF_MIDDLE);
	}

	void DrawSelected(CDCHandle dc)
	{
		dc.DrawEdge(m_rcItem, EDGE_SUNKEN, BF_RECT);
	}
};

/////////////////////////////////////////////////////////////////////////////
// CTabCtrl2Base - base class for the Tab Ctrl2 implementation

class CTabCtrl2Base : public CWindow
{
public:
	CTabCtrl2Base()
	{
	}
};

/////////////////////////////////////////////////////////////////////////////
// CTabCtrl2 - MTL implementation of Tab Ctrl2

template <class T, class TBase = CTabCtrl2Base, class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CTabCtrl2Impl :
	public CWindowImpl< T, TBase, TWinTraits >,
	public CTrackMouseLeave<CTabCtrl2Impl>
{
public:
	DECLARE_WND_CLASS_EX(NULL, CS_DBLCLKS, -1)
	typedef CTabCtrl2Impl< T, TBase, TWinTraits > thisClass;

// Constants
	enum _TabCtrl2DrawConstants
	{
		s_kcxTextMargin = 7,
		s_kcyTextMargin = 3,
		s_kcxGap = 2,
		s_kcyGap = 2,
		s_kcxSeparator = 2,

		s_kcxUpDown = 28,
		s_kcyUpDown = 14
	};

	enum
	{
		_nMaxMenuItemTextLength = 100,
	};
	
	enum _CurrentState
	{
		none = 0,
		pressed,
		captured,
		hot_by_mouse
	};

// Data members
	std::vector<CTabCtrlItem> m_items;
	CImageList m_imgs;
	_CurrentState m_nCurrentState;
	CFont m_font;
	DWORD m_dwTabCtrl2ExtendedStyle;		// Tab Ctrl2 specific extended styles
	int m_nHotIndex;						// Current hot index
	int m_nPressedIndex;					// Current capturing index
	CSimpleArray<CPoint> m_arrSeparators;	// Point of separator
	int m_nFirstIndexOnSingleLine;	// for single line
	CUpDownCtrl m_wndUpDown;		//
	CSize m_sizeItem;				// for fixed size
	bool m_bLockRefreshBandInfo;

	CToolTipCtrl m_tip;

// Constructor/destructor
	CTabCtrl2Impl() : 
			m_dwTabCtrl2ExtendedStyle(TAB2_EX_TRANSPARENT|TAB2_EX_SUPPORTREBAR|TAB2_EX_SCROLLOPPOSITE),
			m_nCurrentState(none),
			m_nFirstIndexOnSingleLine(0),
			m_sizeItem(200, 50),
			m_nHotIndex(-1),
			m_nPressedIndex(-1),
			m_bLockRefreshBandInfo(false)
	{
 	}
 	
	~CTabCtrl2Impl()
	{
		if (m_imgs.m_hImageList != NULL && (m_dwTabCtrl2ExtendedStyle & TAB2_EX_SHAREIMGLIST) == 0)
			m_imgs.Destroy();
	}

// Overridables
	void OnSetCurSel(int nIndex)
	{
	}

	CString OnGetToolTipText(int nIndex)
	{
		CString strItem;
		GetItemText(nIndex, strItem);
		return strItem;
	}

// Attributes
	DWORD GetTabCtrl2ExtendedStyle() const
	{
		return m_dwTabCtrl2ExtendedStyle;
	}

	void SetItemSize(const CSize& size)
	{
		CSize sizePrev = m_sizeItem;
		m_sizeItem = size;
		if (sizePrev != m_sizeItem &&
			m_dwTabCtrl2ExtendedStyle & TAB2_EX_FIXEDSIZE)
		{
			_UpdateLayout();
		}
	}

	CSize GetItemSize()
	{
		return m_sizeItem;
	}

	void ModifyTabCtrl2ExtendedStyle(DWORD dwRemove, DWORD dwAdd)
	{
		DWORD dwOldStyle = m_dwTabCtrl2ExtendedStyle;
		m_dwTabCtrl2ExtendedStyle = (m_dwTabCtrl2ExtendedStyle & ~dwRemove) | dwAdd;
		if (dwOldStyle != m_dwTabCtrl2ExtendedStyle) {
			m_nFirstIndexOnSingleLine = 0;
			_UpdateLayout();
		}

		if ( (dwOldStyle & TAB2_EX_ANCHORCOLOR) != (m_dwTabCtrl2ExtendedStyle & TAB2_EX_ANCHORCOLOR) )
			Invalidate();
	}

	int GetItemCount()
	{
		return m_items.size();
	}

	int GetCurSel()
	{
		for (int i = 0; i < m_items.size(); ++i) {
			if (m_items[i].m_fsState & TCISTATE_SELECTED)
				return i;
		}
		
		return -1;
	}

	int HitTest(CPoint point)
	{
		CRect rc;
		GetClientRect(&rc);
		if (!rc.PtInRect(point))
			return -1;

		int i = (m_dwTabCtrl2ExtendedStyle & TAB2_EX_MULTILINE) ? 0 : m_nFirstIndexOnSingleLine;
		for (; i < m_items.size(); ++i) {
			if (m_items[i].m_rcItem.PtInRect(point)/* &&
				m_items[i].m_fsState & TCISTATE_ENABLED*/) {
				return i;
			}
		}

		return -1;
	}

	bool InsertItem(int nIndex, const CTabCtrlItem& item)
	{// if nDestIndex is invalid, added to tail
		_HotItem();

		if (m_items.size() == 0) {
			m_items.push_back(item);
		}
		else {
			if (nIndex < 0 || nIndex > m_items.size()) {
				nIndex = m_items.size();
			}

			m_items.insert(m_items.begin() + nIndex, item);
		}

		_UpdateLayout();
	
		return true;
	}

	void DeleteItems(CSimpleArray<int>& arrSrcs)
	{
		for (int i = arrSrcs.GetSize() - 1; i >= 0; --i) {
			int nIndex = arrSrcs[i];
			if (!_IsValidIndex(nIndex))
				continue;
			DeleteItem(nIndex);
		}
	}

	bool MoveItems(int nDestIndex, CSimpleArray<int>& arrSrcs)
	{// arrSrcs has to be sorted! if nDestIndex is invalid, added to tail
		TCTRACE(_T("CTabCtrlImpl::MoveItems\n"));
		if (arrSrcs.GetSize() <= 0)
			return false;

		int i = 0;
		if (arrSrcs.GetSize() == 1) {
			if (nDestIndex == arrSrcs[0] || nDestIndex == arrSrcs[0] + 1)
				return true;// no need

			if (!_IsValidIndex(nDestIndex) && arrSrcs[0] == m_items.size() - 1)
				return true;// no need
		}

		CLockRedraw lock(m_hWnd);
		m_bLockRefreshBandInfo = true;

		std::vector<CTabCtrlItem> temp;

		TCTRACE(_T(" save src indexs - "));
		for (i = 0; i < arrSrcs.GetSize(); ++i) {
			int nIndex = arrSrcs[i];
			if (!_IsValidIndex(nIndex))
				continue;
			TCTRACE(_T(" %d"), nIndex);
			temp.push_back(m_items[nIndex]);
		}
		TCTRACE(_T("\n"));

		TCTRACE(_T(" delete item indexs - "));
		for (i = arrSrcs.GetSize() - 1; i >= 0; --i) {
			int nIndex = arrSrcs[i];
			if (!_IsValidIndex(nIndex))
				continue;

			if (nDestIndex > nIndex)
				--nDestIndex;
			TCTRACE(_T(" %d"), nIndex);
			DeleteItem(nIndex);
		}
		TCTRACE(_T("\n"));

		// add all
		if (!_IsValidIndex(nDestIndex)) {
			nDestIndex = GetItemCount();
		}

		for (i = 0; i < temp.size(); ++i) {
			InsertItem(nDestIndex, temp[i]);
			++nDestIndex;
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -