自绘Tab控件

22 篇文章 0 订阅

自绘tab按钮效果图如下:

 

使用例子:

MyTabControl *tabControl = NULL;

tabControl = new MyTabControl();
tabControl->Create(this, CRect(0,0,125,27), L"花生", ID_BTN_MYTAB);
tabControl->SetTabIndex(index);

tabControl->SetShowText(L"花生");

tabControl->SetTabState(TAB_STATE_DOWN);

tabControl->SetToolTipText(L"花生");

头文件:

#pragma once
#include "LhsButton.h"

// MyTabControl

#define ID_BTN_MYTAB_CLOSE	2100			//关闭按钮的id
#define MYWM_BTN_TAB_CLOSE WM_USER+2001		//关闭按钮单击响应
#define MYWM_BTN_TAB_CLICK WM_USER+2002		//tab按钮单击

//tab按钮的状态
enum TabState
{
	TAB_STATE_NOR			= 0,
	TAB_STATE_DOWN			= 1,
};
class MyTabControl : public CWnd
{
	DECLARE_DYNAMIC(MyTabControl)

public:
	MyTabControl();
	virtual ~MyTabControl();

	 bool Create(CWnd* pParent,CRect rc,CString text,DWORD id = 0,DWORD style = WS_VISIBLE|WS_CHILD);  

	DECLARE_MESSAGE_MAP()

public:
	void SetShowText(CString strShowText);

protected:
	CString szClassName;  
	bool m_isMouseHover;		//鼠标是否悬浮
	bool m_isMouseClicked;		//鼠标是否单击
	CString m_strShowText;		//要显示的文字
	CString m_strTabText;		//绘制在tab按钮下的文字

	Image*						m_pImgNor;			//正常时的图片
	Image*						m_pImgHot;			//鼠标悬浮时的图片
	Image*						m_pImgDown;			//单击按下时的图片
	
	void PostClickEvent();
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
	afx_msg void OnMouseHover(UINT nFlags, CPoint point);  
	afx_msg void OnMouseLeave();  
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);  
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);  
	afx_msg void OnPaint();  
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg LRESULT OnBtnClose(WPARAM wParam, LPARAM lParam);
	virtual BOOL PreTranslateMessage(MSG* pMsg);
public:
	void SetTabState(TabState state){m_tabState = state; Invalidate();}	//设置tab状态
	TabState GetTabState(){return m_tabState;}
	void SetToolTipText(CString spText, BOOL bActivate = TRUE);
	void SetTabIndex(int idx){m_nIndex = idx;}
	int GetTabIndex(){return m_nIndex;}
private:
	DWORD GetComfortSize(HDC hdc, DWORD dwWidth, CString &strText);
private:
	TabState m_tabState;							//tab的状态
	CLhsButton m_btnClose;							//关闭按钮
	CToolTipCtrl*	m_pToolTip;
	CString m_tooltext;
	bool m_bCenterAlign;							//是否居中对齐
	int m_nIndex;									//tab按钮的索引

public:
	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
};

// MyTabControl.cpp : 实现文件
//

#include "stdafx.h"
#include "../Lander_mini.h"
#include "MyTabControl.h"
#include "memdc.h"
#include "../Utility.h"
// MyTabControl

IMPLEMENT_DYNAMIC(MyTabControl, CWnd)

MyTabControl::MyTabControl()
{
	m_isMouseHover = false;  
	m_isMouseClicked = false;  
	// 注册控件类  
	szClassName = AfxRegisterWndClass(0); 
	m_pImgNor = NULL;
	m_pImgHot = NULL;
	m_pImgDown = NULL;
	m_tabState = TAB_STATE_NOR;
	m_pToolTip = NULL;
	m_bCenterAlign = false;
	m_nIndex = 0;
}

MyTabControl::~MyTabControl()
{
	SAFE_RELEASE(m_pToolTip);
	SAFE_RELEASE(m_pImgNor);
	SAFE_RELEASE(m_pImgHot);
	SAFE_RELEASE(m_pImgDown);
}


BEGIN_MESSAGE_MAP(MyTabControl, CWnd)
	ON_WM_MOUSEMOVE()  
	ON_WM_MOUSEHOVER()  // 此消息系统并不会给我们发送  
	ON_WM_MOUSELEAVE()  
	ON_WM_LBUTTONDOWN()  
	ON_WM_LBUTTONUP()  
	ON_WM_PAINT()  
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()  
	ON_WM_CREATE()
	ON_MESSAGE(MYWM_BTN_CLICK, &MyTabControl::OnBtnClose)
	ON_WM_CTLCOLOR()
END_MESSAGE_MAP()

// MyTabControl 消息处理程序
bool MyTabControl::Create(CWnd* pParent,CRect rc,CString text,DWORD id /* = 0 */,DWORD style /* = WS_VISIBLE|WS_CHILD */)  
{  
	// 动态创建控件  	
	BOOL ret = CWnd::CreateEx(0, szClassName, text, style, rc, pParent, id);
	return ret ? true : false;  
}  

int MyTabControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	
	//::SetWindowLong(m_hWnd, GWL_EXSTYLE, GetWindowLong(m_hWnd, GWL_EXSTYLE) ^ WS_EX_LAYERED);
	m_pImgNor = CQYUtility::LoadImgFromRes(_T("PNG"), IDB_PNG_TAB_NOR);
	m_pImgHot = CQYUtility::LoadImgFromRes(_T("PNG"), IDB_PNG_TAB_HOT);
	m_pImgDown = CQYUtility::LoadImgFromRes(_T("PNG"), IDB_PNG_TAB_DOWN);
	
	RECT rc = {0, 0, 20, 20};
	m_btnClose.LoadBtnImg(_T("PNG"),IDB_PNG_TAB_CLOSE_NOR, IDB_PNG_TAB_CLOSE_HOT,IDB_PNG_TAB_CLOSE_HOT);
	m_btnClose.Create(this, rc, L"",ID_BTN_MYTAB_CLOSE);		
	m_btnClose.SetToolTipText(_T("关闭")); 		
	EnableToolTips(TRUE);
	return 0;
}

void MyTabControl::PostClickEvent()  
{  
	if (m_tabState == TAB_STATE_DOWN)
		return;		//选中的tab不响应单击了
	// 该函数用来向父窗口发送 单击 消息  
	CWnd* parent = GetParent();  
	if(parent)  
		parent->SendMessage(MYWM_BTN_TAB_CLICK,m_nIndex,0);  	
}  

void MyTabControl::OnMouseHover(UINT nFlags, CPoint point)  
{  
	// 鼠标进入  
	Invalidate();  
}  

void MyTabControl::OnMouseMove(UINT nFlags, CPoint point)
{
	// 只处理鼠标第一次进入时的情况  
	if(!m_isMouseHover)  
	{  
		m_isMouseHover = true;  

		TRACKMOUSEEVENT evt = { sizeof(evt), TME_LEAVE|TME_HOVER, m_hWnd, 0 };  
		TrackMouseEvent(&evt);  

		OnMouseHover(0,CPoint());  
	}  
}

void MyTabControl::OnMouseLeave()  
{  
	// 鼠标离开  
	m_isMouseHover = false;  
	m_isMouseClicked = false;  
	Invalidate();  
}  

void MyTabControl::OnLButtonDown(UINT nFlags, CPoint point)  
{  
	// 鼠标按下  
	m_isMouseClicked = true;  
	Invalidate();  
}  

void MyTabControl::OnLButtonUp(UINT nFlags, CPoint point)  
{  
	// 鼠标松开  
	if(m_isMouseClicked)  
	{  
		m_isMouseClicked = false;  
		Invalidate(); 
		PostClickEvent();  
	}  
}  

BOOL MyTabControl::OnEraseBkgnd(CDC* pDC)  
{  
//	return CWnd::OnEraseBkgnd(pDC);
	return TRUE;    // 阻止擦除背景,防止闪烁  
}  

void MyTabControl::OnPaint()  
{  
	CPaintDC dc(this);   
	CRect rc;  
	GetClientRect(&rc); 
	
	// 采用双缓存,防止闪烁  
	CMemDC memdc(&dc,&rc,TRUE);
	Graphics graphic(memdc);
	if (!m_pImgNor || !m_pImgHot || !m_pImgDown)
	{//没有提供按钮图片就刷下背景
		// 刷背景  
		COLORREF bkgnd = RGB(100,0,0);  
		if(m_isMouseHover)  
		{  
			if(m_isMouseClicked)  
				bkgnd = RGB(250,0,0);  
			else  
				bkgnd = RGB(180,0,0);  
		}  
		memdc.FillSolidRect(&rc,bkgnd);  
	}
	
	if (m_isMouseClicked || m_tabState == TAB_STATE_DOWN)
	{//单击一定画单击状态
		graphic.DrawImage(m_pImgDown, 0, 0, m_pImgDown->GetWidth(), m_pImgDown->GetHeight());
	}
	else if (m_isMouseHover && !m_isMouseClicked)
	{
		//悬浮,但是没单击
		graphic.DrawImage(m_pImgHot, 0, 0, m_pImgHot->GetWidth(), m_pImgHot->GetHeight());		
	}
	else
	{
		graphic.DrawImage(m_pImgNor, 0, 0, m_pImgNor->GetWidth(), m_pImgNor->GetHeight());	
	}

	if (!m_strTabText.IsEmpty())
	{
		// 设置文字字体  
		CFont font;  
		font.CreatePointFont(100,L"宋体"); // 11号字体,该参数与实际字体号有10倍的关系  
		CFont* poldFont = memdc.SelectObject(&font);  
		// 设置文字属性  
		memdc.SetBkMode(TRANSPARENT);  
		if (m_tabState == TAB_STATE_DOWN)
			memdc.SetTextColor(RGB(136,76,25));  
		else
			memdc.SetTextColor(RGB(255,245,190));  
		// 绘制文本  
		DWORD style = DT_SINGLELINE | DT_VCENTER ;   // 文本格式:单行+水平居中+垂直居中  
		//if (m_bCenterAlign)
		//	style |= DT_CENTER;
		CRect fontRect(rc);
		fontRect.left += 13;
		fontRect.right -= 22;
		memdc.DrawText(m_strTabText, -1, &fontRect, style);    // 更多文本显示格式可参考百度百科DrawText说明 
		memdc->SelectObject(poldFont);		
	}
	
	// 使绘制生效  
	graphic.ReleaseHDC(memdc);			
}  


BOOL MyTabControl::PreTranslateMessage(MSG* pMsg) 
{
	if (m_pToolTip)
	{
		if (::IsWindow(m_pToolTip->m_hWnd))
		{
			m_pToolTip->RelayEvent(pMsg);		
		}
	}

	return CWnd::PreTranslateMessage(pMsg);
}


void MyTabControl::OnSize(UINT nType, int cx, int cy) 
{
	CRect rect;
	GetClientRect(&rect);	
	m_btnClose.SetWindowPos(NULL, rect.right - 22, rect.top + 2, 20, 20, SWP_NOZORDER);
}

LRESULT MyTabControl::OnBtnClose(WPARAM wParam, LPARAM lParam)
{
	// 该函数用来向父窗口发送 单击 消息  
	CWnd* parent = GetParent();  
	if(parent != NULL)  
	{  
		parent->SendMessage(MYWM_BTN_TAB_CLOSE, m_nIndex, 0);
	}  
	return 0;
}

void MyTabControl::SetToolTipText(CString spText, BOOL bActivate)
{
	if (m_pToolTip == NULL)
	{
		m_pToolTip = new CToolTipCtrl;
		// Create ToolTip control
		m_pToolTip->Create(this);
		m_pToolTip->Activate(TRUE);
	}

	m_tooltext = spText;

	// If there is no tooltip defined then add it
	if (m_pToolTip->GetToolCount() == 0)
	{
		CRect rectBtn; 
		GetClientRect(rectBtn);
		m_pToolTip->AddTool(this, m_tooltext, rectBtn, 1);
	}

	// Set text for tooltip
	m_pToolTip->UpdateTipText(m_tooltext, this, 1);
	m_pToolTip->SetDelayTime(2000);
	m_pToolTip->Activate(bActivate);
}


DWORD MyTabControl::GetComfortSize(HDC hdc,DWORD dwWidth,CString &strText)
{
	//二分法查找
	DWORD dwComfortSize = 0;
	DWORD dwBeginSize = 0;
	DWORD dwEndSize = strText.GetLength();

	while(TRUE)
	{
		DWORD dwMiddleSize = (dwEndSize + dwBeginSize) / 2;
		if(dwMiddleSize == dwBeginSize || dwMiddleSize == dwEndSize)
		{
			//两个点之间已经没有数值可以检测,退出循环
			dwComfortSize = dwBeginSize;
			break;
		}

		SIZE sizeChk = {0};
		::GetTextExtentPoint(hdc, strText.GetBuffer(), dwMiddleSize, &sizeChk);

		if(sizeChk.cx == dwWidth)
		{
			//数值刚好合适,跳出循环
			dwComfortSize = dwMiddleSize;
			break;
		}
		else if(static_cast<DWORD>(sizeChk.cx) > dwWidth)
		{
			//重新设置边界
			dwEndSize = dwMiddleSize;
		}
		else
		{
			//重新设置边界
			dwBeginSize = dwMiddleSize;
		}

	}

	return dwComfortSize;
}

void MyTabControl::SetShowText(CString strShowText)
{
	m_strShowText = strShowText;

	CRect rect;
	GetClientRect(&rect);
	SIZE sizeEllipsis = {0};
	::GetTextExtentPoint(GetDC()->GetSafeHdc(), strShowText.GetBuffer(), lstrlen(strShowText.GetBuffer()), &sizeEllipsis);
	if (sizeEllipsis.cx  < rect.Width() - 40)
	{//显示区域够宽
		m_bCenterAlign = true;
		m_strTabText = strShowText;
		return;
	}
	memset(&sizeEllipsis,0, sizeof(sizeEllipsis));
	CString ellipsStr = _T("...");
	::GetTextExtentPoint(GetDC()->GetSafeHdc(), ellipsStr.GetBuffer(), lstrlen(ellipsStr.GetBuffer()), &sizeEllipsis);
	DWORD dwMaxDisp = GetComfortSize(GetDC()->GetSafeHdc(), rect.Width() - sizeEllipsis.cx - 20, strShowText);
	if (dwMaxDisp >= strShowText.GetLength())
	{
		m_strTabText = strShowText;
	}
	else
	{
		m_strTabText = m_strShowText.Left(dwMaxDisp);
		m_strTabText += ellipsStr;		
	}	

}



HBRUSH MyTabControl::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CWnd::OnCtlColor(pDC, pWnd, nCtlColor);

	// TODO:  在此更改 DC 的任何属性
//	m_btnClose.SetBkGnd(pDC);
	// TODO:  如果默认的不是所需画笔,则返回另一个画笔
	return hbr;
}

//内存DC类和按钮类见链接: 点击打开链接



  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MFC(Microsoft Foundation Class)是一种基于Windows操作系统的软件开发框架,用于开发图形用户界面(GUI)应用程序。MFC包含了丰富的自绘Tab控件样式,可供开发人员选择和应用。 首先,MFC提供了丰富的颜色和字体样式选项。开发人员可以根据应用程序的需求自定义Tab控件的背景颜色、边框颜色、选中和未选中状态的文本颜色等。同时,也可以设置不同的字体样式,如字体、大小、加粗、倾斜等,以满足用户界面设计的需求。 其次,MFC还支持不同的Tab控件形状。除了常见的矩形形状外,还可以使用椭圆形状、圆角矩形形状等来美化Tab控件的外观。这些不同形状的Tab控件可以使应用程序的界面更加独特、吸引人。 此外,MFC还提供了不同的Tab控件标签布局选项。开发人员可以根据界面设计的需要选择标签的位置,如顶部、底部、左侧、右侧等。这可以使用户能够自由选择最适合其操作习惯的Tab控件风格。 最后,MFC还支持自定义Tab控件的图标。开发人员可以添加自定义的图标或者使用系统提供的图标作为Tab控件的标识。这可以帮助用户更直观地理解和导航应用程序的功能。 总之,MFC提供了丰富多样的自绘Tab控件样式,开发人员可以根据应用程序的需要选择和应用不同的样式。这些样式包括颜色和字体样式的调整、不同形状的Tab控件、不同的标签布局选项以及自定义的图标等。这些样式使得应用程序能够提供更好的用户界面体验,增强了应用程序的吸引力和易用性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值