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

MFC 混合靜態分割視窗完整實作指南

     編輯:關於VC++

MFC 的 CSplitterWnd 支援靜態分割,允許在執行期建立固定行列的子視窗,每個窗格可關聯不同的 CView 衍生類,實現複雜的多視圖佈局。本文詳細說明混合靜態分割(巢狀分割)的三大核心步驟與關鍵 API。

核心實作三步驟

  1. 宣告分割視窗成員:在 CMainFrame 中定義 CSplitterWnd 資料成員
  2. 重載 OnCreateClient:建立靜態分割、填充視圖、設定列寬/列高
  3. 建立視圖同步機制:利用 CDocument::UpdateAllViews() 實現多視圖資料同步

關鍵 API 詳解

1. 建立靜態分割:CreateStatic

BOOL CreateStatic(
    CWnd* pParentWnd,   // 父視窗 (通常是 this)
    int nRows,          // 列數 (1~16)
    int nCols,          // 行數 (1~16)
    DWORD dwStyle = WS_CHILD | WS_VISIBLE,
    UINT nID = AFX_IDW_PANE_FIRST); // 巢狀分割時需用 IdFromRowCol() 產生唯一 ID

2. 填充視圖:CreateView

BOOL CreateView(
    int row, int col,           // 目標窗格位置
    CRuntimeClass* pViewClass,  // 視圖類 (需 DECLARE_DYNCREATE)
    SIZE sizeInit,              // 初始大小
    CCreateContext* pContext);  // 來自 OnCreateClient 參數傳遞

3. 尺寸調整與啟用窗格

SetColumnInfo(int col, int cxIdeal, int cxMin); // 設定欄寬/最小寬
SetRowInfo(int row, int cyIdeal, int cyMin);    // 設定列高/最小高
RecalcLayout();                                 // 重新佈局 (必須呼叫)
SetActivePane(int row, int col, CWnd* pWnd = NULL); // 設定作用中窗格

混合分割實作範例

在外層分割器的某窗格中再建立一個 CSplitterWnd 成員,於外層 CreateView 後、內層 OnCreateClient 中初始化:

// CMainFrame 成員
CSplitterWnd m_wndSplitterOuter;
CSplitterWnd m_wndSplitterInner; // 巢狀分割器

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT, CCreateContext* pContext) {
    // 1. 外層 1列 2欄
    if (!m_wndSplitterOuter.CreateStatic(this, 1, 2))
        return FALSE;

    // 2. 左欄放 CLeftView
    if (!m_wndSplitterOuter.CreateView(0, 0,
        RUNTIME_CLASS(CLeftView), CSize(200, 0), pContext))
        return FALSE;

    // 3. 右欄先放佔位視圖,稍後替換為內層分割器
    if (!m_wndSplitterOuter.CreateView(0, 1,
        RUNTIME_CLASS(CPlaceholderView), CSize(0, 0), pContext))
        return FALSE;

    // 4. 取得右欄窗格 HWND,作為內層分割器父視窗
    CWnd* pRightPane = m_wndSplitterOuter.GetPane(0, 1);
    // 內層分割器需為子視窗,故改用 pRightPane 為父
    if (!m_wndSplitterInner.CreateStatic(pRightPane, 2, 1,
        WS_CHILD | WS_VISIBLE, m_wndSplitterOuter.IdFromRowCol(0, 1)))
        return FALSE;

    // 5. 填充內層上下兩個視圖
    if (!m_wndSplitterInner.CreateView(0, 0,
        RUNTIME_CLASS(CTopView), CSize(0, 150), pContext))
        return FALSE;
    if (!m_wndSplitterInner.CreateView(1, 0,
        RUNTIME_CLASS(CBottomView), CSize(0, 0), pContext))
        return FALSE;

    // 6. 尺寸微調
    m_wndSplitterOuter.SetColumnInfo(0, 200, 50);
    m_wndSplitterOuter.RecalcLayout();
    m_wndSplitterInner.SetRowInfo(0, 150, 50);
    m_wndSplitterInner.RecalcLayout();

    return TRUE;
}

多視圖同步更新機制

文檔類呼叫 UpdateAllViews(pSender, lHint, pHint),框架自動遍歷所有關聯視圖呼叫 OnUpdate():

  • pSender:觸發更新的視圖指標,傳 NULL 表全部更新
  • lHint:自定義提示碼 (如 HINT_DATA_CHANGED)
  • pHint:攜帶詳細資料的 CObject*

視圖端覆寫:

void CMyView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) {
    if (pSender == this) return; // 避免自我重繪
    if (lHint == HINT_DATA_CHANGED) {
        // 根據 pHint 重繪或局部更新
        Invalidate();
    }
}

動態視圖切換進階技巧

利用 CCreateContext 的 m_pNewViewClass 指定新視圖類型,配合 DeleteView() + CreateView() 實現執行期視圖替換。注意需手動呼叫 OnInitialUpdate() 與 ShowWindow(SW_SHOW)。

混合靜態分割提供了極大的介面彈性,適用於資訊密集型應用(如 IDE、監控儀表板、郵件用戶端),是 MFC 多文檔介面 (MDI) 之外的另一種強大佈局選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved