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

AppWizard 建立工具列、狀態列、對話列完整實戰

     編輯:關於C語言

專案建立:AppWizard 勾選關鍵選項

  1. File → New → Projects → MFC AppWizard (exe)。
  2. 步驟 1:選 Single Document(單文檔)。
  3. 步驟 4(或 Advanced):勾選 Toolbar、Status Bar、ReBar(可讓工具列拖曳停靠)。
  4. 完成產生專案骨架。

執行畫面

AppWizard 步驟1

AppWizard 步驟4

工具列/狀態列/ReBar 選項

資源編輯:工具列按鈕與選單同步

工具列按鈕 ID **必須與選單項目 ID 相同**,MFC 才能自動同步啟用/禁用、打勾狀態。

  1. 資源視圖 → Toolbar → 雙擊 IDR_MAINFRAME。
  2. 刪除預設按鈕,新增兩顆按鈕:
按鈕ID提示文字(狀態列/ToolTip)圖示
Check DemoIDM_CHECKSetCheck Demo\nSetCheck Demo打勾圖示
Disable DemoIDM_DISABLEDisable Demo\nDisable Demo禁用圖示

提示文字格式:狀態列說明\nToolTip文字,以 \n 分隔。

  1. 同步建立選單項目:資源視圖 → Menu → IDR_MAINFRAME,在適當位置新增彈出選單與項目,ID 必須與工具列按鈕一致。

選單編輯

對話列資源建立

  1. 資源視圖右鍵 → Insert Resource → Dialog → New。
  2. 屬性設定:Style = Child、Border = None、Visible = False。
  3. 放置控件:IDC_EDIT_DLGBAR (Edit)、IDC_BTN_SHOW (Button)。
  4. ID 設為 IDD_DLGBAR。

代碼實作:CMainFrame 整合三大控制列

// 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;
}

訊息映射與 UI 更新: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);

執行結果驗證

  • 工具列 Check 按鈕按下 → 選單項目打勾、Disable 按鈕變啟用。
  • 工具列 Disable 按鈕按下 → 無直接動作,但狀態列提示顯示「Disable Demo」。
  • 對話列編輯框輸入文字 → 按 ShowText → 彈出訊息框顯示內容。
  • 狀態列第 0 格自動顯示滑鼠懸停工具列/選單的提示文字。
  • 狀態列第 4 格每秒更新目前時間。

常見問題排查

  • 工具列按鈕不會按下/打勾:檢查 ID 是否與選單項目完全一致、是否有 ON_UPDATE_COMMAND_UI 映射。
  • 對話列控件不回應 Tab 鍵:資源編輯器中對話框屬性 Style=Child, Border=None,控件需勾選 Tab Stop。
  • 狀態列不顯示提示:確認 SetIndicators 陣列第一個元素為 ID_SEPARATOR,且工具列按鈕/選單項目有提示文字(含 \n)。
  • ReBar 不支援拖曳:AppWizard 步驟需勾選 ReBar,且 CreateEx 風格含 CBRS_GRIPPER。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved