想要工具列按鈕右側帶個小下拉箭頭 (像 IE 早期版本的「返回」、「列印」按鈕)?MFC 內建支援,僅需兩行代碼開啟擴展風格,再設定按鈕樣式即可。本文說明完整步驟,含彈出選單資源建立與 TBN_DROPDOWN 訊息處理。

圖一:IE 風格帶下拉箭頭的工具列按鈕
於 CMainFrame::OnCreate 中,工具列建立後加入:
DWORD dwExStyle = TBSTYLE_EX_DRAWDDARROWS; m_wndToolBar.GetToolBarCtrl().SendMessage(TB_SETEXTENDEDSTYLE, 0, (LPARAM)dwExStyle);
TBSTYLE_DROPDOWN 風格以「開啟檔案」按鈕 (ID_FILE_OPEN) 為例:
int nIndex = m_wndToolBar.CommandToIndex(ID_FILE_OPEN); DWORD dwStyle = m_wndToolBar.GetButtonStyle(nIndex); dwStyle |= TBSTYLE_DROPDOWN; // 添加下拉箭頭風格 m_wndToolBar.SetButtonStyle(nIndex, dwStyle);
編譯執行,箭頭已出現,但點擊無反應,需處理訊息。
TBN_DROPDOWN 通知訊息彈出選單建立選單資源: ResourceView 新增選單 IDR_MENU1,設計下拉項目 (如「新增」、「開啟」、「關閉」)。

圖二:自訂下拉選單資源 IDR_MENU1
主框架類別加入訊息映射與處理:
// MainFrm.h
afx_msg void OnToolbarDropDown(NMHDR* pNMHDR, LRESULT* pResult);
// MainFrm.cpp 訊息映射
ON_NOTIFY(TBN_DROPDOWN, AFX_IDW_TOOLBAR, OnToolbarDropDown)
// 處理函數
void CMainFrame::OnToolbarDropDown(NMHDR* pNMHDR, LRESULT* pResult)
{
NMTOOLBAR* pNMToolBar = (NMTOOLBAR*)pNMHDR;
if (pNMToolBar->iItem == ID_FILE_OPEN) // 判斷是哪個按鈕觸發
{
CMenu menu;
menu.LoadMenu(IDR_MENU1);
CMenu* pPopup = menu.GetSubMenu(0);
if (pPopup)
{
// 計算彈出位置:按鈕左下角
CRect rcBtn;
m_wndToolBar.GetToolBarCtrl().GetRect(
m_wndToolBar.CommandToIndex(ID_FILE_OPEN), &rcBtn);
m_wndToolBar.ClientToScreen(&rcBtn);
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
rcBtn.left, rcBtn.bottom, this);
}
*pResult = TBDDRET_DEFAULT; // 讓系統繪製按下狀態
}
}
TBSTYLE_EX_DRAWDDARROWS:工具列控制項層級擴展風格,啟用下拉箭頭繪製邏輯。TBSTYLE_DROPDOWN:按鈕層級風格,標記該按鈕擁有下拉功能。TBN_DROPDOWN:使用者點擊下拉箭頭區域時發送的通知,NMHDR 中攜帶按鈕索引 (iItem)。TBDDRET_DEFAULT:返回值告知系統按鈕處於按下狀態,視覺回饋更自然。此技術同樣適用於 ReBar、對話框工具列等場景,是打造專業級工具列交互的基礎技能。