www.gusucode.com > VC++的窗体TabView标签切换实现-源码程序 > VC++的窗体TabView标签切换实现-源码程序/code/TabCtrlView.cpp

    // TabCtrlView.cpp : implementation file
// Download by http://www.NewXing.com

#include "stdafx.h"
#include "Tab2.h"
#include "TabCtrlView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CTabCtrlView

IMPLEMENT_DYNCREATE(CTabCtrlView, CView)

CTabCtrlView::CTabCtrlView()
{
}

CTabCtrlView::~CTabCtrlView()
{
}


BEGIN_MESSAGE_MAP(CTabCtrlView, CWnd)
	//{{AFX_MSG_MAP(CTabCtrlView)
	ON_WM_SIZE()
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTabCtrlView drawing

void CTabCtrlView::OnDraw(CDC* pDC)
{
	//CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/////////////////////////////////////////////////////////////////////////////
// CTabCtrlView diagnostics

#ifdef _DEBUG
void CTabCtrlView::AssertValid() const
{
	//CView::AssertValid();
}

void CTabCtrlView::Dump(CDumpContext& dc) const
{
	//CView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CTabCtrlView message handlers

BOOL CTabCtrlView::HandleTabs(int iSel)
{

    CWnd* pWnd = AfxGetMainWnd();

    switch(iSel)
    {
    case 0:
        pWnd->SendMessage(WM_MYMESSAGE, ID_VIEW1, 0);
        break;
    case 1:
        pWnd->SendMessage(WM_MYMESSAGE, ID_VIEW2, 0);
        break;
    case 2:
        pWnd->SendMessage(WM_MYMESSAGE, ID_VIEW3, 0);
        break;
	default:
		ASSERT(0);
		return FALSE;
	}

	return TRUE;
}

void CTabCtrlView::SetTab(int iTab)
{
    m_TabCtl.SetCurSel(iTab);
}

BOOL CTabCtrlView::CreateStatic(CWnd * pParentWnd, DWORD dwstyle, UINT nID)
{
    ASSERT(pParentWnd!= NULL);
    ASSERT(dwstyle & WS_CHILD);
    ASSERT(!(dwstyle & SPLS_DYNAMIC_SPLIT));
    ASSERT(nID != 0);

    // create with the same wnd-class as mdi-frame (no erase bkgnd)
    if (!CreateEx(0, NULL, NULL, dwstyle, 0, 0, 0, 0,
		          pParentWnd->m_hWnd, (HMENU)nID, NULL))
    return FALSE;// create invisible

    //create the tab control
	DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;

	dwstyle |= TCS_TABS;
    BOOL iResult=m_TabCtl.Create(dwstyle, CRect(0,0,0,0), this, 1000);

	if(!iResult)
		return FALSE;

    //overide this function to provide your tabs
    InitTabs(this);

    return TRUE;
}

CView * CTabCtrlView::CreateView(CRuntimeClass * pViewClass, SIZE sizeInit, CCreateContext * pContext)
{
#ifdef _DEBUG 
    ASSERT_VALID(this);
    ASSERT(pViewClass != NULL);
    ASSERT(pViewClass->IsDerivedFrom(RUNTIME_CLASS(CWnd)));
    ASSERT(AfxIsValidAddress(pViewClass, sizeof(CRuntimeClass), FALSE));
#endif

	BOOL bSendInitialUpdate = FALSE;

    CCreateContext contextT;
    if (pContext == NULL)
	{
        // if no context specified, generate one from the currently selected
        // client if possible
        CView* pOldView = NULL;
        if (pOldView != NULL && pOldView->IsKindOf(RUNTIME_CLASS(CView)))
		{
            // set info about last pane
            ASSERT(contextT.m_pCurrentFrame == NULL);
            contextT.m_pLastView = pOldView;
            contextT.m_pCurrentDoc = pOldView->GetDocument();
            if (contextT.m_pCurrentDoc != NULL)
                   contextT.m_pNewDocTemplate =
                     contextT.m_pCurrentDoc->GetDocTemplate();
		}
        pContext = &contextT;
        bSendInitialUpdate = TRUE;
	}

    CWnd* pWnd;
    TRY
	{
        pWnd = (CWnd*)pViewClass->CreateObject();
        if (pWnd == NULL)
            AfxThrowMemoryException();
	}
    CATCH_ALL(e)
	{
        TRACE0("out of memory creating a splitter pane.\n");
        // note: delete_exception(e) not required
        return (CView*) NULL;
	}
    END_CATCH_ALL

    ASSERT_KINDOF(CWnd, pWnd);
    ASSERT(pWnd->m_hWnd == NULL); // not yet created

    DWORD dwstyle = AFX_WS_DEFAULT_VIEW;

    // create with the right size (wrong position)
    CRect rect(CPoint(0,0), sizeInit);
    if (!pWnd->Create(NULL, NULL, dwstyle,rect, this, 0, pContext))
	{
        TRACE0("warning: couldn't create client pane for splitter.\n");
        // pwnd will be cleaned up by postncdestroy
        return (CView*) NULL;
	}

    m_ActiveView = (CView*) pWnd;
    return m_ActiveView;
}


//调节窗口之间的大小关系
void CTabCtrlView::OnSize(UINT nType, int cx, int cy) 
{
    if (nType != SIZE_MINIMIZED && cx > 0 && cy > 0)
           RecalcLayout();

    CWnd::OnSize(nType, cx, cy);
    return;
}


void CTabCtrlView::RecalcLayout()
{
    CWnd* pWnd = (CWnd*) GetActiveView();

	//得到CTabCtrlView的窗口的客户区大小
    CRect rect;
    GetClientRect(&rect);

    m_TabCtl.RecalcLayout(rect, pWnd);
}

CView* CTabCtrlView::GetActiveView()
{
    return m_ActiveView;
}

void CTabCtrlView::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
}

void CTabCtrlView::InitTabs(CTabCtrlView * pView)
{
    TC_ITEM TabCtrlItem;

    TabCtrlItem.mask = TCIF_TEXT ;

    TabCtrlItem.pszText = "CView1";   
    m_TabCtl.InsertItem( 0, &TabCtrlItem );

    TabCtrlItem.pszText = "CView2";
    m_TabCtl.InsertItem( 1, &TabCtrlItem );

    TabCtrlItem.pszText = "CView3";
    m_TabCtl.InsertItem( 2, &TabCtrlItem );

    m_TabCtl.SetView(pView);
	return;
}



/////////////////////////////////////////////////////////////////////////////
// CViewTabCtrl

CViewTabCtrl::CViewTabCtrl()
{
}

CViewTabCtrl::~CViewTabCtrl()
{
}


BEGIN_MESSAGE_MAP(CViewTabCtrl, CTabCtrl)
	//{{AFX_MSG_MAP(CViewTabCtrl)
	ON_NOTIFY_REFLECT(TCN_SELCHANGE, OnSelchange)
	ON_WM_ERASEBKGND()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CViewTabCtrl message handlers

void CViewTabCtrl::SetView(CTabCtrlView * pView)
{
    m_pView=pView;
	return;
}

void CViewTabCtrl::RecalcLayout(CRect & rect, CWnd * pWnd)
{
	//标签控件占据CTabCtrlView的客户区
    SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left, 
		         rect.bottom - rect.top, SWP_NOZORDER);

    //调整要显示的视窗口位置,使其占据标签控件的显示区
    AdjustRect(FALSE, &rect);
    pWnd->SetWindowPos( NULL, rect.left, rect.top, rect.right - rect.left,
		                rect.bottom - rect.top, SWP_NOZORDER);
}


BOOL CViewTabCtrl::HandleTabs(int sel)
{
    return m_pView->HandleTabs(sel);
}

void CViewTabCtrl::OnSelchange(NMHDR* pNMHDR, LRESULT* pResult) 
{
    int iSel = GetCurSel();

    HandleTabs(iSel);

 	*pResult = 0;
}

BOOL CTabCtrlView::OnEraseBkgnd(CDC* pDC) 
{
	// TODO: Add your message handler code here and/or call default

	return FALSE;//CWnd::OnEraseBkgnd(pDC);
}

BOOL CViewTabCtrl::OnEraseBkgnd(CDC* pDC) 
{
   
	CRect Rect;

    m_pView->m_ActiveView->GetWindowRect(&Rect);
	ScreenToClient(&Rect);

	//去掉视窗口的显示的区域,防止ERASE覆盖视窗口
	pDC->ExcludeClipRect(&Rect);

	return CTabCtrl::OnEraseBkgnd(pDC);
}