Dialog Bar(對話列) 是一種特殊的控制列,外觀像工具列,但內容是一個**對話框資源**。它停靠在框架視窗邊緣(上/下/左/右),可包含任意控件(編輯框、按鈕、下拉框、進度條等),並支援 ON_UPDATE_COMMAND_UI 機制,適合做「永遠可見的工具面板」。
CDialogBar繼承自 CControlBar → CWnd。不處理自身訊息,**所有子控件訊息轉發給父框架視窗**處理。
// 1. 資源編輯器建立對話框資源
// Style = Child, Border = None, Visible = False
// ID = IDD_MY_DIALOGBAR
// 2. 框架視窗類別宣告成員
class CMainFrame : public CFrameWnd
{
CDialogBar m_wndDialogBar;
// ...
};
// 3. OnCreate 中建立
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
if (!m_wndDialogBar.Create(this, IDD_MY_DIALOGBAR,
CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR))
{
TRACE0("DialogBar 建立失敗\n");
return -1;
}
return 0;
}
Create 參數詳解| 參數 | 說明 |
|---|---|
pParentWnd | 父框架視窗指標(通常是 this) |
nIDTemplate | 對話框資源 ID |
nStyle | 停靠位置與行為旗標(見下表) |
nID | 控制列 ID,用於儲存/恢復停靠狀態,通常用 AFX_IDW_DIALOGBAR 或自訂 |
nStyle 專用旗標| 旗標 | 效果 |
|---|---|
CBRS_TOP | 停靠在框架視窗頂部(預設) |
CBRS_BOTTOM | 停靠在底部 |
CBRS_LEFT | 停靠在左側 |
CBRS_RIGHT | 停靠在右側 |
CBRS_ALIGN_TOP | 同上,語意更明確(MFC 4.0+ 推薦) |
CBRS_ALIGN_BOTTOM | 同上 |
CBRS_ALIGN_LEFT | 同上 |
CBRS_ALIGN_RIGHT | 同上 |
CBRS_GRIPPER | 顯示拖曳把手(需 ReBar 支援) |
CBRS_SIZE_DYNAMIC | 允許使用者調整大小 |
CBRS_TOOLTIPS | 啟用控件 ToolTip |
CBRS_FLYBY | 滑鼠飛越顯示狀態列提示 |
CBRS_HIDE_INPLACE | 隱藏時不佔空間 |
Dialog Bar **本身不處理訊息**。其子控件產生的訊息(WM_COMMAND、WM_NOTIFY 等)會自動路由到**父框架視窗**(CMainFrame 或 CMDIFrameWnd)。
// CMainFrame 訊息映射
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
// 按鈕點擊
ON_BN_CLICKED(IDC_BTN_DLG_ACTION, OnDlgAction)
ON_COMMAND(IDC_BTN_DLG_ACTION, OnDlgAction) // 同 ID 也可用 ON_COMMAND
// 編輯框變更
ON_EN_CHANGE(IDC_EDIT_DLG_INPUT, OnEditChange)
// 下拉框選擇變更
ON_CBN_SELCHANGE(IDC_COMBO_DLG_OPTIONS, OnComboSelChange)
// UI 更新(啟用/禁用/打勾/設定文字)
ON_UPDATE_COMMAND_UI(IDC_BTN_DLG_ACTION, OnUpdateDlgAction)
ON_UPDATE_COMMAND_UI(IDC_EDIT_DLG_INPUT, OnUpdateEditInput)
END_MESSAGE_MAP()
ON_UPDATE_COMMAND_UI 支援Dialog Bar 子控件完整支援 CCmdUI 操作:
void CMainFrame::OnUpdateDlgAction(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_bDataReady); // 啟用/禁用按鈕
pCmdUI->SetCheck(m_bModeActive); // 按鈕按下/彈起狀態
pCmdUI->SetText(_T("執行動作")); // 動態修改按鈕文字
}
void CMainFrame::OnUpdateEditInput(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_bAllowInput); // 啟用/禁用編輯框
// 注意:SetText 對編輯框無效,需用 SetWindowText
}
// 取得編輯框指標
CEdit* pEdit = (CEdit*)m_wndDialogBar.GetDlgItem(IDC_EDIT_DLG_INPUT);
if (pEdit)
{
pEdit->SetWindowText(_T("新內容"));
pEdit->SetSel(0, -1); // 全選
}
// 取得按鈕狀態
CButton* pBtn = (CButton*)m_wndDialogBar.GetDlgItem(IDC_CHECK_OPTION);
BOOL bChecked = pBtn->GetCheck();
| 特性 | Dialog Bar | ToolBar | Property Sheet |
|---|---|---|---|
| 內容定義 | 對話框資源(任意控件) | 位圖按鈕陣列 | 多個對話框頁面 |
| 停靠行為 | 支援四邊停靠、浮動 | 支援四邊停靠、浮動 | 獨立視窗(模態/非模態) |
| 訊息處理 | 父框架視窗 | 父框架視窗 | 各頁面自行處理 |
| Tab 順序 | 支援 | 不支援(非鍵盤導航) | 支援 |
| 適用場景 | 工具面板、屬性檢視器、搜尋列 | 命令按鈕群組 | 設定對話框、多步精靈 |
EnableDocking()。m_wndDialogBar.SetDialogBarStyle(...) 或確保 PreTranslateMessage 正確轉發。OnCreate 後呼叫 m_wndDialogBar.SetFont(&m_font) 統一設定。LoadBarState()/SaveBarState()(需框架視窗支援),nID 參數作為註冊表鍵值一部分。// 動態建立
void CMainFrame::OnCreateDialogBar()
{
if (!m_wndDialogBar.m_hWnd)
{
m_wndDialogBar.Create(this, IDD_DYNAMIC_BAR, CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR);
RecalcLayout(); // 重新計算控制列佈局
}
}
// 動態銷毀
void CMainFrame::OnDestroyDialogBar()
{
if (m_wndDialogBar.m_hWnd)
{
m_wndDialogBar.DestroyWindow();
RecalcLayout();
}
}