Menu Object

From Auto Hotkey

Menu Object

Used to modify and display menus. MenuCreate, MenuFromHandle and A_TrayMenu return an object of this type.

Properties:

  • ClickCount: Retrieves or sets the number of clicks required to activate the tray menu's default item.
  • Default: Retrieves or sets the default menu item.
  • Handle: Retrieves the menu's Win32 handle.
  • Standard: Adds or removes the standard menu items.

Methods:

  • Add: Adds or modifies a menu item.
  • Check: Adds a visible checkmark next to a menu item.
  • Delete: Deletes a menu item or all menu items.
  • Disable: Changes a menu item to a gray color to indicate that the user cannot select it.
  • Enable: Allows the user to once again select a menu item if was previously disabled (grayed).
  • Insert: Inserts a new item before the specified item.
  • Rename: Renames a menu item.
  • SetColor: Changes the background color of the menu.
  • SetIcon: Sets the icon to be displayed next to a menu item.
  • Show: Displays the menu.
  • ToggleCheck: Toggles the checkmark next to a menu item.
  • ToggleEnable: Enables or disables a menu item.
  • Uncheck: Removes the checkmark (if there is one) from a menu item.

General:

Add

Adds or modifies a menu item.

Menu.Add(MenuItemName, Label-or-Submenu, Options)
MenuItemName

The text to display on the menu item, or the position& of an existing item to modify. See MenuItemName.

Label-or-Submenu

A label or function name (or a reference to a function object) to run as a new thread when the menu item is selected, or a reference to a Menu object to use as a submenu.

If Label-or-Submenu is omitted, MenuItemName will be used as both the label or function name and the menu item name.

If a function is specified, it can optionally define parameters as shown below:

FunctionName(ItemName, ItemPos, Menu)
Options

If not omitted, Options must be a space- or tab-delimited list of one or more of the following options:

Pn Replace n with the menu item's thread priority, e.g. P1. If this option is omitted when adding a menu item, the priority will be 0, which is the standard default. If omitted when updating a menu item, the item's priority will not be changed. Use a decimal (not hexadecimal) number as the priority.
+Radio If the item is checked, a bullet point is used instead of a check mark.
+Right The item is right-justified within the menu bar. This only applies to menu bars, not popup menus or submenus.
+Break The item begins a new column in a popup menu.
+BarBreak As above, but with a dividing line between columns.

The plus sign (+) is optional and can be replaced with minus (-) to remove the option, as in -Radio. Options are not case sensitive.

To change an existing item's options without affecting its label or submenu, simply omit the Label-or-Submenu parameter.

Remarks

This is a multipurpose method that adds a menu item, updates one with a new submenu, label or function, or converts one from a normal item into a submenu (or vice versa). If MenuItemName does not yet exist, it will be added to the menu. Otherwise, MenuItemName is updated with the newly specified Label-or-Submenu and/or Options.

To add a menu separator line, omit all three parameters.

Add always adds new menu items at the bottom of the menu, but Insert can be used to insert an item before an existing custom menu item.

Check

Adds a visible checkmark in the menu next to MenuItemName (if there isn't one already).

Menu.Check(MenuItemName)
MenuItemName

The name or position of a menu item. See MenuItemName.

ClickCount

Retrieves or sets the number of clicks required to activate the tray menu's default item.

Menu.ClickCount := Count
Count

Specify 1 to allow a single-click to activate the tray menu's default menu item. Specify 2 to return to the default behavior (double-click).

For example: A_TrayMenu.ClickCount := 1

Delete

Deletes a menu item or all custom menu items.

Menu.Delete(MenuItemName)
MenuItemName

The name or position of a menu item. See MenuItemName.

If MenuItemName is omitted, all custom menu items are deleted from the menu, leaving the menu empty unless it contains the standard items. An empty menu still exists and thus any other menus that use it as a submenu will retain those submenus. However, the current Win32 menus of this menu and its parent and submenus are destroyed, to be recreated later as needed.

To delete a separator line, identify it by its position in the menu. For example, use MyMenu.Delete("3&") if there are two items preceding the separator.

Standard menu items such as Exit cannot be individually deleted.

If the default menu item is deleted, the effect will be similar to having set Menu.Default := "".

Default

Retrieves or sets the default menu item.

CurrentDefault := Menu.Default
CurrentDefault

The name of the default menu item, or an empty string if there is no default (or if the default item is one of the standard items).

Menu.Default := MenuItemName
MenuItemName

The name or position of a menu item. See MenuItemName.

To restore the menu to standard behavior, assign an empty string. For the tray menu: This restores the menu back to having its standard default menu item, which is OPEN for non-compiled scripts and none for compiled scripts (except when the MainWindow option is in effect). If the OPEN menu item does not exist due to a previous use of Menu.Standard := false, there will be no default and thus double-clicking the tray icon will have no effect. For other menus: Any existing default item is returned to a non-bold font.

Setting the default item makes that item's font bold (setting a default item in menus other than the tray menu is currently purely cosmetic). When the user double-clicks the tray icon, its default menu item is launched. If there is no default, double-clicking has no effect.

Disable

Changes MenuItemName to a gray color to indicate that the user cannot select it.

Menu.Disable(MenuItemName)
MenuItemName

The name or position of a menu item. See MenuItemName.

Enable

Allows the user to once again select MenuItemName if it was previously disabled (grayed).

Menu.Enable(MenuItemName)
MenuItemName

The name or position of a menu item. See MenuItemName.

Insert

Inserts a new item before the specified item.

Menu.Insert(ItemToInsertBefore, NewItemName, Label-or-Submenu, Options)
ItemToInsertBefore

The name of an existing item or a position& between 1 and the current number of custom items plus 1 (following the same rules as MenuItemName). Items can also be appended by omitting ItemToInsertBefore.

NewItemName

The text to display on the menu item. Unlike Add, this cannot be a position.

The remaining parameters behave as per the Add method, except that Insert creates a new item even if NewItemName matches the name of an existing item.

As Standard menu items are not counted ("1&" always refers to the first custom item), an item cannot be inserted immediately before the standard items.

Rename

Renames MenuItemName to NewName.

Menu.Rename(MenuItemName , NewName)
MenuItemName

The name or position of a menu item. See MenuItemName.

NewName

The new name. If empty or omitted, MenuItemName will be converted into a separator line.

The menu item's current target label or submenu is unchanged.

A separator line can be converted to a normal item by specifying the position& of the separator and a non-blank NewName, and then using the Add method to give the item a label or submenu.

SetColor

Changes the background color of the menu to ColorValue.

Menu.SetColor(ColorValue, Submenus := true)
ColorValue

One of the 16 primary HTML color names, a hexadecimal RGB color string (the 0x prefix is optional), or a pure numeric RGB color value. Omit ColorValue (or specify an empty string or the word "Default") to restore the menu to its default color. Example values: "Silver", "FFFFAA", 0xFFFFAA, "Default".

Submenus

True if the color should be applied to all of this menu's submenus, otherwise false. Defaults to true.

SetIcon

Sets the icon to be displayed next to MenuItemName.

Menu.SetIcon(MenuItemName, FileName , IconNumber, IconWidth)
MenuItemName

The name or position of a menu item. See MenuItemName.

FileName

The path of an icon or image file. For a list of supported formats, see the Picture control.

A bitmap or icon handle can be used instead of a filename. For example, "HICON:" handle.

Omit FileName or specify an empty string or "*" to remove the item's current icon.

IconNumber

To use an icon group other than the first one in the file, specify its number for IconNumber (if omitted, it defaults to 1). If IconNumber is negative, its absolute value is assumed to be the resource ID of an icon within an executable file.

IconWidth

The desired width of the icon. If the icon group indicated by IconNumber contains multiple icon sizes, the closest match is used and the icon is scaled to the specified size. See the Examples section for usage examples.

Currently it is necessary to specify "actual size" when setting the icon to preserve transparency on Windows Vista and later. For example:

MyMenu.SetIcon "My menu item", "Filename.png",, 0

Known limitation: Icons on Gui menu bars are positioned incorrectly on Windows XP and older.

A bitmap or icon handle can be used instead of a filename. For example, "HBITMAP:" handle.

Show

Displays the menu, allowing the user to select an item with arrow keys, menu shortcuts (underlined letters), or the mouse.

Menu.Show(X, Y)
X, Y

The coordinates at which to display the menu. If both X and Y are omitted, the menu is displayed at the current position of the mouse cursor. If only one of them is omitted, the mouse cursor's position will be used for it. X and Y are relative to the active window's client area by default. To override this default, use CoordMode, "Menu", Mode or A_CoordModeMenu := Mode.

Any menu can be shown, including the tray menu but with the exception of GUI menu bars.

ToggleCheck

Adds a checkmark if there wasn't one; otherwise, removes it.

Menu.ToggleCheck(MenuItemName)
MenuItemName

The name or position of a menu item. See MenuItemName.

ToggleEnable

Disables MenuItemName if it was previously enabled; otherwise, enables it.

Menu.ToggleEnable(MenuItemName)
MenuItemName

The name or position of a menu item. See MenuItemName.

Uncheck

Removes the checkmark (if there is one) from a menu item.

Menu.Uncheck(MenuItemName)
MenuItemName

The name or position of a menu item. See MenuItemName.

Standard

Adds or removes the standard menu items.

Menu.Standard := IncludeStandardItems

Standard returns a boolean value (0 or 1) indicating whether the standard items are present in the menu. When its value is changed, the standard items are either removed from the menu or inserted at the bottom of the menu.

This property can be used with the tray menu or any other menu.

To put your menu items on top of the standard menu items, after adding your own menu items, set A_TrayMenu.Standard := false (if the standard items were already present) followed by A_TrayMenu.Standard := true.

The standard menu items such as "Pause Script" and "Suspend Hotkeys" cannot be individually operated upon by any Menu method, and are not counted for the purpose of addressing items by position&.

Handle

Returns a handle to a Win32 menu (a handle of type HMENU), constructing it if necessary.

Menu.Handle

The returned handle is valid only until the Win32 menu is destroyed. Once the menu is destroyed, the operating system may reassign the handle value to any menus subsequently created by the script or any other program. Conditions which can cause the menu to be destroyed are listed under Win32 Menus.

The name or position of a menu item. Some common rules apply to this parameter across all sub-commands which use it:

To underline one of the letters in a menu item's name, precede that letter with an ampersand (&). When the menu is displayed, such an item can be selected by pressing the corresponding key on the keyboard. To display a literal ampersand, specify two consecutive ampersands as in this example: "Save && Exit"

When referring to an existing menu or menu item, the name is not case sensitive but any ampersands must be included. For example: "&Open"

The names of menu items can be up to 260 characters long.

To identify an existing item by its position in the menu, write the item's position followed by an ampersand. For example, "1&" indicates the first item. Standard menu items are not counted. If the menu contains only standard items, "1&" refers to the next position below the standard items.

Win32 Menus

Windows provides a set of functions and notifications for creating, modifying and displaying menus with standard appearance and behavior. We refer to a menu created by one of these functions as a Win32 menu.

As items are added to a menu or modified, the name and other properties of each item are stored in the Menu object. A Win32 menu is constructed when the menu or its parent menu is attached to a GUI or shown, either for the first time or if the menu has been "destroyed" since it was last shown. Any of the following can cause this Win32 menu to be destroyed, along with any parent menus and submenus:

  • Deleting a menu.
  • Replacing an item's submenu with a label or a different menu.
  • Calling Menu.Delete() with no parameters.
  • Setting Menu.Standard := false (if the standard items were present).

Menu.Handle returns a handle to a Win32 menu (a handle of type HMENU), constructing it if necessary.

Any modifications which are made to the menu directly by Win32 functions are not reflected by the script's Menu object, so are lost when the Win32 menu is destroyed.

Each menu item is assigned an ID when it is first added to the menu. Scripts cannot rely on an item receiving a particular ID, but can retrieve the ID of an item by using GetMenuItemID as shown in the example below. This ID cannot be used with the Menu object, but can be used with various Win32 functions.

Remarks

If a menu ever becomes completely empty -- such as by using MyMenu.Delete() -- it cannot be shown. If the tray menu becomes empty, right-clicking and double-clicking the tray icon will have no effect (in such cases it is usually better to use #NoTrayIcon).

If a menu item's subroutine is already running and the user selects the same menu item again, a new thread will be created to run that same subroutine, interrupting the previous thread. To instead buffer such events until later, use Critical as the subroutine's first line (however, this will also buffer/defer other threads such as the press of a hotkey).

Whenever a subroutine is launched via a menu item, it starts off fresh with the default values for settings such as SendMode. These defaults can be changed in the auto-execute section.

When building a menu whose contents are not always the same, it is usually best to point all such menu items to the same function and have that function refer to its parameters to determine what action to take.

GUI, Threads, Thread, Critical, #NoTrayIcon, Gosub, Functions, Return, SetTimer

Examples

; EXAMPLE #1: This is a working script that adds a new menu item to the bottom of the tray icon menu.

A_TrayMenu.Add()  ; Creates a separator line.
A_TrayMenu.Add("Item1", "MenuHandler")  ; Creates a new menu item.
return

MenuHandler(ItemName, ItemPos, Menu) {
    MsgBox "You selected " ItemName " (position " ItemPos ")"
}
; EXAMPLE #2: This is a working script that creates a popup menu that is displayed when the user presses the Win-Z hotkey.

; Create the popup menu by adding some items to it.
MyMenu := MenuCreate()
MyMenu.Add "Item 1", "MenuHandler"
MyMenu.Add "Item 2", "MenuHandler"
MyMenu.Add  ; Add a separator line.

; Create another menu destined to become a submenu of the above menu.
Submenu1 := MenuCreate()
Submenu1.Add "Item A", "MenuHandler"
Submenu1.Add "Item B", "MenuHandler"

; Create a submenu in the first menu (a right-arrow indicator). When the user selects it, the second menu is displayed.
MyMenu.Add "My Submenu", Submenu1

MyMenu.Add  ; Add a separator line below the submenu.
MyMenu.Add "Item 3", "MenuHandler"  ; Add another menu item beneath the submenu.
return  ; End of script's auto-execute section.

MenuHandler(Item) {
    MsgBox "You selected " Item
}

#z::MyMenu.Show  ; i.e. press the Win-Z hotkey to show the menu.
; EXAMPLE #3: This is a working script that demonstrates some of the various menu object members.

#SingleInstance
tray := A_TrayMenu ; For convenience.
tray.add ; separator
tray.add "TestToggle&Check"
tray.add "TestToggleEnable"
tray.add "TestDefault"
tray.add "TestStandard"
tray.add "TestDelete"
tray.add "TestDeleteAll"
tray.add "TestRename"
tray.add "Test"
return

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

TestToggle&Check:
tray.ToggleCheck "TestToggle&Check"
tray.Enable "TestToggleEnable" ; Also enables the next test since it can't undo the disabling of itself.
tray.add "TestDelete" ; Similar to above.
return

TestToggleEnable:
tray.ToggleEnable "TestToggleEnable"
return

TestDefault:
if tray.default = "TestDefault"
    tray.default := ""
else
    tray.default := "TestDefault"
return

TestStandard:
tray.Standard := !tray.Standard
return

TestDelete:
tray.delete "TestDelete"
return

TestDeleteAll:
tray.delete
MsgBox "The script may exit now, as the tray menu no longer contains custom items."
return

TestRename:
if NewName <> "renamed"
{
    OldName := "TestRename"
    NewName := "renamed"
}
else
{
    OldName := "renamed"
    NewName := "TestRename"
}
tray.rename OldName, NewName
return

Test(Item) {
    MsgBox 'You selected "' Item '"'
}
; EXAMPLE #4: This is a working script that adds icons to its menu items.

FileMenu := MenuCreate()
FileMenu.Add("Script Icon", "MenuHandler")
FileMenu.Add("Suspend Icon", "MenuHandler")
FileMenu.Add("Pause Icon", "MenuHandler")
FileMenu.SetIcon("Script Icon", A_AhkPath, 2) ; 2nd icon group from the file
FileMenu.SetIcon("Suspend Icon", A_AhkPath, -206) ; icon with resource ID 206
FileMenu.SetIcon("Pause Icon", A_AhkPath, -207) ; icon with resource ID 207
MyMenuBar := MenuCreate()
MyMenuBar.Add("&File", FileMenu)
Gui := GuiCreate()
Gui.Menu := MyMenuBar
Gui.Add("Button",, "Exit This Example").OnEvent("Click", "Exit_Click")
Gui.Show

MenuHandler() {
    ; For this example, the menu items don't do anything.
}

Exit_Click() {
    WinClose
}
; EXAMPLE #5: Retrieving item count and ID.

MyMenu := MenuCreate()
MyMenu.Add "Item 1", "no"
MyMenu.Add "Item 2", "no"
MyMenu.Add "Item B", "no"

; Retrieve the number of items in a menu.
item_count := DllCall("GetMenuItemCount", "ptr", MyMenu.Handle)

; Retrieve the ID of the last item.
last_id := DllCall("GetMenuItemID", "ptr", MyMenu.Handle, "int", item_count-1)

MsgBox "MyMenu has " item_count " items, and its last item has ID " last_id

no:
return