選單 是一個項目清單,指定應用程式的選項或選項群組(即子選單)。 按兩下選單項會開啟子選單,或讓應用程式執行命令。 本節提供下列主題的相關信息:
功能表欄和功能表
選單是以階層方式排列的。 階層的最上層是 選單欄,其中包含 選單清單,而選單可以包含 子選單。 功能表欄有時稱為 最上層功能表,功能表和子功能表也稱為 快顯功能表。
功能表項可以執行命令或開啟子功能表。 執行指令的項目稱為 指令項目 或 命令。
選單列上的項目通常會開啟一個選單。 功能表列很少包含命令項目。 選單從選單列下拉,有時被稱為 下拉選單。 顯示下拉功能表時,會附加至功能表欄。 選單列上開啟下拉選單的選單項也稱為 選單名稱。
功能表欄上的功能表名稱代表應用程式提供的主要命令類別。 從選單列選取選單名稱通常會開啟一個選單,其中的選單項目對應到類別中的命令。 例如,功能表欄可能包含 [檔案] 功能表名稱,當使用者按兩下時,會啟動功能表項,例如 [新增]、[開啟],以及 [儲存]。 若要取得選單列的相關信息,請呼叫 GetMenuBarInfo。
只有重疊或彈出視窗可以包含功能表欄;子視窗不能包含一個。 如果視窗有標題列,系統會將功能表欄放在其正下方。 選單列始終可見。 不過,當用戶選取啟動它的選單項目之前,次選單是不可見的。 如需重疊和彈出視窗的詳細資訊,請參閱 視窗類型。
每個功能表都必須有擁有者視窗。 當使用者選取功能表或從功能表選擇專案時,系統會將訊息傳送至功能表的擁有者視窗。
本節討論下列主題。
捷徑菜單
系統也提供快捷功能表。 快捷方式功能表未附加至功能表欄;它可以出現在畫面上的任何位置。 應用程式通常會將快捷方式功能表與視窗的一部分產生關聯,例如工作區或特定物件,例如圖示。 因此,這些功能表也稱為 快捷功能表。
快捷方式功能表會保持隱藏,直到用戶啟動它為止,通常是以滑鼠右鍵按下選取專案、工具列或任務欄按鈕。 選單通常會顯示在插入點或滑鼠游標的位置。
視窗選單
視窗 功能表(也稱為 系統 功能表或 控制 功能表)是幾乎完全由作業系統定義和管理的彈出功能表。 使用者可以單擊標題列上的應用程式圖示,或以滑鼠右鍵按下標題列上的任何位置,來開啟視窗功能表。
視窗 功能表提供一組標準功能表項,讓使用者可以選擇變更視窗的大小或位置,或關閉應用程式。 視窗功能表上的專案可以新增、刪除和修改,但大部分的應用程式只會使用標準功能表項集。 重疊視窗、彈出視窗或子視窗都可以有視窗功能表。 在重疊或彈出視窗中不包括視窗選單是不常見的。
當使用者從 [視窗] 功能表選擇命令時,系統會將 WM_SYSCOMMAND 訊息傳送至功能表的擁有者視窗。 在大部分應用程式中,視窗程式不會從視窗功能表處理訊息。 相反地,它只會將訊息傳遞至 DefWindowProc 函式,以便系統默認處理訊息。 如果應用程式將命令新增至視窗功能表,視窗程式就必須處理命令。
應用程式可以使用 GetSystemMenu 函式來建立要修改的預設視窗功能表複本。 未使用 GetSystemMenu 函式來建立視窗功能表本身複本的任何視窗,都會收到標準視窗功能表。
幫助識別碼
與每個功能表欄、功能表、子功能表和快捷方式功能表相關聯的是說明標識碼。 如果使用者在功能表作用中時按下 F1 鍵,這個值就會傳送至擁有者視窗,做為 WM_HELP 訊息的一部分。
功能表的鍵盤存取
系統提供功能表的標準鍵盤介面。 您可以為選單項目提供助記鍵和加速鍵(快捷鍵)來增強此介面。
下列主題描述標準鍵盤介面、存取鍵和快速鍵:
標準鍵盤介面
系統設計旨在無論有無滑鼠或其他指標設備都能使用。 因為系統提供標準鍵盤介面,使用者可以使用鍵盤來選取功能表項。 此鍵盤介面不需要特殊程序代碼。 應用程式會收到命令訊息,不論使用者是透過鍵盤還是使用滑鼠來選取功能表項。 標準鍵盤介面會處理下列按鍵。
按鍵 | 行動 |
---|---|
字母字元 | 選取具有指定字元做為其訪問鍵的第一個功能表項。 如果選取的項目呼叫出功能表,將顯示功能表,並突出顯示第一個項目。 否則,選擇菜單項目。 |
Alt鍵 | 切換進入或退出選單列模式。 |
ALT+空格鍵 | 顯示視窗功能表。 |
進入 | 啟動功能表,如果項目有相關聯的功能表,則會選取第一個功能表項。 否則,這個擊鍵會選擇專案,就像使用者在選取專案時放開滑鼠按鈕一樣。 |
ESC | 結束功能表模式。 |
左箭頭 | 切換到上一個最上層功能表項。 最上層功能表項包括功能表名稱和視窗功能表。 如果選取的項目位於功能表中,則會選取功能表中的上一個數據行,或選取上一個最上層功能表項。 |
右箭頭 | 如同左箭頭鍵運作,但方向相反。 在選單中,此擊鍵會向前移動一欄;當目前選取的項目位於最右邊的欄時,會選取下一個選單。 |
向上或向下箭頭 | 按下菜單名稱時啟動菜單。 在功能表中按下時,向上箭頭鍵擊鍵會選取上一個項目;向下箭頭鍵擊鍵會選取下一個項目。 |
功能表存取鍵
將訪問鍵(助記鍵)新增至功能表項,即可增強功能表的標準鍵盤介面。 訪問鍵是功能表項文字中的加底線字母。 當功能表處於活動狀態時,使用者可以按下與項目加底線字母對應的按鍵來選擇功能表項。 使用者按下 ALT 鍵後,功能表欄的第一個項目會被醒目提示,使功能表欄成為作用中。 功能表在顯示時為作用中。
若要建立功能表項的存取鍵,請在項目文字字串中的任何字元前面加上符號 &。 例如,文字字串「&Move」會導致系統加上底線字母「M」。
選單快捷鍵
除了具有存取鍵之外,功能表項還可以有與其相關聯的快捷鍵。 快捷鍵與存取鍵不同,因為功能表不需要被啟用,快捷鍵仍然可以運作。 此外,訪問鍵 一律 與功能表項相關聯,而快捷鍵 通常 與功能表項相關聯(但不需要)。
識別快速鍵的文字會新增至功能表項文字字串。 捷徑文字會出現在選單項目名稱的右側,後面是反斜線和跳格字元(\t)。 例如,“&Close\tAlt+F4” 代表 Close 命令,使用 ALT+F4 按鍵組合做為其快捷鍵,並以字母 “C” 做為其存取鍵。 如需詳細資訊,請參閱 鍵盤快捷鍵。
菜單製作
您可以使用功能表範本或選單建立函式來建立選單。 功能表範本通常定義為資源。 選單範本資源可以明確載入或指定為視窗類別的預設選單。 您也可以在記憶體中動態建立功能表範本資源。
下列主題將詳細說明選單建立:
功能表範本資源
大部分的應用程式都會使用功能表範本資源來建立功能表。 功能表範本 定義選單,包括選單列和所有選單的項目。 如需建立選單範本資源的資訊,請參閱開發工具附帶的文件。
建立功能表範本資源並將其新增至應用程式的可執行檔 (.exe) 檔案之後,您可以使用 LoadMenu 函式將資源載入記憶體中。 此功能將傳回一個功能表的控制代碼,然後您可以使用 SetMenu 函式將其指派給視窗。 您可以將選單指派給不是子視窗的任何視窗。
將功能表實作為資源,可讓應用程式更容易當地語系化以用於多個國家/地區。 每個語言只需要在地化資源定義檔案,而不是應用程式的原始程式碼。
記憶體中的選單範本
可以從在記憶體中於運行時生成的功能表範本建立功能表。 例如,允許使用者自定義其功能表的應用程式,可能會根據使用者的喜好設定,在記憶體中建立功能表範本。 然後,應用程式可以將範本儲存在檔案或登錄中,以供日後使用。 若要從記憶體中的範本建立功能表,請使用 LoadMenuIndirect 函式。 如需選單範本格式的描述,請參閱 選單範本資源。
標準功能表範本是由 MENUITEMTEMPLATEHEADER 結構所組成,後面接著一或多個 MENUITEMTEMPLATE 結構。
擴充功能表範本包含一個 MENUEX_TEMPLATE_HEADER 結構,後面接著一或多個 MENUEX_TEMPLATE_ITEM 結構。
功能表握柄
系統會為每個功能表生成唯一的識別碼。 功能表句柄 是 HMENU 類型的值。 應用程式必須在許多功能表函式中指定功能表句柄。 當您建立選單或載入選單資源時,您會收到選單欄位的控制代碼。
若要擷取已建立或載入之選單欄的句柄,請使用 GetMenu 函式。 若要擷取與選單項目相關聯的子選單控制代碼,請使用 GetSubMenu 或 GetMenuItemInfo 函式。 若要擷取視窗選單的控制代,請使用 GetSystemMenu 函式。
菜單建立功能
您可以使用建立功能表的函式,在執行時期建立功能表,或將功能表項新增至現有的功能表。 您可以使用 CreateMenu 函式來建立空白菜單欄和 CreatePopupMenu 函式來建立空白菜單。 您可以使用 MENUINFO 結構來儲存選單的特定設定資訊。 若要取得或擷取功能表的設定,請使用 GetMenuInfo 或 SetMenuInfo。 若要將項目新增至功能表,請使用 InsertMenuItem 函式。 仍然支援較舊的 AppendMenu 和 InsertMenu 函式,但應該 InsertMenuItem 用於新的應用程式。
選單顯示
載入或建立功能表之後,必須先將功能表指派給視窗,系統才能顯示它。 您可以藉由定義類別來指派菜單。 如需詳細資訊,請參閱 視窗類別選單。 您也可以將功能表指派給視窗,方法是將功能表的句柄指定為 CreateWindow 或 CreateWindowEx 函式的 hMenu 參數,或呼叫 SetMenu 函式。
若要顯示快捷方式功能表,請使用 TrackPopupMenuEx 函式。 捷徑選單也稱為浮動快顯選單或內容選單,通常會在處理 WM_CONTEXTMENU 訊息時顯示。
您可以將選單指派給不是子視窗的任何視窗。
仍然支援較舊的 TrackPopupMenu 函式,但新的應用程式應該使用 TrackPopupMenuEx 函式。
視窗類別菜單
您可以在註冊視窗類別時,指定稱為 類別功能表的預設功能表,。 若要這樣做,您需要將功能表範本資源的名稱指派給結構 WNDCLASS 中的 lpszMenuName 成員,這是用來註冊類別的。
根據預設,每個視窗都會為其窗口類別指派類別功能表,因此您不需要明確載入功能表,並將它指派給每個視窗。 您可以在呼叫 createWindowEx 函式時指定不同的功能表句柄,以覆寫類別功能表。 您可以在建立視窗後,使用 SetMenu 函式來變更視窗的功能表。 如需詳細資訊,請參閱 視窗類別。
選單項目
下列主題討論當使用者選擇功能表項時,系統會執行哪些工作,以及應用程式可以控制項目的外觀和功能的方式:
- 指令項目及開啟子功能表的項目
- Menu-Item 識別碼
- Menu-Item 位置
- 透過程式碼存取功能表項目
- 預設選單項目
- 已選取和已清除的選單項目
- [已啟用]、[灰色] 和 [停用] 功能表項
- 醒目提示的功能表項
- Owner-Drawn 選單項目
- 選單項目分隔符和換行符
開啟子功能表的命令項目和專案
當使用者選擇命令專案時,系統會將命令訊息傳送至擁有功能表的視窗。 如果命令項目位於視窗功能表上,系統會傳送 WM_SYSCOMMAND 訊息。 否則,它會傳送 WM_COMMAND 訊息。
與開啟子功能表的每個功能表項目相關聯的是一個對應子功能表的控制代碼。 當使用者指向這類項目時,系統會開啟子功能表。 不會將命令訊息傳送至擁有者視窗。 不過,系統會在顯示子功能表之前,先將 WM_INITMENUPOPUP 訊息傳送至擁有者視窗。 您可以使用 getSubMenu或 GetMenuItemInfo 函式,取得與項目相關聯的子功能表句柄。
選單列通常包含選單名稱,但也可以包含指令項目。 子功能表通常會包含命令項目,但它也可以包含開啟嵌套子功能表的項目。 藉由將這類項目新增至子選單,您可以將選單巢狀到任何深度。 為了提供使用者的視覺提示,系統會自動在開啟子功能表的功能表項文字右邊顯示一個小箭號。
Menu-Item 標識碼
與每個功能表項相關聯的是唯一的應用程式定義整數,稱為 選單項識別碼。 當使用者從功能表中選擇命令專案時,系統會將專案的標識碼傳送至擁有者視窗,做為 WM_COMMAND 訊息的一部分。 視窗程式會檢查標識碼以判斷訊息的來源,並據以處理訊息。 此外,當您呼叫功能表函式時,可以使用功能表項的標識碼來指定功能表項;例如,若要啟用或停用功能表項。
開啟子功能表的功能表項具有標識碼,就像命令項目一樣。 不過,當從功能表選取這類專案時,系統不會傳送命令訊息。 而是,系統會開啟與選單項目相關聯的子選單。
若要擷取位於指定位置的功能表項標識碼,請使用 getMenuItemID 或 GetMenuItemInfo 函式。
Menu-Item 位置
除了具有唯一標識碼之外,功能表欄或功能表中的每一個功能表項都有其獨特的位置值。 功能表列中最左邊的項目,或功能表中的頂部項目,其位置為零。 後續的選單項目的位置值會遞增。 系統會將排序值指派給選單中的所有專案,包括分隔符。 以下插圖顯示功能表列中的項目和功能表中的項目位置值。
呼叫用來修改或擷取特定選單項目資訊的選單函式時,您可以使用其識別碼或其位置來指定該項目。 如需詳細資訊,請參閱下一節。
透過程式存取選單項目
大部分的功能表函式都可讓您依位置或命令指定功能表項。 某些函式會使用 MF_BYPOSITION 和 MF_BYCOMMAND 旗標來指出搜尋演算法;其他人有明確的 fByPosition 參數。 如果您依位置指定功能表項,則項目編號是功能表中以零起始的索引。 如果您依命令指定選單項目,系統會搜尋選單及其子選單,尋找選單識別碼等於所提供項目編號的項目。 如果功能表階層中的多個項目符合項目編號,則未明確指出使用哪一個項目。 如果您的功能表包含重複的功能表識別碼,您應該使用根據位置的功能表操作來避免這種模糊性。
預設選單項目
子選單可以包含一個預設選單項目。 當使用者按兩下來開啟子選單時,系統會將命令訊息傳送至功能表的擁有者視窗,並關閉功能表,就像已選擇預設命令項目一樣。 如果沒有預設的命令專案,子功能表會保持開啟狀態。 若要擷取和設定子功能表的預設項目,請使用 GetMenuDefaultItem 和 SetMenuDefaultItem 函式。
選取和清除功能表項
選單項目可以被選取或清除。 系統會在選取的功能表項旁邊顯示點陣圖,以指出其選取的狀態。 除非應用程式指定了「清除」位圖,否則系統不會顯示在清除項目旁的位圖。 只能選取功能表中的項目;無法選取功能表列中的項目。
應用程式通常會檢查或清除功能表項,以指出選項是否有效。 例如,假設應用程式具有工具列,用戶可以在功能表上使用 工具列 命令來顯示或隱藏。 當工具列隱藏時,工具列 功能表項會清除。 當使用者選擇命令時,應用程式會檢查功能表項並顯示工具列。
核取記號屬性控制功能表項是否被選取。 您可以使用 CheckMenuItem 函式來設定選單項目的勾選屬性。 您可以使用 GetMenuState 函式來判斷功能表項目前已選取或清除。
您可以使用 GetMenuItemInfo 和 SetMenuItemInfo 函式,來取代 CheckMenuItem 和 GetMenuState,以取得和設定功能表項的檢查狀態。
有時候,一組選單項目會對應到一組互斥選項。 在此情況下,您可以使用已選擇的單選選單項目來表示選取的選項(類似於單選按鈕控制項)。 選取的單選項目會顯示為圓點位圖,而不是勾選符號位圖。 若要檢查功能表項並將其設為單選專案,請使用 CheckMenuRadioItem 函式。
根據預設,系統會在選取的功能表項旁邊顯示複選標記或點符位圖,而且清除功能表項旁沒有點符陣圖。 不過,您可以使用 SetMenuItemBitmaps 函式,將應用程式定義的已選取和清除的點陣圖與功能表項產生關聯。 系統接著會使用指定的點陣圖來指出功能表項的選取或清除狀態。
與功能表項相關聯的應用程式定義點陣圖的大小必須與預設複選標記點陣圖相同,其尺寸可能會因螢幕解析度而有所不同。 若要擷取正確的維度,請使用 GetSystemMetrics 函式。 您可以為不同的螢幕解析度建立多個點陣圖資源;視需要建立一個位圖資源並加以縮放;或在運行時間建立位圖,並在其中繪製影像。 點陣圖可以是單色或色彩。 不過,由於選單項目在反白顯示時會顛倒,因此某些顛倒色彩位圖的外觀可能不受歡迎。 如需詳細資訊,請參閱 位陣圖。
已啟用、灰顯和停用功能表項
功能表項可以啟用、灰色或停用。 預設情況下,功能表項是被啟用的。 當使用者選擇啟用的功能表項時,系統會根據功能表項的類型,將命令訊息傳送至擁有者視窗或顯示對應的子功能表。
當使用者無法使用功能表項時,應該會呈現灰色或停用。 無法選擇被灰色顯示和停用的選單選項。 停用的項目看起來與已啟用的項目一樣。 當使用者點擊已停用的專案時,不會選取該專案,且不會有任何反應。 例如,在教學課程中顯示一個看起來活躍但實際上沒有的功能表時,停用的項目可能很有用。
應用程式會將無法使用的功能表項呈現灰色,向使用者提供無法使用命令的視覺提示。 當某個動作不適合時,您可以將選項設為灰色(例如,當系統未安裝印表機時,您可以將 [檔案] 功能表中的 [列印] 命令設為不可用狀態)。
EnableMenuItem 函式會啟用、使之顯示為灰色或停用功能表項。 若要判斷功能表項已啟用、灰色或停用,請使用 getMenuItemInfo函式。
除了 GetMenuItemInfo,您也可以使用 GetMenuState 函式來判斷功能表項已啟用、灰色或停用。
突出顯示的選單項目
當使用者選取功能表時,系統會自動醒目提示功能表中的項目。 不過,您可以使用 HiliteMenuItem函式,從功能表欄的功能表名稱中明確新增或移除醒目提示。 此函式對於位於功能表中的選項沒有任何作用。 不過,當 HiliteMenuItem 用來反白功能表名稱時,名稱就只是看起來像被選取而已。 如果使用者按下 ENTER 鍵,則不會選擇醒目提示的專案。 例如,這項功能在示範功能表用法的定型應用程式中可能很有用。
Owner-Drawn 選單項目
應用程式可以使用 自行繪製項目,完全控制功能表項的外觀。 擁有者繪製專案需要應用程式對選取的繪圖(醒目提示)、選取和已清除的狀態承擔全部責任。 例如,如果應用程式提供了字型功能表,就可以使用對應的字型來顯示每個項目;羅馬字型的項目會用羅馬字顯示,斜體字型的項目會用斜體顯示,以此類推。 如需詳細資訊,請參閱 建立 Owner-Drawn 選單項目。
功能表項分隔符和換行符
系統會提供特殊的功能表項類型,稱為 分隔符,顯示為水平線。 您可以使用分隔符將選單分成相關項目的群組。 分隔符不能用於功能表欄,而且使用者無法選取分隔符。
當選單列包含的選單名稱多到無法在一行中顯示時,系統會自動換行成兩行或多行。 您可以將類型旗標 MFT_MENUBREAK 指派給功能表欄上的特定項目,以造成該項目的換行符號。 系統會將該專案和所有後續專案放在新行上。
當功能表包含的項目多於一欄所能容納的時候,功能表將會被截斷。 您可以通過將 MFT_MENUBREAK 類型旗標指派給功能表中的特定項目,或在 MENUITEM 語句中使用 MENUBREAK 選項,來造成該項目的分欄中斷。 系統會將該專案和所有後續專案放在新數據行中。 MFT_MENUBARBREAK 類型旗標的效果相同,不同之處在於新欄與舊欄之間會出現垂直線。
如果您使用 AppendMenu、InsertMenu或 ModifyMenu 函式來指派換行符,則應該 MF_MENUBREAK 或 MF_MENUBARBREAK指派類型旗標。
與功能表搭配使用的訊息
系統會將訊息傳送至擁有選單的視窗程序碼,以報告選單相關活動。 當使用者選取功能表列上的專案,或按下滑鼠右鍵以顯示快捷方式選單時,系統會傳送一系列訊息。
當使用者在功能表列上啟動專案時,擁有者視窗會先收到 WM_SYSCOMMAND 訊息。 此訊息包含旗標,指出使用者是否使用鍵盤 (SC_KEYMENU) 或滑鼠 (SC_MOUSEMENU) 來啟動功能表。 如需詳細資訊,請參閱 使用鍵盤存取選單。
接下來,在顯示任何功能表之前,系統會將 WM_INITMENU 訊息傳送至視窗程式,讓應用程式可以在使用者看到功能表之前修改功能表。 系統只會在每個功能表啟用時傳送 WM_INITMENU 訊息一次。
當使用者指向開啟子功能表的功能表項時,系統會在顯示子功能表之前,先傳送擁有者視窗 WM_INITMENUPOPUP 訊息。 此訊息可讓應用程式在顯示之前修改子功能表。
當使用者將醒目提示從某個專案移至另一個專案時,系統會將 WM_MENUSELECT 訊息傳送至功能表擁有者視窗的視窗程式。 此訊息會識別目前選取的功能表項。 許多應用程式在其主視窗底部提供資訊區域,並使用此訊息來顯示所選單單項的其他資訊。
當使用者從功能表中選擇命令專案時,系統會將 WM_COMMAND 訊息傳送至視窗程式。 WM_COMMAND 訊息的 wParam 參數的低位字包含所選項目的識別碼。 視窗程式應該檢查標識碼,並據以處理訊息。
您可以使用 MENUINFO 結構來儲存選單的資訊。 如果選單是以 MENUINFO 定義,。dwStyle 值MNS_NOTIFYBYPOS,系統會在選取專案時傳送 WM_MENUCOMMAND,而不是 WM_COMMAND。 這可讓您存取 MENUINFO 結構中的資訊,也可直接提供所選專案的索引。
並非所有功能表都可透過視窗的功能表欄存取。 當使用者在特定位置按下滑鼠右鍵時,許多應用程式都會顯示快捷功能表。 這類應用程式應該處理 WM_CONTEXTMENU 訊息,並視需要顯示快捷方式功能表。 如果應用程式未顯示快捷方式功能表,它應該會將 WM_CONTEXTMENU 訊息傳遞至 DefWindowProc 函式以進行預設處理。
當使用者在游標位於功能表項時放開滑鼠右鍵時,就會傳送 WM_MENURBUTTONUP 訊息。 提供此訊息,以便應用程式可以為功能表項目顯示內容相關或捷徑功能表。
有幾個訊息只涉及拖放選單。 當滑鼠游標進入功能表項或從專案中央移至專案頂端或底部時,會將 WM_MENUGETOBJECT 傳送給拖放功能表的擁有者。 當用戶實際拖曳功能表項時,就會傳送 WM_MENUDRAG 訊息。
當下拉功能表或子功能表被銷毀時,系統會傳送 WM_UNINITMENUPOPUP 訊息。
菜單摧毀
如果將功能表指派給視窗,而該視窗已被銷毀,系統會自動銷毀功能表及其子功能表,釋放功能表的控制碼及其所使用的記憶體。 系統不會自動刪除未指派給視窗的功能表。 應用程式必須藉由呼叫 DestroyMenu 函式來終結未指派的功能表。 否則,即使應用程式關閉,功能表仍會繼續存在於記憶體中。 若要結束呼叫線程的使用中選單,請使用 EndMenu。 如果平臺不支援 EndMenu,請向使用中功能表的擁有者傳送 WM_CANCELMODE 訊息。