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

📄 customtabctrl.h

📁 These listed libraries are written in WTL. But it s really hard to mix both MFC & WTL together. Obvi
💻 H
📖 第 1 页 / 共 5 页
字号:
		// returning TRUE tells us not to do our default handling
		NMCTCITEM nmh = {{ m_hWnd, this->GetDlgCtrlID(), CTCN_MDBLCLK }, 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 OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
	{
		T* pT = static_cast<T*>(this);
		switch( wParam )
		{
		case VK_LEFT:
			if( m_iCurSel > 0 )
			{
				pT->SetCurSel(m_iCurSel-1);
			}
			return 0;
		case VK_RIGHT:
			if( m_iCurSel < (int)m_Items.GetCount()-1 )
			{
				pT->SetCurSel(m_iCurSel+1);
			}
			return 0;
		case VK_ESCAPE:
			if(ectcDraggingItem == (m_dwState & ectcDraggingItem))
			{
				pT->CancelItemDrag(true);
				return 0;
			}
			break;
		}
		bHandled = FALSE;
		return 0;
	}

	LRESULT OnGetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		// DDB: 2002/04/22
		// The code was doing GetFont and SetFont, but wasn't actually
		//  properly dealing with implementing it if the window
		//  was not a subclassed static control.
		return (LRESULT)(HFONT)m_font;
	}

	LRESULT OnSetFont(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		// DDB: 2002/04/22
		// The code was doing GetFont and SetFont, but wasn't actually
		//  properly dealing with implementing it if the window
		//  was not a subclassed static control.
		//
		// Also, we're managing the lifetime of our font
		//  (i.e., we're going to DeleteObject it in our destructor),
		//  so if someone calls SetFont, keep a copy of the
		//  font instead of just "pointing" to it
		LOGFONT lfCopy = {0};
		::GetObject((HFONT)wParam, sizeof(LOGFONT), &lfCopy);

		if(!m_font.IsNull()) m_font.DeleteObject();

		m_font.CreateFontIndirect(&lfCopy);

		if(LOWORD(lParam))
		{
			this->Invalidate();
		}

		return 0;
	}

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

				// Tooltips
				if((((pStyles->styleOld) & CTCS_TOOLTIPS) != CTCS_TOOLTIPS) &&
					(((pStyles->styleNew) & CTCS_TOOLTIPS) == CTCS_TOOLTIPS))
				{
					this->ActivateTooltips(TRUE);
				}
				else if((((pStyles->styleOld) & CTCS_TOOLTIPS) == CTCS_TOOLTIPS) &&
					(((pStyles->styleNew) & CTCS_TOOLTIPS) != CTCS_TOOLTIPS))
				{
					this->ActivateTooltips(FALSE);
				}

				// Scroll to fit
				if((((pStyles->styleOld) & CTCS_SCROLL) != CTCS_SCROLL) &&
					(((pStyles->styleNew) & CTCS_SCROLL) == CTCS_SCROLL))
				{
					if(m_tooltip.IsWindow())
					{
						m_tooltip.AddTool(m_hWnd, _T("Scroll Right"), &rcDefault, (UINT)ectcToolTip_ScrollRight);
						m_tooltip.AddTool(m_hWnd, _T("Scroll Left"), &rcDefault, (UINT)ectcToolTip_ScrollLeft);
					}

					//pT->UpdateLayout();
					//this->Invalidate();
				}
				else if((((pStyles->styleOld) & CTCS_SCROLL) == CTCS_SCROLL) &&
					(((pStyles->styleNew) & CTCS_SCROLL) != CTCS_SCROLL))
				{
					if(m_tooltip.IsWindow())
					{
						m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_ScrollRight);
						m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_ScrollLeft);
					}

					m_iScrollOffset = 0;
					//pT->UpdateLayout();
					//this->Invalidate();
				}

				// Close Button
				if((((pStyles->styleOld) & CTCS_CLOSEBUTTON) != CTCS_CLOSEBUTTON) &&
					(((pStyles->styleNew) & CTCS_CLOSEBUTTON) == CTCS_CLOSEBUTTON))
				{
					if(m_tooltip.IsWindow())
					{
						m_tooltip.AddTool(m_hWnd, _T("Close"), &rcDefault, (UINT)ectcToolTip_Close);
					}

					//pT->UpdateLayout();
					//this->Invalidate();
				}
				else if((((pStyles->styleOld) & CTCS_CLOSEBUTTON) == CTCS_CLOSEBUTTON) &&
					(((pStyles->styleNew) & CTCS_CLOSEBUTTON) != CTCS_CLOSEBUTTON))
				{
					if(m_tooltip.IsWindow())
					{
						m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_Close);
					}

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

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

		bHandled = FALSE;
		return 0;
	}

	LRESULT OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
	{
		T* pT = static_cast<T*>(this);
		switch(wParam)
		{
		case ectcTimer_ScrollRight:
			if(ectcOverflowRight != (m_dwState & ectcOverflowRight))
			{
				this->KillTimer(ectcTimer_ScrollRight);
			}
			else // ectcOverflowRight == (m_dwState & ectcOverflowRight)
			{
				if(ectcDraggingItem == (m_dwState & ectcDraggingItem))
				{
					// We're scrolling because they're dragging a tab near the edge.
					// First kill the timer, then update the drag
					// (which might set the timer again)
					this->KillTimer(ectcTimer_ScrollRight);

					POINT ptCursor = {0};
					::GetCursorPos(&ptCursor);
					this->ScreenToClient(&ptCursor);
					pT->ContinueItemDrag(ptCursor);
				}
				else if(ectcMouseDownL_ScrollRight == (m_dwState & ectcMouseDown) &&
					ectcMouseOver_ScrollRight == (m_dwState & ectcMouseOver))
				{
					// We're scrolling because they're holding down the scroll button
					pT->ScrollRight(true);

					if(ectcScrollRepeat_None == (m_dwState & ectcScrollRepeat))
					{
						this->KillTimer(ectcTimer_ScrollRight);
					}
				}
			}
			break;
		case ectcTimer_ScrollLeft:
			if(ectcOverflowLeft != (m_dwState & ectcOverflowLeft))
			{
				this->KillTimer(ectcTimer_ScrollLeft);
			}
			else // ectcOverflowLeft == (m_dwState & ectcOverflowLeft)
			{
				if(ectcDraggingItem == (m_dwState & ectcDraggingItem))
				{
					// We're scrolling because they're dragging a tab near the edge.
					// First kill the timer, then update the drag
					// (which might set the timer again)
					this->KillTimer(ectcTimer_ScrollLeft);

					POINT ptCursor = {0};
					::GetCursorPos(&ptCursor);
					this->ScreenToClient(&ptCursor);
					pT->ContinueItemDrag(ptCursor);
				}
				else if(ectcMouseDownL_ScrollLeft == (m_dwState & ectcMouseDown) &&
					ectcMouseOver_ScrollLeft == (m_dwState & ectcMouseOver))
				{
					// We're scrolling because they're holding down the scroll button
					pT->ScrollLeft(true);

					if(ectcScrollRepeat_None == (m_dwState & ectcScrollRepeat))
					{
						this->KillTimer(ectcTimer_ScrollLeft);
					}
				}
			}
			break;
		default:
			bHandled = FALSE;
			break;
		}
		return 0;
	}

	LRESULT OnSetRedraw(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
	{
		// If someone sends us WM_SETREDRAW with FALSE, we can avoid
		// doing an update layout until they set it back to TRUE.
		if(wParam)
		{
			if(ectcEnableRedraw != (m_dwState & ectcEnableRedraw))
			{
				// Redrawing was turned off, but now its being
				// turned back on again
				m_dwState |= ectcEnableRedraw;

				T* pT = static_cast<T*>(this);
				pT->UpdateLayout();

				// The caller will typically call InvalidateRect
				// or RedrawWindow after sending WM_SETREDRAW with TRUE,
				// so we won't do that here (but we will UpdateLayout,
				// so that we'll be ready to redraw)
			}
		}
		else
		{
			if(ectcEnableRedraw == (m_dwState & ectcEnableRedraw))
			{
				// Redrawing was turned on, but now its being turned off
				m_dwState &= ~ectcEnableRedraw;
			}
		}

		bHandled = FALSE;
		return 0;
	}

	LRESULT OnGetToolTipInfo(int /*idCtrl*/, LPNMHDR pnmh, BOOL& /*bHandled*/)
	{
		LPNMTTDISPINFO pToolTipInfo = (LPNMTTDISPINFO)pnmh;
		if(pToolTipInfo)
		{
			// The way we implement tooltips for tab items
			// is to have as many "tools" as there are tabs.
			// The relationship of tool ID => tab index is:
			// tool ID = tab index + 1	(to avoid 0 as an ID)
			//
			// We supply the RECT elsewhere and the text here
			UINT_PTR id = pToolTipInfo->hdr.idFrom;
			if(id > 0 && id <= m_Items.GetCount())
			{
				TItem* pItem = m_Items[id-1];
				ATLASSERT(pItem != NULL);
				if(pItem)
				{
					if(pItem->UsingToolTip())
					{
						pToolTipInfo->lpszText = const_cast<LPTSTR>(pItem->GetToolTipRef());
					}
					else if(pItem->UsingText())
					{
						pToolTipInfo->lpszText = const_cast<LPTSTR>(pItem->GetTextRef());
					}
				}
			}
		}

		return 0;
	}

// Overridables
public:

	void Initialize(void)
	{
		ATLASSERT(::IsWindow(m_hWnd));

		this->SendMessage(WM_SETTINGCHANGE, 0, 0);

		this->InitializeTooltips();

		// NOTE: you can change the style at any time
		//  for a number of the cool tab control styles
		//  (tool tips, close button, scroll buttons, etc.)
		DWORD dwStyle = this->GetStyle();

		this->ActivateTooltips(CTCS_TOOLTIPS == (dwStyle & CTCS_TOOLTIPS));

		if(CTCS_SCROLL == (dwStyle & CTCS_SCROLL))
		{
			if(m_tooltip.IsWindow())
			{
				m_tooltip.AddTool(m_hWnd, _T("Scroll Right"), &rcDefault, (UINT)ectcToolTip_ScrollRight);
				m_tooltip.AddTool(m_hWnd, _T("Scroll Left"), &rcDefault, (UINT)ectcToolTip_ScrollLeft);
			}
		}

		if(CTCS_CLOSEBUTTON == (dwStyle & CTCS_CLOSEBUTTON))
		{
			if(m_tooltip.IsWindow())
			{
				m_tooltip.AddTool(m_hWnd, _T("Close"), &rcDefault, (UINT)ectcToolTip_Close);
			}
		}
	}

	void Uninitialize(void)
	{
		T* pT = static_cast<T*>(this);

		DWORD dwStyle = this->GetStyle();

		if(m_tooltip.IsWindow())
		{
			if(CTCS_SCROLL == (dwStyle & CTCS_SCROLL))
			{
				m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_ScrollRight);
				m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_ScrollLeft);
			}

			if(CTCS_CLOSEBUTTON == (dwStyle & CTCS_CLOSEBUTTON))
			{
				m_tooltip.DelTool(m_hWnd, (UINT)ectcToolTip_Close);
			}
		}

		pT->DeleteAllItems();

		if(m_tooltip.IsWindow())
		{
			// Also sets the contained m_hWnd to NULL
			m_tooltip.DestroyWindow();
		}
		else
		{
			m_tooltip = NULL;
		}
	}

	TItem* CreateNewItem(void* pInitData = NULL)
	{
		pInitData; // avoid level 4 warning

#if defined (_CPPUNWIND) & (defined(_ATL_EXCEPTIONS) | defined(_AFX))
		TItem* pNewItem = NULL;
		try { pNewItem = new TItem; }
		catch (...) { ATLTRACE(_T("!! Exception thrown in CCustomTabCtrl::CreateNewItem\r\n")); }
#else
		TItem* pNewItem = new TItem;
#endif
		return pNewItem;
	}

	void DeleteItem(TItem* pOldItem)
	{
#if defined (_CPPUNWIND) & (defined(_ATL_EXCEPTIONS) | defined(_AFX))
		try { delete pOldItem; }
		catch (...) { ATLTRACE(_T("!! Exception thrown in CCustomTabCtrl::DeleteItem\r\n")); }
#else
		delete pOldItem;
#endif
	}

	void UpdateLayout(void)
	{
		if(	!m_hWnd ||
			!::IsWindow(m_hWnd) ||
			(ectcEnableRedraw != (m_dwState & ectcEnableRedraw)))
		{
			return;
		}

		this->GetClientRect(&m_rcTabItemArea);

		T* pT = static_cast<T*>(this);

		DWORD dwStyle = this->GetStyle();

		pT->CalcSize_NonClient(&m_rcTabItemArea);

		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->CalcSize_CloseButton(&m_rcTabItemArea);
				}
			}
		}

		if(CTCS_SCROLL == (dwStyle & CTCS_SCROLL))
		{
			pT->CalcSize_ScrollButtons(&m_rcTabItemArea);
			pT->UpdateLayout_ScrollToFit(m_rcTabItemArea);
			pT->UpdateScrollOverflowStatus();
		}
		else
		{
			pT->UpdateLayout_Default(m_rcTabItemArea);
		}

		pT->UpdateTabItemTooltipRects();
	}

	void CalcSize_NonClient(LPRECT prcTabItemArea)
	{
	}

	void CalcSize_CloseButton(LPRECT prcTabItemArea)
	{
	}

	void CalcSize_ScrollButtons(LPRECT prcTabItemArea)
	{
	}

	void UpdateLayout_Default(RECT rcTabItemArea)
	{
		UpdateLayout_ScrollToFit(rcTabItemArea);
	}

	void UpdateLayout_ScrollToFit(RECT rcTabItemArea)
	{
		WTL::CClientDC dc(m_hWnd);
		HFONT hOldFont = dc.SelectF

⌨️ 快捷键说明

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