用于修改和显示菜单或菜单栏.
class Menu extends Object
菜单对象用于定义, 修改和显示弹出菜单. Menu(), MenuFromHandle 和 A_TrayMenu 返回此类对象.
class MenuBar extends Menu
MenuBar 对象用于定义和修改与 Gui.MenuBar 一起使用的菜单栏. 它们是使用 MenuBar() 创建的. 如果给定菜单栏句柄, 则 MenuFromHandle 返回此类型的对象.
下面使用 "MyMenu" 作为任何 Menu 对象的占位符, 因为 "Menu" 就是类本身.
除了从 Object 继承的方法和属性外, Menu 对象还具有以下预定义的方法和属性.
创建新的 Menu 或 MenuBar 对象.
MyMenu := Menu() MyMenuBar := MenuBar()
添加或修改菜单项.
MyMenu.Add(MenuItemName, Function-or-Submenu, Options)
类型: 字符串
要显示在菜单项上的文字, 或者要修改的现有项的位置&. 请参阅 MenuItemName.
类型: 函数对象或 Menu
当选择菜单项时, 函数对象作为新线程调用, 或对 Menu 对象的引用, 作为子菜单使用.
创建新项目时需要此参数, 但在更新现有项目的 Options 时, 此参数是可选的.
该函数应该接受以下参数:
FunctionName(ItemName, ItemPos, MyMenu)
类型: 字符串
如果没有省略, Options 必须是由下列一个或多个选项组成的以空格或制表符分隔的列表:
选项 | 描述 |
---|---|
Pn | 指定 n 为菜单项的线程优先级, 例如 P1 . 如果在添加菜单项时省略该选项, 优先级将为 0, 这是标准的默认值. 如果在更新菜单项时省略该选项, 则该项目的优先级将不会改变. 请使用十进制(不是十六进制) 数字作为优先级. |
+Radio | 如果该项目被选中, 则使用个空心圆代替复选标记. |
+Right | 该项目在菜单栏内右对齐. 这只适用于菜单栏, 不适用于弹出式菜单或子菜单. |
+Break | 该项在弹出式菜单中开始一个新的列. |
+BarBreak | 同上, 但在列之间有一条分界线. |
加号(+) 是可选的, 可以用减号(-) 代替来删除选项, 如 -Radio
. 选项不区分大小写.
要改变一个现有项目的选项而不影响它的回调或子菜单, 只需省略 Callback-or-Submenu 参数.
这是一个多用途的方法, 它可以添加一个菜单项, 用新的子菜单或回调更新一个菜单项, 或者将一个菜单项从普通项转换为子菜单(反之亦然). 如果 MenuItemName 还不存在, 它将被添加到菜单中. 否则, 将用新指定的 Callback-or-Submenu 和/或 Options 更新 MenuItemName.
要添加菜单分隔线, 请省略所有三个参数.
Add 总是在菜单底部添加新的菜单项, 但 Insert 可以用来在现有的自定义菜单项之前插入一个项目.
添加标准的托盘菜单项.
MyMenu.AddStandard()
此方法可以与托盘菜单或任何其他菜单一起使用.
标准项目被插入到任何现有项目之后. 任何已经在菜单中的标准项不会被重复, 但任何缺失的项目会被添加. 下表显示了在空菜单上调用 AddStandard 后标准项的名称和位置:
&Open | 1 | 0 |
&Help | 2 | |
3 | ||
&Window Spy | 4 | |
&Reload Script | 5 | |
&Edit Script | 6 | |
7 | ||
&Suspend Hotkeys | 8 | 1 |
&Pause Script | 9 | 2 |
E&xit | 10 | 3 |
编译后的脚本默认只包含最后三个. 只有在 A_AllowMainWindow 为 1 时, 调用 AddStandard 才会包含 &Open
(在这种情况下, 在第三列显示的位置上加 1). 如果托盘菜单中包含标准项目, 每当改变 A_AllowMainWindow 时, 就会插入或移除 &Open
. 对于其他菜单, 如果 A_AllowMainWindow 为 0, 则 &Open
没有效果.
每个标准项都有一个内部的菜单项 ID, 与它所执行的功能相对应, 但也可以像其他菜单项一样被修改或删除. AddStandard 通过 ID 而不是名称来检测现有的项目. 如果使用 Add 方法来改变与标准菜单项相关联的回调函数, 那么它将被分配一个新的唯一 ID, 并且不再被认为是一个标准项.
将 &Open
项添加到托盘菜单中会导致它成为默认项, 如果还没有的话.
在 MenuItemName 旁边添加一个可见的复选标记(如果还没有).
MyMenu.Check(MenuItemName)
类型: 字符串
菜单项的名称或位置. 请参阅 MenuItemName.
删除一个或所有自定义菜单项.
MyMenu.Delete(MenuItemName)
类型: 字符串
菜单项的名称或位置. 请参阅 MenuItemName.
如果省略 MenuItemName, 则所有项目都会从菜单中删除, 使菜单为空. 空菜单仍然存在, 因此, 任何使用它作为子菜单的其他菜单将保留这些子菜单.
要删除一个分隔线, 请通过它在菜单中的位置来识别它. 例如, 如果分隔符前面有两个项目, 则使用 MyMenu.Delete("3&")
.
如果删除了 default 菜单项, 其效果将类似于设置了 Menu.Default := ""
.
将 MenuItemName 更改为灰色, 表示用户无法选择它.
MyMenu.Disable(MenuItemName)
类型: 字符串
菜单项的名称或位置. 请参阅 MenuItemName.
允许用户再次选择 MenuItemName, 如果它之前被禁用(灰色).
MyMenu.Enable(MenuItemName)
类型: 字符串
菜单项的名称或位置. 请参阅 MenuItemName.
在指定的项之前插入一个新项.
Menu.Insert(ItemToInsertBefore, NewItemName, Callback-or-Submenu, Options)
类型: 字符串
现有项目的名称或位置&, 介于 1 和当前自定义项目数加 1 之间(遵循与 MenuItemName 相同的规则). 也可以通过省略 ItemToInsertBefore 来追加项目.
类型: 字符串
要在菜单项上显示的文字. 与 Add 方法不同, 它不能是一个位置.
除了 Insert 会创建一个新的项目, 即使 NewItemName 与现有项目的名称相匹配, 其余的参数与 Add 方法一样.
重命名 MenuItemName 为 NewName.
MyMenu.Rename(MenuItemName , NewName)
类型: 字符串
菜单项的名称或位置. 请参阅 MenuItemName.
类型: 字符串
新名称. 如果为空或省略, MenuItemName 将被转换为分隔线.
菜单项的当前回调或子菜单不变.
通过指定分隔线的位置, 如 "1&"
for MenuItemName 和一个非空白名称 for NewName, 然后使用 Add 方法给项目一个回调或子菜单, 可以将分隔线转换为一个普通项目.
改变菜单的背景颜色为 ColorValue.
MyMenu.SetColor(ColorValue, ApplyToSubmenus)
设置显示在 MenuItemName 旁边的图标.
MyMenu.SetIcon(MenuItemName, FileName , IconNumber, IconWidth)
类型: 字符串
菜单项的名称或位置. 请参阅 MenuItemName.
类型: 字符串
图标或图像文件的路径. 关于支持的格式列表, 请参阅 Picture 控件.
位图或图标句柄可用来代替文件名. 例如, "HICON:" handle
.
省略 FileName 或指定一个空字符串或 "*"
来删除项目的当前图标.
类型: 整数
要使用文件中第一个图标以外的图标组, 请指定其编号为 IconNumber(如果省略, 则默认为 1). 如果 IconNumber 为负数, 它的绝对值被认为是一个可执行文件中图标的资源 ID.
类型: 整数
图标的宽度. 如果 IconNumber 表示的图标组包含多个图标尺寸, 则使用最接近的尺寸, 并将图标缩放到指定的尺寸. 请参阅示例部分了解使用方法.
目前, 在设置图标时必须指定 "实际大小" 以保持透明度, 例如 MyMenu.SetIcon "My menu item", "Filename.png",, 0
.
位图或图标句柄可用来代替文件名. 例如, "HBITMAP:" handle
.
显示菜单, 允许用户使用箭头按键, 菜单快捷键(下划线字母), 或鼠标来选择一个项目.
MyMenu.Show(X, Y)
类型: 整数
显示菜单的坐标. 如果 X 和 Y 都省略, 则菜单显示在鼠标光标的当前位置. 如果只省略其中一个, 则用鼠标光标的位置代替省略的这个. X 和 Y 默认是相对于活动窗口的客户端区域. 要覆盖这个默认值, 请使用 CoordMode "Menu", Mode
或 A_CoordModeMenu := Mode
.
任何弹出式菜单都可以被显示, 包括子菜单和托盘菜单. 但是, 如果 Menu 是 MenuBar 对象, 则抛出异常.
如果没有复选标记, 则添加; 否则, 就移除.
MyMenu.ToggleCheck(MenuItemName)
类型: 字符串
菜单项的名称或位置. 请参阅 MenuItemName.
如果之前已经启用, 则禁用 MenuItemName; 否则启用.
MyMenu.ToggleEnable(MenuItemName)
类型: 字符串
菜单项的名称或位置. 请参阅 MenuItemName.
移除菜单项上的复选标记(如果有的话).
Menu.Uncheck(MenuItemName)
类型: 字符串
菜单项的名称或位置. 请参阅 MenuItemName.
检索或设置必须点击多少次托盘图标才能选择其默认菜单项.
MyMenu.ClickCount := Count
类型: 整数
指定 1, 允许单次点击选择托盘菜单的默认菜单项. 指定 2 可返回默认行为(双击).
例如: A_TrayMenu.ClickCount := 1
检索或设置默认菜单项.
CurrentDefault := MyMenu.Default
类型: 字符串
默认菜单项的名称, 如果没有默认项, 则为空字符串.
MyMenu.Default := MenuItemName
类型: 字符串
菜单项的名称或位置. 请参阅 MenuItemName.
如果 MenuItemName 是一个空字符串, 则没有默认项.
设置默认项会使该项的字体变粗(在托盘菜单以外的其他菜单中设置默认项目前没有效果). 当用户双击托盘图标时, 其默认的菜单项就会被启动(即使该项目被禁用). 如果没有默认项, 双击没有效果.
托盘菜单的默认项目最初是 &Open
, 如果存在的话. 通过调用 AddStandard 将 &Open
添加到托盘菜单中或改变 A_AllowMainWindow 如果没有默认项, 也会使其成为默认项.
如果删除了默认项, 则菜单中没有默认项.
返回一个 Win32 menu 的句柄(HMENU
类型的句柄), 必要时构造它.
MyMenu.Handle
返回的句柄只在 Win32 菜单被销毁之前有效, 这通常发生在菜单对象被释放时. 一旦菜单被销毁, 操作系统可以将句柄值重新分配给脚本或任何其他程序随后创建的任何菜单.
菜单项的名称或位置. 一些通用规则适用于所有使用该参数的方法:
要为菜单项名称的某个字母加下划线, 在这个字母前加一个 & 符号. 当菜单显示出来时, 此项可以通过按键盘上对应的按键来选中. 要显示原义的 & 符号, 指定连续的两个 & 号, 如此例所示: "Save && Exit"
当引用到一个已存在的菜单或菜单项时, 其名称不区分大小写但 & 号不能少. 例如: "&Open"
菜单项的名称最多可以有 260 个字符.
要通过菜单中的位置来识别一个现有的项目, 请在项目的位置后写上一个 &. 例如, "1&"
表示第一个项目.
Windows 提供了一组函数和通知, 用于创建, 修改和显示具有标准外观和行为的菜单. 我们把由这些函数之一创建的菜单称为 Win32 menu.
当项目被添加到菜单中或修改时, 每个项目的名称和其他属性都存储在 Menu 对象. 当菜单或它的父菜单第一次连接到 GUI 或显示时, 就会构造一个 Win32 menu. 当菜单对象被删除时, 它就会被自动销毁(当它的引用计数达到零时就会发生).
Menu.Handle 返回一个 Win32 menu 的句柄(HMENU
类型的句柄), 必要时构造它.
任何由 Win32 函数直接对菜单进行的修改都不会反映在脚本的 Menu 对象中, 所以如果一个项目被内置方法修改, 可能会丢失.
当每个菜单项第一次被添加到菜单中时, 它被分配了一个 ID. 脚本不能依赖一个项目收到一个特定的 ID, 但是可以通过使用 GetMenuItemID 来检索一个项目的 ID, 如示例 #5 所示. 这个 ID 不能用于 Menu 对象, 但可以用于各种 Win32 函数.
菜单通常看起来像这样:
如果一个菜单完全变空 -- 比如使用 MyMenu.Delete()
-- 它就不能被显示. 如果托盘菜单变成空的, 右击和双击托盘图标将没有任何效果(在这种情况下, 通常最好使用 #NoTrayIcon).
如果一个菜单项的回调已经在运行, 而用户再次选择同一个菜单项, 则会创建一个新的线程来运行同样的回调, 从而中断之前的线程. 如果要把这些事件缓冲到以后, 可以使用 Critical 作为回调的第一行(然而, 这也会缓冲/延迟其他线程, 比如按下热键).
每当通过菜单项调用一个函数时, 它都会以默认值(如 SendMode) 重新开始. 这些默认值可以在脚本启动时更改.
当建立一个内容不总是相同的菜单时, 一种方法是将所有这样的菜单项指向同一个函数, 并让该函数参考它的参数来决定采取什么行动. 另外, 可以使用函数对象, 闭包或胖箭头函数将一个或多个值或变量绑定到菜单项的回调函数上.
GUI, 线程, Thread, Critical, #NoTrayIcon, 函数, Return, SetTimer
添加一个新菜单项到托盘图标菜单的底部.
A_TrayMenu.Add() ; 创建分隔线. A_TrayMenu.Add("Item1", MenuHandler) ; 创建新菜单项. Persistent MenuHandler(ItemName, ItemPos, MyMenu) { MsgBox "You selected " ItemName " (position " ItemPos ")" }
; 添加一些菜单项来创建弹出菜单. MyMenu := Menu() MyMenu.Add "Item 1", MenuHandler MyMenu.Add "Item 2", MenuHandler MyMenu.Add ; 添加分隔线. ; 添加子菜单到上面的菜单中. Submenu1 := Menu() Submenu1.Add "Item A", MenuHandler Submenu1.Add "Item B", MenuHandler ; 创建第一个菜单的子菜单(右箭头指示符). 当用户选择它时会显示第二个菜单. MyMenu.Add "My Submenu", Submenu1 MyMenu.Add ; 在子菜单下添加分隔线. MyMenu.Add "Item 3", MenuHandler ; 在子菜单下添加另一个菜单项. MenuHandler(Item, *) { MsgBox "You selected " Item } #z::MyMenu.Show ; 即按下 Win-Z 热键来显示菜单.
#SingleInstance Persistent tray := A_TrayMenu ; 为了方便. tray.delete ; 删除标准项目. tray.add ; 分隔线 tray.add "TestToggleCheck", TestToggleCheck tray.add "TestToggleEnable", TestToggleEnable tray.add "TestDefault", TestDefault tray.add "TestAddStandard", TestAddStandard tray.add "TestDelete", TestDelete tray.add "TestDeleteAll", TestDeleteAll tray.add "TestRename", TestRename tray.add "Test", Test ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; TestToggleCheck(*) { tray.ToggleCheck TestToggleCheck tray.Enable "TestToggleEnable" ; 由于自己无法撤销禁用, 所以还能进行下一次测试. tray.add "TestDelete", TestDelete ; 类似于上面. } TestToggleEnable(*) { tray.ToggleEnable "TestToggleEnable" } TestDefault(*) { if tray.default = "TestDefault" tray.default := "" else tray.default := "TestDefault" } TestAddStandard(*) { tray.addStandard } TestDelete(*) { tray.delete "TestDelete" } TestDeleteAll(*) { tray.delete } TestRename(*) { static OldName := "", NewName := "" if NewName != "renamed" { OldName := "TestRename" NewName := "renamed" } else { OldName := "renamed" NewName := "TestRename" } tray.rename OldName, NewName } Test(Item, *) { MsgBox 'You selected "' Item '"' }
FileMenu := Menu() FileMenu.Add("Script Icon", MenuHandler) FileMenu.Add("Suspend Icon", MenuHandler) FileMenu.Add("Pause Icon", MenuHandler) FileMenu.SetIcon("Script Icon", A_AhkPath, 2) ; 使用文件中的第二个图标组 FileMenu.SetIcon("Suspend Icon", A_AhkPath, -206) ; 使用资源标识符 206 表示的图标 FileMenu.SetIcon("Pause Icon", A_AhkPath, -207) ; 使用资源标识符 207 表示的图标 MyMenuBar := MenuBar() MyMenuBar.Add("&File", FileMenu) MyGui := Gui() MyGui.MenuBar := MyMenuBar MyGui.Add("Button",, "Exit This Example").OnEvent("Click", (*) => WinClose()) MyGui.Show MenuHandler(*) { ; 在这个例子中, 菜单项没有任何作用. }
MyMenu := Menu() MyMenu.Add "Item 1", NoAction MyMenu.Add "Item 2", NoAction MyMenu.Add "Item B", NoAction ; 检索菜单中的项目数. item_count := DllCall("GetMenuItemCount", "ptr", MyMenu.Handle) ; 检索最后一个项目的 ID. 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 NoAction(*) { ; 什么都不做. }