首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

MFC 單文檔多視圖 (SDI) 靜態建立法完整實作

     編輯:關於C語言

MFC 預設單文檔架構 (SDI) 僅支援單一視圖。若需在同一文檔下切換多種視圖 (如表單、列表、圖表),採用 **靜態建立** 方式:在 `CWinApp::InitInstance` 中一次性建立所有視圖物件,運行期僅切換顯示/隱藏,避免動態建立/銷毀的閃爍與狀態丟失。本文提供完整實作步驟與核心切換邏輯。

架構設計

  • 應用程式類別 (CMyApp) 持有視圖指標陣列:CView* m_pView[4];
  • 文檔指標共享:所有視圖關聯同一 `CDocument` 實例。
  • 視窗 ID 輪換:切換時交換視圖的 `GWL_ID`,配合 `RecalcLayout()` 正確更新框架視窗佈局。

核心程式碼:InitInstance 靜態建立

BOOL CMyApp::InitInstance() {
    // ... 標準 MFC 初始化 (文檔範本、主框架建立) ...
    // 主框架建立後,取得預設視圖 (索引 0)
    CView* pActiveView = ((CFrameWnd*)m_pMainWnd)->GetActiveView();
    m_pView[0] = pActiveView; // 預設視圖

    // 建立其餘視圖 (隱藏狀態)
    m_pView[1] = new CProductionFormView;
    m_pView[2] = new CEventsListView;
    m_pView[3] = new CRunningFormView;

    // 共享文檔指標的建立內容
    CCreateContext context;
    context.m_pCurrentDoc = ((CFrameWnd*)m_pMainWnd)->GetActiveDocument();

    for (int i = 1; i < 4; ++i) {
        m_pView[i]->Create(NULL, NULL,
            AFX_WS_DEFAULT_VIEW & ~WS_VISIBLE, // 初始隱藏
            CFrameWnd::rectDefault, m_pMainWnd,
            AFX_IDW_PANE_FIRST + i, &context); // 唯一視窗 ID
    }

    // 手動觸發 OnInitialUpdate (因非框架自動建立)
    for (int i = 0; i < 4; ++i)
        m_pView[i]->OnInitialUpdate();

    return TRUE;
}

視圖切換核心函數:SwithToView

void CMyApp::SwithToView(int nView) {
    ASSERT(nView >= 0 && nView < 4);
    CView* pOldView = ((CFrameWnd*)m_pMainWnd)->GetActiveView();
    CView* pNewView = m_pView[nView];
    if (pOldView == pNewView) return;

    // 1. 交換視窗 ID (關鍵:讓 RecalcLayout 識別新的作用中視圖)
    UINT nOldID = ::GetWindowLong(pOldView->m_hWnd, GWL_ID);
    UINT nNewID = ::GetWindowLong(pNewView->m_hWnd, GWL_ID);
    ::SetWindowLong(pOldView->m_hWnd, GWL_ID, nNewID);
    ::SetWindowLong(pNewView->m_hWnd, GWL_ID, nOldID);

    // 2. 顯示/隱藏
    pOldView->ShowWindow(SW_HIDE);
    pNewView->ShowWindow(SW_SHOW);

    // 3. 通知框架視窗更新作用中視圖與佈局
    ((CFrameWnd*)m_pMainWnd)->SetActiveView(pNewView);
    ((CFrameWnd*)m_pMainWnd)->RecalcLayout();
    pNewView->Invalidate(); // 強制重繪
}

選單命令對接

// 在 CMyApp 或主框架中對應選單 ID
void CMainFrame::OnViewProduction()  { ((CMyApp*)AfxGetApp())->SwithToView(1); }
void CMainFrame::OnViewEvents()      { ((CMyApp*)AfxGetApp())->SwithToView(2); }
void CMainFrame::OnViewRunning()     { ((CMyApp*)AfxGetApp())->SwithToView(3); }
void CMainFrame::OnViewDefault()     { ((CMyApp*)AfxGetApp())->SwithToView(0); }

優缺點與替代方案

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案優點缺點
靜態建立 (本文)切換極快、視圖狀態保留 (捲軸位置、輸入焦點)、程式碼簡單啟動較慢、佔用記憶體固定、視圖數固定
動態建立/銷毀啟動快、記憶體按需、視圖類型可擴展切換有延遲、狀態需手動序列化/還原、程式碼複雜
CSplitterWnd 分割視窗原生支援多視圖並列、拖曳分割非「切換」模式、UI 風格不同