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

📄 dotnettabctrl.h

📁 These listed libraries are written in WTL. But it s really hard to mix both MFC & WTL together. Obvi
💻 H
📖 第 1 页 / 共 3 页
字号:
	{
		// Tab is not selected

		bool bHighlighted = (CDIS_MARKED == (lpNMCustomDraw->nmcd.uItemState & CDIS_MARKED));

		int nItem = (int)lpNMCustomDraw->nmcd.dwItemSpec;
		WTL::CDCHandle dc( lpNMCustomDraw->nmcd.hdc );

		if(bHighlighted)
		{
			if(CTCS_BOTTOM == (dwStyle & CTCS_BOTTOM))
			{
				RECT rcHighlight = {rcTab.left+1, rcTab.top+3, rcTab.right-2, rcTab.bottom-1};
				if(nItem - 1 == m_iCurSel) rcHighlight.left += 1;  // Item to the right of the selected tab
				dc.FillSolidRect(&rcHighlight, lpNMCustomDraw->clrHighlight);
			}
			else
			{
				RECT rcHighlight = {rcTab.left+1, rcTab.top+2, rcTab.right-2, rcTab.bottom-2};
				if(nItem - 1 == m_iCurSel) rcHighlight.left += 1;  // Item to the right of the selected tab
				dc.FillSolidRect(&rcHighlight, lpNMCustomDraw->clrHighlight);
			}
		}

		// Draw division line on right, unless we're the item
		// on the left of the selected tab
		if(nItem + 1 == m_iCurSel)
		{
			// Item just left of selected tab
		}
		else
		{
			WTL::CPen pen;
			pen.CreatePen(PS_SOLID, 1, lpNMCustomDraw->clrBtnShadow);
			WTL::CPenHandle penOld = dc.SelectPen(pen);
			if(CTCS_BOTTOM == (dwStyle & CTCS_BOTTOM))
			{
				// Important!  Be sure and keep within "our" tab area horizontally
				dc.MoveTo(rcTab.right-1, rcTab.top + 3);
				dc.LineTo(rcTab.right-1, rcTab.bottom - 1);
			}
			else
			{
				// Important!  Be sure and keep within "our" tab area horizontally
				dc.MoveTo(rcTab.right-1, rcTab.top + 2);
				dc.LineTo(rcTab.right-1, rcTab.bottom - 2);
			}
			dc.SelectPen(penOld);
		}
	}

	void DrawItem_ImageAndText(DWORD /*dwStyle*/, LPNMCTCCUSTOMDRAW lpNMCustomDraw, int nIconVerticalCenter, RECT& rcTab, RECT& rcText)
	{
		WTL::CDCHandle dc( lpNMCustomDraw->nmcd.hdc );
		bool bHighlighted = (CDIS_MARKED == (lpNMCustomDraw->nmcd.uItemState & CDIS_MARKED));
		bool bSelected = (CDIS_SELECTED == (lpNMCustomDraw->nmcd.uItemState & CDIS_SELECTED));
		bool bHot = (CDIS_HOT == (lpNMCustomDraw->nmcd.uItemState & CDIS_HOT));
		int nItem = (int)lpNMCustomDraw->nmcd.dwItemSpec;

		TItem* pItem = this->GetItem(nItem);

		HFONT hOldFont = NULL;
		if(bSelected)
		{
			hOldFont = dc.SelectFont(lpNMCustomDraw->hFontSelected);
		}
		else
		{
			hOldFont = dc.SelectFont(lpNMCustomDraw->hFontInactive);
		}

		COLORREF crPrevious = 0;
		if(bHighlighted)
		{
			crPrevious = dc.SetTextColor(lpNMCustomDraw->clrHighlightText);
		}
		else if(bHot)
		{
			crPrevious = dc.SetTextColor(lpNMCustomDraw->clrHighlightHotTrack);
		}
		else if(bSelected)
		{
			crPrevious = dc.SetTextColor(lpNMCustomDraw->clrTextSelected);
		}
		else
		{
			crPrevious = dc.SetTextColor(lpNMCustomDraw->clrTextInactive);
		}


		//--------------------------------------------
		// This is how CDotNetTabCtrlImpl interprets padding, margin, etc.:
		//
		//  M - Margin
		//  P - Padding
		//  I - Image
		//  Text - Tab Text
		//
		// With image:
		//     __________________________
		//
		//    | M | I | P | Text | P | M |
		//     --------------------------
		//
		// Without image:
		//     ______________________
		//
		//    | M | P | Text | P | M |
		//     ----------------------

		//rcText.left += (bSelected ? m_settings.iSelMargin : m_settings.iMargin);
		rcText.left += m_settings.iMargin;
		rcText.right -= m_settings.iMargin;
		if (pItem->UsingImage() && !m_imageList.IsNull())
		{
			// Draw the image.
			IMAGEINFO ii = {0};
			int nImageIndex = pItem->GetImageIndex();
			m_imageList.GetImageInfo(nImageIndex, &ii);

			if((ii.rcImage.right - ii.rcImage.left) < (rcTab.right - rcTab.left))
			{
				int nImageHalfHeight = (ii.rcImage.bottom - ii.rcImage.top) / 2;
				m_imageList.Draw(dc, nImageIndex, rcText.left, nIconVerticalCenter - nImageHalfHeight + m_nFontSizeTextTopOffset, ILD_NORMAL);
			}

			// Offset on the right of the image.
			rcText.left += (ii.rcImage.right - ii.rcImage.left);
		}

		if (rcText.left + m_nMinWidthToDisplayText < rcText.right)
		{
			::InflateRect(&rcText, -m_settings.iPadding, 0);

			_CSTRING_NS::CString sText = pItem->GetText();
			dc.DrawText(sText, sText.GetLength(), &rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
		}

		dc.SetTextColor(crPrevious);
		dc.SelectFont(hOldFont);
	}

	void DrawCloseButton(LPNMCTCCUSTOMDRAW lpNMCustomDraw)
	{
		WTL::CDCHandle dc( lpNMCustomDraw->nmcd.hdc );

		WTL::CPen penButtons;
		penButtons.CreatePen(PS_SOLID, 1, lpNMCustomDraw->clrTextInactive);
		WTL::CBrush brushArrow;
		brushArrow.CreateSolidBrush(lpNMCustomDraw->clrTextInactive);

		WTL::CPenHandle penOld = dc.SelectPen(penButtons);
		WTL::CBrushHandle brushOld = dc.SelectBrush(brushArrow);

		RECT rcX = m_rcCloseButton;

		if(ectcMouseDownL_CloseButton == (m_dwState & ectcMouseDown))
		{
			if(ectcMouseOver_CloseButton == (m_dwState & ectcMouseOver))
			{
				::OffsetRect(&rcX, 1, 1);
			}
		}

		const int sp = 4;

		dc.MoveTo(rcX.left+sp+ -1, rcX.top+sp);
		dc.LineTo(rcX.right-sp -1, rcX.bottom-sp);
		dc.MoveTo(rcX.left+sp, rcX.top+sp);
		dc.LineTo(rcX.right-sp, rcX.bottom-sp);

		dc.MoveTo(rcX.left+sp -1, rcX.bottom-sp -1);
		dc.LineTo(rcX.right-sp -1, rcX.top+sp -1 );
		dc.MoveTo(rcX.left+sp, rcX.bottom-sp -1);
		dc.LineTo(rcX.right-sp, rcX.top+sp -1);

		if(ectcMouseDownL_CloseButton == (m_dwState & ectcMouseDown))
		{
			if(ectcMouseOver_CloseButton == (m_dwState & ectcMouseOver))
			{
				dc.DrawEdge(&m_rcCloseButton, BDR_SUNKENOUTER, BF_RECT);
			}
		}
		else if(ectcHotTrack_CloseButton == (m_dwState & ectcHotTrack))
		{
			dc.DrawEdge(&m_rcCloseButton, BDR_RAISEDINNER, BF_RECT);
		}

		dc.SelectBrush(brushOld);
		dc.SelectPen(penOld);
	}

	void DrawScrollButtons(LPNMCTCCUSTOMDRAW lpNMCustomDraw)
	{
		WTL::CDCHandle dc( lpNMCustomDraw->nmcd.hdc );

		WTL::CPen penButtons;
		penButtons.CreatePen(PS_SOLID, 1, lpNMCustomDraw->clrTextInactive);
		WTL::CBrush brushArrow;
		brushArrow.CreateSolidBrush(lpNMCustomDraw->clrTextInactive);

		WTL::CPenHandle penOld = dc.SelectPen(penButtons);
		WTL::CBrushHandle brushOld = dc.SelectBrush(brushArrow);

		RECT rcArrowRight = m_rcScrollRight;
		RECT rcArrowLeft = m_rcScrollLeft;

		if(ectcMouseDownL_ScrollRight == (m_dwState & ectcMouseDown))
		{
			if(ectcMouseOver_ScrollRight == (m_dwState & ectcMouseOver))
			{
				if(ectcOverflowRight == (m_dwState & ectcOverflowRight))
				{
					::OffsetRect(&rcArrowRight, 1, 1);
				}
			}
		}
		if(ectcMouseDownL_ScrollLeft == (m_dwState & ectcMouseDown))
		{
			if(ectcMouseOver_ScrollLeft == (m_dwState & ectcMouseOver))
			{
				if(ectcOverflowLeft == (m_dwState & ectcOverflowLeft))
				{
					::OffsetRect(&rcArrowLeft, 1, 1);
				}
			}
		}

		const int spRight = 5;
		const int spLeft = 6;

		POINT ptsArrowRight[] = {
			{rcArrowRight.left+spRight, rcArrowRight.top+spRight -2},
			{rcArrowRight.left+spRight, rcArrowRight.bottom-spRight +1},
			{rcArrowRight.right-spRight -1, (rcArrowRight.bottom + m_rcScrollRight.top) / 2},
			{rcArrowRight.left+spRight, rcArrowRight.top+spRight -2}
		};
		if(ectcOverflowRight != (m_dwState & ectcOverflowRight))
		{
			dc.Polyline(ptsArrowRight, 4);
		}
		else
		{
			dc.Polygon(ptsArrowRight, 4);

			if(ectcMouseDownL_ScrollRight == (m_dwState & ectcMouseDown))
			{
				if(ectcMouseOver_ScrollRight == (m_dwState & ectcMouseOver))
				{
					dc.DrawEdge(&m_rcScrollRight, BDR_SUNKENOUTER, BF_RECT);
				}
			}
			else if(ectcHotTrack_ScrollRight == (m_dwState & ectcHotTrack))
			{
				dc.DrawEdge(&m_rcScrollRight, BDR_RAISEDINNER, BF_RECT);
			}
		}

		POINT ptsArrowLeft[] = {
			{rcArrowLeft.right-spLeft, rcArrowLeft.top+spLeft -3},
			{rcArrowLeft.right-spLeft, rcArrowLeft.bottom-spLeft +2},
			{rcArrowLeft.left+spLeft -1, (rcArrowLeft.bottom + m_rcScrollLeft.top) / 2},
			{rcArrowLeft.right-spLeft, rcArrowLeft.top+spLeft -3}
		};
		if(ectcOverflowLeft != (m_dwState & ectcOverflowLeft))
		{
			dc.Polyline(ptsArrowLeft, 4);
		}
		else
		{
			dc.Polygon(ptsArrowLeft, 4);

			if(ectcMouseDownL_ScrollLeft == (m_dwState & ectcMouseDown))
			{
				if(ectcMouseOver_ScrollLeft == (m_dwState & ectcMouseOver))
				{
					dc.DrawEdge(&m_rcScrollLeft, BDR_SUNKENOUTER, BF_RECT);
				}
			}
			else if(ectcHotTrack_ScrollLeft == (m_dwState & ectcHotTrack))
			{
				dc.DrawEdge(&m_rcScrollLeft, BDR_RAISEDINNER, BF_RECT);
			}
		}

		dc.SelectBrush(brushOld);
		dc.SelectPen(penOld);
	}

// Overrides for painting from CCustomTabCtrl
public:

	void InitializeDrawStruct(LPNMCTCCUSTOMDRAW lpNMCustomDraw)
	{
		//DWORD dwStyle = this->GetStyle();

		lpNMCustomDraw->hFontInactive = m_font;
		lpNMCustomDraw->hFontSelected = m_fontSel;
		lpNMCustomDraw->hBrushBackground = m_hbrBackground;
		lpNMCustomDraw->clrTextSelected = ::GetSysColor(COLOR_BTNTEXT);
		lpNMCustomDraw->clrTextInactive = m_clrTextInactiveTab;
		lpNMCustomDraw->clrSelectedTab = m_clrSelectedTab;
		lpNMCustomDraw->clrBtnFace = ::GetSysColor(COLOR_BTNFACE);
		lpNMCustomDraw->clrBtnShadow = ::GetSysColor(COLOR_BTNSHADOW);
		lpNMCustomDraw->clrBtnHighlight = ::GetSysColor(COLOR_BTNHIGHLIGHT);
		lpNMCustomDraw->clrBtnText = ::GetSysColor(COLOR_BTNTEXT);
		lpNMCustomDraw->clrHighlight = ::GetSysColor(COLOR_HIGHLIGHT);
#if WINVER >= 0x0500 || _WIN32_WINNT >= 0x0500
		lpNMCustomDraw->clrHighlightHotTrack = ::GetSysColor(COLOR_HOTLIGHT);
#else
		lpNMCustomDraw->clrHighlightHotTrack = ::GetSysColor(COLOR_HIGHLIGHT);
#endif
		lpNMCustomDraw->clrHighlightText = ::GetSysColor(COLOR_HIGHLIGHTTEXT);
	}

	void DoPrePaint(RECT rcClient, LPNMCTCCUSTOMDRAW lpNMCustomDraw)
	{
		T* pT = static_cast<T*>(this);

		pT->DrawBackground(rcClient, lpNMCustomDraw);
	}

	void DoItemPaint(LPNMCTCCUSTOMDRAW lpNMCustomDraw)
	{
		T* pT = static_cast<T*>(this);

		bool bSelected = (CDIS_SELECTED == (lpNMCustomDraw->nmcd.uItemState & CDIS_SELECTED));
		// NOTE: lpNMCustomDraw->nmcd.rc is in logical coordinates
		RECT &rcItem = lpNMCustomDraw->nmcd.rc;

		DWORD dwStyle = pT->GetStyle();
		RECT rcTab = rcItem;
		RECT rcText = rcItem;
		int nIconVerticalCenter = 0;

		pT->DrawItem_InitBounds(dwStyle, rcItem, rcTab, rcText, nIconVerticalCenter);

		if(bSelected)
		{
			pT->DrawItem_TabSelected(dwStyle, lpNMCustomDraw, rcTab);
		}
		else
		{
			pT->DrawItem_TabInactive(dwStyle, lpNMCustomDraw, rcTab);
		}

		pT->DrawItem_ImageAndText(dwStyle, lpNMCustomDraw, nIconVerticalCenter, rcTab, rcText);
	}

	void DoPostPaint(RECT /*rcClient*/, LPNMCTCCUSTOMDRAW lpNMCustomDraw)
	{
		T* pT = static_cast<T*>(this);

		DWORD dwStyle = this->GetStyle();

		if(0 == (dwStyle & (CTCS_CLOSEBUTTON | CTCS_SCROLL)))
		{
			return;
		}

		// Close Button
		if(CTCS_CLOSEBUTTON == (dwStyle & CTCS_CLOSEBUTTON))
		{
			if( (m_iCurSel >= 0) && ((size_t)m_iCurSel < m_Items.GetCount()) )
			{
				TItem* pItem = m_Items[m_iCurSel];
				ATLASSERT(pItem != NULL);
				if((pItem != NULL) && pItem->CanClose())
				{
					pT->DrawCloseButton(lpNMCustomDraw);
				}
			}
		}

		// Scroll Buttons
		if(CTCS_SCROLL == (dwStyle & CTCS_SCROLL))
		{
			pT->DrawScrollButtons(lpNMCustomDraw);
		}
	}

// Overrides from CCustomTabCtrl
public:

	void CalcSize_NonClient(LPRECT prcTabItemArea)
	{
		// account for "non-client" areas
		// TODO: For the short term, we will use this
		//  for the non-client areas on the left and right.
		//  The drawing code for the tabs already accounts
		//  for the "non-client" areas on the top and bottom, and
		//  would need to be updated if we account for it here.
		//  Tab item rect methods also would need to be
		//  updated to account for the non-client areas
		//  on top and bottom (and effected drawing code
		//  would need to be updated).
		DWORD dwStyle = this->GetStyle();

		if(CTCS_BOTTOM == (dwStyle & CTCS_BOTTOM))
		{
			// TODO: Update to actually specify the
			//  non-client areas, and adjust all of the
			//  effected drawing code, as well as
			//  tab item rect related things
			//prcTabItemArea->top += 3;
		}
		else
		{
			prcTabItemArea->left += 2;
			prcTabItemArea->right -= 2;

			// TODO: Update to actually specify the top and bottom
			//  non-client areas, and adjust all of the
			//  effected drawing code, as well as
			//  tab item rect related things
			//prcTabItemArea->top += 1;
			//// We would have bottom as 3, but we want the
			//// selected tab to actually paint over highlight part
			//prcTabItemArea->bottom -= 2;
		}
	}

	void CalcSize_CloseButton(LPRECT prcTabItemArea)
	{
		//int nButtonSizeX = ::GetSystemMetrics(SM_CXSMSIZE);
		//int nButtonSizeY = ::GetSystemMetrics(SM_CYSMSIZE);
		// NOTE: After several tests, VS.Net does NOT depend on
		//  any system metric for the button size, so neither will we.
		int nButtonSizeX = 15;
		int nButtonSizeY = 15;

		if((prcTabItemArea->right - prcTabItemArea->left) < nButtonSizeX)
		{
			::SetRectEmpty(&m_rcCloseButton);
			return;
		}

		m_rcCloseButton = *prcTabItemArea;

		DWORD dwStyle = this->GetStyle();

		if (CTCS_BOTTOM == (dwStyle & CTCS_BOTTOM))
		{
			m_rcCloseButton.top += 3;
			m_rcCloseButton.right -= 3;
		}
		else
		{
			m_rcCloseButton.top += 1;
			m_rcCloseButton.bottom -= 2;
			m_rcCloseButton.right -= 2;
		}
		m_rcCloseButton.top = (m_rcCloseButton.bottom + m_rcCloseButton.top - nButtonSizeY) / 2;
		m_rcCloseButton.bottom = m_rcCloseButton.top + nButtonSizeY;

		m_rcCloseButton.left = m_rcCloseButton.right - (nButtonSizeX);

		if(m_tooltip.IsWindow())
		{
			m_tooltip.SetToolRect(m_hWnd, (UINT)ectcToolTip_Close, &m_rcCloseButton);
		}

		// Adjust the tab area
		prcTabItemArea->right = m_rcCloseButton.left;
	}

	void CalcSize_ScrollButtons(LPRECT prcTabItemArea)
	{
		//int nButtonSizeX = ::GetSystemMetrics(SM_CXSMSIZE);
		//int nButtonSizeY = ::GetSystemMetrics(SM_CYSMSIZE);
		// NOTE: After several tests, VS.Net does NOT depend on
		//  any system metric for the button size, so neither will we.
		int nButtonSizeX = 15;
		int nButtonSizeY = 15;

		if((prcTabItemArea->right - prcTabItemArea->left) < nButtonSizeX)
		{
			::SetRectEmpty(&m_rcScrollRight);
			::SetRectEmpty(&m_rcScrollLeft);
			return;

⌨️ 快捷键说明

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