gusucode.com > MFC编程,实现类似VC6.0的界面设计源码程序 > MFC编程,实现类似VC6.0的界面设计源码程序/VCface/bardemo/CoolTabCtrl.cpp
//////////////////////////////////////////////////////////////// // CoolTabCtrl.cpp : implementation file // // // // Copyright 2001 WangJun // // All Rights Reserved. // // // // Email: wangjun98@sohu.com // // URL: www.vckbase.com // // // // 1.0 2001/9/30 First release version. // // // // 2004/2/8 添加对WM_NOTIFY消息的处理 // // 2005/2/2 修正内存泄漏 // // // //////////////////////////////////////////////////////////////// #include "stdafx.h" #include "CoolTabCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CCoolTabCtrl IMPLEMENT_DYNCREATE(CCoolTabCtrl, CWnd) #define ITEMBUTTON_HEIGHT 23 static CPen _penW(PS_SOLID,1 ,RGB(255,255,255)); static CPen _penB(PS_SOLID,1 ,RGB(0,0,0)); static CPen _pen3DFace(PS_SOLID,1,GetSysColor(COLOR_3DFACE)); static CPen _pen3DLight(PS_SOLID,1,GetSysColor(COLOR_3DLIGHT)); static CPen _pen3DShadow(PS_SOLID,1,GetSysColor(COLOR_3DSHADOW)); static CPen _pen3DDKShadow(PS_SOLID,1,GetSysColor(COLOR_3DDKSHADOW)); CCoolTabCtrl::CCoolTabCtrl() { m_nStyle = TCS_DOWN; m_nActivePage = -1; m_nBorder = 1; m_bEraseBkgnd = TRUE; } CCoolTabCtrl::~CCoolTabCtrl() { POSITION pos; CPageItem* pItem; for(pos=m_PageList.GetHeadPosition();pos!=NULL;) { pItem=(CPageItem*)m_PageList.GetNext(pos); if(pItem) { if(pItem->m_nStyle == 1 && pItem->m_pWnd) // 动态创建 { pItem->m_pWnd->DestroyWindow(); delete pItem->m_pWnd; } delete pItem; pItem=NULL; } } m_PageList.RemoveAll(); } BEGIN_MESSAGE_MAP(CCoolTabCtrl, CWnd) //{{AFX_MSG_MAP(CCoolTabCtrl) ON_WM_PAINT() ON_WM_ERASEBKGND() ON_WM_LBUTTONDOWN() ON_WM_SIZING() ON_WM_SIZE() ON_WM_TIMER() ON_WM_CREATE() ON_WM_DESTROY() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CCoolTabCtrl message handlers BOOL CCoolTabCtrl::Create(UINT wStyle, const CRect &rect, CWnd *pParentWnd, UINT nID) { m_nStyle = wStyle & TCS_MASK; if(m_nStyle == 0) m_nStyle = TCS_UP; if (CWnd::Create(AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, AfxGetApp()->LoadStandardCursor(IDC_ARROW), (HBRUSH)GetStockObject(LTGRAY_BRUSH), NULL), NULL, wStyle&~TCS_MASK | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, rect, pParentWnd, nID)) { return TRUE; } return FALSE; } BOOL CCoolTabCtrl::OnEraseBkgnd(CDC* pDC) { if(m_bEraseBkgnd) { CRect rect; GetWindowRect(&rect); ScreenToClient(&rect); CBrush brush(GetSysColor(COLOR_3DFACE)); pDC->FillRect(rect,&brush); } return TRUE; } void CCoolTabCtrl::OnPaint() { CPaintDC dc(this); CPen *pOldPen = dc.GetCurrentPen(); CFont *pOldFont = dc.SelectObject(&m_font); int nOldBkMode = dc.SetBkMode(TRANSPARENT); CPageItem *pItem; POSITION pos; int nItemIndex = 0; DrawFrame(&dc); for(pos=m_PageList.GetHeadPosition();pos!=NULL;nItemIndex++) { pItem=(CPageItem*)m_PageList.GetNext(pos); if(pItem) { pItem->Draw(&dc,m_nStyle,(m_nActivePage==nItemIndex)?TRUE:FALSE); } } dc.SetBkMode(nOldBkMode); dc.SelectObject(pOldFont); dc.SelectObject(pOldPen); } CCoolTabCtrl::CPageItem* CCoolTabCtrl::AddPage(CWnd *pWnd, LPCTSTR sText, UINT IconID) { ASSERT(pWnd); ASSERT(IsWindow(pWnd->m_hWnd)); CPageItem *pItem = NULL; pItem = new CPageItem(); pItem->m_pWnd = pWnd; pItem->m_nStyle = 0; //Window pItem->m_sText = sText; if(IconID) pItem->m_hIcon = AfxGetApp()->LoadIcon(IconID); else pItem->m_hIcon = NULL; CRect rect; GetClientRect(rect); pWnd->MoveWindow(rect); m_PageList.AddTail(pItem); // 如果添加的Page index不等于m_nActivePage, 则隐藏 if(m_nActivePage != m_PageList.GetCount()) { pWnd->ShowWindow(SW_HIDE); } return pItem; } BOOL CCoolTabCtrl::AddPage(CRuntimeClass* pClass,UINT nIDTemplate, LPCTSTR sText, UINT IconID) { CDialog *pDlg = (CDialog*)pClass->CreateObject(); if(pDlg != NULL) { if(pDlg->Create(nIDTemplate,this)) { CCoolTabCtrl::CPageItem *pItem = AddPage(pDlg, sText, IconID); if(pItem) { pItem->SetPageStyle(1); return TRUE; } } } return FALSE; } void CCoolTabCtrl::GetClientRect(LPRECT lpRect) { CWnd::GetClientRect(lpRect); if(m_nStyle&TCS_DOWN) { lpRect->left += 2; lpRect->right -= 2; lpRect->top += 2; lpRect->bottom -= ITEMBUTTON_HEIGHT; } else if(m_nStyle&TCS_UP) { lpRect->left += 2; lpRect->right -= 2; lpRect->top += ITEMBUTTON_HEIGHT; lpRect->bottom -= 2; } } ///////取得需要占用的宽度///// UINT CCoolTabCtrl::CPageItem::GetAreaWidth(CDC *pDC) { UINT width = pDC->GetTextExtent(m_sText).cx; if(m_hIcon) width += 18; return width + 9; } void CCoolTabCtrl::CPageItem::Draw(CDC *pDC, UINT nStyle, BOOL bActive) { CRect rect = m_rect; if(nStyle&TCS_DOWN) { if(bActive) { rect.top -= 2; CBrush brush(GetSysColor(COLOR_3DFACE)); pDC->FillRect(rect,&brush); rect.top += 1; } else rect.bottom -= 1; CBrush brush(GetSysColor(COLOR_3DFACE)); pDC->FillRect(m_rect,&brush); pDC->SelectObject(&_penW); pDC->MoveTo(rect.left,rect.top); pDC->LineTo(rect.left,rect.bottom-1); pDC->SelectObject(&_pen3DShadow); pDC->MoveTo(rect.left+1,rect.bottom-2); pDC->LineTo(rect.left+1,rect.bottom-1); pDC->LineTo(rect.right-1,rect.bottom-1); pDC->MoveTo(rect.right-2,rect.bottom-2); pDC->LineTo(rect.right-1,rect.bottom-2); pDC->LineTo(rect.right-1,rect.top-1); pDC->SelectObject(&_penB); pDC->MoveTo(rect.left+2,rect.bottom); pDC->LineTo(rect.right-2,rect.bottom); pDC->LineTo(rect.right,rect.bottom-2); pDC->MoveTo(rect.right,rect.top); pDC->LineTo(rect.right,rect.bottom-1); rect.top -= 1; }//end of TCS_DOWN else if(nStyle&TCS_UP) { CBrush brush(GetSysColor(COLOR_3DFACE)); if(bActive) { rect.bottom += 1; pDC->FillRect(rect,&brush); rect.bottom -= 1; } else { rect.top += 2; pDC->FillRect(rect,&brush); } pDC->SelectObject(&_penW); pDC->MoveTo(rect.left,rect.bottom); pDC->LineTo(rect.left,rect.top + 2); pDC->LineTo(rect.left + 2,rect.top); pDC->LineTo(rect.right,rect.top); pDC->SelectObject(&_pen3DShadow); pDC->MoveTo(rect.right - 1,rect.top); pDC->LineTo(rect.right - 1,rect.bottom); pDC->SelectObject(&_penB); pDC->MoveTo(rect.right,rect.top + 1); pDC->LineTo(rect.right,rect.bottom); } ///////////调整位置////////// rect.left += 5; rect.right -= 2; ///////////显示图标////////// if(rect.Width() > 16 && m_hIcon != NULL) { ::DrawIconEx(pDC->m_hDC,rect.left,rect.top + 3,m_hIcon,16,16,0,NULL,DI_NORMAL); rect.left += 18; } if (!m_sText.IsEmpty()) { ///////////显示文字////////// rect.top += 5; CString sText = m_sText; int l = sText.GetLength(); int i; for(i=0;i<10 && pDC->GetTextExtent(sText).cx > rect.Width();i++,l-=2) sText = sText.Left(l-2); if(i > 0) { sText = sText.Left(l-2); sText += "..."; } pDC->DrawText(sText, &rect, DT_LEFT /*| DT_VCENTER */| DT_SINGLELINE); } } ////调整尺寸//// void CCoolTabCtrl::AutoSize() { UINT PageCount = m_PageList.GetCount(); if(PageCount < 1) return; CPageItem *pItem; POSITION pos; CRect rect,ClientRect,ItemRect; GetClientRect(ClientRect); ClientRect.DeflateRect(m_nBorder+1,m_nBorder+1); GetWindowRect(rect); ScreenToClient(rect); CDC* pDC = GetDC(); CFont *pOldFont = pDC->SelectObject(&m_font); if(m_nStyle&TCS_DOWN) { rect.left += 6; rect.right -= 6; rect.bottom -= 1; rect.top = rect.bottom - ITEMBUTTON_HEIGHT + 1; } else if(m_nStyle&TCS_UP) { rect.left += 2; rect.right -= 6; rect.bottom = rect.top + ITEMBUTTON_HEIGHT; } ItemRect = rect; int AreaWidth = 0,ItemMaxWidth,ItemIndex=0; ItemMaxWidth = rect.Width()/m_PageList.GetCount(); BOOL bMonoSpace = ((m_nStyle&TCS_MONOSPACE) == TCS_MONOSPACE)?1:0; ////////设置按钮初始宽度,并得到按钮所需占用的总宽度/////// for(pos=m_PageList.GetHeadPosition();pos!=NULL;ItemIndex++) { pItem=(CPageItem*)m_PageList.GetNext(pos); if(pItem) { if(!bMonoSpace) ItemMaxWidth = pItem->GetAreaWidth(pDC); AreaWidth += ItemMaxWidth; ItemRect.right = ItemRect.left+ItemMaxWidth-1; pItem->m_rect = ItemRect; ItemRect.left = ItemRect.right + 1; if(pItem->m_pWnd) pItem->m_pWnd->MoveWindow(ClientRect); } } ////////当需要的空间大于实际空间时进行调整//// if(AreaWidth > rect.Width() && !bMonoSpace) { ItemRect = rect; int AreaWidth,MaxWidth = rect.Width()/PageCount; for(pos=m_PageList.GetHeadPosition();pos!=NULL;) { pItem=(CPageItem*)m_PageList.GetNext(pos); if(pItem) { AreaWidth = pItem->GetAreaWidth(pDC); ItemMaxWidth = (ItemMaxWidth < AreaWidth)?MaxWidth:AreaWidth; ItemRect.right = ItemRect.left+ItemMaxWidth; pItem->m_rect = ItemRect; ItemRect.left = ItemRect.right + 1; } } } pDC->SelectObject(pOldFont); ReleaseDC(pDC); } void CCoolTabCtrl::SetActivePage(int nIndex) { if(nIndex == m_nActivePage) return; CPageItem *pOldItem,*pItem; if(m_nActivePage >= 0) { pOldItem = (CPageItem*)GetPageItem(m_nActivePage); if(pOldItem) { pOldItem->m_pWnd->ShowWindow(SW_HIDE); } } pItem = (CPageItem*)GetPageItem(nIndex); if(!pItem) return; m_nActivePage = nIndex; if(m_nStyle&TCS_ANIMATE) SetTimer(100,15,NULL);///为了在95或NT4下也有动画效果,没有使用AnimateWindow函数 else pItem->m_pWnd->ShowWindow(SW_SHOW); } void* CCoolTabCtrl::GetPageItem(UINT nIndex) { CPageItem *pItem = NULL; POSITION pos = m_PageList.FindIndex(nIndex); if(pos) pItem = (CPageItem*)m_PageList.GetAt(pos); return pItem; } void CCoolTabCtrl::UpdateWindow() { AutoSize(); if(m_nActivePage < 0) SetActivePage(0); else SetActivePage(m_nActivePage); Invalidate(); } void CCoolTabCtrl::OnLButtonDown(UINT nFlags, CPoint point) { UINT nItemIndex=0; POSITION pos; CPageItem *pItem; for(pos=m_PageList.GetHeadPosition();pos!=NULL;nItemIndex++) { pItem=(CPageItem*)m_PageList.GetNext(pos); if(pItem) { if(pItem->m_rect.PtInRect(point)) { SetActivePage(nItemIndex); Invalidate(); break; } } } CWnd::OnLButtonDown(nFlags, point); } void CCoolTabCtrl::OnSizing(UINT fwSide, LPRECT pRect) { CWnd::OnSizing(fwSide, pRect); m_bEraseBkgnd = FALSE; AutoSize(); } void CCoolTabCtrl::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); m_bEraseBkgnd = TRUE; AutoSize(); Invalidate(); } void CCoolTabCtrl::DrawFrame(CDC *pDC) { CRect rect; GetClientRect(&rect); switch(m_nBorder) { case 1: pDC->Draw3dRect(rect,RGB(0xff,0xff,0xff),RGB(0,0,0)); break; case 2: pDC->Draw3dRect(rect,RGB(0xff,0xff,0xff),RGB(0,0,0)); rect.DeflateRect(1, 1); pDC->Draw3dRect(rect, GetSysColor(COLOR_3DFACE), GetSysColor(COLOR_3DSHADOW)); break; default:break; } } void CCoolTabCtrl::SetStyle(UINT style) { m_nStyle = style; } UINT CCoolTabCtrl::GetStyle() { return m_nStyle; } void CCoolTabCtrl::OnTimer(UINT nIDEvent) { static step,times = 10; UINT width; CRect rect; GetClientRect(&rect); rect.DeflateRect(m_nBorder+1,m_nBorder+1); POSITION pos = m_PageList.FindIndex(m_nActivePage); if(pos) { CPageItem *pItem = (CPageItem*)m_PageList.GetAt(pos); if(pItem) { width = rect.Width(); if(times == 10) { rect.right = 10; rect.left = rect.right - width + 1; step = width/times; times--; m_bEraseBkgnd = FALSE; pItem->m_pWnd->ShowWindow(SW_SHOW); } else { if(times <= 0) { times = 10; KillTimer(nIDEvent); m_bEraseBkgnd = TRUE; } else { rect.right = width - times*step; rect.left = rect.right - width + 1; times--; } } pItem->m_pWnd->MoveWindow(rect); } } } void CCoolTabCtrl::SetStyleAnimate(BOOL bEnable) { UINT style = GetStyle(); if(bEnable) style |= TCS_ANIMATE; else style &= ~TCS_ANIMATE; SetStyle(style); } void CCoolTabCtrl::SetStyleDirection(int Direction) { UINT style = GetStyle(); switch(Direction) { case TCS_DOWN: style &= ~TCS_UP; style |= TCS_DOWN; break; case TCS_UP: default: style &= ~TCS_DOWN; style |= TCS_UP; break; } SetStyle(style); UpdateWindow(); } void CCoolTabCtrl::SetStyleMonoSpace(BOOL bEnable) { UINT style = GetStyle(); if(bEnable) style |= TCS_MONOSPACE; else style &= ~TCS_MONOSPACE; SetStyle(style); UpdateWindow(); } BOOL CCoolTabCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { // 将WM_NOTIFY消息转交给父窗口处理 GetParent()->SendMessage(WM_NOTIFY, wParam, lParam); *pResult = 0; return TRUE; } int CCoolTabCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) { if(CWnd::OnCreate(lpCreateStruct) == -1) return -1; LOGFONT logFont; ZeroMemory((void*)&logFont,sizeof(logFont)); strcpy(logFont.lfFaceName,"宋体"); logFont.lfHeight = -12; logFont.lfWeight = 400; logFont.lfCharSet = GB2312_CHARSET; logFont.lfOutPrecision = 3; logFont.lfClipPrecision = 2; logFont.lfQuality = 1; logFont.lfPitchAndFamily = 2; m_font.CreateFontIndirect(&logFont); SetFont(&m_font); return 0; } void CCoolTabCtrl::OnDestroy() { CWnd::OnDestroy(); }