首页 随笔 乐走天涯 程序资料 评论中心 Tag 论坛 其他资源 搜索 联系我 关于 RSS

标签视(二)


日期: 2002-01-09 14:00 | 联系我 | 关注我: Telegram, Twitter

VC程序员应该知道MFC例子程序collect,其是一个SDI界面,但它包含多个标签视,用于显示包含在文档中的多个数据类型,参考下图。

本程序根据collect创建了一个CTabCtrlView类,用于实现标签视的功能。关于该类的源码,列在本章的最后,下面介绍如何使用该程序。首先,从CTabCtrlView派生一个类CMyTabView,并重载其InitTabs函数:

void CMyTabView::InitTabs(CTabCtrlView* pView) { TC_ITEM TabCtrlItem; TabCtrlItem.mask = TCIF_TEXT | TCIF_IMAGE; TabCtrlItem.pszText = "CStringList"; TabCtrlItem.iImage = 1; m_TabCtl.InsertItem( 0, &TabCtrlItem ); TabCtrlItem.pszText = "CTypedPtrList"; m_TabCtl.InsertItem( 1, &TabCtrlItem ); TabCtrlItem.pszText = "CList"; m_TabCtl.InsertItem( 2, &TabCtrlItem ); TabCtrlItem.pszText = "CDWordArray"; m_TabCtl.InsertItem( 3, &TabCtrlItem ); TabCtrlItem.pszText = "CTypedPtrArray"; m_TabCtl.InsertItem( 4, &TabCtrlItem ); TabCtrlItem.pszText = "CArray"; m_TabCtl.InsertItem( 5, &TabCtrlItem ); TabCtrlItem.pszText = "CMapStringToString"; m_TabCtl.InsertItem( 6, &TabCtrlItem ); TabCtrlItem.pszText = "CTypedPtrMap"; m_TabCtl.InsertItem( 7, &TabCtrlItem ); TabCtrlItem.pszText = "CMap"; m_TabCtl.InsertItem( 8, &TabCtrlItem );

//Important You must always call the base class CTabCtrlView::InitTabs(pView); return; }

下一步是重载其函数:

BOOL CMyTabView::HandleTabs(int sel) { //The MFC doc/view model expects the //mainFrame to handle changing view //so we let the mainframe do it. CWnd* Wnd = AfxGetMainWnd(); switch(sel) { case 0: Wnd->SendMessage(WM_COMMAND, ID_STRINGLIST, 0); break; case 1: Wnd->SendMessage(WM_COMMAND, ID_TYPEDLIST, 0); break; case 2: Wnd->SendMessage(WM_COMMAND, ID_INTLIST, 0); break; case 3: Wnd->SendMessage(WM_COMMAND, ID_DWORDARRAY, 0); break; case 4: Wnd->SendMessage(WM_COMMAND, ID_TYPEDPTRARRAY, 0); break; case 5: Wnd->SendMessage(WM_COMMAND, ID_POINTARRAY, 0); break; case 6: Wnd->SendMessage(WM_COMMAND, ID_MAPSTRINGTOSTRING, 0); break; case 7: Wnd->SendMessage(WM_COMMAND, ID_TYPEDPTRMAP, 0); break; case 8: Wnd->SendMessage(WM_COMMAND, ID_MAPDWORDTOMYSTRUCT, 0); break; default: ASSERT(0); return FALSE; } return TRUE; }

同时,需要对主框架类进行修改。首先,声明一个protected的派生类CMyTabView对象m_tabView,并重载OnCreateClient函数:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { if(!m_tabView.CreateStatic(this)) { TRACE0("Failed to CreatePropertySheet "); return FALSE; } CRuntimeClass* pNewViewClass = RUNTIME_CLASS(CStringListView); m_tabView.SetTab(0); CSize size(160, 180); if (!m_tabView.CreateView(pNewViewClass, size, pContext)) { TRACE0("Failed to create first pane "); return FALSE; } SetActiveView(m_tabView.GetActiveView()); return TRUE; }

最后一步就是修改OnExample函数:

void CMainFrame::OnExample(UINT nCmdID) { if (nCmdID == m_nCurrentExample) return; // already selected // Set the child window ID of the active view to AFX_IDW_PANE_FIRST. // This is necessary so that CFrameWnd::RecalcLayout will allocate // this "first pane" to that portion of the frame window's client // area not allocated to control bars. Set the child ID of // the previously active view to some other ID; we will use the // command ID as the child ID. CView* pOldActiveView = GetActiveView(); ::SetWindowLong(pOldActiveView->m_hWnd, GWL_ID, m_nCurrentExample); CRuntimeClass* pNewViewClass; switch (nCmdID) { case ID_STRINGLIST: pNewViewClass = RUNTIME_CLASS(CStringListView); break; case ID_TYPEDLIST: pNewViewClass = RUNTIME_CLASS(CTypedPtrListView); break; case ID_INTLIST: pNewViewClass = RUNTIME_CLASS(CIntListView); break; case ID_DWORDARRAY: pNewViewClass = RUNTIME_CLASS(CDWordArrayView); break; case ID_TYPEDPTRARRAY: pNewViewClass = RUNTIME_CLASS(CTypedPtrArrayView); break; case ID_POINTARRAY: pNewViewClass = RUNTIME_CLASS(CPointArrayView); break; case ID_MAPSTRINGTOSTRING: pNewViewClass = RUNTIME_CLASS(CMapStringToStringView); break; case ID_TYPEDPTRMAP: pNewViewClass = RUNTIME_CLASS(CTypedPtrMapView); break; case ID_MAPDWORDTOMYSTRUCT: pNewViewClass = RUNTIME_CLASS(CMapDWordToMyStructView); break; default: ASSERT(0); return; } // create the new view CCreateContext context; context.m_pNewViewClass = pNewViewClass; context.m_pCurrentDoc = GetActiveDocument(); // New Code below CView* pNewView = m_tabView.CreateView(pNewViewClass, CSize(100,100), &context); if (pNewView != NULL) { // the new view is there, but invisible and not active... pNewView->ShowWindow(SW_SHOW); pNewView->OnInitialUpdate(); SetActiveView(pNewView); m_tabView.RecalcLayout(); //<-- New Code RecalcLayout(); m_nCurrentExample = nCmdID; // finally destroy the old view... pOldActiveView->DestroyWindow(); } }

下面是CTabCtrlView的源代码:

#if !defined(AFX_CTabCtrlView_H__8E652EC1_5159_11D1_96A0_0E6B8A000000__INCLUDED_) #define AFX_CTabCtrlView_H__8E652EC1_5159_11D1_96A0_0E6B8A000000__INCLUDED_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 // CTabCtrlView.h : header file // #include "afxcmn.h" class CTabCtrlView; class CViewTabCtl : public CTabCtrl { // Construction public: CViewTabCtl(); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CViewTabCtl) //}}AFX_VIRTUAL // Implementation public: void SetView(CTabCtrlView* pView); virtual void RecalcLayout(CRect& rect, CWnd* wnd); virtual ~CViewTabCtl(); virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); // Generated message map functions protected: CTabCtrlView* m_pView; CString m_sGrayFont; CString m_sSelFont; CDC m_dc; CFont m_selFont; virtual BOOL HandleTabs(int sel); //{{AFX_MSG(CViewTabCtl) afx_msg void OnSelchange(NMHDR* pNMHDR, LRESULT* pResult); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // CCTabCtrlView window // The actual tab control // Wrapper Window Handles Interfacing to MFC doc View Model // and resizing of the Tab Ctrl class CTabCtrlView : public CWnd { // Construction public: CTabCtrlView(); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CCTabCtrlView) //}}AFX_VIRTUAL // Implementation public: virtual BOOL HandleTabs(int sel); void SetTab(int Tab); virtual void SetView(); void RecalcLayout(); CView* GetActiveView(); BOOL CreateStatic(CWnd* pParentWnd, DWORD dwStyle = WS_CHILD | WS_VISIBLE, UINT nID = AFX_IDW_PANE_FIRST); virtual CView* CreateView(CRuntimeClass* pViewClass, SIZE sizeInit, CCreateContext* pContext ); virtual ~CTabCtrlView(); // Generated message map functions protected: virtual void InitTabs(CTabCtrlView* pView); CViewTabCtl m_TabCtl; CView* m_ActiveView; BOOL CreateCommon(CWnd* pParentWnd, SIZE sizeMin, DWORD dwStyle, UINT nID); //{{AFX_MSG(CCTabCtrlView) afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnPaint(); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // CViewTabCtl window //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif // !defined(AFX_CTabCtrlView_H__8E652EC1_5159_11D1_96A0_0E6B8A000000__INCLUDED_) ///////////////////////////////////////////////////////////////////////////// C++ Code file ///////////////////////////////////////////////////////////////////////////// // CTabCtrlView.cpp : implementation file // // core headers #include "afx.h" #include "afxplex_.h" #include "afxcoll.h" #include "afxcmn.h" #include "stdafx.h" #include "TabCtrlView.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define CX_BORDER 1 #define CY_BORDER 1 #define MAX_COLORS 10 // The following colors give a Tab Ctrl an OS/2 look COLORREF colorRef[MAX_COLORS] = { RGB(0,225,255), RGB(0,240,190), RGB(128,128,255), RGB(240,200,175), RGB(240,240,150), RGB(175,130,175), RGB(240,140,0), RGB(255,200,0), RGB(255,160,120), RGB(255,200, 175) }; ///////////////////////////////////////////////////////////////////////////// // CTabCtrlView CTabCtrlView::CTabCtrlView() { } CTabCtrlView::~CTabCtrlView() { } BEGIN_MESSAGE_MAP(CTabCtrlView, CWnd) //{{AFX_MSG_MAP(CTabCtrlView) ON_WM_SIZE() ON_WM_ERASEBKGND() ON_WM_PAINT() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CTabCtrlView message handlers BOOL CTabCtrlView::CreateStatic(CWnd * pParentWnd, DWORD dwStyle, UINT nID) { ASSERT(pParentWnd != NULL); ASSERT(dwStyle & WS_CHILD); ASSERT(!(dwStyle & SPLS_DYNAMIC_SPLIT)); // create with zero minimum pane size if (!CreateCommon(pParentWnd, CSize(0, 0), dwStyle, nID)) return FALSE; // all panes must be created with explicit calls to CreateView return TRUE; } BOOL CTabCtrlView::CreateCommon(CWnd * pParentWnd, SIZE sizeMin, DWORD dwStyle, UINT nID) { ASSERT(pParentWnd != NULL); ASSERT(sizeMin.cx >= 0 && sizeMin.cy >= 0); ASSERT(dwStyle & WS_CHILD); 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 CRect rect; GetClientRect(rect); CImageList pImageList; m_TabCtl.Create(WS_VISIBLE | WS_CHILD | TCS_OWNERDRAWFIXED, rect, this, nID); //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. "); // 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. "); // pWnd will be cleaned up by PostNcDestroy return (CView*) NULL; } // send initial notification message if (bSendInitialUpdate); // pWnd->SendMessage(WM_INITIALUPDATE); 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(); CRect rect; GetClientRect(&rect); m_TabCtl.RecalcLayout(rect, pWnd); } CView* CTabCtrlView::GetActiveView() { return m_ActiveView; } BOOL CTabCtrlView::OnEraseBkgnd(CDC* pDC) { return FALSE; } void CTabCtrlView::OnPaint() { CPaintDC dc(this); // device context for painting } void CTabCtrlView::SetView() { //In most cases your main app window //should handle this. This is becuase //the doc view model expects the view //to be attached to your main frame } void CTabCtrlView::SetTab(int Tab) { m_TabCtl.SetCurSel(Tab); } void CTabCtrlView::InitTabs(CTabCtrlView* pView) { m_TabCtl.SetView(pView); return; } BOOL CTabCtrlView::HandleTabs(int sel) { ASSERT(FALSE); return FALSE; } ///////////////////////////////////////////////////////////////////////////// // CViewTabCtl CViewTabCtl::CViewTabCtl() { m_sSelFont = _T("Helv"); m_sGrayFont= _T("Helv"); } CViewTabCtl::~CViewTabCtl() { } BEGIN_MESSAGE_MAP(CViewTabCtl, CTabCtrl) //{{AFX_MSG_MAP(CViewTabCtl) ON_NOTIFY_REFLECT(TCN_SELCHANGE, OnSelchange) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CViewTabCtl message handlers void CViewTabCtl::OnSelchange(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here int nSel = GetCurSel(); HandleTabs(nSel); *pResult = 0; } BOOL CViewTabCtl::HandleTabs(int sel) { return m_pView->HandleTabs(sel); } void CViewTabCtl::RecalcLayout(CRect & rect, CWnd * wnd) { SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); int ind = GetCurSel(); AdjustRect(FALSE, &rect); wnd->SetWindowPos(NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); } void CViewTabCtl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { int nSel = lpDrawItemStruct->itemID; ASSERT(nSel > -1); ASSERT(nSel < GetItemCount()); TC_ITEM item; char text[255]; item.pszText = text; item.mask = TCIF_TEXT; GetItem(nSel, &item); if(!m_dc.Attach(lpDrawItemStruct->hDC)) return; CRect rect = CRect(&(lpDrawItemStruct->rcItem)); rect.NormalizeRect(); rect.DeflateRect(CX_BORDER, CY_BORDER); CBrush brush(colorRef[nSel - (nSel / MAX_COLORS) * MAX_COLORS]); m_dc.FillRect(rect, &brush); COLORREF tcolor; if (nSel == GetCurSel()) { m_selFont.DeleteObject(); m_selFont.CreatePointFont(100, LPCTSTR(m_sGrayFont), &m_dc); m_dc.SelectObject(m_selFont); tcolor = RGB(0,0,0); } else { m_selFont.DeleteObject(); m_selFont.CreatePointFont(80, LPCTSTR(m_sSelFont), &m_dc); m_dc.SelectObject(m_selFont); tcolor = GetSysColor(COLOR_3DSHADOW); } m_dc.SetBkMode(TRANSPARENT); m_dc.SetTextColor(tcolor); m_dc.DrawText(text, rect, DT_VCENTER|DT_CENTER); m_dc.Detach(); return; } void CViewTabCtl::SetView(CTabCtrlView * pView) { m_pView = pView; return; }


 文章评论
目前没有任何评论.

↓ 快抢占第1楼,发表你的评论和意见 ↓

发表你的评论
如果你想针对此文发表评论, 请填写下列表单:
姓名: * 必填 (Twitter 用户可输入以 @ 开头的用户名, Steemit 用户可输入 @@ 开头的用户名)
E-mail: 可选 (不会被公开。如果我回复了你的评论,你将会收到邮件通知)
反垃圾广告: 为了防止广告机器人自动发贴, 请计算下列表达式的值:
5 x 5 + 5 = * 必填
评论内容:
* 必填
你可以使用下列标签修饰文字:
[b] 文字 [/b]: 加粗文字
[quote] 文字 [/quote]: 引用文字

 
首页 随笔 乐走天涯 猎户星 Google Earth 程序资料 程序生活 评论 Tag 论坛 资源 搜索 联系 关于 隐私声明 版权声明 订阅邮件

程序员小辉 建站于 1997 ◇ 做一名最好的开发者是我不变的理想。
Copyright © XiaoHui.com; 保留所有权利。