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

MFC 對話框專案嵌入 DialogBar:繞過無 CMainFrame 限制的完整方案

     編輯:關於VC++

問題背景

MFC CDialogBar 需掛載於 CFrameWnd 衍生類(如 CMainFrame)才能正常運作。對話框專案(CDialog 基礎)缺乏 Frame 視窗,直接建立 CDialogBar 會失敗。本文提供一個可復用的 CStTbar 類別,透過建立隱藏的 CMiniFrameWnd 容器,在對話框中完美嵌入 CDialogBar,支援停靠、浮動、工具提示等完整功能。

核心架構


// 1. 迷你框架視窗:轉發命令訊息給父視窗(對話框)
class CMyMiniFrm : public CMiniFrameWnd {
    BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) {
        BOOL br = GetParent()->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); // 先讓父視窗處理
        CMiniFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);          // 再走預設流程
        return br;
    }
};

// 2. 靜態控制項衍生類:作為 DialogBar 的佔位符與建立器
class CStTbar : public CStatic {
    CMyMiniFrm* m_minifrm;
    CDialogBar m_wndMyDialogBar;

    void PreSubclassWindow() {
        CStatic::PreSubclassWindow();
        CRect rt; GetWindowRect(&rt); GetParent()->ScreenToClient(&rt);
        ShowWindow(SW_HIDE); // 隱藏佔位符

        m_minifrm = new CMyMiniFrm();
        m_minifrm->Create(AfxRegisterWndClass(0), _T(""), WS_VISIBLE|WS_CHILD, rt, GetParent());

        // 建立 DialogBar 掛載到 m_minifrm
        if (!m_wndMyDialogBar.Create(m_minifrm, GetDlgCtrlID(),
            CBRS_RIGHT|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_HIDE_INPLACE, CG_ID_VIEW_MYDIALOGBAR)) {
            TRACE0("Failed to create dialog bar\n"); return;
        }
        m_wndMyDialogBar.EnableDocking(CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT);
        m_minifrm->EnableDocking(CBRS_ALIGN_ANY);
        // 依佔位符寬高決定初始停靠方向
        if (rt.Width() > rt.Height()) m_minifrm->DockControlBar(&m_wndMyDialogBar, CBRS_ALIGN_LEFT);
        else m_minifrm->DockControlBar(&m_wndMyDialogBar, CBRS_ALIGN_RIGHT);
        m_minifrm->RecalcLayout();
    }

    // 轉發閒置更新訊息給 DialogBar
    void PreTranslate(MSG* pMsg) {
        if (m_wndMyDialogBar.IsWindowVisible())
            m_wndMyDialogBar.OnUpdateCmdUI(m_minifrm, TRUE);
    }

    // 清理
    ~CStTbar() {
        if (m_minifrm) { m_minifrm->DestroyWindow(); delete m_minifrm; }
    }
};

使用步驟

  1. 將 CStTbar.h/.cpp 加入專案
  2. 對話框資源編輯器:拖入一個 Static 控制項,ID 設為 IDC_MY_DIALOGBAR(或自訂),大小即為 DialogBar 初始區域
  3. 類別向導為該 Static 控制項新增控制變數,類型選 CStTbar,變數名如 m_wndNavBar
  4. 建立一個 Dialog 資源(Child、無邊框)作為 DialogBar 內容,ID 如 IDD_MY_DIALOGBAR,並用類別向導建立對應類別 CMyDialogBar : public CDialog
  5. 在 CStTbar::PreSubclassWindow 中將 CG_ID_VIEW_MYDIALOGBAR 對應到 IDD_MY_DIALOGBAR,或修改 Create 參數直接指定資源 ID

執行效果

DialogBar 停靠左側 DialogBar 停靠右側

關鍵技術點總結

  • CMiniFrameWnd 容器:提供 Docking 架構所需的 Frame 視窗
  • 命令路由轉發:OnCmdMsg 先讓父對話框處理,保證按鈕/選單命令正常觸發
  • 閒置更新轉發:PreTranslate 呼叫 OnUpdateCmdUI 讓工具列按鈕狀態(啟用/禁用/勾選)正常運作
  • 記憶體管理:CMyMiniFrm 在 OnNcDestroy 自動 delete this,CStTbar 解構時銷毀框架視窗

適用場景

  • 對話框專案需導覽列、屬性面板、工具箱等可停靠/浮動 UI
  • WPS Office 風格側邊欄、Visual Studio 風格工具視窗
  • 需在 DialogBar 內放置複雜控制項(Tree/List/Edit/Combo 等)

完整原始碼請參考本文配套下載。此方案在 VC6.0+Win2000 驗證通過,亦適用於新版 MFC。

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