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

Windows API 選單管理函式完整參考與實務模式

     編輯:關於C++

選單系統架構

Windows 選單分為主選單列 (附著於視窗頂列) 與彈出式選單 (下拉/右鍵/子選單)。所有選單本質皆為 HMENU 控制代碼,操作函式統一適用。現代應用多採用資源腳本 (.rc) 定義選單結構,再以 LoadMenu 載入,但動態建立/修改選單仍需精通核心 API。

核心函式分類表

1. 建立與銷毀

函式用途備註
CreateMenu建立空主選單須配合 AppendMenu/InsertMenuItem 填充
CreatePopupMenu建立空彈出式選單用於子選單、右鍵選單
LoadMenu / LoadMenuIndirect從資源/記憶體模板載入Indirect 版接受記憶體 MENUITEMTEMPLATE
DestroyMenu銷毀選單並釋放資源必須先從視窗移除 (SetMenu NULL)

2. 項目增刪與修改

函式用途關鍵參數
AppendMenu尾端附加項目uFlags: MF_STRING, MF_POPUP, MF_SEPARATOR, MF_BITMAP, MF_OWNERDRAW
InsertMenu / InsertMenuItem指定位置插入InsertMenuItem 支援完整 MENUITEMINFO 結構 (現代首選)
DeleteMenu依位置/命令 ID 刪除uFlags: MF_BYPOSITION / MF_BYCOMMAND
RemoveMenu刪除但保留彈出子選單控制代碼配合 DestroyMenu 釋放子選單
ModifyMenu修改現有項目屬性舊版 API,建議改用 SetMenuItemInfo
SetMenuItemInfo / GetMenuItemInfo完整屬性設定/查詢支援位圖、檢查標記、快速鍵、子選單等所有屬性

3. 狀態控制 (啟用/檢查/預設/加亮)

函式用途
EnableMenuItemMF_ENABLED / MF_GRAYED / MF_DISABLED
CheckMenuItemMF_CHECKED / MF_UNCHECKED
CheckMenuRadioItem群組單選效果 (自動取消同群組其他項)
SetMenuDefaultItem / GetMenuDefaultItem雙擊標題列/Enter 鍵觸發的預設命令
HiliteMenuItem主選單列項目加亮/取消 (WM_MENUSELECT 內部使用)

4. 資訊查詢

函式用途
GetMenuItemCount項目總數 (含分隔線)
GetMenuItemID依位置取得命令 ID
GetMenuString取得項目文字
GetMenuState取得項目狀態旗標組合
GetSubMenu依位置取得子選單 HMENU
GetMenuItemRect取得項目螢幕矩形 (Owner-draw 定位用)
MenuItemFromPoint依螢幕點擊座標反查項目

5. 系統選單與關聯

函式用途
GetSystemMenu取得視窗系統選單副本 (可自訂關閉/最大化等項目)
SetMenu / GetMenu視窗主選單綁定/取得
DrawMenuBar主選單列變更後強制重繪

6. 追蹤彈出式選單 (右鍵/按鍵觸發)

函式用途
TrackPopupMenu顯示彈出選單並阻塞直到選取/取消
TrackPopupMenuEx支援 TPM_RECURSE (巢狀彈出) 等進階旗標

7. 視覺客製化

函式用途
SetMenuItemBitmaps以位圖取代核取方塊/圓形按鈕
SetMenuContextHelpId / GetMenuContextHelpId說明內容 ID 關聯

實務開發模式範例

動態建立右鍵選單

HMENU hPopup = CreatePopupMenu();
AppendMenu(hPopup, MF_STRING, ID_COPY,   L"複製 (&C)");
AppendMenu(hPopup, MF_STRING, ID_PASTE,  L"貼上 (&P)");
AppendMenu(hPopup, MF_SEPARATOR, 0, NULL);
AppendMenu(hPopup, MF_STRING, ID_DELETE, L"刪除 (&D)");

POINT pt; GetCursorPos(&pt);
TrackPopupMenu(hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
DestroyMenu(hPopup);  // TrackPopupMenu 返回後立即銷毀

執行時切換主選單

HMENU hNewMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU_ADMIN));
SetMenu(hWnd, hNewMenu);
DrawMenuBar(hWnd);  // 必須呼叫以更新標題列

Owner-Draw 選單項目測量與繪製

設定 MF_OWNERDRAW 旗標,視窗程序處理 WM_MEASUREITEM (回傳寬高) 與 WM_DRAWITEM (繪製邏輯),配合 GetMenuItemRect 定位圖示/文字區域。

常見陷阱與最佳實務

  • 資源洩漏:動態建立的選單 (CreateMenu/Popup) 必須配對 DestroyMenu;從資源載入 (LoadMenu) 的選單在視窗銷毀時由系統自動釋放,但若 SetMenu(hWnd, NULL) 卸載後重新載入,舊選單需手動 DestroyMenu。
  • 命令 ID 衝突:主選單、彈出選單、工具列、快速鍵共用命令 ID 空間,請統一規劃資源 ID 範圍。
  • DPI 縮放:Owner-draw 選單需自行處理 GetDpiForWindow 縮放圖示/字型大小。
  • 無障礙:MF_OWNERDRAW 項目必須支援 WM_GETOBJECT 回傳 IAccessible 供螢幕閱讀器使用。

結語

選單 API 雖歷經數十年演進仍保持向下相容,現代開發建議:靜態結構用資源腳本 + LoadMenu,動態調整用 InsertMenuItem/SetMenuItemInfo,彈出選單用 TrackPopupMenuEx。深入理解 MENUITEMINFO 結構的 fMask、fType、fState、hbmpItem/hbmpChecked/hbmpUnchecked 等欄位,即可掌握所有選單客製化需求。

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