在單文檔界面(SDI)應用中,有時需要在同一主框架內動態切換多個不同的表單視圖(如數據庫前端應用的多表單切換)。本文通過一個完整示例,演示如何在 VC++ 6.0 / MFC 環境下,基於 CFormView 實現菜單驅動的多視圖無縫切換。
CSwitchFormDoc - 數據載體,被多個視圖共享CSwitchFormView - 對應資源 IDD_SWITCHFORM_FORMCNextFormView - 對應資源 IDD_NEXTFORMCMainFrame - 管理視圖創建、切換、菜單響應使用 MFC AppWizard 創建「Single Document」類型項目,視圖基類選 CFormView,專案名 SwitchForm。
IDD_NEXTFORMCNextFormView,基類 CFormView,關聯 IDD_NEXTFORMID_FIRSTFORM,初始勾選)、「第二個窗體」(ID_SECONDFORM)void CMainFrame::SwitchToForm(int nFormID)
{
// 1. 獲取當前活動視圖
CView* pOldView = GetActiveView();
if (!pOldView) return;
// 2. 根據 ID 查找或創建目標視圖
CView* pNewView = (CView*)GetDlgItem(nFormID);
if (!pNewView)
{
CCreateContext context;
context.m_pCurrentDoc = pOldView->GetDocument(); // 共享同一文檔
if (nFormID == IDD_SWITCHFORM_FORM)
pNewView = new CSwitchFormView;
else if (nFormID == IDD_NEXTFORM)
pNewView = new CNextFormView;
// 創建視圖窗口(作為框架窗口子窗口)
pNewView->Create(NULL, NULL, WS_CHILD | WS_VISIBLE,
CRect(0,0,0,0), this, nFormID, &context);
pNewView->OnInitialUpdate();
}
// 3. 切換活動視圖
SetActiveView(pNewView);
pNewView->ShowWindow(SW_SHOW);
pOldView->ShowWindow(SW_HIDE);
// 4. 更新控件 ID:舊視圖恢復資源 ID,新視圖設置為標準窗格 ID
UINT nOldID = (pOldView->IsKindOf(RUNTIME_CLASS(CSwitchFormView)))
? IDD_SWITCHFORM_FORM : IDD_NEXTFORM;
pOldView->SetDlgCtrlID(nOldID);
pNewView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
// 5. 重新佈局
RecalcLayout();
}
// 菜單命令響應
void CMainFrame::OnFirstForm()
{
if (GetActiveView()->IsKindOf(RUNTIME_CLASS(CSwitchFormView))) return;
SwitchToForm(IDD_SWITCHFORM_FORM);
}
void CMainFrame::OnSecondForm()
{
if (GetActiveView()->IsKindOf(RUNTIME_CLASS(CNextFormView))) return;
SwitchToForm(IDD_NEXTFORM);
}
// 菜單狀態更新(勾選當前視圖)
void CMainFrame::OnUpdateFirstForm(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(GetActiveView()->IsKindOf(RUNTIME_CLASS(CSwitchFormView)));
}
void CMainFrame::OnUpdateSecondForm(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(GetActiveView()->IsKindOf(RUNTIME_CLASS(CNextFormView)));
}
因框架類需動態 new 視圖對象,必須將視圖類構造函數由 protected 改為 public:
// CSwitchFormView.h / CNextFormView.h
class CSwitchFormView : public CFormView
{
public: // 關鍵修改:由 protected 改為 public
CSwitchFormView();
DECLARE_DYNCREATE(CSwitchFormView)
// ...
};
在 MainFrm.cpp 頂部按順序包含:
#include "SwitchFormDoc.h" // 文檔類必須最先包含
#include "SwitchFormView.h"
#include "NextFormView.h"
否則會因類型未定義導致編譯錯誤。
CCreateContext 傳遞同一文檔指針,實現多視圖數據同步AFX_IDW_PANE_FIRST 與資源 ID,確保框架正確識別活動視圖IsKindOf / RUNTIME_CLASS 判斷視圖類型,驅動菜單狀態同理可擴展至多文檔界面(MDI)的「單文檔多視圖」場景:同一文檔對象關聯多個視圖類,通過不同視圖以表格、圖表、報表等形式展示同一數據集,滿足多維分析需求。