一般書中介紹的是使用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)
return FALSE;
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指針了。
即將OnCreate的代碼修改如下
int CMyTabView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CTabView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您專用的創建代碼
AddView(RUNTIME_CLASS(CView1),"哈哈",100,&context);
AddView(RUNTIME_CLASS(CEditView),"呵呵",101,&context);
return 0;
}