【VS開發】使用CTabView分割多頁卡視窗
一般書中介紹的是使用CSplitterWnd來拆分視窗實現多檢視,CSplitterWnd中的CreateClient可以儲存其建立的pCreateContext指標,以便子檢視共享Document。這我用一篇文章詳細說明。CTabView建立多檢視的好處在於簡單的標籤切換,可以讓每個View的視窗都很大。下面說說如何操作:
在建立專案時,程式嚮導最後一步並未提供讓View為CTabView型別,因此我們需要自己新建一個CTabView的子類。
在vc2008中,在專案選單中“專案”->“新增類”,可以自動生成類,像vc6的話ClassWizard也可以自動新增。
修改WinApp中的InitInstance中的new CMultiDocTemplate(),修改其中的View型別為剛剛新建的CTabView子類。
// 註冊應用程式的文件模板。文件模板 // 將用作文件、框架視窗和檢視之間的連線 CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_TestTabViewTYPE, RUNTIME_CLASS(CTestTabViewDoc), RUNTIME_CLASS(CChildFrame), // 自定義 MDI 子框架 RUNTIME_CLASS(CMyTabView)); if (!pDocTemplate) returnFALSE; AddDocTemplate(pDocTemplate);
修改完成後,可以看出TabView的形態已經出來了,不過裡面沒有子View。下面來新增子view。
一般子view也需要新建,繼續使用自動新建類,可以建立CFormView、ClistView等等的檢視來顯示資料。
新建子view在CTabView的OnCreate函式中,在新建類中需要新建CCreateContext來將Doc給新的View。
int CMyTabView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CTabView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: 在此新增您專用的建立程式碼 CCreateContext context; context.m_pNewViewClass = RUNTIME_CLASS(CView1); context.m_pCurrentDoc = GetDocument(); AddView(RUNTIME_CLASS(CView1),"哈哈",100,&context); context.m_pNewViewClass = RUNTIME_CLASS(CEditView); AddView(RUNTIME_CLASS(CEditView),"呵呵",101,&context); return 0; }
上述程式碼新建了2個檢視,CCreateContext指定需要新建View,指定Doc為TabView的Doc,在AddView中的最後引數中將CCreateContext傳入。
至此,子檢視中可以使用GetDocument來得到在WinApp中CTestTabViewDoc的類例項指標,這些子檢視共享了同一份Doc。
後續:
過了幾天,我無意間發現AddView的程式碼,是自動將自己的Doc傳給子tab,請看程式碼:
int CTabView::AddView(CRuntimeClass* pViewClass, const CString& strViewLabel, int iIndex /*= -1*/, CCreateContext* pContext/* = NULL*/) { ASSERT_VALID(this); ENSURE(pViewClass != NULL); ENSURE(pViewClass->IsDerivedFrom(RUNTIME_CLASS(CView))); CView* pView = DYNAMIC_DOWNCAST(CView, pViewClass->CreateObject()); ASSERT_VALID(pView); if (!pView->Create(NULL, _T(""), WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), &m_wndTabs, (UINT) -1, pContext)) { TRACE1("CTabView:Failed to create view '%s'\n", pViewClass->m_lpszClassName); return -1; } CDocument* pDoc = GetDocument(); if (pDoc != NULL) { ASSERT_VALID(pDoc); BOOL bFound = FALSE; for (POSITION pos = pDoc->GetFirstViewPosition(); !bFound && pos != NULL;) { if (pDoc->GetNextView(pos) == pView) { bFound = TRUE; } } if (!bFound) { pDoc->AddView(pView); } } m_wndTabs.InsertTab(pView, strViewLabel, iIndex); int nTabs = m_wndTabs.GetTabsNum(); return nTabs - 1; }
所以,只要AddView就可以,不再需要CCreateContext結構體作為引數,子tab就可以獲得Doc指標了。