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

📄 customtabctrl.h

📁 These listed libraries are written in WTL. But it s really hard to mix both MFC & WTL together. Obvi
💻 H
📖 第 1 页 / 共 5 页
字号:
			tme.hwndTrack = m_hWnd;
			if( _TrackMouseEvent(&tme) )
			{
				m_dwState |= ectcMouseInWindow;

				pT->UpdateLayout();
				this->Invalidate();

				// "OnMouseEnter"
				//...
			}
		}

		if(	(m_iDragItem >= 0) &&
			(ectcMouseInWindow == (m_dwState & ectcMouseInWindow)) &&
			(ectcDraggingItem != (m_dwState & ectcDraggingItem)) &&
			(ectcMouseDownL_TabItem == (m_dwState & ectcMouseDown)) &&
			(m_ptDragOrigin.x != ptCursor.x))
		{
			pT->BeginItemDrag(m_iDragItem, m_ptDragOrigin);
		}
		else if(ectcDraggingItem == (m_dwState & ectcDraggingItem))
		{
			pT->ContinueItemDrag(ptCursor);
		}
		else if(ectcMouseInWindow == (m_dwState & ectcMouseInWindow))
		{
			// hit test
			if(::PtInRect(&m_rcCloseButton, ptCursor))
			{
				if( ectcMouseOver_CloseButton != (m_dwState & ectcMouseOver))
				{
					this->ClearCurrentMouseOverTracking(true);
					m_dwState |= ectcMouseOver_CloseButton;

					if(ectcMouseDownL_CloseButton == (m_dwState & ectcMouseDown))
					{
						this->InvalidateRect(&m_rcCloseButton);
					}
				}
				else if( 0 == (m_dwState & ectcMouseDown) &&
					ectcHotTrack_CloseButton != (m_dwState & ectcHotTrack))
				{
					this->ClearCurrentHotTracking(true);
					m_dwState |= ectcHotTrack_CloseButton;
					this->InvalidateRect(&m_rcCloseButton);
				}
			}
			else
			{
				if(ectcMouseOver_CloseButton == (m_dwState & ectcMouseOver))
				{
					this->ClearCurrentMouseOverTracking(true);
				}
				if(ectcHotTrack_CloseButton == (m_dwState & ectcHotTrack))
				{
					this->ClearCurrentHotTracking(true);
				}
			}

			if(::PtInRect(&m_rcScrollRight, ptCursor))
			{
				if( ectcMouseOver_ScrollRight != (m_dwState & ectcMouseOver))
				{
					this->ClearCurrentMouseOverTracking(true);
					m_dwState |= ectcMouseOver_ScrollRight;

					if(ectcMouseDownL_ScrollRight == (m_dwState & ectcMouseDown))
					{
						this->InvalidateRect(&m_rcScrollRight);
					}
				}
				else if(0 == (m_dwState & ectcMouseDown) &&
					ectcHotTrack_ScrollRight != (m_dwState & ectcHotTrack))
				{
					this->ClearCurrentHotTracking(true);
					m_dwState |= ectcHotTrack_ScrollRight;
					this->InvalidateRect(&m_rcScrollRight);
				}
			}
			else
			{
				if(ectcMouseOver_ScrollRight == (m_dwState & ectcMouseOver))
				{
					this->ClearCurrentMouseOverTracking(true);
				}
				if(ectcHotTrack_ScrollRight == (m_dwState & ectcHotTrack))
				{
					this->ClearCurrentHotTracking(true);
				}
			}

			if(::PtInRect(&m_rcScrollLeft, ptCursor))
			{
				if( ectcMouseOver_ScrollLeft != (m_dwState & ectcMouseOver))
				{
					this->ClearCurrentMouseOverTracking(true);
					m_dwState |= ectcMouseOver_ScrollLeft;

					if(ectcMouseDownL_ScrollLeft == (m_dwState & ectcMouseDown))
					{
						this->InvalidateRect(&m_rcScrollLeft);
					}
				}
				else if(0 == (m_dwState & ectcMouseDown) &&
					ectcHotTrack_ScrollLeft != (m_dwState & ectcHotTrack))
				{
					this->ClearCurrentHotTracking(true);
					m_dwState |= ectcHotTrack_ScrollLeft;
					this->InvalidateRect(&m_rcScrollLeft);
				}
			}
			else
			{
				if(ectcMouseOver_ScrollLeft == (m_dwState & ectcMouseOver))
				{
					this->ClearCurrentMouseOverTracking(true);
				}
				if(ectcHotTrack_ScrollLeft == (m_dwState & ectcHotTrack))
				{
					this->ClearCurrentHotTracking(true);
				}
			}

			if(::PtInRect(&m_rcTabItemArea, ptCursor))
			{
				if( ectcMouseOver_TabItem != (m_dwState & ectcMouseOver))
				{
					this->ClearCurrentMouseOverTracking(true);
					m_dwState |= ectcMouseOver_TabItem;

					// Not needed for simple hot tracking:
					//if(ectcMouseDownL_TabItem == (m_dwState & ectcMouseDown))
					//{
					//	this->InvalidateRect(&m_rcTabItemArea);
					//}
				}
				else if( CTCS_HOTTRACK == (dwStyle & CTCS_HOTTRACK) )
					// && ectcHotTrack_TabItem != (m_dwState & ectcHotTrack))
				{
					this->ClearCurrentHotTracking(true);

					CTCHITTESTINFO tchti = { 0 };
					tchti.pt = ptCursor;
					int nIndex = pT->HitTest(&tchti);
					if(nIndex >= 0)
					{
						m_iHotItem = nIndex;

						m_dwState |= ectcHotTrack_TabItem;
						RECT rcItem = {0};
						this->GetItemRect(nIndex, &rcItem);
						this->InvalidateRect(&rcItem);
					}
				}
			}
			else
			{
				if(ectcMouseOver_TabItem == (m_dwState & ectcMouseOver))
				{
					this->ClearCurrentMouseOverTracking(true);
				}
				if( CTCS_HOTTRACK == (dwStyle & CTCS_HOTTRACK) &&
					ectcHotTrack_TabItem == (m_dwState & ectcHotTrack))
				{
					this->ClearCurrentHotTracking(true);
				}
			}
		}

		return 1;
	}

	LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		T* pT = static_cast<T*>(this);

		bHandled = FALSE;

		m_dwState &= ~ectcMouseInWindow;
		this->ClearCurrentHotTracking(false);
		this->ClearCurrentMouseOverTracking(false);

		pT->UpdateLayout();
		this->Invalidate();

		return 0;
	}

	LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		T* pT = static_cast<T*>(this);

		bHandled = FALSE;

		this->ClearCurrentMouseDownTracking(false);
		if(ectcDraggingItem == (m_dwState & ectcDraggingItem))
		{
			pT->CancelItemDrag(false);
		}

		return 0;
	}

	LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		T* pT = static_cast<T*>(this);
		POINT ptCursor = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
		if(::PtInRect(&m_rcCloseButton, ptCursor))
		{
			m_dwState |= (ectcMouseDownL_CloseButton | ectcMouseOver_CloseButton);
			this->InvalidateRect(&m_rcCloseButton);
			this->SetCapture();
		}
		else if(::PtInRect(&m_rcScrollRight, ptCursor))
		{
			m_dwState |= (ectcMouseDownL_ScrollRight | ectcMouseOver_ScrollRight);
			if(ectcOverflowRight == (m_dwState & ectcOverflowRight))
			{
				int nScrollSpeed = 0;
				switch(m_dwState & ectcScrollRepeat)
				{
				case ectcScrollRepeat_Slow:
					nScrollSpeed = CTCSR_SLOW;
					break;
				case ectcScrollRepeat_Normal:
					nScrollSpeed = CTCSR_NORMAL;
					break;
				case ectcScrollRepeat_Fast:
					nScrollSpeed = CTCSR_FAST;
					break;
				case ectcScrollRepeat_None:
				default:
					nScrollSpeed = CTCSR_NONE;
					break;
				}

				pT->ScrollRight(true);
				this->SetTimer(ectcTimer_ScrollRight, nScrollSpeed);
			}
			this->SetCapture();
		}
		else if(::PtInRect(&m_rcScrollLeft, ptCursor))
		{
			m_dwState |= (ectcMouseDownL_ScrollLeft | ectcMouseOver_ScrollLeft);
			if(ectcOverflowLeft == (m_dwState & ectcOverflowLeft))
			{
				int nScrollSpeed = 0;
				switch(m_dwState & ectcScrollRepeat)
				{
				case ectcScrollRepeat_Slow:
					nScrollSpeed = CTCSR_SLOW;
					break;
				case ectcScrollRepeat_Normal:
					nScrollSpeed = CTCSR_NORMAL;
					break;
				case ectcScrollRepeat_Fast:
					nScrollSpeed = CTCSR_FAST;
					break;
				case ectcScrollRepeat_None:
				default:
					nScrollSpeed = CTCSR_NONE;
					break;
				}

				pT->ScrollLeft(true);
				this->SetTimer(ectcTimer_ScrollLeft, nScrollSpeed);
			}
			this->SetCapture();
		}
		else
		{
			// Search for a tab
			CTCHITTESTINFO tchti = { 0 };
			tchti.pt = ptCursor;
			int nIndex = pT->HitTest(&tchti);

			NMCTCITEM nmh = {{ m_hWnd, this->GetDlgCtrlID(), NM_CLICK }, nIndex, {ptCursor.x, ptCursor.y} };
			if(FALSE == ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
			{
				// returning FALSE let's us do our default handling
				if(nIndex >= 0)
				{
					// NOTE: If they click on a tab, only grab the focus
					//  if a drag operation is started.
					//pT->SetFocus();
					pT->SetCurSel(nIndex);

					m_iDragItem = nIndex;
					m_ptDragOrigin = ptCursor;

					m_dwState |= ectcMouseDownL_TabItem;

					// This could be a drag operation.  We'll start the actual drag
					// operation in OnMouseMove if the mouse moves while the left mouse
					// button is still pressed.  OnLButtonUp will ReleaseCapture.
					this->SetCapture();
				}
			}
		}

		return 0;
	}

	LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		if(m_hWnd == ::GetCapture())
		{
			T* pT = static_cast<T*>(this);

			POINT ptCursor = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};

			if(ectcDraggingItem == (m_dwState & ectcDraggingItem))
			{
				pT->AcceptItemDrag();
			}

			// Before we release the capture, remember what the state was
			// (in WM_CAPTURECHANGED we ClearCurrentMouseDownTracking)
			DWORD dwState = m_dwState;

			::ReleaseCapture();

			if(ectcMouseDownL_CloseButton == (dwState & ectcMouseDown) &&
				ectcMouseOver_CloseButton == (dwState & ectcMouseOver))
			{
				// Close Button
				NMCTCITEM nmh = {{ m_hWnd, this->GetDlgCtrlID(), CTCN_CLOSE }, m_iCurSel, {ptCursor.x, ptCursor.y}};
				::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh);
			}

			pT->UpdateLayout();
			this->Invalidate();
		}
		return 0;
	}

	LRESULT OnLButtonDoubleClick(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		POINT ptCursor = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};

		// Search for a tab
		T* pT = static_cast<T*>(this);
		CTCHITTESTINFO tchti = { 0 };
		tchti.pt = ptCursor;
		int nIndex = pT->HitTest(&tchti);

		// returning TRUE tells us not to do our default handling
		NMCTCITEM nmh = {{ m_hWnd, this->GetDlgCtrlID(), NM_DBLCLK }, nIndex, {ptCursor.x, ptCursor.y}};
		if(FALSE == ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
		{
			// returning FALSE let's us do our default handling
			if(nIndex >= 0)
			{
				//pT->SetFocus();
				//pT->SetCurSel(nIndex);
			}
		}

		return 0;
	}

	LRESULT OnRButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		POINT ptCursor = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};

		// Search for a tab
		T* pT = static_cast<T*>(this);
		CTCHITTESTINFO tchti = { 0 };
		tchti.pt = ptCursor;
		int nIndex = pT->HitTest(&tchti);

		// returning TRUE tells us not to do our default handling
		NMCTCITEM nmh = {{ m_hWnd, this->GetDlgCtrlID(), NM_RCLICK }, nIndex, {ptCursor.x, ptCursor.y}};
		if(FALSE == ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
		{
			// returning FALSE let's us do our default handling
			if(nIndex >= 0)
			{
				// NOTE: If they click on a tab, only grab the focus
				//  if a drag operation is started.
				//pT->SetFocus();
				pT->SetCurSel(nIndex);
			}
		}

		return 0;
	}

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

	LRESULT OnRButtonDoubleClick(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		POINT ptCursor = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};

		// Search for a tab
		T* pT = static_cast<T*>(this);
		CTCHITTESTINFO tchti = { 0 };
		tchti.pt = ptCursor;
		int nIndex = pT->HitTest(&tchti);

		// returning TRUE tells us not to do our default handling
		NMCTCITEM nmh = {{ m_hWnd, this->GetDlgCtrlID(), NM_RDBLCLK }, nIndex, {ptCursor.x, ptCursor.y}};
		if(FALSE == ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
		{
			// returning FALSE let's us do our default handling
			if(nIndex >= 0)
			{
				//pT->SetFocus();
				//pT->SetCurSel(nIndex);
			}
		}

		return 0;
	}

	LRESULT OnMButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		POINT ptCursor = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};

		// Search for a tab
		T* pT = static_cast<T*>(this);
		CTCHITTESTINFO tchti = { 0 };
		tchti.pt = ptCursor;
		int nIndex = pT->HitTest(&tchti);

		// returning TRUE tells us not to do our default handling
		NMCTCITEM nmh = {{ m_hWnd, this->GetDlgCtrlID(), CTCN_MCLICK }, nIndex, {ptCursor.x, ptCursor.y}};
		if(FALSE == ::SendMessage(GetParent(), WM_NOTIFY, nmh.hdr.idFrom, (LPARAM)&nmh))
		{
			// returning FALSE let's us do our default handling
			if( nIndex!=-1 )
			{
				//pT->SetFocus();
				//pT->SetCurSel(nIndex);
			}
		}

		return 0;
	}

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

	LRESULT OnMButtonDoubleClick(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
	{
		POINT ptCursor = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};

		// Search for a tab
		T* pT = static_cast<T*>(this);
		CTCHITTESTINFO tchti = { 0 };
		tchti.pt = ptCursor;
		int nIndex = pT->HitTest(&tchti);

⌨️ 快捷键说明

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