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

📄 tabctrl.h

📁 一个使用wtl写的完整的多窗口浏览器
💻 H
📖 第 1 页 / 共 3 页
字号:

		{
			CSize size(lpwndpos->cx, lpwndpos->cy);
			m_wndUpDown.MoveWindow(size.cx - s_kcxUpDown, size.cy - s_kcyUpDown, s_kcxUpDown, s_kcyUpDown);
			_ShowOrHideUpDownCtrl(CRect(0, 0, size.cx, size.cy));

			if (m_dwTabCtrl2ExtendedStyle & TAB2_EX_MULTILINE) {
				_UpdateMultiLineLayout(size.cx);
				if (m_dwTabCtrl2ExtendedStyle & TAB2_EX_SUPPORTREBAR) {
					RefreshBandInfo();
				}
			}
		}
		return 0;
	}

	bool _MustBeInvalidateOnMultiLine(CSize size)
	{
		CRect rc; GetClientRect(rc);

		if (rc.Width() < size.cx) // expanding
			return true;

		int cxLeft = 0;
		for (int i = 0; i < m_items.size(); ++i) {
			cxLeft = max(m_items[i].m_rcItem.right, cxLeft);
		}

		if (cxLeft != 0 && cxLeft < size.cx) {
			return false;
		}
		else
			return true;
	}

	LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
	{
		if (m_dwTabCtrl2ExtendedStyle & TAB2_EX_TRANSPARENT) {
			bHandled = FALSE;
			return 0;
		}

		RECT rect;
		GetClientRect(&rect);
		::FillRect((HDC)wParam, &rect, (HBRUSH)LongToPtr(COLOR_BTNFACE + 1));

		return 1;	// don't do the default erase
	}

	LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		if (wParam != NULL)	{
			_DoPaint((HDC)wParam);
		}
		else {
			CPaintDC dc(m_hWnd);
			_DoPaint(dc.m_hDC, &dc.m_ps.rcPaint);
		}

		return 0;
	}

	LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		TCTRACE(_T("OnLButtonDown\n"));
		POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
		
		int nIndex = HitTest(pt);
		if (nIndex != -1) {
			ATLASSERT(_IsValidIndex(nIndex));
			if ((wParam & MK_CONTROL) && GetCurSel() != nIndex) {
				if (!_FindIndexFromCurMultiSelected(nIndex)) {
					if (m_items[nIndex].ModifyState(TCISTATE_SELECTED, TCISTATE_MSELECTED))
						InvalidateRect(m_items[nIndex].m_rcItem);
				}
				else {
					if (m_items[nIndex].ModifyState(TCISTATE_MSELECTED, 0))
						InvalidateRect(m_items[nIndex].m_rcItem);
				}
			}
			else {
				_PressItem(nIndex);
				SetCapture();
			}
		}

		return 0;
	}

	LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		TCTRACE(_T("OnLButtonUp\n"));
		POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };

		if (GetCapture() == m_hWnd) {
			ReleaseCapture();

			int nIndex = HitTest(pt);
			if (nIndex != -1 && nIndex == m_nPressedIndex) {
				TCTRACE(_T(" change current selelected item\n"));
				ATLASSERT(_IsValidIndex(nIndex));
				_PressItem();// always clean up pressed flag
				SetCurSel(nIndex, true);
				NMHDR nmhdr = { m_hWnd, GetDlgCtrlID(), TCN_SELCHANGE };
				::SendMessage(GetParent(), WM_NOTIFY, (WPARAM)GetDlgCtrlID(), (LPARAM)&nmhdr);
			}
			else {
				_PressItem();// always clean up pressed flag
			}
		}

		return 0;
	}

// Implementation
	bool _FindIndexFromCurMultiSelected(int nIndex)
	{
		CSimpleArray<int> arrCurMultiSel;
		GetCurMultiSel(arrCurMultiSel, false);
		if (arrCurMultiSel.Find(nIndex) != -1)
			return true;
		return false;
	}

//	void _UpdateItems(int nFirst)
//	{
//		_InvalidateItemsRect(nFirst, m_items.size());	// first, invalidate prev rects
//		_UpdateLayout();								// rect updated
//		_InvalidateItemsRect(nFirst, m_items.size());	// add invalidate rects
//		UpdateWindow();									// redraw now
//	}

	void _UpdateLayout()
	{
		if (m_items.size() == 0) {
			m_arrSeparators.RemoveAll();
			Invalidate();
			if (m_dwTabCtrl2ExtendedStyle & TAB2_EX_SUPPORTREBAR)
				RefreshBandInfo();
			return;
		}

		CRect rc;
		GetClientRect(&rc);

		if (m_dwTabCtrl2ExtendedStyle & TAB2_EX_MULTILINE) {
			_UpdateMultiLineLayout(rc.Width());
		}
		else {
			_UpdateSingleLineLayout(m_nFirstIndexOnSingleLine);
		}

		_ShowOrHideUpDownCtrl(rc);
		if (m_dwTabCtrl2ExtendedStyle & TAB2_EX_SUPPORTREBAR)
			RefreshBandInfo();

		UpdateWindow();
	}

	void _HotItem(int nNewHotIndex = -1)
	{
		TCTRACE(_T("_HotItem\n"));
		// clean up
		if (_IsValidIndex(m_nHotIndex)) {
			TCTRACE(_T(" clean up - %d\n"), m_nHotIndex);
			CTabCtrlItem& item = m_items[m_nHotIndex];
			if (item.ModifyState(TCISTATE_HOT, 0))
				InvalidateRect(item.m_rcItem);
		}

		m_nHotIndex = nNewHotIndex;

		if (_IsValidIndex(m_nHotIndex)) {
			TCTRACE(_T(" hot - %d\n"), m_nHotIndex);
			CTabCtrlItem& item = m_items[m_nHotIndex];
			if (item.ModifyState(0, TCISTATE_HOT))
				InvalidateRect(item.m_rcItem);	
		}
	}

	void _PressItem(int nPressedIndex = -1)
	{
		TCTRACE(_T("_PressItem\n"));
		// clean up prev
		if (_IsValidIndex(m_nPressedIndex)) {
			TCTRACE(_T(" clean up - %d\n"), m_nPressedIndex);
			CTabCtrlItem& item = m_items[m_nPressedIndex];
			if (item.ModifyState(TCISTATE_PRESSED, 0))
				InvalidateRect(item.m_rcItem);
		}

		m_nPressedIndex = nPressedIndex;

		if (_IsValidIndex(m_nPressedIndex)) {
			TCTRACE(_T(" press - %d\n"), m_nPressedIndex);
			CTabCtrlItem& item = m_items[m_nPressedIndex];
			if (item.ModifyState(0, TCISTATE_PRESSED))
				InvalidateRect(item.m_rcItem);	
		}
	}

	void _ResetMultiSelectedItems()
	{
		for (int i = 0; i < m_items.size(); ++i) {
			if (m_items[i].ModifyState(TCISTATE_MSELECTED, 0))
				InvalidateRect(m_items[i].m_rcItem);
		}
	}

	void _DoPaint(CDCHandle dc, LPCRECT lpRect = NULL)
	{
		CFontHandle fontOld = dc.SelectFont(m_font.m_hFont);
		int modeOld = dc.SetBkMode(TRANSPARENT);

		int i = m_dwTabCtrl2ExtendedStyle & TAB2_EX_MULTILINE ? 0 : m_nFirstIndexOnSingleLine;
		for (; i < m_items.size(); ++i) {
			if (lpRect == NULL || MtlIsCrossRect(m_items[i].m_rcItem, lpRect)) {
				m_items[i].Update(dc.m_hDC, m_imgs.m_hImageList, _check_flag(TAB2_EX_ANCHORCOLOR, m_dwTabCtrl2ExtendedStyle));
			}
		}

		_DrawSeparators(dc, lpRect);

		dc.SelectFont(fontOld);
		dc.SetBkMode(modeOld);
	}

	void _UpdateSingleLineLayout(int nFirstIndex, bool bForce = false)
	{
		TCTRACE(_T("_UpdateSingleLineLayout index(%d)\n"), nFirstIndex);
		ATLASSERT(_IsValidIndex(nFirstIndex));
		m_arrSeparators.RemoveAll();

		// clean invisible items
		int i;
		for (i = 0; i < nFirstIndex && i < m_items.size(); ++i) {
			m_items[i].m_rcItem.SetRectEmpty();
		}

		int cxOffset = 0;//s_kcxGap;
		for (i = nFirstIndex; i < m_items.size(); ++i) {
			CTabCtrlItem& item = m_items[i];
			CRect rcSrc = item.m_rcItem;

			// update the rect
			if (m_dwTabCtrl2ExtendedStyle & TAB2_EX_FIXEDSIZE)
				item.m_rcItem = CRect(cxOffset, 0, cxOffset + m_sizeItem.cx, m_sizeItem.cy);
			else
				item.m_rcItem = _MeasureItem(m_items[i].m_strItem) + CPoint(cxOffset, 0);

			cxOffset = cxOffset + item.m_rcItem.Width();
			cxOffset += s_kcxGap;
			m_arrSeparators.Add(CPoint(cxOffset, 0));
			cxOffset += s_kcxSeparator + s_kcxGap;

			//
			if (bForce || rcSrc != item.m_rcItem) {
				InvalidateRect(_InflateGapWidth(rcSrc));
				InvalidateRect(_InflateGapWidth(item.m_rcItem));
			}
		}
	}

	void _UpdateMultiLineLayout(int nWidth)
	{
		TCTRACE(_T("_UpdateMultiLineLayout\n"));

		m_arrSeparators.RemoveAll();

		int cxOffset = 0;
		int cyOffset = 0;

		for (int i = 0; i < m_items.size(); ++i) {
			CTabCtrlItem& item = m_items[i];
			CRect rcSrc = item.m_rcItem;
	
			// update the rect
			if (m_dwTabCtrl2ExtendedStyle & TAB2_EX_FIXEDSIZE)
				item.m_rcItem = CRect(cxOffset, cyOffset, cxOffset + m_sizeItem.cx, cyOffset + m_sizeItem.cy);
			else
				item.m_rcItem = _MeasureItem(m_items[i].m_strItem) + CPoint(cxOffset, cyOffset);

			if (i != 0 && item.m_rcItem.right > nWidth) { // do wrap
				cxOffset = 0;
				cyOffset += GetItemHeight() + s_kcyGap;

				if (m_dwTabCtrl2ExtendedStyle & TAB2_EX_FIXEDSIZE)
					item.m_rcItem = CRect(cxOffset, cyOffset, cxOffset + m_sizeItem.cx, cyOffset + m_sizeItem.cy);
				else
					item.m_rcItem = _MeasureItem(m_items[i].m_strItem) + CPoint(cxOffset, cyOffset);
			}

			cxOffset = cxOffset + m_items[i].m_rcItem.Width();
			cxOffset += s_kcxGap;
			m_arrSeparators.Add(CPoint(cxOffset, cyOffset));
			cxOffset += s_kcxSeparator + s_kcxGap;
			//

			if (rcSrc != item.m_rcItem) {
				InvalidateRect(_InflateGapWidth(rcSrc));
				InvalidateRect(_InflateGapWidth(item.m_rcItem));
			}
		}
	}

	void _ShowOrHideUpDownCtrl(const CRect& rcClient)
	{
		TCTRACE(_T("_ShowOrHideUpDownCtrl\n"));
		if ((m_dwTabCtrl2ExtendedStyle & TAB2_EX_MULTILINE) || m_items.size() < 1) {
			m_wndUpDown.ShowWindow(SW_HIDE);
			return;
		}

		m_wndUpDown.SetRange(0, GetItemCount());

		if (m_nFirstIndexOnSingleLine != 0) {
			m_wndUpDown.ShowWindow(SW_SHOWNORMAL);
			return;
		}
		else if (m_items[m_items.size() - 1].m_rcItem.right > rcClient.right) {
			TCTRACE(_T(" show!\n"));
			m_wndUpDown.ShowWindow(SW_SHOWNORMAL);
			return;
		}

		m_wndUpDown.ShowWindow(SW_HIDE);
	}

	CRect _MeasureItem(const CString& strText)
	{
		if (m_dwTabCtrl2ExtendedStyle & TAB2_EX_FIXEDSIZE)
			return CRect(0, 0, m_sizeItem.cx, m_sizeItem.cy);

		// compute size of text - use DrawText with DT_CALCRECT
		int cx = MtlComputeWidthOfText(strText, m_font);

		int cxIcon = 0, cyIcon = 0;
		if (m_imgs.m_hImageList != NULL)
			m_imgs.GetIconSize(cxIcon, cyIcon);

		LOGFONT lf;
		m_font.GetLogFont(lf);
		int cy = lf.lfHeight;
		if(cy < 0)
			cy = -cy;
		cy += 2 * s_kcyTextMargin;

		// height of item is the bigger of these two
		cy = MtlMax(cy, cyIcon);

		// width is width of text plus a bunch of stuff
		cx += 2 * s_kcxTextMargin;	// L/R margin for readability
		
//		ATLTRACE(_T("(cx, cy) = (%d, %d)\n"), cx, cy);
		return CRect(0, 0, cx, cy);
	}

	int _GetRequiredHeight()
	{
		if (GetItemCount () == 0) {
			return GetItemHeight();
		}
		else {
			return m_items[m_items.size() - 1].m_rcItem.bottom;
		}

		return 0;
	}

	bool _IsValidIndex(int nIndex)
	{
		if (0 <= nIndex && nIndex < m_items.size())
			return true;
		else
			return false;
	}

	void _ClearAll()
	{
		m_items.clear();
	}

	CRect _InflateGapWidth(const CRect& rc)
	{
		int cxSeparatorOffset = s_kcxGap*2 + s_kcxSeparator;
		return CRect(rc.left, rc.top, rc.right + cxSeparatorOffset, rc.bottom);
	}

//	void _InvalidateItemsRect(int nFirst, int nLast, bool bAlsoSeparator = true)
//	{
//		int cxSeparatorOffset = bAlsoSeparator ? s_kcxGap*2 + s_kcxSeparator : 0;
//
//		for (int i = nFirst; i < nLast; ++i) {
//			CRect rc = m_items[i].m_rcItem;
//			InvalidateRect(CRect(rc.left, rc.top, rc.right + cxSeparatorOffset, rc.bottom));
//		}
//	}

//	void _InvalidateItemRect(int nIndex, bool bAlsoSepartor = true)
//	{
//		int cxSeparatorOffset = bAlsoSeparator ? s_kcxGap*2 + s_kcxSeparator : 0;
//
//		InvalidateRect(CRect(rc.left, rc.top, rc.right + cxSeparatorOffset, rc.bottom));
//	}

	void _DrawSeparators(CDCHandle dc, LPCRECT lpRect = NULL)
	{
		int cy = GetItemHeight();
		CRect rect(lpRect);
		for (int i = 0; i < m_arrSeparators.GetSize(); ++i) {
			CPoint& pt = m_arrSeparators[i];
			CRect rc(pt.x, pt.y + 2, pt.x + 2, pt.y + cy - 2);
			if (lpRect == NULL || MtlIsCrossRect(rc, lpRect)) {
				dc.DrawEdge(rc, EDGE_ETCHED, BF_LEFT);	// draw separator line				
			}
		}
	}

	void GetSystemSettings()
	{
		// refresh our font
		NONCLIENTMETRICS info;
		info.cbSize = sizeof(info);
		::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
		LOGFONT logfont;
		memset(&logfont, 0, sizeof(LOGFONT));
		if(m_font.m_hFont != NULL)
			m_font.GetLogFont(logfont);
		if(logfont.lfHeight != info.lfMenuFont.lfHeight ||
		   logfont.lfWidth != info.lfMenuFont.lfWidth ||
		   logfont.lfEscapement != info.lfMenuFont.lfEscapement ||
		   logfont.lfOrientation != info.lfMenuFont.lfOrientation ||
		   logfont.lfWeight != info.lfMenuFont.lfWeight ||
		   logfont.lfItalic != info.lfMenuFont.lfItalic ||
		   logfont.lfUnderline != info.lfMenuFont.lfUnderline ||
		   logfont.lfStrikeOut != info.lfMenuFont.lfStrikeOut ||
		   logfont.lfCharSet != info.lfMenuFont.lfCharSet ||
		   logfont.lfOutPrecision != info.lfMenuFont.lfOutPrecision ||
		   logfont.lfClipPrecision != info.lfMenuFont.lfClipPrecision ||
		   logfont.lfQuality != info.lfMenuFont.lfQuality ||
		   logfont.lfPitchAndFamily != info.lfMenuFont.lfPitchAndFamily ||
		   lstrcmp(logfont.lfFaceName, info.lfMenuFont.lfFaceName) != 0)
		{
			HFONT hFontMenu = ::CreateFontIndirect(&info.lfMenuFont);
			ATLASSERT(hFontMenu != NULL);
			if(hFontMenu != NULL)
			{
				if(m_font.m_hFont != NULL)
					m_font.DeleteObject();
				m_font.Attach(hFontMenu);
				SetFont(m_font);
			}
		}
	}

	void _InitToolTip()
	{
		// create a tool tip
		m_tip.Create(m_hWnd);
		ATLASSERT(m_tip.IsWindow());
		CToolInfo tinfo(TTF_SUBCLASS, m_hWnd);
		tinfo.hwnd = m_hWnd;	// WTL always sucks...
		m_tip.AddTool(tinfo);
		m_tip.SetMaxTipWidth(SHRT_MAX);
	}
};

class CTabCtrl2 : public CTabCtrl2Impl<CTabCtrl2>
{
public:
	DECLARE_WND_CLASS_EX(_T("MTL_TabCtrl2"), CS_DBLCLKS, COLOR_BTNFACE)
};

////////////////////////////////////////////////////////////////////////////
} //namespace MTL

#ifndef _MTL_NO_AUTOMATIC_NAMESPACE
using namespace MTL;
#endif //!_MTL_NO_AUTOMATIC_NAMESPACE

⌨️ 快捷键说明

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