單文檔介面 (SDI) 需在分割視窗 (CSplitterWnd) 中動態替換視圖類別,支援多種視圖切換。
class CMainFrame : public CFrameWnd {
CSplitterWnd m_wndSplitter; // 成員分割視窗
// ...
};
void CMainFrame::OnSwitchView1() {
CRect cr; GetClientRect(&cr);
CSize paneSize(cr.Width() * 3 / 4, cr.Height()); // 新視圖大小
CCreateContext context;
context.m_pNewViewClass = RUNTIME_CLASS(CSwitchView1);
context.m_pCurrentDoc = ((CMyApp*)AfxGetApp())->m_pDoc; // 共享文檔
context.m_pCurrentFrame = this;
context.m_pNewDocTemplate = context.m_pCurrentDoc->GetDocTemplate();
context.m_pLastView = (CView*)m_wndSplitter.GetPane(0, 0); // 參考現有視圖
m_wndSplitter.DeleteView(0, 1); // 刪除第 0 行第 1 列舊視圖
m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CSwitchView1), paneSize, &context); // 建立新視圖
CView* pNewView = (CView*)m_wndSplitter.GetPane(0, 1);
pNewView->GetParentFrame()->RecalcLayout();
m_wndSplitter.RecalcLayout();
pNewView->OnInitialUpdate();
m_wndSplitter.SetActivePane(0, 1); // 激活新窗格
}
void CMainFrame::SwitchToView(int nFormID) {
CView* pOldView = GetActiveView();
CView* pNewView = (CView*)GetDlgItem(nFormID); // 嘗試取得現有子視窗
if (!pNewView) { // 不存在則動態建立
switch (nFormID) {
case IDD_FORM1: pNewView = new CFormView1; break;
case IDD_FORM2: pNewView = new CFormView2; break;
}
CCreateContext ctx;
ctx.m_pCurrentDoc = pOldView->GetDocument();
pNewView->Create(NULL, NULL, WS_CHILD | WS_BORDER, rectDefault, this, nFormID, &ctx);
pNewView->OnInitialUpdate();
}
SetActiveView(pNewView);
pNewView->ShowWindow(SW_SHOW);
pOldView->ShowWindow(SW_HIDE);
// 交換控制項 ID 以便下次 GetDlgItem 找到舊視圖
if (pOldView->IsKindOf(RUNTIME_CLASS(CFormView1))) pOldView->SetDlgCtrlID(IDD_FORM1);
else if (pOldView->IsKindOf(RUNTIME_CLASS(CFormView2))) pOldView->SetDlgCtrlID(IDD_FORM2);
pNewView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
delete pOldView; // 釋放舊視圖
RecalcLayout();
}
| 特性 | 分割視窗模式 | 無分割模式 |
|---|---|---|
| 核心物件 | CSplitterWnd 管理窗格 | 框架直接管理視圖 |
| 建立/刪除 | CreateView/DeleteView | Create/Delete + SetActiveView |
| 文檔共享 | 透過 CCreateContext 傳遞同一文檔指標 | 同樣透過 Context 傳遞 |
| 版面更新 | m_wndSplitter.RecalcLayout() | RecalcLayout() |
void CMainFrame::OnSwitchViewSimple() {
m_wndSplitter.DeleteView(1, 0); // 刪除指定窗格
m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CNewView), CSize(0,0), NULL);
m_wndSplitter.RecalcLayout();
}
適用於視圖大小由分割條自動管理、無特殊初始化需求的情況。