CToolBar 是框架視窗頂部(或底部/浮動)的命令按鈕列,按鈕 ID **必須與選單項目 ID 一致**,MFC 才能自動同步啟用/禁用、打勾狀態。AppWizard 產生的專案已內建工具列建立代碼,支援停靠、拖曳、ToolTip、飛越提示。
// OnCreate 中
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT,
WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("工具列建立失敗\n");
return -1;
}
LoadToolBar 會從工具列資源(IDR_MAINFRAME)讀取按鈕陣列、圖示、提示文字。
// 位圖資源 IDB_TOOLBAR:16x16 像素/按鈕,水平排列
UINT btnIDs[] = { IDM_NEW, IDM_OPEN, IDM_SAVE, ID_SEPARATOR, IDM_CUT, IDM_COPY, IDM_PASTE };
if (!m_wndToolBar.Create(this) ||
!m_wndToolBar.LoadBitmap(IDB_TOOLBAR) ||
!m_wndToolBar.SetButtons(btnIDs, _countof(btnIDs)))
{
TRACE0("動態工具列建立失敗\n");
return -1;
}
// 設定按鈕大小與圖示大小
m_wndToolBar.SetSizes(CSize(24, 22), CSize(16, 16)); // 按鈕 24x22, 圖示 16x16
dwStyle)| 旗標 | 效果 |
|---|---|
CBRS_TOP | 頂部停靠(預設) |
CBRS_BOTTOM | 底部停靠 |
CBRS_LEFT | 左側停靠 |
CBRS_RIGHT | 右側停靠 |
CBRS_FLOATING | 初始為浮動視窗 |
CBRS_GRIPPER | 顯示拖曳把手(需 ReBar) |
CBRS_TOOLTIPS | 啟用按鈕 ToolTip |
CBRS_FLYBY | 滑鼠飛越顯示狀態列提示 |
CBRS_SIZE_DYNAMIC | 允許使用者調整工具列寬度 |
CBRS_HIDE_INPLACE | 隱藏時不佔空間 |
ON_UPDATE_COMMAND_UI工具列按鈕視為「選單項目的視覺化映射」,同樣支援 CCmdUI:
// 映射表(ID 與選單/按鈕資源一致)
ON_UPDATE_COMMAND_UI(IDM_CHECK, OnUpdateCheck)
ON_UPDATE_COMMAND_UI(IDM_BOLD, OnUpdateBold)
void CMainFrame::OnUpdateCheck(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_bCheckMode); // 按鈕按下/彈起
pCmdUI->Enable(m_bDataReady); // 啟用/禁用(灰化)
}
void CMainFrame::OnUpdateBold(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_pDoc->IsBoldSelection()); // 依文件狀態打勾
}
// 取得按鈕索引(0-based)
int nIndex = m_wndToolBar.CommandToIndex(IDM_SAVE);
// 啟用/禁用
m_wndToolBar.GetToolBarCtrl().EnableButton(IDM_SAVE, FALSE);
// 設定/清除按下狀態
m_wndToolBar.GetToolBarCtrl().CheckButton(IDM_BOLD, TRUE);
// 設定按鈕文字(僅支援文字按鈕模式)
m_wndToolBar.SetButtonText(nIndex, _T("儲存"));
// 設定按鈕圖示(需 ImageList)
m_wndToolBar.GetToolBarCtrl().SetButtonImage(nIndex, nImageIndex);
// 新增/刪除按鈕(執行時期)
m_wndToolBar.GetToolBarCtrl().InsertButton(nIndex, &tbButton);
m_wndToolBar.GetToolBarCtrl().DeleteButton(nIndex);
資源編輯器中工具列按鈕屬性 Prompt 欄位:
狀態列顯示文字\nToolTip 顯示文字
// 例:
儲存目前文件\n儲存 (Ctrl+S)
\n 前:狀態列第 0 格顯示(飛越時)。\n 後:ToolTip 小視窗顯示。
// 啟用停靠(OnCreate 中)
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar); // 預設停靠頂部
// 程式控制浮動/停靠
m_wndToolBar.FloatControlBar(CRect(100,100,300,50)); // 浮動於指定矩形
DockControlBar(&m_wndToolBar, AFX_IDW_DOCKBAR_TOP); // 重新停靠頂部
// 禁止使用者拖曳
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() & ~CBRS_GRIPPER);
WM_DRAWITEM(或 ON_WM_DRAWITEM 映射)。
void CMainFrame::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (lpDrawItemStruct->CtlType == ODT_BUTTON && nIDCtl == AFX_IDW_TOOLBAR)
{
CDC dc;
dc.Attach(lpDrawItemStruct->hDC);
CRect rc = lpDrawItemStruct->rcItem;
BOOL bSelected = lpDrawItemStruct->itemState & ODS_SELECTED;
BOOL bDisabled = lpDrawItemStruct->itemState & ODS_DISABLED;
UINT nID = lpDrawItemStruct->itemID;
// 自訂繪製邏輯...
dc.FillSolidRect(rc, bSelected ? RGB(200,230,255) : RGB(240,240,240));
dc.DrawEdge(rc, bSelected ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT);
dc.DrawText(_T("自訂"), rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
dc.Detach();
return;
}
CFrameWnd::OnDrawItem(nIDCtl, lpDrawItemStruct);
}
LoadBitmap 失敗。CBRS_TOOLTIPS、按鈕 ID 無提示文字、EnableToolTips(TRUE) 未呼叫。ON_UPDATE_COMMAND_UI 映射、按鈕樣式非 TBSTYLE_CHECK(資源編輯器按鈕屬性 Group 勾選可設為檢查型)。ShowControlBar(&m_wndToolBar, TRUE, FALSE)。