一个简单的TabCtrl

来源:互联网 发布:js. bind 编辑:程序博客网 时间:2024/06/07 05:45
//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();}//画Tabint 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一个TabCtrlBOOL 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_NOTIFYvoid 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);}



 

原创粉丝点击