



工具列按鈕 ID **必須與選單項目 ID 相同**,MFC 才能自動同步啟用/禁用、打勾狀態。
IDR_MAINFRAME。| 按鈕 | ID | 提示文字(狀態列/ToolTip) | 圖示 |
|---|---|---|---|
| Check Demo | IDM_CHECK | SetCheck Demo\nSetCheck Demo | 打勾圖示 |
| Disable Demo | IDM_DISABLE | Disable Demo\nDisable Demo | 禁用圖示 |
提示文字格式:狀態列說明\nToolTip文字,以 \n 分隔。
IDR_MAINFRAME,在適當位置新增彈出選單與項目,ID 必須與工具列按鈕一致。
IDC_EDIT_DLGBAR (Edit)、IDC_BTN_SHOW (Button)。IDD_DLGBAR。// MainFrm.h
class CMainFrame : public CFrameWnd
{
CToolBar m_wndToolBar;
CStatusBar m_wndStatusBar;
CDialogBar m_wndDialogBar; // 對話列成員
// ...
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnUpdateCheck(CCmdUI* pCmdUI);
afx_msg void OnUpdateDisable(CCmdUI* pCmdUI);
afx_msg void OnCheck();
afx_msg void OnDisable();
afx_msg void OnShowText();
DECLARE_MESSAGE_MAP()
};
// MainFrm.cpp
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
// 1. 工具列(AppWizard 已產生,這裡示範手動建立)
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;
}
// 2. 狀態列(AppWizard 已產生)
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))
{
TRACE0("狀態列建立失敗\n");
return -1;
}
// 3. 對話列 —— 關鍵步驟
if (!m_wndDialogBar.Create(this, IDD_DLGBAR, CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR))
{
TRACE0("對話列建立失敗\n");
return -1;
}
// 讓對話列上的控件能收到 ON_UPDATE_COMMAND_UI
m_wndDialogBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndDialogBar);
// 4. 啟用 ToolTip(工具列按鈕提示)
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY);
return 0;
}
ON_UPDATE_COMMAND_UI 核心邏輯BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_COMMAND(IDM_CHECK, OnCheck)
ON_COMMAND(IDM_DISABLE, OnDisable)
ON_COMMAND(IDM_SHOW_TXT, OnShowText)
ON_UPDATE_COMMAND_UI(IDM_CHECK, OnUpdateCheck)
ON_UPDATE_COMMAND_UI(IDM_DISABLE, OnUpdateDisable)
// 對話列上的按鈕也用同樣 ID 映射
END_MESSAGE_MAP()
// 狀態變數
BOOL CMainFrame::m_bChecked = FALSE;
void CMainFrame::OnCheck()
{
m_bChecked = !m_bChecked; // 切換狀態
}
void CMainFrame::OnUpdateCheck(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_bChecked); // 工具列按鈕按下/彈起、選單打勾
}
void CMainFrame::OnDisable()
{
// 這裡不直接改狀態,由 OnUpdateDisable 根據 m_bChecked 決定
}
void CMainFrame::OnUpdateDisable(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_bChecked); // Check 為真時啟用 Disable 按鈕
}
// 對話列按鈕:顯示編輯框文字
void CMainFrame::OnShowText()
{
CWnd* pEdit = m_wndDialogBar.GetDlgItem(IDC_EDIT_DLGBAR);
CString str;
pEdit->GetWindowText(str);
AfxMessageBox(_T("對話列輸入: ") + str);
}
// 對話列控件的啟用/禁用同步
void CMainFrame::OnUpdateShowText(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_bChecked); // 按鈕與編輯框同步啟用
}
// 狀態列指標陣列(資源中定義)
static UINT indicators[] =
{
ID_SEPARATOR, // 第 0 格:訊息列(自動顯示選單/工具列提示)
ID_INDICATOR_CAPS, // 第 1 格:Caps Lock
ID_INDICATOR_NUM, // 第 2 格:Num Lock
ID_INDICATOR_SCRL, // 第 3 格:Scroll Lock
ID_INDICATOR_TIME // 第 4 格:自訂時間(需自行更新)
};
// 定時器更新時間
void CMainFrame::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == ID_TIMER_CLOCK)
{
CTime t = CTime::GetCurrentTime();
CString str = t.Format(_T("%H:%M:%S"));
m_wndStatusBar.SetPaneText(4, str); // 第 4 格顯示時間
}
CFrameWnd::OnTimer(nIDEvent);
}
// OnCreate 中啟動計時器
SetTimer(ID_TIMER_CLOCK, 1000, NULL);
ON_UPDATE_COMMAND_UI 映射。SetIndicators 陣列第一個元素為 ID_SEPARATOR,且工具列按鈕/選單項目有提示文字(含 \n)。CreateEx 風格含 CBRS_GRIPPER。