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

Visual C++.NET 程式設計講座第四講:選單、工具列與狀態列互動機制

     編輯:VC.NET

第 3 講:選單、工具列與狀態列的互動

本講涵蓋選單與工具列的視覺化設計、命令訊息對應 (COMMAND 與 UPDATE_COMMAND_UI)、工具按鈕與選單命令的聯動、工具列顯示/隱藏的多種控制方式(選單命令、快速鍵、捷徑選單),以及狀態列窗格的動態文字顯示技巧。

選單的視覺化設計與命令對應

1. 選單設計規範

  • 選單層級建議 2~3 層,避免過深。
  • 彈出對話框的選單項後方加上「...」。
  • 助記符(底線字元)以 & 標示,如「格式(&M)」。
  • 快速鍵顯示於選單項文字之後。

2. 為 Viewer 專案加入「格式」選單

  1. 切換至 [資源檢視],展開節點,雙擊 Menu 下的 IDR_MAINFRAME。
  2. 在頂層選單最右側「請在此處輸入」處,按 Insert 或右鍵選 [新增插入],輸入「格式(&M)」。
  3. 在其下加入兩個子選單項:
    • 「設定字型(&F)」,ID 改為 ID_FOMAT_TXTFONT
    • 「文字顏色(&C)」,ID 設為 ID_FORMAT_TXTCOLOR
  4. 將「格式」選單拖曳至「檢視」與「說明」之間。

頂層選單資源
圖 1 頂層選單資源編輯

選單屬性視窗
圖 2 選單項屬性設定(Caption、Popup、Separator、Prompt)

完成的格式選單
圖 3 加入完成的「格式」選單

3. 選單命令訊息對應 (COMMAND)

執行程式時新選單項呈現灰色無法選取,因尚未對應命令訊息。對應步驟:

  1. 切換至 [類別檢視],選取 CViewerView,屬性視窗點選 [事件] 按鈕。
  2. 找到 ID_FORMAT_TXTFONT,展開其 [+] 號,於 COMMAND 欄位選擇 <新增> OnFormatTxtfont。
  3. 同樣為 ID_FORMAT_TXTCOLOR 加入 COMMAND 對應。

事件對應視窗
圖 4 事件對應介面

COMMAND 訊息對應
圖 5 選單 COMMAND 訊息對應

注意:單一檔案應用程式中,命令訊息回應優先順序為:視圖類別 > 文件類別 > 主框架視窗類別 > 應用程式類別。

4. 完善「格式」選單功能代碼

  1. 於 CViewerView 加入兩個成員變數:
    • LOGFONT m_lfTextFont — 邏輯字型結構,描述理想字型特性
    • COLORREF m_crTxtColor — RGB 顏色值
  2. 在建構函數初始化:m_lfTextFont 設為預設字型,m_crTxtColor = RGB(0,0,0)(黑色)。
  3. OnFormatTxtfont 使用 CFontDialog 通用字型對話框:
void CViewerView::OnFormatTxtfont()
{
    CFontDialog dlg(&m_lfTextFont);
    if (dlg.DoModal() == IDOK)
    {
        dlg.GetCurrentFont(&m_lfTextFont);
        Invalidate(); // 觸發重繪
    }
}

OnFormatTxtfont 代碼
圖 6 字型選擇代碼

  1. OnFormatTxtcolor 使用 CColorDialog 通用顏色對話框:
void CViewerView::OnFormatTxtcolor()
{
    CColorDialog dlg(m_crTxtColor);
    if (dlg.DoModal() == IDOK)
    {
        m_crTxtColor = dlg.GetColor();
        Invalidate();
    }
}

OnFormatTxtcolor 代碼
圖 7 顏色選擇代碼

  1. 修改 OnDraw 套用字型與顏色繪製文字。

修改後的 OnDraw
圖 8 修改後的 OnDraw 繪製代碼

執行結果
圖 9 程式執行結果:字型與顏色變更生效

工具列設計與選單命令聯動

1. 新增並設計工具列

  1. [資源檢視] 中右鍵 Toolbar 選 [插入 Toolbar],預設 ID 為 IDR_TOOLBAR1。
  2. 設計兩個工具按鈕圖示(16×15 像素),操作技巧:
  • 點選空白按鈕編輯圖示,系統自動在後添加空白按鈕。
  • 拖曳按鈕可移動位置;按 Ctrl 拖曳可複製;拖出工具列可刪除。
  • Delete 可清除按鈕圖示。
  • 間隔調整:拖曳按鈕覆蓋相鄰按鈕一半以上可產生/移除間隔。

工具按鈕設計
圖 10 工具按鈕設計介面

  1. 設定按鈕屬性實現聯動:
    • 按鈕 1:ID 設為 ID_FORMAT_TXTFONT,Prompt 設為「改變顯示的字型\n字型」
    • 按鈕 2:ID 設為 ID_FORMAT_TXTCOLOR,Prompt 設為「改變文字的顯示顏色\n顏色」

Prompt 屬性說明:\n 前文字顯示於狀態列,\n 後文字作為工具提示彈出視窗內容。

2. 工具列程式碼實作

  1. 於 CMainFrame 加入成員變數 CToolBar m_wndFormatBar。
  2. 在 CMainFrame::OnCreate 中建立工具列:
if (!m_wndFormatBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
    !m_wndFormatBar.LoadToolBar(IDR_TOOLBAR1))
{
    TRACE0("無法建立工具列\n");
    return -1;
}

m_wndFormatBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndFormatBar);

// 避免與預設工具列 ID 衝突
m_wndFormatBar.SetWindowLong(GWL_ID, AFX_IDW_TOOLBAR + 10);

工具列建立代碼
圖 11 工具列建立代碼

關鍵點說明:

  • CreateEx 建立工具列物件,LoadToolBar 載入資源。
  • EnableDocking / DockControlBar 實現停靠/浮動功能。
  • 重新指定子視窗 ID 避免與系統預設工具列衝突。

工具列停靠工具列浮動
圖 12 新工具列的停靠與浮動狀態

因工具按鈕 ID 與選單命令相同,無需額外對應 COMMAND 訊息;若為獨立按鈕則需自行對應。

工具列顯示/隱藏的多種快捷方式

1. 選單命令方式

在 [檢視] 選單加入「格式工具列(&F)」,ID 為 ID_VIEW_FORMAT。

檢視選單加入項目
圖 13 [檢視] 選單加入工具列切換項目

於 CMainFrame 加入 BOOL m_bViewFormat 追蹤顯示狀態,建構函數初始化為 TRUE。對應 ID_VIEW_FORMAT 的 COMMAND 與 UPDATE_COMMAND_UI:

void CMainFrame::OnViewFormat() 
{
    m_bViewFormat = !m_bViewFormat;
    ShowControlBar(&m_wndFormatBar, m_bViewFormat, FALSE);
}

void CMainFrame::OnUpdateViewFormat(CCmdUI* pCmdUI) 
{
    pCmdUI->Enable();
    pCmdUI->SetCheck(m_bViewFormat);
}

顯示/隱藏代碼
圖 14 工具列顯示控制代碼

CCmdUI::Enable() 控制啟用/停用,SetCheck() 控制選單項前的核取記號。

2. 快速鍵方式

  1. [資源檢視] 展開 Accelerator,雙擊 IDR_MAINFRAME。
  2. 新增一筆:ID 選擇 ID_VIEW_FORMAT,修飾鍵 Ctrl,鍵 1,類型 VIRTKEY。

快速鍵資源
圖 15 快速鍵資源編輯器

預設快速鍵
圖 16 新增預設快速鍵項目

設定快速鍵
圖 17 設定 Ctrl+1 快速鍵

執行後按 Ctrl+1 即可切換工具列。建議於選單項文字後加上 \t Ctrl+1 讓使用者知悉快速鍵。

3. 捷徑選單 (右鍵選單) 方式

最常用的工具列切換方式。實作步驟:

  1. 於 CMainFrame 屬性視窗 [訊息] 頁面加入 WM_CONTEXTMENU 對應。
  2. 於 OnContextMenu 撰寫代碼:
void CMainFrame::OnContextMenu(CWnd* pWnd, CPoint point)
{
    if (pWnd->GetDlgCtrlID() >= AFX_IDW_DOCKBAR_TOP && 
        pWnd->GetDlgCtrlID() <= AFX_IDW_DOCKBAR_FLOAT)
    {
        CMenu menu;
        menu.LoadMenu(IDR_MAINFRAME);
        CMenu* pPopup = menu.GetSubMenu(1); // 取得第 2 個子選單 (檢視)
        pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
    }
}

WM_CONTEXTMENU 對應
圖 18 加入 WM_CONTEXTMENU 訊息對應

OnContextMenu 代碼
圖 19 OnContextMenu 實作代碼

說明:AFX_IDW_DOCKBAR_TOP~AFX_IDW_DOCKBAR_FLOAT 為工具列停靠/浮動視窗 ID 範圍。GetSubMenu(1) 取得第 2 個子選單 (索引從 0 起)。TrackPopupMenu 於滑鼠右鍵位置彈出選單。

捷徑選單結果1捷徑選單結果2
圖 20 不同位置右鍵彈出的捷徑選單

狀態列動態文字顯示

1. 新增狀態列窗格

  1. [資源檢視] 右鍵專案資源檔選 [資源符號],新增兩個 ID:
    • ID_STAT_TXTFONT (值 101)
    • ID_STAT_TXTCOLOR (值 102)
  2. 開啟 [字串表] 資源,為上述 ID 分別加入字串「顯示字型」與「目前文字顏色」。字串長度決定窗格寬度。

新增資源符號
圖 21 新增資源符號 ID

字串表新增
圖 22 字串表加入窗格文字

  1. 修改 MainFrm.cpp 中 indicators 陣列,加入兩個新 ID:
static UINT BASED_CODE indicators[] =
{
    ID_SEPARATOR,           // 狀態列訊息區
    ID_INDICATOR_CAPS,
    ID_INDICATOR_NUM,
    ID_INDICATOR_SCRL,
    ID_STAT_TXTFONT,        // 新增:字型顯示窗格
    ID_STAT_TXTCOLOR        // 新增:顏色顯示窗格
};

indicators 陣列修改
圖 23 狀態列窗格陣列修改

初始執行結果
圖 24 初始執行結果(僅顯示靜態字串)

2. 更新狀態列窗格內容 (UPDATE_COMMAND_UI)

因類別屬性視窗無法直接對窗格 ID 對應事件,採用臨時選單法:

  1. 暫時在 [格式] 選單加入兩個項目「1」、「2」,ID 分別設為 ID_STAT_TXTFONT、ID_STAT_TXTCOLOR。
  2. 於 CViewerView 對應兩個 ID 的 UPDATE_COMMAND_UI 事件。
  3. 撰寫更新代碼:
void CViewerView::OnUpdateStatTxtfont(CCmdUI* pCmdUI)
{
    pCmdUI->Enable();
    CString str;
    str.Format(_T("字型: %s"), m_lfTextFont.lfFaceName);
    pCmdUI->SetText(str);
}

void CViewerView::OnUpdateStatTxtcolor(CCmdUI* pCmdUI)
{
    pCmdUI->Enable();
    CString str;
    str.Format(_T("顏色: RGB(%d,%d,%d)"), 
        GetRValue(m_crTxtColor), GetGValue(m_crTxtColor), GetBValue(m_crTxtColor));
    pCmdUI->SetText(str);
}

窗格更新代碼
圖 22 狀態列窗格動態更新代碼

  1. 重新建置方案。
  2. 刪除暫時加入的選單項「1」、「2」。

最終執行結果
圖 23 最終執行結果:狀態列即時顯示目前字型與顏色

常見操作問題解決

問題解決方法
新增選單/工具按鈕 ID 數值固定為 0屬性視窗中 ID 名稱後加 =200 按 Enter,或指定其他唯一值
事件對應頁面找不到新增的命令 ID,或顯示為數值以「原始碼 (文字) 編輯器」開啟 .rc 檔,將數值改回符號名稱
編譯出現「無法開啟 xxx 資源」錯誤執行 [重新建置方案]
執行時出現 LNK1168 無法寫入 .exe關閉正在執行的程式後再編譯執行

指定開啟方式
圖 24 以原始碼編輯器開啟 .rc 檔

選單文字片段
圖 25 .rc 檔選單文字片段

結語

本講詳細說明選單、工具列、狀態列三大介面元素的設計、訊息對應、聯動機制與動態更新技巧。下一講將進入對話框介面設計、模態/非模態對話框建立,以及 DDX/DDV 資料交換驗證機制的應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved