一个简单的TabCtrl

//Tab.h

#ifndef _TAB__X_H
#define _TAB__X_H


#define CXOFF    8
#define CYMARGIN 1
#define CXMARGIN 1

//
///
//
class CTabItem
{
public:
 CTabItem(CString str);
 CTabItem();
 virtual ~CTabItem();

 ///
 friend class CMyTabCtrl;
 ///
private:
 CString m_strText; //文本内容
 CRect   m_rect;    //区域
 CRgn    m_Rgn;     //区域
 CPoint  m_pts[4];  //四个点

public:
 void SetText(CString strText);
 void GetText(CString &strText);

private:
 BOOL HitTest(CPoint pt);
 void GetRect(CRect &rc);
 
protected:
 int  ComputerRgn(CDC &dc,int x); //计算区域
 void GetFourPoint();//得到四个点
 int  Draw(CDC &dc,BOOL bSelected);//画图
};


//
//
enum{ MTC_SELCHANGED = 1 };

struct NMMYTAB :public NMHDR
{
 int nItem;
 const CTabItem *pItem;
};

//
//
//
class CMyTabCtrl:public CWnd
{
 DECLARE_MESSAGE_MAP()
public:
 CMyTabCtrl();
 virtual ~CMyTabCtrl();

private:
 CPtrList m_lsTabs;
 int m_nCurSel;

protected:
 int  HitTest(CPoint pt);
 void InvalidateTab(int iTab,BOOL bErase = TRUE);

public:
 virtual BOOL Create(CWnd *pParent,CPoint &pt,UINT nID);
 int  AddItem(CString strItem);
 BOOL RemoveItem(int iPos);
 int  GetItemCount();
 int  SelectItem(int iPos);
 CTabItem *GetTab(int iPos);

 void RecomputeLayout();

protected:
 afx_msg void OnPaint();
 afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
};

 
#endif

 

 

//Tab.cpp
#include "StdAfx.h"

#include "Tab.h"


//
//CTabItem
//
CTabItem::CTabItem()
{

}

CTabItem::CTabItem(CString str)
{
	this->m_strText = str;
}

CTabItem::~CTabItem()
{

}
//
//设定文本
void CTabItem::SetText(CString strText)
{
	this->m_strText = strText;
}

//得到文本
void CTabItem::GetText(CString &strText)
{
	strText = this->m_strText;
}

//单击测试
BOOL CTabItem::HitTest(CPoint pt)
{
	return m_Rgn.PtInRegion(pt);
}

//得到矩形区域
void CTabItem::GetRect(CRect &rc)
{
	rc = this->m_rect;
}

//
//
//
//得到四个点
void CTabItem::GetFourPoint()
{
	m_pts[0] = CPoint( m_rect.left  + CXMARGIN , m_rect.top + CYMARGIN );
	m_pts[1] = CPoint( m_rect.left  + CXMARGIN + CXOFF , m_rect.bottom - CYMARGIN );
	m_pts[2] = CPoint( m_rect.right - CXMARGIN - CXOFF , m_rect.bottom - CYMARGIN );
	m_pts[3] = CPoint( m_rect.right - CXMARGIN , m_rect.top + CYMARGIN );
}

//计算Rgn,返回宽度
int CTabItem::ComputerRgn(CDC &dc,int x)
{
	if(m_Rgn.m_hObject != NULL)
		m_Rgn.DeleteObject();
	m_rect.SetRectEmpty();

	//得到文本内容大小区域
	dc.DrawText(m_strText,&m_rect,DT_CALCRECT);
	//CXOFF + CXMARGIN 
	m_rect.right +=2 * (CXOFF + CXMARGIN);
	m_rect.bottom = m_rect.top + GetSystemMetrics(SM_CYHSCROLL) + (2*CYMARGIN);
	//右移X个单位,
	m_rect.OffsetRect(x,0);

	//得到四个点
	GetFourPoint();

	//得到区域
	m_Rgn.CreatePolygonRgn(m_pts,4,WINDING);
	return m_rect.Width();
}

//画Tab
int CTabItem::Draw(CDC &dc,BOOL bSelected)
{
	//前景色,背景色
	COLORREF bgclr = bSelected ? RGB(197,214,252) : GetSysColor(COLOR_BTNFACE);
	COLORREF fgclr = GetSysColor(COLOR_BTNTEXT);

	//设定背景色,前景色
	dc.SetBkColor(bgclr);
	dc.SetTextColor(fgclr);

	//填充区域
	CBrush brush(bgclr);
	dc.FillRgn(&m_Rgn,&brush);

	//黑笔,阴影笔
	CPen blackPen(PS_SOLID,1,RGB(0,0,0));
	CPen shadowPen(PS_SOLID,1,::GetSysColor(COLOR_BTNSHADOW));
	CPen *pOldPen = NULL;

	// .--------.
	//   .----.  
	//
	pOldPen = dc.SelectObject(&blackPen);
	dc.MoveTo(m_pts[0]);
	dc.LineTo(m_pts[1]);

	pOldPen = dc.SelectObject(&shadowPen);
	dc.MoveTo(m_pts[1]);
	dc.LineTo(m_pts[2]);

	pOldPen = dc.SelectObject(&blackPen);
	dc.MoveTo(m_pts[2]);
	dc.LineTo(m_pts[3]);

	if(!bSelected)
	{
		pOldPen = dc.SelectObject(&shadowPen);
		dc.MoveTo(m_pts[2]);
		dc.LineTo(m_pts[3]);
	}

	dc.SelectObject(pOldPen);

	CFont font;
	font.CreatePointFont(120,"宋体");
	CFont *pOldFont = dc.SelectObject(&font);

	CRect rc = m_rect;
	rc.DeflateRect( CXOFF + CXMARGIN , CYMARGIN );
	dc.DrawText(m_strText,&rc,DT_CENTER | DT_VCENTER | DT_SINGLELINE );

	dc.SelectObject(pOldFont);

	return rc.right;
}


//
///CMyTabCtrl
//
BEGIN_MESSAGE_MAP(CMyTabCtrl , CWnd)

 ON_WM_PAINT()
 ON_WM_LBUTTONDOWN()

END_MESSAGE_MAP()

CMyTabCtrl::CMyTabCtrl()
{
	m_nCurSel = 0;
}

CMyTabCtrl::~CMyTabCtrl()
{
	if(!m_lsTabs.IsEmpty())
	{
		m_lsTabs.RemoveAll();
	}
}

//根据坐标来Create一个TabCtrl
BOOL CMyTabCtrl::Create(CWnd *pParent,CPoint &pt,UINT nID)
{
	ASSERT(pParent);
	LPCTSTR lpClassName=_T("MyTabCtrl");

	WNDCLASS wc={0};
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hbrBackground = ::CreateSolidBrush(::GetSysColor(COLOR_BTNFACE));
	wc.hCursor       = LoadCursor(NULL , IDC_ARROW );
	wc.hIcon         = NULL;
	wc.hInstance     = AfxGetInstanceHandle();
	wc.lpszClassName = lpClassName;
	wc.lpszMenuName  = NULL;
	wc.style         = CS_VREDRAW | CS_HREDRAW;
	wc.lpfnWndProc   = (WNDPROC)::DefWindowProc; 

	if(!AfxRegisterClass(&wc))
	{
		TRACE("**********CMyTabCtrl::AfxRegisterClass Failed!\n");
		return FALSE;
	}

	CRect rc(pt.x , pt.y , 30 + pt.x , 30+pt.y);
	if(!CWnd::Create(lpClassName,NULL,WS_CHILD | WS_VISIBLE,rc,pParent,nID))
	{
		TRACE("**********CMyTabCtrl::Create Failed!\n");
		return FALSE;
	}
	return TRUE;
}

//增加一项
int CMyTabCtrl::AddItem(CString strItem)
{
	CTabItem *pTab = new CTabItem(strItem);
	m_lsTabs.AddTail(pTab);
	return m_lsTabs.GetCount();
}

//移除一项
BOOL CMyTabCtrl::RemoveItem(int iPos)
{
	POSITION pos = m_lsTabs.FindIndex(iPos);
	if(pos)
	{
		CTabItem *pTab = (CTabItem*)m_lsTabs.GetAt(pos);
		delete pTab;
	}
	return pos != NULL;
}

//得到有多少个项
int CMyTabCtrl::GetItemCount()
{
	return m_lsTabs.GetCount();
}

//得到指定位置的CTabItem对像
CTabItem* CMyTabCtrl::GetTab(int iPos)
{
	int n = GetItemCount();
	ASSERT(iPos < n);

	POSITION pos = m_lsTabs.FindIndex(iPos);
	if(pos)
	{
		CTabItem *pTab = (CTabItem*)m_lsTabs.GetAt(pos);
		return pTab;
	}
	return NULL;
}

//单击测试
int CMyTabCtrl::HitTest(CPoint pt)
{
	CRect rc;
	GetClientRect(rc);
	if(rc.PtInRect(pt))
	{
		int n = GetItemCount();
		for(int i = 0 ; i < n ; i++)
		{
			if(GetTab(i)->HitTest(pt))
			{
				return i;
			}
		}
	}
	return -1;
}

//使指定的位置的Tab无效
void CMyTabCtrl::InvalidateTab(int iTab,BOOL bErase /* = TRUE*/)
{
	CRect rc;
	GetTab(iTab)->GetRect(rc);
	InvalidateRect(rc,bErase);
}

//选择一项
int CMyTabCtrl::SelectItem(int iPos)
{
	int nTemp = m_nCurSel;

	if(iPos < 0 || iPos >=GetItemCount() )
		return -1;
	if(iPos == m_nCurSel)
		return iPos;

	//擦除以前的
	InvalidateTab(m_nCurSel);

	m_nCurSel = iPos;
	//绘画现在的
	InvalidateTab(m_nCurSel);

	return nTemp;
}

//绘画
void CMyTabCtrl::OnPaint()
{
	CPaintDC dc(this);
	CRect rc;
	GetClientRect(rc);
	int n = GetItemCount();

	CTabItem *pCurTab = NULL;
	for(int i = 0 ; i < n ; i++)
	{
		CTabItem *pTab = GetTab(i);
		ASSERT(pTab);
		if(i==m_nCurSel)
		{
			pCurTab = pTab;
		}
		else 
			pTab->Draw(dc,FALSE);
	}
	//画现在的
	if(pCurTab)
		pCurTab->Draw(dc , TRUE);
}

//发送WM_NOTIFY
void CMyTabCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
	int i = HitTest(point);
	if(i >=0 && i !=m_nCurSel)
	{
		//使其选中
		SelectItem(i);
		NMMYTAB nm;
		nm.nItem = i;
		nm.pItem = GetTab(i);
		nm.hwndFrom = GetSafeHwnd();
		nm.idFrom = GetDlgCtrlID();
		nm.code = MTC_SELCHANGED;
		GetParent()->SendMessage(WM_NOTIFY,nm.idFrom,(LPARAM)&nm);
	}
}

//重新计算区域
void CMyTabCtrl::RecomputeLayout()
{
	CClientDC dc(this);
	int x = 0;
	int n = GetItemCount();
	CTabItem *pTab = NULL;

	for(int i = 0 ; i < n ; i++)
	{
		pTab = GetTab(i);
		x+= (pTab->ComputerRgn(dc,x) - CXMARGIN - CXOFF);
	}

	//自动调整窗口位置
	CRect rc;
	GetWindowRect(rc);
	CRect temp;
	pTab->GetRect(temp);
	rc.right = rc.left + x + CXOFF + CXMARGIN;
	rc.bottom = rc.top + temp.Height();
	ScreenToClient(rc);
	MoveWindow(rc,TRUE);
}



 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值