# GUI 控件类型

## 目录

- Text, Edit, UpDown, Picture
- Button, Checkbox, Radio
- DropDownList, ComboBox
- ListBox, ListView, TreeView
- Link, Hotkey, DateTime
- MonthCal, Slider, Progress
- GroupBox, Tab3, StatusBar
- ActiveX(例如 Internet Explorer 控件)
- Custom(自定义)

## Text

描述: 包含用户不能编辑的无边界文本的区域. 常用来标识其他控件.

例如:

    MyGui.Add("Text",, "Please enter your name:")

或者:

    MyGui.AddText(, "Please enter your name:")

外观:

此时最后一个参数为要显示的字符串. 它可以包含换行符(`n) 来开始新行. 此外, 一个长行可以使用延续片段的方法分成较短的几行.

如果 Options 中指定了宽度(W) 而没有指定行数(R) 或高度(H), 那么在需要时控件的文本将自动换行, 同时自动设置控件的高度.

若要检测用户单击文本, 请使用 Click(单击) 事件. 例如:

    MyGui := Gui()
    FakeLink := MyGui.Add("Text", "", "Click here to launch Google.")
    FakeLink.SetFont("underline cBlue")
    FakeLink.OnEvent("Click", LaunchGoogle)

    ; 或者可以使用 Link 控件:
    MyGui.Add("Link",, 'Click <a href="www.google.com">here</a> to launch Google.')
    MyGui.Show()

    LaunchGoogle(*) {
        Run("www.google.com")
    }

Text(文本) 控件也支持 DoubleClick(双击) 事件.

只有带有 SS_NOTIFY(0x100) 样式的文本控件才能发送单击和双击通知, 因此 OnEvent 在注册单击或双击回调时自动添加这种样式. SS_NOTIFY 样式会导致操作系统在双击控件时自动将其文本复制到剪贴板.

在文本中使用和符号(&) 可以让其中的某个字母带下划线. 例如:

    MyGui.Add("Text",, "&First Name:")
    MyGui.Add("Edit")

在上述示例中, 字母 F 将添加下划线, 这允许用户按下快捷键 `Alt`+`F` 将键盘焦点设置到此文本控件之后添加的首个可输入型控件中. 要显示一个文字的和符号(&), 请指定两个连续的和符号(&&). 要取消控件中和符号的特殊含义, 请在控件的选项中包含 0x80.

有关其他选项, 如 Right, Center 和 Hidden, 请参阅常规选项. 另请参阅: 控件的位置和大小.

## Edit

描述: 用户可以在其中键入自由格式文本的区域.

例如:

    MyGui.Add("Edit", "r9 vMyEdit w135", "Text to appear inside the edit control (omit this parameter to start off empty).")

或者:

    MyGui.AddEdit("r9 vMyEdit w135", "Text to appear inside the edit control (omit this parameter to start off empty).")

外观:

如果控件具有多行文本, 则它将是多行的. 例如, 在 Options 中指定 `r3` 将创建一个 3 行的编辑(Edit) 控件, 并拥有后面这些默认属性: 垂直滚动条, 启用自动换行, 并且 `Enter` 作为输入的一部分, 而不触发窗口的默认按钮.

要在多行编辑控件中开始新行, 请在最后一个参数中(内容) 包含单独的换行符(`n) 或回车换行符(`r`n). 这两种方法都会在编辑控件中产生原义的 `r`n 对. 然而, 当通过 MyGui.Submit 或 GuiCtrl.Value 来检索控件的内容时, 文本中的每对 `r`n 总是被转换成单独的换行符(`n). 要绕过这个行尾转换, 请使用 GuiCtrl.Text. 要把文本写入到文件中, 请参照此例: `FileAppend(MyEdit.Text, "C:\Saved File.txt")`.

如果控件启用了自动换行(对于多行编辑控件默认是启用的), 那么用户输入时任何自动换行的地方不会产生换行字符(仅 `Enter` 才会).

当用户或脚本改变控件的内容时, 触发 Change 事件.

提示: 要加载一个文本文件的内容到编辑控件中, 请使用 FileRead 和 GuiCtrl.Value. 例如:

    MyEdit := MyGui.Add("Edit", "R20")
    MyEdit.Value := FileRead("C:\My File.txt")

### Edit 选项

要移除而非添加选项, 请在选项前加上负号:

Limit: 限制用户的输入在编辑区域的可见宽度内. 另外, 要限制输入指定数目的字符, 请在该选项后跟着数字. 例如, `Limit10` 将允许输入不超过 10 个字符.

Lowercase: 把用户输入的字符自动转换成小写形式.

Multi: 让控件可以含有多行文本. 然而, 通常没必要指定此选项, 因为它会根据高度(H), 行数(R) 或内容(Text) 自动判断.

Number: 阻止用户输入数字以外的其他字符到编辑区域(然而, 还是可能粘贴非数字字符到里面). 强制输入数字的另一种方法是添加 UpDown 控件到编辑控件中.

Password: 通过将用户输入替换为掩码字符来隐藏用户输入(例如密码输入). 如果想使用非默认的掩码字符, 请在单词 Password 后加上此符号. 例如, `Password*` 将使用星号而不是黑色圆(项目符号) 作为掩码符号. 注意: 此选项对于多行编辑控件没有效果.

ReadOnly: 阻止用户改变控件的内容. 不过, 仍然可以滚动, 选择文本或将文本复制到剪贴板.

T n: 字母 T 可以用来设置多行编辑控件的制表位(因为制表位决定了原义的 TAB 字符跳转的列位置, 所以它们可以把文本格式成列). 如果没有使用字母 T, 则每 32 个对话框单位设置一次制表位(每个 "对话框单位" 由操作系统决定). 如果仅使用一次字母 T, 则每 n 个单位设置一次横跨整个控件宽度的制表位. 例如, `MyGui.Add("Edit", "vMyEdit r16 t64")` 将设置制表位之间的距离为默认的两倍. 要自定义制表位, 请指定字母 T 多次, 如下例所示: `MyGui.Add("Edit", "vMyEdit r16 t8 t16 t32 t64 t128")`. 在列表中每个绝对的列位置设置一个制表位, 制表位数目最大可达 50 个. 注意: 制表位仅用于多行编辑控件.

Uppercase: 将用户输入的字符自动转换成大写形式.

WantCtrlA: 指定 `-WantCtrlA`(负 WantCtrlA) 来阻止用户按下 `Ctrl`+`A` 来选择编辑控件中所有文本.

WantReturn: 指定 `-WantReturn`(负 WantReturn) 来阻止多行编辑控件捕获 `Enter`. 按下 `Enter` 相当于点击了窗口的默认按钮(如果有). 在这种情况下, 用户可以使用 `Ctrl`+`Enter` 来开始新行.

WantTab: 使得 `Tab` 键击产生制表符而不是导航到下一个控件. 如果没有这个选项, 则在多行编辑控件中用户可以按下 `Ctrl`+`Tab` 来产生制表符. 注意: WantTab 也可以用于单行编辑控件.

Wrap: 指定 `-Wrap`(负 Wrap) 来关闭多行编辑控件中的自动换行属性. 由于在控件创建后不能改变此样式, 所以需要使用下列方法中的一个来改变它:: 1) Destroy 后重新创建窗口和其中的控件; 或 2) 创建两个重叠的编辑控件, 其中一个启用自动换行而另一个禁用. 当前没有使用的那个可以保持空的和/或隐藏.

请参阅常规选项来了解其他选项, 例如 Right, Center 和 Hidden. 另请参阅: 控件的位置和大小.

更强大的编辑控件: HiEdit 是免费, 多选项卡, 支持大文件且消耗很少内存的编辑控件. 它可以编辑文本和二进制文件. 有关详情和演示, 请参阅 HiEdit on GitHub.

## UpDown

描述: 一对箭头组成的按钮, 用户点击后会增加或减少值. 默认情况下, UpDown 控件自动依附于前一个添加的控件上. 这里的前一个控件被称为 UpDown 的 伙伴控件. 最常见的例子是 "微调器", 由 UpDown 附加到 Edit 控件.

例如:

    MyGui.Add("Edit")
    MyGui.Add("UpDown", "vMyUpDown Range1-10", 5)

或者:

    MyGui.AddUpDown("vMyUpDown Range1-10", 5)

外观:

在上面的例子中, Edit 控件是 UpDown 的伙伴控件. 每当用户按下了增减按钮的其中一个, Edit 控件中的数字会自动增加或减少.

UpDown 的伙伴控件也可以是 Text 控件或 ListBox. 然而, 由于操作系统的限制, 除了这些以外的其他控件类型(例如 ComboBox 和 DropDownList) 可能无法和 Change 事件以及其他特性一起正常工作.

在最后一个参数中指定 UpDown 的初始位置(如果省略, 则初始为 0 或允许的范围中最接近 0 的数字).

当使用 MyGui.Submit 或 GuiCtrl.Value 时, 返回值是 UpDown 的当前数字位置. 如果 UpDown 与 Edit 控件相连, 而您又不想验证用户的输入, 那么最好使用 UpDown 的值而不是 Edit 的值. 这是因为 UpDown 总是会产生一个范围内的数字, 即使用户在编辑控件中输入了一些非数字或超出范围的数字. 与此相关的是, 超过三位数的数字默认会有一个千位分隔符(如逗号). 这些分隔符是由 Edit 控件返回的, 但不是由 UpDown 控件返回的.

每当用户点击一个箭头按钮或按下键盘上的一个箭头键时, 就会触发 Change 事件.

### UpDown 选项

Horz(水平): 使控件的按钮点指向左/右而不是上/下. 默认情况下, Horz 还会让控件变成孤立的(没有伙伴控件). 通过在控件选项中指定 `Horz 16` 可以覆盖此特性.

Left: 把 UpDown 放在其伙伴控件的左边而不是右边.

Range: 使用 0 到 100 外的其他范围. 在单词 Range 后指定最小值, 破折号和最大值. 例如, `Range1-1000` 将允许选择一个介于 1 和 1000 之间的数字; `Range-50-50` 将允许介于 -50 和 50 之间的数字; 而 `Range-10--5` 将允许介于 -10 和 -5 之间的数字. 交换最小值和最大值可以让箭头往与正常方向相反的方向移动. 最大的允许范围是 -2147483648-2147483647. 最后, 如果伙伴控件为 ListBox, 那么垂直的默认范围是 32767-0, 而水平的则反向(Horz).

Wrap: 当用户试图超出最小值或最大值时使得控件返回到其范围的另一端. 如果没有 Wrap, 当达到最小值或最大值时控件会停止.

-16(负 16): 让垂直的 UpDown 成为孤立的; 即让它没有伙伴控件. 这还可以让控件符合任何指定的宽度, 高度和位置而不是适应于其伙伴控件的大小. 此外, 孤立的 UpDown 会内部跟踪它自己的位置. 使用如 MyGui.Submit 可以正常获取此位置.

0x80: 在 Options 中包含 0x80 来省略伙伴控件中正常出现在每三位十进制数间的千位分隔符. 然而, 通常不使用此样式, 因为当脚本从 UpDown 控件(而不是其伙伴控件) 获取的数字中不包含分隔符.

使用 1 以外的其他增量: 在此脚本中, 演示了如何改变 UpDown 增量为 1 以外的其他值(例如 5 或 0.1).

十六进制数字格式: 在伙伴控件中显示的数字格式可以通过以下示例从十进制改为十六进制:

    SendMessage 0x046D, 16, 0, "msctls_updown321" ; 0x046D 为 UDM_SETBASE

但是, 这只影响伙伴控件, 而不影响 UpDown 报告的位置.

另请参阅: 控件的位置和大小.

## Picture(或 Pic)

描述: 包含图像的区域(请参阅最后两段来了解支持的文件类型). 最后一个参数是图像的文件名, 如果未指定绝对路径, 则假定在 A_WorkingDir 中.

例如:

    MyGui.Add("Picture", "w300 h-1", "C:\My Pictures\Company Logo.gif")

或者:

    MyGui.AddPicture("w300 h-1", "C:\My Pictures\Company Logo.gif")

要保持图像的实际宽度和/或高度, 请省略 W 和/或 H 选项. 否则, 缩放图像的尺寸到指定的宽度和/或高度(此宽度和高度也决定了从多图标的 .ICO 文件中加载哪个图标). 要保持高宽比来缩放图像, 请在其中一个尺寸中指定 -1 而在另一个中指定正数. 例如, 指定 `"w200 h-1"` 将缩放图像到 200 像素的宽度同时自动设置其高度. 如果图片无法加载或显示(例如找不到文件), 则抛出一个错误并且控件不会被添加.

Picture(图片) 控件支持 Click 和 DoubleClick 事件, 其注意事项与 Text 控件相同.

要使用图片作为其他控件的背景, 则应该在其他控件之前正常添加图片. 然而, 如果这些控件是可输入型且此图片控件含有 SS_NOTIFY 样式(可能由 OnEvent 自动添加), 则在其他控件之后创建图片, 并在图片的 Options 中包含 0x4000000(即 WS_CLIPSIBLINGS). 这个技巧还可以让图片成为 Tab 控件或 ListView 后面的背景.

图标, 光标和动画光标: 图标和光标可以从下列类型的文件中加载: ICO, CUR, ANI, EXE, DLL, CPL, SCR 以及包含图标资源的其他类型. 要使用文件中的图标组而不是首个图标, 请在 Options 包含单词 Icon 和图标组编号. 在下面的例子中, 将使用第二个图标组中的默认图标: `MyGui.Add("Picture", "Icon2", "C:\My Application.exe")`.

在 Options 中指定单词 AltSubmit 会让程序使用微软的 GDIPlus.dll 来加载图像, 这可能让 GIF, BMP 和图标图像产生不同的外观. 例如, 它可以把含透明背景的 ICO/GIF 作为透明的位图进行加载, 这样允许 BackgroundTrans 选项生效(但图标支持透明而无需 AltSubmit).

在不使用 GDIPlus 的情况下, 支持的格式包括 GIF, JPG, BMP, ICO, CUR 和 ANI 图像. GDIPlus 默认用于其他图像格式, 如 PNG, TIF, Exif, WMF 和 EMF.

动态 GIFs: 虽然 GIF 动画文件可以显示在图片控件中, 但实际上它们并不会动起来. 要解决此问题, 请使用 AniGIF DLL(对非商业用途免费), 演示的例子请参阅 AutoHotkey 论坛. 此外, 可以使用 ActiveX 控件类型. 例如:

    ; 指定下面的路径到 GIF 文件以实现动态效果(也允许使用本地文件):
    pic := "http://www.animatedgif.net/cartoons/A_5odie_e0.gif"
    MyGui := Gui()
    MyGui.Add("ActiveX", "w100 h150", "mshtml:<img src='" pic "' />")
    MyGui.Show

位图或图标的句柄可完全替代文件名使用. 例如, `"HBITMAP:" handle`.

## Button

描述: 按下后可以触发动作的按钮. 此时最后一个参数为按钮的名称(显示在按钮上), 其中可以包含换行符(`n) 来开始新行.

例如:

    MyBtn := MyGui.Add("Button", "Default w80", "OK")
    MyBtn.OnEvent("Click", MyBtn_Click)  ; 当点击时, 调用 MyBtn_Click.

或者:

    MyBtn := MyGui.AddButton("Default w80", "OK")
    MyBtn.OnEvent("Click", MyBtn_Click)  ; 当点击时, 调用 MyBtn_Click.

外观:

每当用户点击按钮或在其具有焦点时按下 `Space` 或 `Enter` 键, Click 事件就会被触发.

同时也支持 DoubleClick, Focus 和 LoseFocus 事件. 由于这些事件只有在控件具有 BS_NOTIFY(0x4000) 样式时才会被触发, 所以它是由 OnEvent 自动添加的.

上面的例子在其 Options 中包含单词 Default 来让 "OK" 成为默认按钮. 每当用户按下 `Enter` 键时会自动触发默认按钮的 Click 事件, 除非此时键盘焦点在另一个按钮上或具有 WantReturn 样式的多行编辑控件中. 以后要改变默认按钮为另一个按钮, 请参照此例, 这里让 Cancel 按钮成为默认按钮: `MyGui["Cancel"].Opt("+Default")`. 以后要让窗口没有默认按钮, 请参照此例: `MyGui["OK"].Opt("-Default")`.

在按钮名称中使用和符号(&) 可以让其中的某个字母带下划线显示. 例如:

    MyGui.Add("Button",, "&Pause")

在上面的示例中, 字母 P 将被添加下划线, 这允许用户按下 `Alt`+`P` 作为其快捷键. 要显示一个原义的和符号, 请指定两个连续的和符号(&&).

已知限制: 某些桌面主题可能无法正确的显示按钮文本. 如果遇到此情况, 请尝试在控件的选项中包含 `-Wrap`(负 Wrap). 不过这样也使得按钮名称中无法包含多行文本.

## Checkbox

描述: 一个小方框, 可以选中或取消选中来表示 On/Off, Yes/No, 等等.

例如:

    MyGui.Add("CheckBox", "vShipToBillingAddress", "Ship to billing address?")

或者:

    MyGui.AddCheckBox("vShipToBillingAddress", "Ship to billing address?")

外观:

对于最后一个参数, 指定要显示在框右侧的标签. 这个标签通常是关于复选框用途的提示或描述, 它可以包含换行符(`n) 来开始新行. 如果 Options 中指定了宽度(W) 而没有指定行数(R) 或高度(H), 那么在需要时控件的文本将自动换行, 同时自动设置控件的高度.

GuiCtrl.Value 返回数字 1 表示选中, 0 表示未选中, -1 表示灰色/不确定.

在 Options 中指定单词 Check3 来启用第三种状态即显示灰色的选择标记而不是黑色的(灰色状态表示复选框既不处于选中状态也不处于未选中状态). 在 Options 中指定单词 Checked 或 CheckedGray 可以让复选框初始状态分别为黑色选中状态或灰色状态. 单词 Checked 后面可以紧跟着 0, 1 或 -1 来表示初始状态. 换句话说, `"Checked"` 和 `"Checked" VarContainingOne` 是一样的.

每当复选框被点击时, 它就会自动在它的两个或三个可能的状态之间循环, 然后触发 Click 事件, 允许脚本立即响应用户的输入.

同时也支持 DoubleClick, Focus 和 LoseFocus 事件. 由于这些事件只有在控件具有 BS_NOTIFY(0x4000) 样式时才会被触发, 所以它是由 OnEvent 自动添加的. 默认情况下不应用该样式, 因为它可以阻止快速点击改变复选标记的状态(例如用户点击两次从未选中切换到选中, 然后再切换到不确定).

已知限制: 某些桌面主题可能无法正确的显示 checkbox 的文本. 如果遇到此情况, 请尝试在控件的选项中包含 `-Wrap`(负 Wrap). 不过这样也使得按钮名称中无法包含多行文本.

## Radio

描述: 单选按钮是一个小空圆, 可以被选中(打开) 或不选中(关闭).

例如:

    MyGui.Add("Radio", "vMyRadioGroup", "Wait for all items to be in stock before shipping.")

或者:

    MyGui.AddRadio("vMyRadioGroup", "Wait for all items to be in stock before shipping.")

外观:

这些控件经常出现在 单选按钮组 中, 每组包含两个或多个单选按钮. 当用户点击一个单选按钮来打开它时, 其所在的单选按钮组中其他所有的单选按钮会自动关闭(在单选按钮组中用户也可以使用方向键导航). 在所有连续添加的单选按钮周围会自动创建一个单选按钮组. 要开始一个新组, 请在新组的首个单选按钮的 Options 中指定单词 Group -- 或者在新组和之前的组之间简单地添加一个非单选按钮控件, 因为这样会自动开始一个新组.

在最后一个参数中指定的标注会显示在单选按钮的右侧. 此标注通常作为提示或描述, 它可以包含换行符(`n) 来开始新行. 如果在 Options 中指定了宽度(W) 而没有指定行数(R) 或高度(H), 那么在需要时控件的文本将自动换行, 同时自动设置控件的高度.

在 Options 中指定单词 Checked 来让按钮初始为选中状态. 可以在单词 Checked 后紧跟着 0 或 1 来表示初始状态: 0 表示未选中, 而 1 表示选中. 换句话说, `"Checked"` 和 `"Checked" VarContainingOne` 是一样的.

GuiCtrl.Value 返回数字 1 表示 "on", 0 表示 "off". 如果要在单选组中检索所选单选选项的位置号, 只需命名其中一个单选按钮, 然后使用 MyGui.Submit.

每当用户打开按钮时, 就会触发 Click 事件. 与前一段的单变量模式不同, 事件回调必须为单选组中的每个按钮注册, 并为其调用. 这样就可以灵活地忽略某些按钮的点击.

同时也支持 DoubleClick, Focus 和 LoseFocus 事件. 由于这些事件只有在控件具有 BS_NOTIFY(0x4000) 样式时才会被触发, 所以它是由 OnEvent 自动添加的.

已知限制: 某些桌面主题可能无法正确的显示 checkbox 的文本. 如果遇到此情况, 请尝试在控件的选项中包含 `-Wrap`(负 Wrap). 不过这样也使得按钮名称中无法包含多行文本.

## DropDownList(或 DDL)

描述: 当按下一个小按钮时显示的选择列表. 此时, MyGui.Add 的最后一个参数是像 `["Choice1","Choice2","Choice3"]` 这样的数组.

例如:

    MyGui.Add("DropDownList", "vColorChoice", ["Black","White","Red"])

或者:

    MyGui.AddDropDownList("vColorChoice", ["Black","White","Red"])

外观:

要在窗口第一次出现时预选其中一个项目, 请在 Options 中加入单词 Choose 后面紧跟着要预选的项目编号. 例如, `Choose5` 会预选第五项(和其他选项一样, 它也可以为变量, 例如 `"Choose" Var`). 在控件创建后, 请使用 GuiCtrl.Value, GuiCtrl.Text 或 GuiCtrl.Choose 来改变选择, 和使用 GuiCtrl.Add 或 GuiCtrl.Delete 来添加或移除列表中的条目.

在 Options 中指定单词 Uppercase 或 Lowercase 来把列表中的所有项目自动转换成大写字母或小写字母. 指定单词 Sort 来按字母顺序自动排列列表的内容(这也会影响后面通过 GuiCtrl.Add 添加的所有项目). Sort 选项还会启用在弹出下拉列表时的增量搜索; 这使得可以通过输入一个项目名称的前几个字符来选择此项.

当使用 MyGui.Submit 或 GuiCtrl.Value 时, 返回值是当前选中的项目的位置号(第一个项目是 1, 第二个项目是 2, 等等.), 如果没有选中, 则返回值为 0. 如果要获取其文本, 则使用 GuiCtrl.Text.

每当用户选择一个新的项目时, 就会触发 Change 事件. 同时也支持 Focus 和 LoseFocus 事件.

使用 R 或 H 选项来控制弹出列表的高度. 例如, 指定 `R5` 会设置列表为 5 行高, 而 `H400` 会设置选区字段和列表的总高度为 400 像素. 如果同时省略 R 和 H 选项, 则列表会自动扩展到用户桌面的可用高度.

要设置选区字段或列表项的高度, 请使用 CB_SETITEMHEIGHT 消息, 如下例所示:

    MyGui := Gui()
    DDL := MyGui.Add("DDL", "vcbx w200 Choose1", ["One","Two"])
    ; CB_SETITEMHEIGHT = 0x153
    PostMessage(0x153, -1, 50, DDL)  ; 设置选区字段的高度.
    PostMessage(0x153, 0, 50, DDL)  ; 设置列表项的高度.
    MyGui.Show("h70")

## ComboBox

描述: 和 DropDownList 一样, 但也允许输入自由格式的文本, 作为从列表中选择项目的替代.

例如:

    MyGui.Add("ComboBox", "vColorChoice", ["Red","Green","Blue"])

或者:

    MyGui.AddComboBox("vColorChoice", ["Red","Green","Blue"])

外观:

除了可以使用上面描述的所有 DropDownList 选项外, Options 中还可以包含单词 Limit 来限制用户的输入在 ComboBox 编辑区域的可见宽度内. 此外, 可以指定单词 Simple 来让 ComboBox 表现的像一个下方带有 ListBox 的 Edit 区域.

GuiCtrl.Value 返回当前选中项的位置编号(第一项为 1, 第二项为 2, 等等.), 如果控件包含的文本与列表项不匹配, 则返回 0. 要获得 ComboBox 的编辑栏的内容, 使用 GuiCtrl.Text. MyGui.Submit 会存储文本, 除非在控件的 Options 中含有单词 AltSubmit 并且文本与列表项相匹配, 在这种情况下, 它会存储该项目的位置编号.

每当用户选择一个新的项目或更改控件的文本时, 就会触发 Change 事件. 同时也支持 Focus 和 LoseFocus 事件.

## ListBox

描述: 一个包含选择列表的较高的框. 此时, MyGui.Add 的最后一个参数是像 `["Choice1","Choice2","Choice3"]` 这样的数组.

例如:

    MyGui.Add("ListBox", "r5 vColorChoice", ["Red","Green","Blue"])

或者:

    MyGui.AddListBox("r5 vColorChoice", ["Red","Green","Blue"])

外观:

要在窗口第一次出现时预选其中一个项目, 请在 Options 中加入单词 Choose 后面紧跟着要预选的项目编号. 例如, `Choose5` 会预选第五项. 若要预选多个项目, 可多次使用 GuiCtrl.Choose(需要 Multi 选项). 在控件创建后, 请使用 GuiCtrl.Value, GuiCtrl.Text 或 GuiCtrl.Choose 来改变选择, 和使用 GuiCtrl.Add 或 GuiCtrl.Delete 来添加或移除列表中的条目.

如果没有 Multi 选项, GuiCtrl.Value 返回当前所选项目的位置编号(第一个项目为 1, 第二个项目为 2, 等等.), 如果没有选择项目, 则返回 0. 如果要获取所选项目的文本, 则使用 GuiCtrl.Text. 如果使用 Multi 选项, GuiCtrl.Value 和 GuiCtrl.Text 将返回一个项目数组, 而不是单个项目.

MyGui.Submit 默认存储 GuiCtrl.Text, 但如果控件的 Options 中包含单词 AltSubmit, 则存储 GuiCtrl.Value.

每当用户选择或取消选择一个或多个项目时, 就会触发 Change 事件. 同时也支持 DoubleClick, Focus 和 LoseFocus 事件.

当在 ListBox 中添加大量的项目时, 在操作之前使用 `MyListBox.Opt("-Redraw")`, 在操作之后使用 `MyListBox.Opt("+Redraw")`, 可以提高性能. 有关详情, 请参阅 Redraw.

### ListBox 选项

Choose: 请参阅上面.

Multi: 允许使用 shift-click 和 control-click 同时选择多个项目(如果不希望使用 shift/control-click, 请指定数字 8 代替单词 Multi). 此时, MyGui.Submit 或 GuiCtrl.Value 返回一个选定位置编号的数组. 例如, `[1, 2, 3]` 表示前三个项目被选中. 如果要得到一个选定的文本数组, 可以使用 GuiCtrl.Text. 要从数组中提取单个项目, 使用 `MyListBox.Text[1]`(1 是第一个项目) 或 For-loop 如下例所示:

    For Index, Field in MyListBox.Text
    {
        MsgBox "Selection number " Index " is " Field
    }

ReadOnly: 对选择的项目不进行高亮显示(但 MyGui.Submit, GuiCtrl.Value 或 GuiCtrl.Text 仍会返回选择的项目).

Sort: 按字母顺序自动排列列表的内容(这也会影响后面通过 GuiCtrl.Add 添加的所有项目). Sort 选项还会启用增量搜索; 这使得可以通过输入一个项目名称的前几个字符来选择此项.

T n: 字母 T 可以用来设置制表位, 它可以把文本格式成列. 如果没有使用字母 T, 则每 32 个对话框单位设置一次制表位(每个 "对话框单位" 的宽度由操作系统决定). 如果仅使用一次字母 T, 则每 n 个单位设置一次横跨整个控件宽度的制表位. 例如, `MyGui.Add("ListBox", "vMyListBox t64")` 将设置制表位之间的距离为默认的两倍. 要自定义制表位, 请指定字母 T 多次, 如下例所示: `MyGui.Add("ListBox", "vMyListBox t8 t16 t32 t64 t128")`. 在列表中每个绝对的列位置设置一个制表位, 制表位数目最大可达 50 个.

0x100: 在 Options 中包含 0x100 来打开 LBS_NOINTEGRALHEIGHT 样式. 此选项强制 ListBox 准确符合指定的高度而不是适应于避免在底部的行只显示一部分的高度. 此选项也避免了其字体改变时 ListBox 缩小的情况.

要指定文本的行数(或高度和宽度), 请参阅控件的位置和大小.

## ListView 和 TreeView

请参阅 ListView 和 TreeView 的单独页面.

## Link

描述: 一个可以包含类似于网络浏览器中的链接的文本控件. 在控件的文本中, 将链接文本包含在 `<A>` 和 `</A>` 中, 以创建一个可点击的链接. 虽然这看起来像 HTML, 但 Link 控件只支持左 `<A>` 标签(可选择使用 ID 和/或 HREF 属性) 和右`</A>` 标签.

例如:

    MyGui.Add("Link",, 'This is a <a href="https://www.autohotkey.com">link</a>')
    MyGui.Add("Link",, 'Links may be used anywhere in the text like <a id="A">this</a> or <a id="B">that</a>')

或者:

    MyGui.AddLink(, 'This is a <a href="https://www.autohotkey.com">link</a>')
    MyGui.AddLink(, 'Links may be used anywhere in the text like <a id="A">this</a> or <a id="B">that</a>')

外观:

每当用户点击一个链接, 就会触发 Click 事件. 如果控件没有 Click 回调(通过调用 OnEvent 注册), 链接的 HREF 会自动执行, 就像传递给 Run 函数一样.

    Gui := Gui()
    Link := MyGui.Add("Link",
        , 'Click to run <a href="notepad" id="notepad">Notepad</a> or open '
        . '<a id="help" href="https://www.autohotkey.com/docs/">online help</a>.')
    Link.OnEvent("Click", Link_Click)
    Link_Click(Ctrl, ID, HREF)
    {
        if MsgBox("ID: " ID "`nHREF: " HREF "`n`nExecute this link?",, "y/n") = "yes"
            Run(HREF)
    }
    MyGui.Show()

## Hotkey

描述: 一个看起来像单行编辑控件的框, 但它接受用户按下的按键组合. 例如, 在英语键盘布局的系统中如果用户按下 `Ctrl`+`Alt`+`C`, 那么此框中将显示 "Ctrl + Alt + C".

例如:

    MyGui.Add("Hotkey", "vChosenHotkey")

或者:

    MyGui.AddHotkey("vChosenHotkey")

外观:

GuiCtrl.Value 返回控件的热键修饰符和名称, 与热键函数兼容. 例如: `^!C`, `+!Home`, `+^Down`, `^Numpad1`, `!NumpadEnd`. 如果控件中没有热键, 则该值为空白.

注意: 一些按键即使它们作为不同的名称获取也显示为相同的名称. 例如, `^Numpad7` 和 `^NumpadHome` 都可能显示为 Ctrl + Num 7.

默认情况下, 控件在初始时不含有热键. 要让控件含有默认的热键, 请在最后一个参数中指定热键修饰符和按键名称, 如此例所示: `MyGui.Add("Hotkey", "vChosenHotkey", "^!p")`. 支持的修饰符仅包含 ^(Control), !(Alt) 和 +(Shift). 请参阅按键列表了解可用的按键名称.

每当用户改变控件的内容时(通过按键), 则将触发 Change 事件.

注意: 即使存在不完整的热键, 该事件也会被触发. 例如, 如果用户按住 `Ctrl`, 该事件就会被触发一次, Value 只返回一个抑扬符(^). 当用户完成热键时, 事件再次被触发, Value 返回完整的热键.

要限制用户可以使用的热键类型, 请在选项中包含单词 Limit 接着一个或多个下列数字的和:

- 1: 阻止不带有修饰符的按键
- 2: 仅阻止 `Shift`
- 4: 仅阻止 `Ctrl`
- 8: 仅阻止 `Alt`
- 16: 阻止 `Shift`+`Ctrl`
- 32: 阻止 `Shift`+`Alt`
- 64: 不支持这个值(它不会正确执行).
- 128: 阻止 `Shift`+`Ctrl`+`Alt`.

例如, `Limit1` 将阻止输入不带修饰符的热键(例如单独的字母和数字), 而 `Limit15` 则要求至少有两个修饰键. 如果用户输入了被禁止的修饰键组合, 则自动使用 `Ctrl`+`Alt` 组合代替.

Hotkey 控件对热键的支持有限. 例如, 它不支持鼠标/控制器热键或 `Win`(LWin 和 RWin). 解决此问题的一种方法是提供一个或多个 checkbox 作为用户启用额外的修饰键的工具, 如 `Win`.

## DateTime

描述: 一个看起来像单行编辑控件的框, 不过它接受日期和/或时间. 同时提供下拉日历.

例如:

    MyGui.Add("DateTime", "vMyDateTime", "LongDate")

或者:

    MyGui.AddDateTime("vMyDateTime", "LongDate")

外观:

最后一个参数可以为下列的其中一个.

### SetFormat

设置 DateTime 控件的显示格式.

    DateTime.SetFormat(Format)

Format

  类型: 字符串

  下列之一:

  ShortDate(或省略/空白): 使用区域设置的短日期格式. 例如, 在某些区域设置中它看起来像这样: 6/1/2005

  LongDate: 使用区域设置的长日期格式. 例如, 在某些区域设置中它看起来像这样: Wednesday, June 01, 2005

  Time: 仅显示时间, 使用区域设置的时间格式. 尽管不显示日期, 但它仍然存在于控件中并且与 YYYYMMDDHH24MISS 格式的时间一起被获取. 例如, 在某些区域它看起来像这样: 9:37:45 PM

  (自定义格式): 指定日期和时间格式的任意组合. 例如, `"M/d/yy HH:mm"` 显示的时间看起来像 6/1/05 21:37. 同样, `"dddd MMMM d, yyyy hh:mm:ss tt"` 显示的时间看起来像 June 1, 2005 09:37:45 PM. 想要原义显示的字母和数字应该括在一对单引号中, 如此例所示: `"'Date:' MM/dd/yy 'Time:' hh:mm:ss tt"`. 与之相比, 非字母数字字符(例如空格, tab, 斜杠, 冒号, 逗号和其他标点) 不需要包围在单引号中. 例外情况是单引号字符本身: 要产生原义的单引号, 请使用四个连续的单引号(''''), 不过如果它们已经包含在一对外部引号中则仅使用连续的两个就行了.

### DateTime 的用法

要预选今天外的其他日期, 请在 Options 中包含单词 Choose 紧跟着 YYYYMMDD 格式的日期. 例如, `Choose20050531` 将预选 May 31, 2005(和其他选项一样, 它还可以为变量, 例如 `"Choose" Var`). 要不预选日期/时间, 请指定 ChooseNone. ChooseNone 还在控件内部创建了一个复选框, 只要控件没有日期, 这个复选框就会被取消选中. 当控件中没有选择日期时, MyGui.Submit 或 GuiCtrl.Value 将检索一个空白值(空字符串).

日期的时间部分是可选的. 但是, 当进入或离开控件时, 时间部分必须总是在日期之前. 时间部分的格式为 HH24MISS(小时数, 分钟数, 秒数), 其中 HH24 含义是用 24 小时格式表示; 例如, 09 为 9am, 而 21 为 9pm. 因此, 完整的日期时间字符串的格式应为 YYYYMMDDHH24MISS.

当指定了 YYYYMMDDHH24MISS 格式的日期时, 只有前导部分是不能缺少的. 其他任何省略的元素将使用下列默认值代替: MM: 月份 01, DD: 日期 01, HH24: 小时 00, MI: 分钟 00, SS: 秒 00.

在下拉日历中, 可以点击底部的今日字符串来选择今天的日期. 此外, 还可以点击年份和月份名称来方便地导航到新的月份或年份.

当使用 MyGui.Submit 或 GuiCtrl.Value 时, 返回值是所选的日期和时间, 格式为 YYYYMMDDHH24MISS. 无论日期和时间是否在控件中实际可见, 它们都是存在的.

每当用户更改日期或时间时, 就会触发 Change 事件. 同时也支持 Focus 和 LoseFocus 事件.

### DateTime 选项

Choose: 请参阅上面.

Range: 限制可以选择的日期范围. 在单词 Range 后指定以 YYYYMMDD 格式表示的最小和最大的日期(它们之间使用破折号连接). 例如, `Range20050101-20050615` 将限制可选择的日期为 5.5 年的前 5 个半月. 最小或最大的日期可以省略, 此时控件中在这个方向上的日期不受限制. 例如, `Range20010101` 将禁止选择早于 2001 年的日期而 `Range-20091231` 有前导的破折号) 将禁止选择迟于 2009 年的日期. 如果不含 Range 选项, 则可以选择介于 1601 和 9999 年份之间的任何日期. 无法限制日期的时间部分.

Right: 让下拉日历在控件的右边而不是左边拉下.

1: 在 Options 中指定数字 1 会在此控件的右边提供一个增减控件来修改日期和时间的值, 这会取代其他地方可用的下拉月历的修改按钮. 这不能和上面所述的 LongDate 格式选项联用.

2: 在 Options 中指定数字 2 在控件中提供复选框, 用户可以取消此复选框选择来表示没有选择日期/时间. 控件创建后无法改变此选项.

下拉式日历内的颜色: 下拉式日历中天数的颜色由 Gui.SetFont 或 c(Color) 选项设置. 要改变日历其他部分的颜色, 如下例所示:

    SendMessage 0x1006, 4, 0xFFAA99, "SysDateTimePick321" ; 0x1006 为 DTM_SETMCCOLOR. 4 为 MCSC_MONTHBK(背景颜色). 颜色必须以 BGR 格式指定, 而不是 RGB 格式(红蓝分量互换).

## MonthCal

描述: 一个又高又宽的控件, 其中以日历的格式显示一个月中的所有日子. 用户可以选择单个日期或日期范围.

例如:

    MyGui.Add("MonthCal", "vMyCalendar")

或者:

    MyGui.AddMonthCal("vMyCalendar")

外观:

要预选今天外的其他日期, 请在最后一个参数中指定 YYYYMMDD 格式的日期(例如 `20050531`). 通过在两个日期间包含破折号可以预选一个日期范围(例如 `"20050525-20050531"`).

通常最好忽略 MonthCal 的宽度(W) 和高度(H), 这样它会自动调整大小来准确适应一个月份. 要垂直地显示多个月份, 请在 Options 中指定 `R2` 或更高. 要水平地显示多个月份, 请指定 `W-2`(W 负 2) 或更高. 这两个选项可以同时出现, 此时会在两个方向上扩展.

可以点击控件底部的今日字符串来选择今天的日期. 此外, 还可以点击年份和月份名称来方便地选择新的月份或年份.

键盘导航: 在 MonthCal 中完全支持键盘导航, 但只有当它具有键盘焦点时才支持. 有关支持的键盘快捷方式, 请参阅 DateTime 的键盘导航(带有下拉日历).

当使用 MyGui.Submit 或 GuiCtrl.Value 时, 返回值是所选的以 YYYYMMDD 格式表示的日期(没有任何时间部分). 但是, 存在多选选项时, 会得到以破折号连接的最小和最大日期(例如 `20050101-20050108`). 在可以多选的日历中如果仅选择单个日期, 则最小和最大日期都会存在但它们是相同的. 可以使用 StrSplit 来分隔日期. 例如, 下面将把最小值放在 Date[1] 中, 最大值放在 Date[2] 中: `Date := StrSplit(MyMonthCal.Value, "-")`.

当用户更改选择时, 将触发更改事件.

指定 YYYYMMDD 格式的日期时, MM 和/或 DD 部分可以省略, 此时它们默认为 1. 例如, `200205` 被视为 20020501, 而 `2005` 被视为 20050101.

### MonthCal 选项

Multi: 多选. 允许用户使用 shift-click 或 click-drag 来选择一个连续的日期范围(此时用户仍然可以选择单个日期). 可以明确指定此选项或在创建控件时通过指定一个选择范围的方法来让此选项自动生效. 例如: `MyGui.Add("MonthCal", "vMyCal", "20050101-20050108")`. 控件创建后无法改变此选项.

Range: 限制日历中可以选择的时间范围. 在单词 Range 后指定以 YYYYMMDD 格式表示的最小和最大的日期(它们之间使用破折号连接). 例如, `Range20050101-20050615` 将限制选区为 2005 年的前 5 个半月. 最小或最大的日期可以省略, 此时日历中在这个方向上的日期不受限制. 例如, `Range20050101-20050615` 将禁止选择早于 2001 年的日期而 `Range-20091231`(有前导的破折号) 将禁止选择迟于 2009 年的日期. 如果不含 Range 选项, 则可以选择介于 1601 和 9999 年份之间的任何日期.

4: 在 Options 中指定数字 4 来在每行日期的左边显示周数(1-52). Week 1 被定义为至少包含四天的第一周.

8: 在 Options 中指定数字 8 来禁止控件中当前日期往复循环.

16: 在 Options 中指定数字 16 来禁止在控件的底部显示今天的日期.

Colors: 日历中天数的颜色由 Gui.SetFont 或 c(Color) 选项设置. 要改变日历其他部分的颜色, 如下例所示:

    SendMessage 0x100A, 5, 0xFFAA99, "SysMonthCal321" ; 0x100A 为 MCM_SETCOLOR. 5 为 MCSC_TITLETEXT(标题文本颜色). 颜色必须以 BGR 格式指定, 而不是 RGB 格式(红蓝分量互换).

## Slider

描述: 一个滑动栏, 用户可以让它沿着垂直或水平轨道移动. 滑动栏的一个常见的例子是在任务栏托盘中的标准音量控件.

例如:

    MyGui.Add("Progress", "w200 h20 cBlue vMyProgress", 75)

或者:

    MyGui.AddProgress("w200 h20 cBlue vMyProgress", 75)

外观:

请在最后一个参数中指定滑动栏的初始位置. 如果最后一个参数省略, 则滑动栏初始位置为 0 或允许的范围中最接近 0 的数字.

用户可以通过下列方法滑动控件: 1) 使用鼠标拖拉滑动栏; 2) 用鼠标在滑动栏的轨道区域点击; 3) 当焦点在控件上时转动鼠标滚轮; 或 4) 当焦点在控件上时使用下列键: `↑`, `→`, `↓`, `←`, `PgUp`, `PgDn`, `Home` 和 `End`.

GuiCtrl.Value 和 MyGui.Submit 返回或存储滑块的当前数值位置.

### 检测变化

默认情况下, 当用户停止移动滑块时, 例如在拖动滑块后释放鼠标按钮, 就会触发滑块的 Change 事件. 如果控件有 AltSubmit 选项, 那么当用户用鼠标拖动滑块时, 每次滑块的可见移动后, 也将触发 Change 事件(非常频繁).

    Ctrl_Change(GuiCtrlObj, Info)

Info

  类型: 整数

  下面的表格中的数值, 表示滑块的移动方式. 这些值和相应的名称在 Windows SDK 中定义了.

值 | 名称 | 意义
--- | --- | ---
0 | TB_LINEUP | 用户按下了 `←` 或 `↑` 键.
1 | TB_LINEDOWN | 用户按下了 `→` 或 `↓` 键.
2 | TB_PAGEUP | 用户按下了 `PgUp` 键.
3 | TB_PAGEDOWN | 用户按下了 `PgDn` 键.
4 | TB_THUMBPOSITION | 用户用鼠标滚轮移动了滑块或已经把滑块拖放到新的位置.
6 | TB_TOP | 用户按下了 `Home` 键来移动滑块到左端或顶部.
7 | TB_BOTTOM | 用户按下了 `End` 键来移动滑块到右端或底部.

仅当使用 AltSubmit 选项时:

值 | 名称 | 意义
--- | --- | ---
5 | TB_THUMBTRACK | 用户正用鼠标拖动滑块, 即鼠标按钮当前是按住的.
8 | TB_ENDTRACK | 用户已经使用鼠标或键盘移动了滑块. 注意: 除了鼠标滚轮移动(#4) 之外, Change 事件在 #8 中再次被触发, 尽管它已经被上面的一个数字触发了.

### Slider 选项

Buddy1 和 Buddy2: 最多可以指定两个现有的控件来自动定位到滑动条的两侧. Buddy1 显示在左边或顶部(取决于是否存在 Vertical 选项). Buddy2 显示在右侧或底部. 在单词 Buddy1 或 Buddy2 后指定现有控件的名称或 HWND. 例如, `Buddy1MyTopText` 将分配变量名为 MyTopText 的控件. 控件的文本或 ClassNN 也能使用, 但只到第一个空格或制表符.

Center: 滑块(用户移动的滑动栏) 两端将是钝的而不指向其中一端.

Invert: 反转控件, 把较低值作为右边/底端而不是左边/顶端. 此选项常用来让垂直滑动栏在传统的音量控件方向上移动. 注: 下面描述的工具提示选项不会遵循反转, 因此此时不应该使用.

Left: 滑块(用户移动的滑动栏) 将指向上方而不是下方(原文中为顶端和底端, 这里用上/下放是为了避免和滑动栏的顶端/底端混淆). 但如果存在 Vertical 选项, 则滑块将指向左边而不是右边.

Line: 指定当用户按下其中一个方向键时要移动位置的数目. 在单词 Line 后指定移动位置的数目. 例如: `Line2`.

NoTicks: 不在轨道旁边显示刻度标记.

Page: 指定当用户按下 `PgUp` 或 `PgDn` 键时移动位置的数目. 在单词 Page 后指定移动位置的数目. 例如: `Page10`.

Range: 使用 0 到 100 外的其他范围. 在单词 Range 后指定最小值, 破折号和最大值. 例如, `Range1-1000` 将允许选择一个介于 1 和 1000 之间的数字; `Range-50-50` 将允许介于 -50 和 50 之间的数字; 而 `Range-10--5` 将允许介于 -10 和 -5 之间的数字.

Thick: 指定滑块的长度. 在单词 Thick 后指定以像素为单位的厚度(例如 `Thick30`). 如果要超过一定的厚度, 可能需要指定 Center 选项或者从控件中删除主题(可以通过在控件的选项中指定 `-Theme` 来实现).

TickInterval: 在轨道旁边指定间隔的位置显示刻度标记. 在单词 TickInterval 后指定间隔来显示附加的刻度标记(如果省略从未设置, 则默认为 1). 例如, `TickInterval10` 将每隔 10 位置显示一个刻度标记.

ToolTip: 创建工具提示, 当用户拖动滑动栏时显示它的数字位置. 要让工具提示不显示在默认位置, 请指定下列单词的其中一个代替: `ToolTipLeft` 或 `ToolTipRight`(对于水平滑动条); `ToolTipTop` 或 `ToolTipBottom`(对于水平滑动条).

Vertical: 让控件上下滑动而不是左右滑动.

在控件创建后, 可以使用 GuiCtrl.Opt 来改变上面的选项.

## Progress

描述: 一个双彩条, 通常用来指示一个操作接近完成的程度.

例如:

    MyGui.Add("Progress", "w200 h20 cBlue vMyProgress", 75)

或者:

    MyGui.AddProgress("w200 h20 cBlue vMyProgress", 75)

外观:

在最后一个参数中指定进度条的初始位置(如果省略, 则进度条的初始位置为 0 或允许的范围中最接近 0 的数字). 之后要改变进度条的位置, 请参照下面的例子, 所有这些都是在一个名称为 MyProgress 的进度条上操作:

    MyGui["MyProgress"].Value += 20  ; 增加 20 到当前位置.
    MyGui["MyProgress"].Value := 50  ; 设置当前位置为 50.

对于水平进度条, 进度条的厚度等于控件的高度. 对于垂直进度条它等于控件的宽度.

### Progress 选项

C n: 改变进度条的颜色. 指定 n 为 16 种 HTML 基础颜色之一或 6 位的 RGB 颜色值. 例如: `cRed`, `cFFFF33`, `cDefault`. 如果从没有使用过 C 选项(或指定了 `cDefault`), 则使用系统默认的进度条颜色.

>Background N: 改变进度条的背景颜色. 指定 N 为 16 种 HTML 基础颜色之一或 6 位的 RGB 颜色值. 例如: `BackgroundGreen`, `BackgroundFFFF33`, `BackgroundDefault`. 如果从没有使用过 Background 选项(或指定了 `BackgroundDefault`), 则使用窗口的或进度条后选项卡控件的颜色作为背景颜色.

Range: 使用 0 到 100 外的其他范围. 在单词 Range 后指定最小值, 破折号和最大值. 例如, `Range0-1000` 将允许一个介于 0 和 1000 之间的数字; `Range-50-50` 将允许介于 -50 和 50 之间的数字; 而 `Range-10--5` 将允许介于 -10 和 -5 之间的数字.

Smooth: 显示一个简单的连续条. 如果不使用该选项, 并且进度条没有任何自定义颜色, 则进度条的外观由当前系统主题定义. 否则, 进度条将显示为一段段的长度.

Vertical: 让进度条垂直上升或下降而不是水平移动.

在控件创建后, 可以使用 GuiCtrl.Opt 来改变上面的选项.

## GroupBox

描述: 一个矩形的框, 常用来封装一组相关的控件. 此时最后一个参数为分组框的标题, 其(如果存在) 显示在分组框的左上角.

例如:

    MyGui.Add("GroupBox", "w200 h100", "Geographic Criteria")

或者:

    MyGui.AddGroupBox("w200 h100", "Geographic Criteria")

外观:

默认情况下, 分组框的标题可以只有一行文本. 在 Options 中指定 `Wrap` 可以改变此特性.

要指定控件中的行数(或高度和宽度), 请参阅控件的位置和大小.

## Tab3

描述: 一个包含多个页面的大型控件, 其中每个页面包含其他控件. 从这里开始, 这些页面被称为 "选项卡(标签页)".

选项卡控件有以下三种类型:

- Tab3: 修复若干影响 Tab2 和 Tab 的问题. 各控件位于一个可见的 "标签页对话框", 其位置和大小随选项卡控件的移动和大小的改变而改变. 选项卡控件使用默认主题.
- Tab2: 修正了原有 "Tab" 控件罕见的重绘问题, 但是引入了一些其他问题.
- Tab: 保留向后兼容性, 因为在 Tab2/Tab3 和 Tab 之间有着行为差异.

例如:

    MyGui.Add("Tab3",, ["General","View","Settings"])

或者:

    MyGui.AddTab3(, ["General","View","Settings"])

外观:

上面的最后一个参数是一个标签页名称的数组. 要在窗口初次出现时预选其中的某个选项卡, 请在 Options 中包含单词 Choose 紧跟着想预选的选项卡的编号. 例如, `Choose5` 会预选第五个选项卡(和其他选项一样, 它也可以为变量, 例如 `"Choose" Var`). 要在控件创建后改变选择的选项卡, 请使用 Value, Text 或 Choose 和 Add 或 Delete 来添加或删除选项卡.

创建选项卡控件后, 随后添加的控件自动属于其首个选项卡. 这可以在任何时候改变, 请参照这些例子(在本例中, Tab 是第一个选项卡控件的 GuiControl 对象, 而 Tab2 是第二个标签控件的 GuiControl 对象):

    Tab.UseTab()  ; 随后的控件不属于任何选项卡控件的一部分.
    Tab.UseTab(3)  ; 随后的控件属于当前选项卡控件的第三个选项卡.
    Tab2.UseTab(3)  ; 随后的控件属于第二个选项卡控件的第三个选项卡.
    Tab.UseTab("Name")  ; 随后的控件属于名称以 Name(不区分大小写) 开始的选项卡.
    Tab.UseTab("Name", true)  ; 与上面相同, 不过这里需要准确匹配(并区分大小写).

还可以使用上面的每个例子分配控件到还不存在的选项卡或选项卡控件(不包括使用 Name 方法的情况). 但在此情况下, 不支持下面描述的相对位置选项.

位置: 当一个选项卡控件的每个选项卡接收到其首个子控件, 此子控件在下列情况下将具有特殊的默认位置: 1) 同时省略 X 和 Y 坐标, 此时首个子控件放在选项卡控件内部的左上角(带有标准的边距), 而首个子控件后的其他子控件放在之前控件的下面; 2) 指定了 X+n 和/或 Y+n 位置选项, 此时子控件放在相对于选项卡控件内部的左上角的位置. 例如, 指定 `x+10 y+10` 会把控件放置在左上角往右和往下各 10 个像素的位置.

当前标签页: GuiCtrl.Value 返回当前选中的标签页的位置编号(第一个标签页是 1, 第一个标签页是 2, 等等.). 要获取其文本, 请使用 GuiCtrl.Text. MyGui.Submit 默认存储 GuiCtrl.Text, 但如果控件的 Options 中含有单词 AltSubmit, 则存储 GuiCtrl.Value.

检测标签页选择: 每当用户切换标签页时, Change 事件就会被触发.

键盘导航: 用户可以按下 `Ctrl`+`PgDn`/`PgUp` 来在选项卡控件的页面间导航; 如果键盘焦点在不属于选项卡的控件上, 则会导航到窗口的首个选项卡控件. 也可以使用 `Ctrl`+`Tab` 和 `Ctrl`+`Shift`+`Tab`, 除非当前焦点控件在多行编辑控件中(此时它们不起作用).

限制: 每个窗口的选项卡控件不能超过 255 个. 每个选项卡控件不能含有超过 256 个选项卡(页面). 此外, 选项卡控件不能包含其他选项卡控件.

### Tab3 vs. Tab2 vs. Tab

父窗口: 控件的父窗口影响控件的位置和可见性以及 Tab 键的导航顺序. 如果控件添加到已存在的 Tab3 选项卡控件, 其父窗口是 "tab dialog", 该父窗口填充选项卡控件的显示区域. 大部分其他控件, 包括 Tab 或 Tab2 中的子控件, 没有父窗口除了 Gui 界面本身.

位置: 对于 Tab 和 Tab2, 子控件不需要在他们的选项卡控件的边界内: 当标签页是激活或未激活时他们总是会显示和隐藏. 这种行为特别适合下面描述的 "按钮" 样式.

对于 Tab3, 在标签页控件创建之 前, 添加子控件的行为与 Tab 或 Tab2 是一致的. 所有其他子控件只在选项卡控件的显示区域内可见.

如果 Tab3 控件移动, 他的子控件也随之移动. Tab 和 Tab2 控件没有这个行为.

在极少数情况下, WinMove(或等效的 DllCall) 用于移动控件, 坐标必须相对于控件的父窗口, 而不是 Gui(参阅上面的信息)). 相比之下, GuiCtrl.Move 采用 GUI 坐标, ControlMove 采用窗口坐标, 与控件的父窗口无关.

自动尺寸: 如果脚本没有指定, 在下列情况下 Tab3 控件的宽度 和/或 高度将会自动计算(在控件创建后以先到者为准):

- 第一次 Tab3 控件不再是当前标签页控件. 这可能是调用了 GuiCtrl.UseTab(有或没有参数) 或创建另一个标签页控件所导致的.
- 对于特定的 Gui, 首次调用 MyGui.Show.

存在的子控件计算尺寸时, 自动调整的尺寸再加上默认边距. 尺寸只计算一次, 即使添加控件也不会重新计算. 如果 Tab3 控件是空的, 与 Tab 或 Tab2 控件相同的默认大小.

Tab 和 Tab2 控件不会自动计算尺寸; 它们接受任意默认大小.

Tab 键导航顺序: `Tab` 导航顺序通常取决于控件创建的顺序. 当选项卡控件激活时, 顺序也取决于选项卡控件的类型:

- Tab 和 Tab2 允许其子控件与其他控件混合.
- Tab2 将标签页按钮置于其子控件之后.
- Tab3 的子控件组合在一起并置于标签页按钮之后.

通知消息(Tab3): 命令和自定义控件通常向他们的父窗口发送通知消息. Tab3 控件的 tab dialog 接收到的任何 WM_COMMAND, WM_NOTIFY, WM_VSCROLL, WM_HSCROLL 或 WM_CTLCOLOR 消息转发到 GUI 窗口和能被 OnMessage 检测. 如果标签页控件使用主题并且其子控件没有 +BackgroundTrans 选项, tab dialog 处理 WM_CTLCOLORSTATIC 消息而不转发. 其他的通知消息(例如自定义消息) 不被支持.

Tab2 选项卡控件的已知问题:

- BackgroundTrans 在 Tab2 控件中没有效果.
- WebBrowser 控件重绘不正确.
- 动态窗口和其他的某些 Win32 API 调用导致其中的控件不显示.

Tab 选项卡控件的已知问题:

- 通过单击界面窗口中的某个控件来激活界面窗口, 例如滚动条, 将会出现重绘不正确的情况.
- 如果 Tab 控件包含 ListView 控件, BackgroundTrans 没有效果.
- WebBrowser 控件不可见.

### Tab 选项

Choose: 请参阅上面描述的内容.

Background: 指定 `-Background`(负 Background) 覆盖窗口的自定义背景颜色, 而使用系统默认的选项卡控件的颜色. 指定 `+Theme -Background` 来让选项卡控件适应于当前桌面主题. 然而, 在这样选项卡控件内的大多数类型的控件看起来会很奇怪, 因为它们的背景颜色不匹配选项卡控件的背景颜色. 对于某些类型的控件(例如 Text), 这种情况可以在它们的选项中添加 BackgroundTrans 来修复.

Buttons: 在控件的顶部创建一系列按钮而不是选项卡(此时在默认情况下将没有边界, 因为显示的区域实际并不包含控件).

Left/Right/Bottom: 指定这些单词的其中一个让选项卡显示在左边, 右边或底部而不是顶部. 请参阅 TCS_VERTICAL 了解对于 Left 和 Right 的限制.

Wrap: 指定 `-Wrap`(负 Wrap) 阻止选项卡占用多行(此时为了适应过多的选项卡, 会显示箭头按钮以允许用户滑动来查看更多选项卡).

要指定控件中文本的行数(或高度和宽度), 请参阅控件的位置和大小.

在选项卡中添加图标: 通过 SendMessage 可以在每个选项卡的名称/文本旁边显示图标. 演示的例子请参阅论坛主题 Icons in tabs.

## StatusBar

描述: 附加到窗口底部的一行文本和/或图标, 通常用来报告状态的变化.

例如:

    SB := MyGui.Add("StatusBar",, "Bar's starting text (omit to start off empty).")

或者:

    SB := MyGui.AddStatusBar(, "Bar's starting text (omit to start off empty).")
    SB.SetText("There are " . RowCount . " rows selected.")

外观:

状态栏最简单的用法是每当应该报告给用户一些状态改变时调用 SB.SetText. 要报告多片的信息, 请使用 SB.SetParts 把状态栏分成多段. 要在状态栏中显示图标, 请调用 SB.SetIcon.

### StatusBar 方法

### SetText

在状态栏指定部分显示 NewText.

    Success := SB.SetText(NewText , PartNumber, Style)

NewText

  类型: 字符串

  在 NewText 中的任意地方可以使用最多两个两个制表符(`t): 第一个制表符右边的任何东西在该部分中居中, 而第二个制表符右边的任何东西是右对齐的.

PartNumber

  类型: 整数

  如果省略 PartNumber, 则使用默认值 1. 否则, 请指定介于 1 和 256 之间的整数.

Style

  类型: 整数

  如果省略 Style, 则使用默认值 0, 此时使用让状态栏那部分看起来凹陷的传统边界. 否则, 指定 1 为无边框, 2 为带边框, 让状态栏看起来是凸起的.

### SetParts

根据指定的宽度(单位为像素) 把状态栏分成多个部分, 并返回非零值(状态栏的 HWND).

    Hwnd := SB.SetParts(Width1, Width2, ... Width255)

Width1 ... Width255

  类型: 整数

  如果省略所有参数, 则状态栏恢复为只有一个很长的部分. 否则, 指定除了最后一部分外的其他每个部分的宽度(最后一部分将填充状态栏的剩余宽度). 例如, `SB.SetParts(50, 50)` 将创建三个部分: 前两个部分的宽度都为 50, 而最后一部分占据剩余的所有宽度.

注意: 通过 `SB.SetParts()` "删除" 的任何部分下次显示时都不会显示文本(而且它们的图标会自动销毁).

### SetIcon

在指定部分的文本左边显示一个小图标, 并返回图标的句柄.

    HICON := SB.SetIcon(Filename , IconNumber, PartNumber)

FileName

  类型: 字符串

  图标或图像文件的路径. 关于支持的格式列表, 请参阅图片控件.

  可以使用位图或图标句柄来代替文件名. 例如, `SB.SetIcon("HICON:" handle)`.

IconNumber

  类型: 整数

  要使用文件中第一个以外的图标组, 请为 IconNumber 指定其编号. 例如, `SB.SetIcon("Shell32.dll", 2)` 将使用第二个图标组中的默认图标. 如果 IconNumber 为负数, 则假定其绝对值表示可执行文件中图标的资源 ID.

PartNumber

  类型: 整数

  如果省略 PartNumber, 则默认为 1. 否则, 请指定介于 1 和 256 之间的整数.

注意: 是一种系统资源, 它可以被大多数脚本安全地忽略, 因为当状态栏的窗口被销毁时它会被自动销毁. 同样, 当 `SB.SetIcon()` 用新图标替换旧图标时会销毁旧图标. 这种情况可以使用以下方法避免:

    MyGui.Opt("+LastFound")
    SendMessage(0x40F, part_number - 1, my_hIcon, "msctls_statusbar321")  ; 0x40F is SB_SETICON.

### SetProgress

创建和控制状态栏中的进度条. 此函数可以从 www.autohotkey.com/forum/topic37754.html 获取.

### StatusBar 的使用

对鼠标点击做出反应: 每当用户点击状态栏时, Click, DoubleClick 或 ContextMenu 事件都会被触发, Info 或 Item 参数包含状态栏部分的编号. 但是, 如果用户点击状态栏右边靠近大小调整手柄的地方时, 目标部分的编号可能是很大的整数.

字体和颜色: 尽管字体大小, 外观和样式可以使用 MyGui.SetFont 来设置(像普通控件一样), 但是无法改变文本颜色. 状态栏的背景颜色可以通过在 Options 中指定单词 Background 后紧跟颜色名称(请参阅颜色表) 或 RGB 值(0x 前缀是可选的). 例如: `BackgroundSilver`, `BackgroundFFDD99`, `BackgroundDefault`. 注意, 控件必须具有经典主题外观. 因此, `-Theme` 选项必须与 Background 选项一起指定, 例如 `-Theme BackgroundSilver`.

隐藏状态栏: 创建时, 可以使用 `MyStatusBar := MyGui.Add("StatusBar", "Hidden")` 隐藏状态栏. 要在创建后某个时候隐藏它, 请使用 `MyStatusBar.Visible := false`. 要显示, 请使用 `MyStatusBar.Visible := true`. 注意: 隐藏状态栏不会降低窗口的高度. 如果希望这样, 一个简便的方法是 `MyGui.Show("AutoSize")`.

样式(很少使用): 请参阅状态栏样式表.

已知限制: 1) 如果某个控件的位置和状态栏重叠, 那么它有可能会被绘制在状态栏的上方. 避免这种情况的一种方法是通过 Size 事件动态地缩小这样的控件. 2) 每个窗口只允许有一个状态栏控件.

示例: 示例 #1 在 TreeView 页面底部演示了一个多部分的状态栏.

## ActiveX

ActiveX 组件(例如 MSIE 浏览器控件) 可以按照以下方式嵌入到 GUI 窗口. 有关下面使用的 ActiveX 组件及其方法的详细信息, 请参阅 WebBrowser object (Microsoft Docs) 和 Navigate method (Microsoft Docs).

    MyGui := Gui()
    WB := MyGui.Add("ActiveX", "w980 h640", "Shell.Explorer").Value  ; 最后一个参数是 ActiveX 组件的名称.
    WB.Navigate("https://www.autohotkey.com/docs/")  ; 这是特定于网页浏览器控件的.
    MyGui.Show()

当控件被创建时, ActiveX 对象可以通过 GuiCtrl.Value 来检索.

要处理对象公开的事件, 请使用 ComObjConnect, 如下所示. 有关下面使用的事件的详细信息, 请参阅 NavigateComplete2 event (Microsoft Docs).

    MyGui := Gui()
    URL := MyGui.Add("Edit", "w930 r1", "https://www.autohotkey.com/docs/")
    MyGui.Add("Button", "x+6 yp w44 Default", "Go").OnEvent("Click", ButtonGo)
    WB := MyGui.Add("ActiveX", "xm w980 h640", "Shell.Explorer").Value
    ComObjConnect(WB, WB_events)  ; 连接 WB 事件到 WB_events 类对象.
    MyGui.Show()
    ; 继续加载初始页面:
    ButtonGo()

    ButtonGo(*) {
        WB.Navigate(URL.Value)
    }

    class WB_events {
        NavigateComplete2(wb, &NewURL, *) {
            URL.Value := NewURL  ; 更新 URL 编辑控件.
        }
    }

ComObjType 可以用来确定检索对象的类型.

## Custom

AutoHotkey 不直接支持的控件也可以嵌入到 GUI 窗口. 要实现这样的操作, 在 Options 中包含单词 Class 后跟所需控件的 Win32 类名. 例如:

    MyGui.Add("Custom", "ClassComboBoxEx32")  ; 添加 ComboBoxEx 控件.
    MyGui.Add("Custom", "ClassScintilla")  ; 添加 Scintilla 控件. 注意必须加载 SciLexer.dll 库后才能添加此控件.

AutoHotkey 通过 `MyGui.Add` 或 `GuiCtrl.Value` 使用标准的 Windows 操作方法来获取或替换控件中的文本.

Events: 由于每个通知代码的含义取决于发送它的控件, 因此 OnEvent不支持自定义控件. 然而, 如果控件以 WM_NOTIFY 或 WM_COMMAND 消息的形式发送通知, 脚本可以使用 OnNotify 或 OnCommand 来检测它们.

下面这个例子演示了如何添加和使用 IP 地址控件:

    MyGui := Gui()
    IP := MyGui.Add("Custom", "ClassSysIPAddress32 r1 w150")
    IP.OnCommand(0x300, IP_EditChange)  ; 0x300 = EN_CHANGE
    IP.OnNotify(-860, IP_FieldChange)  ; -860 = IPN_FIELDCHANGED
    IPText := MyGui.Add("Text", "wp")
    IPField := MyGui.Add("Text", "wp y+m")
    MyGui.Add("Button", "Default", "OK").OnEvent("Click", OK_Click)
    MyGui.Show()

    IPCtrlSetAddress(IP, SysGetIPAddresses()[1])

    OK_Click(*)
    {
        MyGui.Hide()
        MsgBox("You chose " IPCtrlGetAddress(IP))
        ExitApp()
    }

    IP_EditChange(*)
    {
        IPText.Text := "New text: " IP.Text
    }

    IP_FieldChange(thisCtrl, NMIPAddress)
    {
        ; 从 NMIPADDRESS 结构体中提取信息.
        iField := NumGet(NMIPAddress, 3*A_PtrSize + 0, "int")
        iValue := NumGet(NMIPAddress, 3*A_PtrSize + 4, "int")
        if (iValue >= 0)
            IPField.Text := "Field #" iField " modified: " iValue
        else
            IPField.Text := "Field #" iField " left empty"
    }

    IPCtrlSetAddress(GuiCtrl, IPAddress)
    {
        static WM_USER := 0x400
        static IPM_SETADDRESS := WM_USER + 101

        ; 把 IP 地址打包成 32 位字以用于 SendMessage.
        IPAddrWord := 0
        Loop Parse IPAddress, "."
            IPAddrWord := (IPAddrWord * 256) + A_LoopField
        SendMessage(IPM_SETADDRESS, 0, IPAddrWord, GuiCtrl)
    }

    IPCtrlGetAddress(GuiCtrl)
    {
        static WM_USER := 0x400
        static IPM_GETADDRESS := WM_USER + 102

        AddrWord := Buffer(4)
        SendMessage(IPM_GETADDRESS, 0, AddrWord, GuiCtrl)
        Loop 4
            IPPart.Push(NumGet(AddrWord, 4 - A_Index, "UChar"))
        return IPPart[1] "." IPPart[2] "." IPPart[3] "." IPPart[4]
    }

## 相关页面

ListView, TreeView, Gui(), Gui 对象, GuiControl 对象, Menu 对象

dftg