關於功能表

功能表是專案清單,可指定應用程式的選項或選項群組(子功能表)。 按兩下選單項會開啟子選單,或讓應用程式執行命令。 本節提供下列主題的相關信息:

功能表會排列在階層中。 階層的最上層是功能表欄;其中包含功能表清單,接著可以包含子功能表 功能表欄有時稱為 最上層功能表,功能表和子功能表也稱為 快捷功能表

功能表項可以執行命令或開啟子功能表。 執行命令的專案稱為 命令專案命令

功能表欄上的項目幾乎一律會開啟功能表。 功能表列很少包含命令專案。 從功能表欄下拉式清單開啟的功能表,有時稱為 下拉功能表。 顯示下拉功能表時,會附加至功能表欄。 功能表欄上開啟下拉功能表的功能表項也稱為 功能表名稱

功能表欄上的功能表名稱代表應用程式提供的主要命令類別。 從功能表欄選取選單名稱通常會開啟功能表,功能表項對應至類別中的命令。 例如,功能表欄可能包含 [檔案] 功能表名稱,當使用者按兩下時,會啟動具有功能表項的功能表項,例如 [新增]、[開啟] 和 [儲存]。 若要取得功能表欄的相關信息,請呼叫 GetMenuBarInfo

只有重疊或彈出視窗可以包含功能表欄;子視窗不能包含一個。 如果視窗有標題列,系統會將功能表欄放在其正下方。 功能表欄一律會顯示。 不過,在用戶選取啟動它的功能表項之前,看不到子功能表。 如需重疊和彈出視窗的詳細資訊,請參閱 窗口類型

每個功能表都必須有擁有者視窗。 當使用者選取功能表或從功能表選擇專案時,系統會將訊息傳送至功能表的擁有者視窗。

本節討論下列主題。

快顯功能表

系統也提供 快捷功能表。 快捷方式功能表未附加至功能表欄;它可以出現在畫面上的任何位置。 應用程式通常會將快捷方式功能表與視窗的一部分產生關聯,例如工作區或特定物件,例如圖示。 因此,這些功能表也稱為 操作功能表

快捷方式功能表會保持隱藏,直到用戶啟動它為止,通常是以滑鼠右鍵按下選取專案、工具列或任務欄按鈕。 功能表通常會顯示在插入號或滑鼠游標的位置。

視窗功能表

[ 視窗 ] 選單(也稱為 [系統 ] 功能表或 [控件 ] 功能表)是作業系統幾乎完全由操作系統定義和管理的快捷功能表。 使用者可以單擊標題列上的應用程式圖示,或以滑鼠右鍵按下標題列上的任何位置,來開啟視窗功能表。

[ 視窗 ] 選單提供一組標準功能表項,使用者可以選擇變更視窗的大小或位置,或關閉應用程式。 視窗功能表上的專案可以新增、刪除和修改,但大部分的應用程式只會使用標準功能表項集。 重疊、彈出視窗或子視窗可以有視窗功能表。 重疊或彈出視窗不包含視窗功能表並不常見。

當使用者從 [視窗] 功能表選擇命令時,系統會將WM_SYSCOMMAND訊息傳送至功能表的擁有者視窗。 在大部分應用程式中,視窗程式不會從視窗功能表處理訊息。 相反地,它只會將訊息傳遞至 DefWindowProc 函式,以便系統默認處理訊息。 如果應用程式將命令新增至視窗功能表,視窗程式就必須處理命令。

應用程式可以使用 GetSystemMenu 函式來建立要修改的預設視窗選單複本。 未使用 GetSystemMenu 函式來建立視窗功能表本身複本的任何視窗,都會收到標準視窗功能表。

說明標識碼

與每個功能表欄、功能表、子功能表和快捷方式功能表相關聯的是說明標識碼。 如果使用者在功能表作用中時按下 F1 鍵,這個值就會傳送至擁有者視窗做為WM_HELP訊息的一部分。

功能表的鍵盤存取

系統提供功能表的標準鍵盤介面。 您可以為功能表項提供助記鍵和快速鍵(快速鍵)來增強此介面。

下列主題描述標準鍵盤介面、存取鍵和快速鍵:

標準鍵盤介面

系統的設計目的是要與滑鼠或其他指向裝置搭配使用或不使用滑鼠或其他指標裝置。 因為系統提供標準鍵盤介面,使用者可以使用鍵盤來選取功能表項。 此鍵盤介面不需要特殊程序代碼。 應用程式會收到命令訊息,不論使用者是透過鍵盤還是使用滑鼠來選取功能表項。 標準鍵盤介面會處理下列按鍵。

按鍵輸入 動作
字母字元 選取具有指定字元做為其訪問鍵的第一個功能表項。 如果選取的專案叫用功能表,就會顯示功能表,並反白顯示第一個專案。 否則,會選擇功能表項。
ALT 切換和離開功能表欄模式。
ALT+空格鍵 顯示視窗功能表。
ENTER 啟動功能表,如果項目有相關聯的功能表,則會選取第一個功能表項。 否則,這個擊鍵會選擇專案,就像使用者在選取專案時放開滑鼠按鈕一樣。
ESC 結束功能表模式。
向左鍵 迴圈至上一個最上層功能表項。 最上層功能表項包括功能表名稱和視窗功能表。 如果選取的項目位於功能表中,則會選取功能表中的上一個數據行,或選取上一個最上層功能表項。
向右鍵 像向左鍵一樣運作,但方向相反。 在功能表中,此擊鍵會向前移動一欄;當目前選取的項目位於最右邊的數據行時,會選取下一個功能表。
向上或向下箭號 在功能表名稱中按下時啟動功能表。 在功能表中按下時,向上鍵擊鍵會選取上一個專案;向下鍵擊鍵會選取下一個專案。

 

將訪問鍵(助記鍵)新增至功能表項,即可增強功能表的標準鍵盤介面。 訪問鍵是功能表項文字中的加底線字母。 當功能表作用中時,用戶可以按下對應至專案加底線字母的按鍵來選取功能表項。 使用者按下 ALT 鍵以醒目提示功能表欄上的第一個專案,讓功能表欄變成作用中。 功能表在顯示時為作用中。

若要建立功能表項的存取鍵,請在專案文字字串中的任何字元前面加上 ampersand。 例如,文字字串 “&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 結構來儲存選單的特定設定資訊。 若要取得或擷取功能表的設定,請使用 GetMenuInfoSetMenuInfo。 若要將專案新增至功能表,請使用 InsertMenuItem 函式。 仍然支援較舊的 AppendMenuInsertMenu 函式,但 InsertMenuItem 應該用於新的應用程式。

載入或建立功能表之後,必須先將功能表指派給視窗,系統才能顯示它。 您可以藉由定義類別功能表來指派功能表。 如需詳細資訊,請參閱 視窗類別功能表。 您也可以將功能表指派給視窗,方法是將功能表的句柄指定為 CreateWindow 或 CreateWindowEx 函式的 hMenu 參數,或呼叫 SetMenu 函式。

若要顯示快捷方式功能表, 請使用 TrackPopupMenuEx 函式。 快捷功能表,也稱為浮動快捷功能表或操作功能表,通常會在處理WM_CONTEXTMENU訊息時顯示。

您可以將選單指派給不是子視窗的任何視窗。

仍然支援較舊的 TrackPopupMenu 函式,但新的應用程式應該使用 TrackPopupMenuEx 函式。

窗口類別功能表

當您註冊視窗類別時,您可以指定稱為類別功能表的預設選單。 若要這樣做,您可以將功能表範本資源的名稱指派給用來註冊類別之 WNDCLASS 結構的 lpszMenuName 成員。

根據預設,每個視窗都會為其窗口類別指派類別功能表,因此您不需要明確載入功能表,並將它指派給每個視窗。 您可以在呼叫 CreateWindowEx 函式時指定不同的功能表句柄,以覆寫類別功能表。 您也可以在使用 SetMenu 函式建立視窗之後變更視窗的功能表。 如需詳細資訊,請參閱 窗口類別

下列主題討論當使用者選擇功能表項時,系統會執行哪些工作,以及應用程式可以控制項目的外觀和功能的方式:

開啟子功能表的命令項目和專案

當使用者選擇命令專案時,系統會將命令訊息傳送至擁有功能表的視窗。 如果命令項目位於視窗功能表上,系統會傳送 WM_SYSCOMMAND 訊息。 否則,它會傳送 WM_COMMAND 訊息。

與開啟子功能表的每個功能表項相關聯的是對應子功能表的句柄。 當使用者指向這類專案時,系統會開啟子功能表。 不會將命令訊息傳送至擁有者視窗。 不過,系統會在顯示子功能表之前,先將 WM_INITMENUPOPUP 訊息傳送至擁有者視窗。 您可以使用 GetSubMenu GetMenuItemInfo 函式,取得與專案相關聯的子功能表句柄。

功能表欄通常包含功能表名稱,但也可以包含命令專案。 子功能表通常包含命令專案,但它也可以包含開啟巢狀子功能表的專案。 藉由將這類專案新增至子功能表,您可以將功能表巢狀至任何深度。 為了提供使用者的視覺提示,系統會自動在開啟子功能表的功能表項文字右邊顯示一個小箭號。

與每個功能表項相關聯的是唯一的應用程式定義整數,稱為 功能表項標識碼。 當使用者從功能表中選擇命令專案時,系統會將專案的標識碼傳送至擁有者視窗,做為WM_COMMAND訊息的一部分。 視窗程式會檢查標識碼以判斷訊息的來源,並據以處理訊息。 此外,當您呼叫功能表函式時,可以使用功能表項的標識碼來指定功能表項;例如,若要啟用或停用功能表項。

開啟子功能表的功能表項具有標識碼,就像命令項目一樣。 不過,當從功能表選取這類專案時,系統不會傳送命令訊息。 相反地,系統會開啟與功能表項相關聯的子功能表。

若要擷取位於指定位置之功能表項的標識碼,請使用 GetMenuItemID GetMenuItemInfo 函式。

除了具有唯一標識碼之外,功能表欄或功能表中的每個功能表項都有唯一的位置值。 功能表欄中最左邊的專案,或功能表的頂端專案,具有零的位置。 後續功能表項的位置值會遞增。 系統會將位置值指派給功能表中的所有專案,包括分隔符。 下圖顯示功能表列和功能表中專案的位置值。

menu bar and menu

呼叫修改或擷取特定功能表項資訊的功能表函式時,您可以使用其識別碼或其位置來指定專案。 如需詳細資訊,請參閱一節。

以程式設計方式存取功能表項

大部分的功能表函式都可讓您依位置或命令指定功能表項。 某些函式會使用 MF_BYPOSITIONMF_BYCOMMAND 旗標來表示搜尋演算法;其他函式則具有明確的 fByPosition 參數。 如果您依位置指定功能表項,則項目編號是功能表中以零起始的索引。 如果您依命令指定功能表項,則會搜尋功能表及其子功能表,其功能表標識碼等於提供的項目編號。 如果功能表階層中的多個專案符合項目編號,則未指定使用哪一個專案。 如果您的功能表包含重複的功能表標識碼,您應該使用位置型功能表作業來避免這種模棱兩可。

默認功能表項

子功能表可以包含一個預設功能表項。 當使用者按兩下來開啟子選單時,系統會將命令訊息傳送至功能表的擁有者視窗,並關閉功能表,就像已選擇預設命令項目一樣。 如果沒有預設的命令專案,子功能表會保持開啟狀態。 若要擷取和設定子功能表的預設專案,請使用 GetMenuDefaultItem SetMenuDefaultItem 函式。

選取和清除功能表項

功能單項可以選取或清除。 系統會在選取的功能表項旁邊顯示點陣圖,以指出其選取的狀態。 除非指定應用程式定義的「清除」位圖,否則系統不會在清除專案旁邊顯示點陣圖。 只能選取功能表中的功能表項;無法選取選單列中的專案。

應用程式通常會檢查或清除功能表項,以指出選項是否有效。 例如,假設應用程式有一個工具列,用戶可以在功能表上使用 [工具列 ] 命令來顯示或隱藏。 當工具列隱藏時, 工具列 功能表項會清除。 當使用者選擇命令時,應用程式會檢查功能表項並顯示工具列。

複選標記屬性會控制是否選取功能表項。 您可以使用 CheckMenuItem 函式來設定功能表項的複選標記屬性 您可以使用 GetMenuState 函式來判斷選單項目前已選取或清除。

您可以使用 GetMenuItemInfo 和 SetMenuItemInfo 函式來擷取和設定功能表項的檢查狀態,而不是 CheckMenuItem GetMenuState。

有時候,一組功能表項會對應至一組互斥選項。 在此情況下,您可以使用選取的單選功能表項來指出選取的選項(類似於單選按鈕控制件)。 選取的單選項目會顯示項目符號位圖,而不是複選標記點陣圖。 若要檢查功能表項並將其設為單選專案,請使用 CheckMenuRadioItem 函式。

根據預設,系統會在選取的功能表項旁邊顯示複選標記或點符位圖,而且清除功能表項旁沒有點符陣圖。 不過,您可以使用 SetMenuItemBitmaps 函式,將應用程式定義的已選取和清除的點陣圖與功能表項產生關聯。 系統接著會使用指定的點陣圖來指出功能表項的選取或清除狀態。

與功能表項相關聯的應用程式定義點陣圖的大小必須與預設複選標記點陣圖相同,其尺寸可能會因螢幕解析度而有所不同。 若要擷取正確的維度,請使用 GetSystemMetrics 函式。 您可以為不同的螢幕解析度建立多個點陣圖資源;視需要建立一個位圖資源並加以縮放;或在運行時間建立位圖,並在其中繪製影像。 點陣圖可以是單色或色彩。 不過,由於功能表項會在反白顯示時反轉,因此某些反轉色彩點圖的外觀可能不受歡迎。 如需詳細資訊,請參閱 位圖

已啟用、灰色和停用功能表項

功能表項可以啟用、灰色或停用。 根據預設,會啟用功能表項。 當使用者選擇啟用的功能表項時,系統會根據功能表項的類型,將命令訊息傳送至擁有者視窗或顯示對應的子功能表。

當使用者無法使用功能表項時,應該會呈現灰色或停用。 無法選擇灰色和停用的功能表項。 停用的專案看起來就像已啟用的專案。 當使用者按兩下已停用的專案時,不會選取該專案,而且不會發生任何動作。 例如,停用的專案在提供看起來作用中但不是的功能表的教學課程中很有用。

應用程式會將無法使用的功能表項呈現灰色,向使用者提供無法使用命令的視覺提示。 當動作不適合時,您可以使用灰色專案(例如,當系統未安裝印表機時,您可以在 [檔案] 選單中顯示 [列印] 命令

EnableMenuItem 函式會啟用、灰色或停用功能表項。 若要判斷功能表項已啟用、灰色或停用,請使用 GetMenuItemInfo 函式。

除了 GetMenuItemInfo,您也可以使用 GetMenuState 函式來判斷功能表項是否已啟用、灰色或停用。

醒目提示的功能表項

當使用者選取功能表時,系統會自動醒目提示功能表上的功能表項。 不過,您可以使用HiliteMenuItem函式,從功能表欄上的功能表名稱明確新增或移除醒目提示。 此函式對功能表上的功能表項沒有任何作用。 不過,當HiliteMenuItem用來醒目提示功能表名稱時,只會選取名稱。 如果使用者按下 ENTER 鍵,則不會選擇醒目提示的專案。 例如,這項功能在示範功能表用法的定型應用程式中可能很有用。

擁有者繪製的功能表項

應用程式可以使用擁有者繪製的專案,完全控制功能表項的外觀。 擁有者繪製專案需要應用程式對選取的繪圖(醒目提示)、選取和已清除的狀態承擔全部責任。 例如,如果應用程式提供了字型功能表,就可以使用對應的字型來繪製每個功能表項;羅馬的專案會以羅馬繪製,斜體的專案會以斜體繪製,依序繪製。 如需詳細資訊,請參閱 建立擁有者繪製功能表項

系統會提供特殊的功能表項類型,稱為 分隔符,顯示為水平線。 您可以使用分隔符將功能表分成相關專案的群組。 分隔符不能用於功能表欄,而且使用者無法選取分隔符。

當功能表列包含的功能表名稱超過一行大小時,系統會自動將功能表欄分成兩行或多行來包裝功能表欄。 您可以將MFT_MENUBREAK類型旗標指派給專案,在功能表欄上的特定項目發生換行符。 系統會將該專案和所有後續專案放在新行上。

當功能表包含的項目超過一個數據行中容納的專案時,將會截斷功能表。 您可以將MFT_MENUBREAK類型旗標指派給專案,或使用 MENUITEM 語句中的 MENUBREAK 選項,在功能表中的特定項目發生數據行中斷。 系統會將該專案和所有後續專案放在新數據行中。 MFT_MENUBARBREAK類型旗標的效果相同,不同之處在於新數據行與舊數據行之間會出現垂直線。

如果您使用 AppendMenu、InsertMenu ModifyMenu 函式來指派換行符,則應該指派類型旗標MF_MENUBREAKMF_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訊息。