# GUI

创建和管理窗口和控件. 这种窗口可以用作数据输入窗体或自定义用户界面.

    Gui, SubCommand , Value1, Value2, Value3

SubCommand, Value1, Value2 和 Value3 相互依赖, 它们的用法如下所述.

## 目录

- 子命令
- 控件的选项(Gui Add)
  - 控件的位置和大小
  - 保存和响应用户的输入
  - 控件: 通用样式和其他选项
- 窗口事件: GuiClose | GuiEscape | GuiSize | GuiContextMenu | GuiDropFiles
- 创建多个 GUI 窗口
- GUI 事件, 线程和子程序
- 键盘导航
- 窗口外观
- 一般说明
- 示例

## 子命令

对于 SubCommand, 指定以下命令之一:

- New [v1.1.04+]: 创建新窗口.
- Add: 创建控件, 例如文本, 按钮或复选框.
- Show: 显示窗口. 同时可以最小化, 最大化和移动窗口.
- Submit: 保存用户的输入并可以隐藏窗口.
- Cancel(或 Hide): 隐藏窗口.
- Destroy: 销毁窗口.
- Font: 为后续创建的控件文本设置文字的字体, 大小, 样式和文本颜色.
- Color: 设置窗口和/或控件的背景颜色.
- Margin: 设置在没有为控件指定明确的位置时使用的边距/间隔.
- 窗口的选项和样式: 设置窗口的外观和行为的各种选项.
- Menu: 添加或移除菜单栏.
- Minimize / Maximize / Restore: 对窗口执行指定的操作.
- Flash: 闪烁窗口及其任务栏按钮.
- Default: 改变当前线程的默认 GUI 窗口编号.

### New [v1.1.04+]

创建新窗口并将其设为当前线程的默认窗口.

    Gui, New , Options, Title
    Gui, GuiName:New , Options, Title

如果指定了 GuiName, 那么将创建一个新的 GUI, 销毁任何具有该名称的现有 GUI. 否则, 将创建一个新的未命名和无编号的 GUI.

Options 可以包含主 GUI 命令支持的任意选项.

如果省略 Title, 则使用脚本文件名.

这个子命令附带以下注意事项:

- 大多数情况下, 会按需自动创建窗口, 所以通常无需调用 `Gui New`.
- 尽管新窗口会被设为 当前 线程的默认窗口, 但非 GUI 线程的默认窗口仍为编号 1 的 GUI.
- 如果该 GUI 没有名称且非默认 GUI, 则操作时必须使用其 HWND. 通过 +HwndGuiHwnd 选项可以保存新窗口的句柄到 GuiHwnd. `Gui, %GuiHwnd%:Default` 可将其设为其他 Gui 命令的默认操作对象.

好的方面是:

- 调用 `Gui New` 可确保脚本创建新的 GUI 而不修改已有的 GUI. 这也使的脚本目的明确, 其他用户(或自己以后) 更容易看懂.
- `Gui New` 使得无需获取每个 GUI 的句柄和编号. 如果脚本需要创建多个 GUI 或打算包含于其他脚本时, 这样特别有用.
- 有时, 创建 GUI 而不显示时设置窗口的标题会更直观.

如果不指定名称, 则应用下列规则:

- 特殊的标签(如 GuiClose) 含有默认的 "Gui" 前缀, 不过可以在选项中使用 +LabelPrefix 覆盖.
- 不论 GUI 是否开启了新线程, A_Gui 总是包含句柄而非名称.

注意: 在 [v1.1.08] 之前, 在指定名称时此子命令不会设置它为默认的 Gui.

### Add

添加控件到 GUI 窗口(必要时首先创建 GUI 窗口).

    Gui, Add, ControlType , Options, Text

ControlType 为下列的其中一个:

- Text(文本), Edit(编辑框), UpDown(加减按钮), Picture(图片)
- Button(按钮), Checkbox(勾选框), Radio(单选按钮)
- DropDownList(下拉列表), ComboBox(组合框)
- ListBox(列表框), ListView(列表视图), TreeView(树形列表)
- Link(链接), Hotkey(热键), DateTime(时间日期选择器), MonthCal(月历)
- Slider(滑块), Progress(进度条)
- GroupBox(分组框), Tab(选项卡), StatusBar(状态栏)
- ActiveX(例如 Internet Explorer 控件)
- Custom(自定义控件)

Options 是一个由零或多个选项组成的字符串, 如以下章节所述:

- 控件的位置和大小
- 存储和响应用户输入
- 控件: 通用样式和其他选项

例如:

    Gui, Add, Text,, Please enter your name:
    Gui, Add, Edit, vName
    Gui, Show

### Show

如果没有在 Options 中明确指定, 那么此命令会让窗口以可见, 非最小化(必要时), 激活并设置它的标题的状态显示.

    Gui, Show , Options, Title

如果省略了 Title, 则保留原来的标题(如果没有, 则使用脚本的文件名).

省略后面的 X, Y, W 和 H 选项则让窗口保持原来的大小和位置. 如果之前没有设置过位置, 则在后面提到的 X 和/或 Y 选项没有指明的坐标上窗口将自动居中. 如果之前没有设置过大小, 则窗口会根据它所包含控件的大小和位置自动调整大小.

在 Options 中可以包含零个或多个下列字符串(规定其中的数字使用十进制, 而不是十六进制):

Wn: 指定 n 为窗口工作区的宽度(单位为像素), 窗口工作区指除了窗口边框, 标题栏和菜单栏的区域.

Hn: 指定 n 为窗口工作区的高度, 单位为像素.

Xn: 指定 n 为窗口在屏幕中的 X 坐标, 单位为像素. 0 表示屏幕最左边首列可见像素的位置.

Yn: 指定 n 为窗口在屏幕中的 Y 坐标, 单位为像素. 0 表示屏幕最上边首行可见像素的位置.

Center: 让窗口在屏幕的水平和垂直方向上居中.

xCenter: 让窗口在屏幕的水平方向上居中. 例如: `Gui, Show, xCenter y0`.

yCenter: 让窗口在屏幕的垂直方向上居中.

AutoSize: 根据窗口当前包含的可见控件调整窗口的大小. 这常在添加新控件, 调整现有控件的大小或隐藏/显示现有控件后用来调整窗口的大小. 例如: `Gui, Show, AutoSize Center`

Minimize: 最小化当前窗口并激活其下方的窗口.

Maximize: 最大化并激活窗口.

Restore: 当窗口处于最小化或最大化状态时, 还原窗口. 当窗口隐藏且不活动时, 则显示并激活窗口.

NoActivate: 当窗口处于最小化或最大化状态时, 还原窗口. 窗口显示但不进行激活.

NA: 显示窗口但不进行激活. 如果窗口处于最小化状态, 那么它仍保持这种状态, 但可能提升它的 z 顺序(这是在 alt-tab 选择器中看到的顺序). 如果窗口之前是隐藏的, 则此参数可能会让它显示在当前仍处于活动状态的窗口上面.

Hide: 隐藏窗口并激活其下方的窗口. 除了允许隐藏窗口被移动, 重设大小或在不显示的情况下设置新的标题外, 此参数与 Gui Cancel 的功能相同. 例如: `Gui, Show, Hide x55 y66 w300 h200, New Title`.

### Submit

保存每个控件的内容到其关联变量中(如果有) 并且在没有使用 NoHide 选项时隐藏窗口.

    Gui, Submit , NoHide

对于那些产生多个字段输出的控件, 例如多选列表框, 输出结果中使用窗口的当前分隔符来分隔多个字段的内容. 如果由于之前使用 Gui Destroy 销毁了窗口或其他原因使得窗口不存在, 那么此子命令没有效果.

### Cancel / Hide

隐藏当前窗口, 并不保存控件的内容到其关联变量中.

    Gui, Cancel
    Gui, Hide

如果由于之前使用 Gui Destroy 销毁了窗口或其他原因使得窗口不存在, 那么此子命令没有效果.

### Destroy

移除当前窗口(如果它存在) 及其所有控件, 并释放其占用的内存和系统资源.

    Gui, Destroy

如果脚本之后重新创建窗口, 那么窗口的所有属性(例如颜色和字体) 初始都为默认值(如同窗口从没有出现过一样). 如果没有使用 `Gui Destroy`, 则当脚本退出时会自动销毁所有的 GUI 窗口.

### Font

为在此处之后创建的控件设置字体字型, 大小, 样式和/或颜色.

    Gui, Font , Options, FontName

例如:

    gui, font, s10, Verdana  ; 设置 10 点大小的 Verdana 字体.

省略最后两个参数可以让字体恢复为系统默认的 GUI 字型, 大小和颜色.

FontName 可以是任意字体的名称, 例如字体表的其中一个. 如果省略了 FontName 或此字体在系统中不存在, 则使用之前的字体字型(如果没有, 则使用系统默认的 GUI 字型). 即使某些系统缺少首选字体, 这种特性也可以让窗口在多个系统上具有类似的字体. 例如, 按顺序执行下列命令, 则 Verdana 字体优先于 Arial, 而 Arial 字体优先于 MS Sans Serif:

    Gui, Font,, MS Sans Serif
    Gui, Font,, Arial
    Gui, Font,, Verdana  ; 首选字体.

如果 Options 参数为空, 则使用之前的字体属性. 或者可以在其中指定下列的一个或多个选项字母:

C: 颜色名称(请参阅颜色图表) 或 RGB 值, 或指定单词 Default 来恢复到系统默认颜色(大多数系统的默认颜色为黑色). 例如: `cRed`, `cFFFFAA`, `cDefault`. 注意: 按钮不遵循自定义颜色. 此外, 可以通过包含 C 选项创建带有字体颜色的特殊控件不会受到当前选项的影响. 例如: `Gui, Add, Text, cRed, My Text`.

S: 字体大小(单位为磅). 例如: `s12`(规定为十进制, 而不是十六进制)

W: 字体粗细, 这是介于 1 和 1000 之间的数字(400 为标准大小而 700 为粗体). 例如: `w600`(规定为十进制, 而不是十六进制)

还支持使用下列单词: bold, italic, strike, underline 和 norm. 指定 Norm 则让字体恢复标准粗细并去除斜体, 删除线和下划线效果(但保持现有的颜色和大小). 可以使用 norm 去除所有属性然后有选择的设置其他属性. 例如, 指定 `norm italic` 将设置字体为标准然后增加斜体属性.

要指定多个选项, 请在选项间使用空格分隔. 例如: `cBlue s12 bold`.

如果一个脚本中创建了多个 GUI 窗口, 那么其中的每个窗口都会记住它自己的 "当前字体" 属性, 可以用于后面创建的控件.

相关提示, 操作系统提供了标准的对话框让用户选取字体, 颜色或图标. 使用 DllCall() 可以显示这些对话框, 演示的例子请参阅 GitHub.

Q: [AHK_L 19+]: 文本呈现质量. 例如: `q3`. 应该在 Q 后跟着下表中的一个数字:

数字 | Windows 常量 | 描述
--- | --- | ---
0 | DEFAULT_QUALITY | 保持字体的外观.
1 | DRAFT_QUALITY | 字体外观不如使用 PROOF_QUALITY 值时那么重要.
2 | PROOF_QUALITY | 字体的字符质量比准确符合逻辑字体属性更重要.
3 | NONANTIALIASED_QUALITY | 不对字体修边, 即不进行平滑处理.
4 | ANTIALIASED_QUALITY | 如果字体支持且字体不会太小或太大时, 则对字体进行修边或平滑.
5 | CLEARTYPE_QUALITY | Windows XP 以及更高版本: 如果设置此选项, 则(尽可能) 使用 ClearType 抗锯齿方法描绘文本.

关于这些值含义的更多细节, 请参阅 MSDN: CreateFont.

由于默认设置通常是最好的品质, 所以这个功能往往用于在特殊情况时禁用抗锯齿效果, 这样可以让文本更清晰.

### Color

设置窗口和/或其控件的背景颜色.

    Gui, Color , WindowColor, ControlColor

设置 WindowColor 为 GUI 窗口自己的背景颜色. ControlColor 应用于窗口中所有现在和将来的控件(不过某些类型的控件不支持自定义颜色). 虽然 ListViews 和 TreeViews 初始颜色遵循 ControlColor, 但之后改变 ControlColor 不会对它们造成影响. 在这种情况下, 使用 `GuiControl +BackgroundFF9977, MyListView` 来明确更改它们的颜色.

让两个参数中的某个留空可以保持当前的颜色设置. 否则, 指定 16 种 HTML 基础颜色之一或 6 位的 RGB 颜色值(0x 前缀可以省略), 或指定单词 Default 来恢复到默认颜色. 例如: `Silver`, `FFFFAA`, `0xFFFFAA`, `Default`.

默认情况下, 窗口的背景颜色为系统按钮的颜色, 而控件的背景颜色为系统默认窗口的颜色(通常为白色).

菜单栏及其子菜单的颜色可以这样改变, 例如: `Menu, MyMenuBar, Color, White`.

要让窗口的背景透明, 请使用 WinSet TransColor. 然而, 如果在进行这样的操作前没有使用 Gui Color 为窗口设置自定义的颜色, 那么按钮也将变成透明的. 要避免此问题, 应首先为窗口设置自定义的颜色, 然后让此颜色透明. 例如:

    Gui, Color, EEAA99
    Gui +LastFound  ; 让 GUI 窗口成为上次找到的窗口以用于下一行的命令.
    WinSet, TransColor, EEAA99

此外, 如果要移除背景透明的窗口的边框和标题栏, 请在设置窗口为透明 后 使用下面的命令:

    Gui -Caption  ; 如果它不是默认窗口, 则使用 Gui, GuiName:-Caption.

为了阐明上面的情况, 请参阅此页面底部的屏幕显示(OSD) 的例子.

### Margin

在自动排列没有明确指定 X 或 Y 坐标的控件时, 设置距离窗口的左/右和上/下侧留下的空间的像素值.

    Gui, Margin , X, Y

此外, 还可以使用边距来确定自动定位控件之间的垂直距离和水平距离. 最后, 第一次使用 Gui Show 来计算窗口的大小时, 要考虑到此边距(在没有明确指定窗口大小时).

`Gui, Margin` 仅影响默认窗口, 而 `Gui, Name:Margin` 仅影响命名窗口. 如果没有使用此命令, 当添加首个控件到窗口时, 窗口会根据当前选择的字体的大小按比例计算出默认的边距(上下边距为字体高度的 0.75 倍, 而左右边距为字体高度的 1.25 倍).

尽管在添加控件的过程中可以改变边距, 但这仅影响后面添加的控件, 而不影响现在的. 最后, X 或 Y 的其中任意一个可以留空来保持相应的边距不变.

### 窗口的选项和样式

在 GUI 命令之后, 可以立即指定一个或多个选项.

    Gui, +/-Option1 +/-Option2 ...

处于性能原因, 最好在一行中设置所有选项, 并在创建窗口之前(即在使用任何其他子命令例如 Gui Add 之前) 使用一行语句指定所有的选项.

此命令的效果是累加的; 即它只改变那些明确指定的选项, 而其他所有选项则保持不变.

在选项前指定加号表示增加此选项, 而减号表示移除它. 例如:

    Gui +Resize -MaximizeBox  ; 改变默认 GUI 窗口的设置.
    Gui MyGui:+Resize -MaximizeBox  ; 改变名称为 MyGui 的 GUI 窗口的设置.

AlwaysOnTop: 让窗口置顶, 与 WinSet AlwaysOnTop 的效果相同.

Border: 为窗口增加细边框. 此选项不常用.

Caption(默认具有此选项): 为窗口增加标题栏和粗边框. 如果要移除将要使用 WinSet TransColor 设置透明的窗口的标题栏, 那么在需要在设置 TransColor 后才进行移除.

Delimiter: 指定管道(|) 外的其他字符作为窗口的字段分隔符, 每当使用 Gui Add 添加, 使用 GuiControl 修改, 使用 Gui Submit 或 GuiControlGet 获取控件的内容时. 在单词 Delimiter 后紧跟着单个字符. 例如, `Gui +Delimiter`n` 将使用换行符, 这可能特别适合于延续片段. 同样, 使用 `Gui +Delimiter|` 将恢复为默认的分隔符. 要使用空格或 tab, 指定 `Gui +DelimiterSpace` 或 `Gui +DelimiterTab`. 一旦改变数据分隔符, 它会影响作用于这个特殊窗口的所有现在和后续的线程.

Disabled: 禁用窗口, 阻止用户和窗口中的控件交互. 此选项常用于含有子窗口的窗口(请参阅 Owner).

DPIScale [v1.1.11+]: 使用 `Gui -DPIScale` 禁用 DPI 缩放, 它默认是启用的. 如果在使用非标准 DPI 设置的系统上启用 DPI 缩放, 则 Gui 子命令会自动调整坐标和尺寸来让控件具有大致相同的外观尺寸(不过解析率更高). 例如, 对于 144(150%) 的 DPI, `Gui Show, w100` 会让 Gui 宽度为 150 像素, 但 A_GuiWidth 将保持 100. A_ScreenDPI 包含了系统当前 DPI.

DPI 缩放比例仅适用于 Gui 子命令, 所以类似 ControlGetPos 或 WinGetPos 命令返回的坐标无法工作. 解决方案如下列:

- 尽量避免使用硬编码坐标系统. 例如, 使用类似 xp, xs, xm 和 x+m 选项设置控件的相对位置且用像素来设置多行文本的高度值.
- 根据具体情况灵活的开启 (`Gui +DPIScale`) 和关闭 (`Gui -DPIScale`) DPI 缩放比例设置. 更改这个设置并不会影响已经设置过的坐标或大小.
- 手动测量坐标. 例如, `x*(A_ScreenDPI/96)` 会将 x 从 Gui 坐标系(逻辑) 转换为非 Gui 坐标系(物理).

Hwnd OutputVar [v1.1.04+]: 此选项保存 GUI 的窗口句柄(HWND) 到 OutputVar. 例如: `Gui +HwndMyGuiHwnd`. 在函数中使用时, MyGuiHwnd 会被视为函数动态变量. GUI 的 HWND 常用于 PostMessage, SendMessage 和 DllCall(). 它还可以直接作为 ahk_id WinTitle 或代替 GUI 名称来使用, 例如 `Gui %MyGuiHwnd%:Destroy`.

Label [v1.0.44.09+]: 为当前窗口的特殊标签指定自定义名称. 例如, `Gui MyGui:+LabelMyGui_On` 将使用标签 MyGui_OnClose 和 MyGui_OnSize(如果它们存在) 分别代替 MyGuiGuiClose 和 MyGuiGuiSize. 换句话说, 在所有特殊标签的名称中字符串 "MyGuiGui" 被替换为 "MyGui_On". 这可以让多个窗口使用一套相同的标签(此时脚本可以根据 A_Gui 来确定运行子程序的窗口是哪个).

LastFound: 设置窗口为上次找到的窗口(对于 Gui 线程这是多余的, 因为它自动设置了), 这样允许类似 WinSet 这样的命令对此窗口进行操作, 即使它当前为隐藏状态(即不需要使用 DetectHiddenWindows). 需要在显示窗口之前改变其属性时, 这是非常有用的. 例如:

    Gui +LastFound
    WinSet, TransColor, %CustomColor% 150
    Gui Show

LastFoundExist [v1.0.43.09+]: 和其他选项不同, LastFoundExist 选项只有在单独使用时才有效. +LastFoundExist 的效果与 +LastFound 相同, 不过如果窗口不存在时不会创建窗口. 此选项的主要用途是判断是否存在某特殊的窗口. 例如:

    Gui MyGui:+LastFoundExist
    if WinExist()
        MsgBox GUI "MyGui" already exists.

MaximizeBox: 启用标题栏上的最大化按钮. 下面的 Resize 也含有此效果.

MinimizeBox(默认含有此选项): 启用标题栏上的最小化按钮.

MinSize 和 MaxSize [v1.0.44.13+]: 限定窗口的最小尺寸和最大尺寸, 例如当用户拖动窗口边框改变其大小的时候. 指定不带后缀的单词 MinSize 和/或 MaxSize 来使用窗口当前尺寸作为限制大小(如果没有窗口当前尺寸, 则使用首次 Gui Show 时显示的大小). 还可以在后面加上宽度, 跟着 X 和高度, 例如: `Gui +Resize +MinSize640x480`. 它们指定了以像素为单位的窗口工作区(不包括边框, 标题栏和菜单栏) 的大小. 规定每个数字为十进制, 而不是十六进制.

可以省略高度或宽度以保持不变(例如 `+MinSize640x` 或 `+MinSizex480`). 而且, 可以多次指定 Min/MaxSize 以便在一个方向上使用窗口当前的尺寸而另一个则使用指定的大小. 例如, `+MinSize +MinSize640x` 表示最小高度限制为窗口当前的大小而最小宽度限制为 640.

如果从没有使用 MinSize 和 MaxSize, 则使用操作系统的默认值(同样地, 可以使用 `Gui -MinSize -MaxSize` 恢复为此默认值).

注意: 必须含有 +Resize 才能允许用户调节窗口的大小.

OwnDialogs: 在每个线程(例如 ButtonOK 子线程) 中指定 `Gui +OwnDialogs`, 这样所有后续的 MsgBox, InputBox, FileSelectFile 以及 FileSelectFolder 对话框才会成为当前窗口的子窗口. 这时这些对话框成为模式对话框, 这意味着用户必须先关闭这些对话框才能和它们的父窗口进行交互. 与之相比, ToolTip, Progress 和 SplashImage 窗口即使成为了其他窗口的子窗口也为非模式的; 它们仅仅是永远显示在其父窗口的上面. 在模式和非模式窗口两种情况中, 当它们的父窗口销毁时它们也会被自动销毁.

一般情况下打开这个设置后不需要再切换到关闭, 因为它不影响其他线程. 但是, 如果一个线程需要显示从属和非从属对话框, 则可以使用 `Gui -OwnDialogs` 关闭此设置.

如果在前缀中没有使用窗口名称(例如使用 `Gui +OwnDialogs` 而不是 `Gui MyGui:+OwnDialogs`), 则当前线程的默认窗口将拥有这些从属对话框.

Owner: 使用 +Owner 可以让当前窗口从属于另一个窗口. 从属的窗口默认不显示在任务栏, 并且它总是显示在其父窗口的上面. 当其父窗口销毁时它也被自动销毁. +Owner 必须在父窗口创建 后 使用, 而在 [v1.1.05] 及更高版本中可以在从属窗口创建前面或后面使用. +owner 有两种使用方法, 如下所示:

    Gui, MyGui:+OwnerMyOtherGui  ; 让 MyGui 成为 MyOtherGui 的子窗口.
    Gui, MyGui:+Owner  ; 让 MyGui 成为脚本主窗口的子窗口, 这样可以阻止任务栏按钮的显示.

[v1.1.03+]: `+Owner` 后面可以紧跟着现有的 Gui 或任何顶级窗口的 HWND 的名称或编号.

兼容性注意: 在 [v1.1.03] 及更高版本中, `+Owner` 移除 WS_CHILD 样式并设置 WS_POPUP 样式. 要设置某个 Gui 的父窗口, 脚本必须使用 `+Parent` 选项或 在 `+Owner` 选项后覆盖适当的样式.

在某个从属窗口显示时要防止用户与其父窗口交互, 请使用 `Gui +Disabled` 禁用父窗口. 之后(当子窗口取消或销毁时), 通过 `Gui -Disabled` 来重新启用父窗口. 在取消或销毁子窗口前这样做可以让父窗口自动恢复有效.

Parent [v1.1.03+]: 使用 `+Parent` 后面紧跟着要拥有此窗口的现有 Gui 或任何窗口或控件的 HWND 的名称或编号. 要恢复 Gui 为顶级窗口, 请使用 `-Parent`. 在窗口创建后此选项也有效.

Resize: 此选项允许用户重新调整窗口的大小并启用标题栏上的最大化按钮. 要禁用最大化按钮, 请指定 `+Resize -MaximizeBox`.

SysMenu(默认含有此选项): 指定 `-SysMenu`(负 SysMenu) 可以删除点击窗口左上角时弹出的系统菜单和图标. 同时也删除标题栏上的最小化, 最大化和关闭按钮.

Theme: 指定 `-Theme`, 可以让后续创建的所有控件在 Windows XP 以及更高版本中使用经典主题外观. 之后要创建其他使用当前主题的控件时, 请使用 `+Theme` 把设置切换回来.

注意: 此选项在比 Windows XP 早的系统上没有效果, 如果 XP 中当前使用经典主题时也没有效果.

最后, 对于单独的控件还可以在其创建的选项中指定 `+Theme` 或 `-Theme` 来改变此设置.

ToolWindow: 让窗口显示细标题栏, 同时去除任务栏按钮. 无论是否存在 WS_MAXIMIZEBOX 和 WS_MINIMIZEBOX 样式, 这总是隐藏了最大化和最小化按钮.

(未命名样式): 在十进制或十六进制的样式编号前加上加号或减号表示添加或删除此样式.

(未命名扩展样式): 在字母 E 和十进制或十六进制的扩展样式编号前加上加号或减号表示添加或删除此扩展样式. 例如, `+E0x40000` 表示添加 WS_EX_APPWINDOW 样式, 此样式让窗口显示任务栏按钮. 对于这里没有列出其他的扩展样式编号(因为它们极少使用), 请参阅 Extended Window Styles | Microsoft Docs 以获取完整的列表.

### Menu

添加菜单栏到窗口.

    Gui, Menu , MenuName

使用 Menu 命令可以创建普通的菜单. 例如:

    Menu, FileMenu, Add, &Open`tCtrl+O, MenuFileOpen  ; 关于 Ctrl+O 请参阅后面的备注.
    Menu, FileMenu, Add, E&xit, MenuHandler
    Menu, HelpMenu, Add, &About, MenuHandler
    Menu, MyMenuBar, Add, &File, :FileMenu  ; 附加上面的两个子菜单.
    Menu, MyMenuBar, Add, &Help, :HelpMenu
    Gui, Menu, MyMenuBar

注意在上面的首行中, `&Open` 后面跟着 `Ctrl+O`(它们之间含 tab). 这表示用户可以按下快捷键代替选择菜单项来执行操作. [v1.1.04+]: 如果这样的快捷键中只使用了标准的修饰键名称 Ctrl, Alt 和 Shift, 那么它会被自动注册为这个 GUI 的 键盘快捷键. 不含修饰键的单字母快捷键是区分大小写的, 且可以使用不常见的方法触发, 例如 IME 或 `Alt`+NNNN.

如果特殊的按键组合没有自动生效, 请使用上下文相关热键. 然而, 这样的热键一般不能使用 Send 触发, 并且比起标准的键盘快捷键它们更可能和其他脚本产生冲突.

要移除窗口当前的菜单栏, 请使用 `Gui Menu`(即省略最后一个参数).

一旦菜单被设置为窗口的菜单栏, 它就不能用于弹出菜单或子菜单. 这是因为菜单栏内部使用了不同的格式(不过, 这只限制菜单栏自身, 而不包括其子菜单). 如果您一定要这样实现, 那么先创建一个菜单用于菜单栏, 再创建另一个相同的菜单用于其他目的.

对当前正用于菜单栏(在某些情况下包括其子菜单) 使用某些破坏性的 menu 子命令(例如 Delete 和 DeleteAll) 时, 这些命令会无效并显示错误对话框(可以使用 UseErrorLevel 来避免). 可以使用下列步骤改变窗口菜单栏中的菜单: 1) 使用 `Gui Menu`(省略 MenuName) 从窗口中分离菜单; 2) 改变菜单; 3) 使用 `Gui, Menu, MyMenuBar` 重新附加菜单到窗口.

### Minimize / Maximize / Restore

打开窗口(如果需要), 然后对其执行指定的操作.

    Gui, Minimize
    Gui, Maximize
    Gui, Restore

如果该窗口不存在 -- 可能由于通过 Gui Destroy 销毁了 -- 则该子命令无效.

### Flash

闪烁窗口的任务栏按钮.

    Gui, Flash , Off

这是通过反转窗口的标题栏和/或任务栏按钮(如果有) 的颜色实现的. 可以加上选项 OFF 让标题栏和任务栏按钮恢复到它们最初的颜色(但实际效果可能受操作系统版本影响). 在下面的例子中, 窗口将闪烁三次, 因为每对闪烁都会在对它们反转后恢复原来的外观:

    Loop 6
    {
        Gui Flash
        Sleep 500  ; 这个时间值十分敏感, 改变它可能引起异常.
    }

### Default

改变当前线程的默认 GUI 窗口名称.

    Gui, GuiName:Default

这是在没有指定窗口名称时用于 GuiControl, GuiControlGet 和 Gui 命令自身的默认窗口. 在接下来的例子中, 默认窗口名称被改变为 "MyGui": `Gui MyGui:Default`. 请参阅线程的默认窗口了解关于默认窗口的更多细节.

[v1.1.03+]: GuiName 可以是一个脚本的 GUI 窗口的 HWND. 如果窗口有一个名称, 它就会成为默认名称并且即使在窗口本身被销毁之后仍然是这样. 如果窗口没有名称, 当窗口被销毁时, 默认名称将恢复为 1.

[v1.1.23+]: 内置变量 A_DefaultGui 包含默认 GUI 的名称或数字.

## 控件的选项(Gui Add)

### 控件的位置和大小

注意: 虽然本节中描述的选项能适用于简单的布局, 但你可能会发现使用 Rajat 的 SmartGUI Creator 更容易, 因为它完全是可视化的, 即 "所见即所得". SmartGUI Creator 是免费的, 可以从 www.autohotkey.com/docs/SmartGUI/ 下载.

如果在 Options 中省略了某些尺寸和/或坐标, 则会根据前一个控件确定它的位置, 根据控件的类型和内容确定它的大小.

支持下列选项:

R: 指定文本的行数(可以为浮点数, 如 R2.5). 使用 R 通常比 H(高度) 更合适. 如果同时指定 R 和 H 选项, 则 R 优先考虑. 对于 GroupBox, 此选项设置在框中可以容纳的控件数目. 对于 DropDownLists, ComboBoxes 和 ListBoxes, 此选项设置在控件的列表部分一次可以看到的项目数(但在 Windows XP 或更高版本中, 对于 DropDownList 和 ComboBox 控件常常同时省略 R 和 H 选项, 这样可以让弹出的列表自动设置为用户桌面的可用高度). 对于其他类型的控件, R 表示控件内可见的文本行数.

W: 宽度, 单位为像素. 如果省略, 对于某些控件则根据其内容自动计算宽度. 其他类型的控件具有下列默认的宽度值; 选项卡控件默认为 30 倍的当前字体大小加上 3 倍的 X-margin(行边距); 垂直进度条默认为 2 倍的当前字体大小; 而水平进度条, 水平滑动条, DropDownList, ComboBox, ListBox, GroupBox, Edit 和 Hotkey 默认为 15 倍的当前字体大小(GroupBox 例外, 其默认宽度为 18 倍, 这样可以显示内部的边距).

H: 高度, 单位为像素. 如果 H 和 R 选项同时省略, 则 DropDownList, ComboBox, ListBox 和初始内容为空的多行 Edit 控件默认为 3 行; GroupBox 默认为 2 行; 垂直滑动条和进度条默认为 5 行; 水平滑动条默认为 30 像素(在没有指定其厚度时); 水平进度条默认为 2 倍的当前字体大小; Hotkey 控件默认为 1 行; 而 Tab 控件默认为 10 行. 对于其他类型的控件, 根据它们的内容自动计算高度. 请注意对于 DropDownList 和 ComboBox, H 为控件总是可见的部分(大概指列表上面的框) 和其列表部分相加的高度(但即使高度设置很小, 也至少会在下拉列表中显示一个项目). 同时对于所有类型的控件, 通过 R 选项指定行数比使用 H 更可取, 因为这样可以避免在控件中显示部分/不完整的文本行.

wp+n, hp+n, wp-n, hp-n(其中 n 可以为任意数字) 用来设置控件的宽度和/或高度等于前一个添加控件的宽度或高度, 可以使用加号或减号进行调整. 例如, `wp` 将设置控件的宽度等于之前的控件, 而 `wp-50` 则设置宽度为之前的控件宽度减去 50 像素.

X, Y: X-坐标, Y-坐标. 例如, 指定 `x0 y0` 则把控件放置到窗口工作区的左上角, 窗口工作区是在标题栏和菜单栏(如果有) 下面的区域.

x+n, y+n (其中 n 可以为任意数字): 可以包括一个可选的加号, 以相对于前一个添加的控件的右边缘或底边缘(分别) 定位一个控件. 例如, 指定 `Y+10` 将把控件放置在前一个控件底部下面 10 个像素的位置, 而不使用标准的填充间距. 同样地, 指定 `X+10` 将把控件放置在前一个控件右边缘的右边 10 个像素的位置. 由于负数如 `X-10` 表示绝对的位置, 因此要使用负的位置偏移, 需要在前面加上一个加号. 例如: `X+-10`.

[v1.1.16+]: 对于 X+ 和 Y+, 可以用字母 M 来代替窗口的当前边距. 例如, `x+m` 使用前一个控件的右边缘位置加上标准填充间隔. `xp y+m` 将控件放置于前一个之下, 而单独指定一个相对的 X 坐标(使用 xp 或 x+), 相当于默认情况下隐式的 `yp`.

xp+n, yp+n, xp-n, yp-n(其中 n 可以为任意数字) 可以用来指定控件相对于前一个控件左上角的位置, 此选项常用于 GroupBox 中的封装控件.

xm 和 ym 可以用来将一个控件分别定位在窗口的最左边和最上面的边缘(它们后面也可以加上一个正/负号和一个数字).

xs 和 ys: 这与 xm 和 ym 类似, 只是它们是相对于前一个选项中带有 Section 单词的控件所保存的坐标(窗口的第一个控件总是开始一个新列, 即使这个单词没有在其选项中指定). 例如:

    gui, add, edit, w600  ; 在窗口的顶部添加一个非常宽的编辑控件.
    gui, add, text, section, First Name:  ; 保存此控件位置并定义一个新控件段.
    gui, add, text,, Last Name:
    gui, add, edit, ys  ; 在此控件段中开始一个新列.
    gui, add, edit
    gui, show

xs 和 ys 后面可以跟着一个加号/减号和一个数字. 并且, 还可以在控件的选项中同时指定单词 Section 和 xs/ys; 这样可以让当前控件使用之前的控件段, 但为后续控件定义一个新段.

省略 X, Y 或两者都是有用的, 可以使 GUI 布局自动调整, 以适应将来可能对控件大小或字体所做的任何更改. 相比之下, 为每个控件指定绝对位置可能需要手动移动正在放大或缩小的控件下面和/或右侧的所有控件的位置.

如果 X 和 Y 都被省略, 控件将使用标准填充距离(当前边距) 被放置在前一个控件的下面.

如果只省略了一个组件, 它的默认值取决于使用哪个选项来指定其他组件:

指定了 X | Y 的默认值
--- | ---
xn 或 xm | 在所有之前控件的下方(最大 Y 范围加边距).
xs | 在最近一次使用 Section 选项后的所有之前控件的下方.
x+n 或 xp | 等同于前一个控件的顶部边缘(yp).
指定了 Y | X 的默认值
yn 或 ym | 在所有之前控件的右边(最大 X 范围加边距).
ys | 自最近一次使用 Section 选项以来, 所有先前控件的右边.
y+n 或 yp | 等同于前一个控件的左边缘(xp).

### 存储和响应用户的输入

V: 变量. 为控件分配关联变量. 在字母 V 后指定一个变量名, 此变量将为全局变量(或指向全局变量的 ByRef 局部变量, 在 [v1.0.46.01+] 还可能为静态变量). 例如, 指定 `vMyEdit` 后, 每当执行 Gui Submit 命令时将把控件的内容保存到变量 MyEdit. 如果控件是不可输入型(例如 Text 控件或 GroupBox), 那么为其分配的关联变量作为控件的唯一标识符仍可用于 GuiControl, GuiControlGet 和 A_GuiControl.

注意: Gui Submit 不会改变不可输入型控件(例如 Text 和 GroupBox) 关联变量的内容, 也不会改变其他某些控件的内容(例如 ListView 和 TreeView).

G: Gosub(g-标签). 当用户点击或改变控件内容时会自动运行的子程序. 在字母 G 后指定需要执行的标签名称. 可以指定 `gCancel` 来隐式执行 Gui Cancel(但如果在脚本中存在名称为 "Cancel" 的标签, 则会执行此标签). 在子程序中可以引用下列内置变量: A_Gui, A_GuiControl, A_GuiEvent, A_EventInfo 和 A_ThisLabel.

[v1.1.20+]: 如果不是一个有效标签名称, 可以用函数名称替代. 或者, 可以用 GuiControl 命令为控件连接一个函数对象. 函数(用 `gCtrlEvent` 设置的函数名称为 CtrlEvent) 可以接受以下可选参数:

    CtrlEvent(CtrlHwnd, GuiEvent, EventInfo, ErrLevel:="")

这些参数的意义取决于控件的类型. 注意, 如果第四个参数声明时没有默认值, 那么只有提供四个参数的事件才会调用该函数.

### 控件: 常用样式和其他选项

注意: 选项前的符号省略时, 默认为加号, 例如 `Wrap` 等同于 `+Wrap`. 相反地, `-Wrap` 将去除自动换行属性.

AltSubmit: 使用备用的提交方法. 对于 DropDownList, ComboBox 和 ListBox 此选项会让 Gui Submit 命令保存选择项目的位置而不是其文本. 如果没有选择项目, 则对于 ComboBox 会保存其编辑区域的文本; 同样地, 对于 DropDownList 或 ListBox 则把它们的关联输出变量设置为空. 注意: AltSubmit 还会影响 GuiControlGet 获取这些控件内容时的行为.

C: 文本颜色(对按钮控件无效). 指定字母 C 后面紧跟着颜色名称(请参阅颜色图表) 或 RGB 值(0x 前缀可以省略). 例如: `cRed`, `cFF2211`, `c0xFF2211`, `cDefault`.

Choose: 在 ComboBox, DateTime, DropDownList, ListBox 或 Tab 控件中预选一个项目. 指定单词 `Choose` 后面紧跟着一个项目的编号. 例如: `Choose2`

Disabled: 让可输入型控件变为灰色禁用状态, 这样可以防止取得焦点或用户改变其内容. 以后可以使用 GuiControl Enable 来启用控件. 注意: 要让编辑控件为只读状态, 请指定 `ReadOnly` 选项代替. 并且, 还可以在单词 Disabled 后紧跟着 0 或 1 来表示控件的初始状态(0 为启用而 1 为禁用). 换句话说, `Disabled` 和 `Disabled%VarContainingOne%` 是一样的.

Hidden: 让控件初始为隐藏状态. 以后可以使用 GuiControl Show 来让它显示. 可以在单词 Hidden 后跟着 0 或 1 来表示初始状态(0 为可见而 1 为隐藏). 换句话说, `Hidden` 和 `Hidden%VarContainingOne%` 是一样的.

Left: 在控件的可用宽度内左对齐控件的文本.

Right: 在控件的可用宽度内右对齐控件的文本. 对于复选框和单选按钮, 此选项也同时把框放置在控件的右边而不是左边.

Center: 在控件的可用宽度内居中对齐控件的文本.

Section: 定义一个新的控件段并保存当前控件的位置以便在之后创建含有 xs 和 ys 选项的控件时使用, 请参阅上文的描述.

Tabstop: 使用 `-Tabstop`(即负 Tabstop) 可以让用户按 `Tab` 导航时跳过输入型控件.

Wrap: 让控件的文本自动换行. 因为几乎所有类型的控件初始状态都启用了自动换行, 所以需要通过 `-Wrap` 禁用它.

VScroll: 当控件支持时为其提供一个垂直滚动条.

HScroll: 当控件支持时为其提供一个水平滚动条. 这个段落的剩余部分仅适用于 ListBox. 水平滚动的宽度默认为 ListBox 宽度的 3 倍. 要使用其他的滚动宽度, 请在单词 HScroll 后紧跟着一个数字表示. 例如, `HScroll500` 将在 ListBox 中使用 500 像素的滚动栏宽度. 但是, 如果指定的滚动宽度小于 ListBox 的宽度, 则不显示滚动条(不过在这种含有 HScroll 的情况下, 可以在之后使用 `GuiControl, +HScroll500, MyScrollBar` 来添加水平滚动条, 否则是无法添加的).

### 控件: 不常用样式和选项

BackgroundTrans: 使用透明的背景, 这样可以让任何一个在 Text, Picture 或 GroupBox 后面的控件显示出来. 例如, 在 Picture 控件上显示一个透明背景的 Text 可以让文字看起来就像图片的一部分. 以后可以使用 `GuiControl +background` 移除此选项. 请参阅 Picture 控件的 AltSubmit 部分来了解关于透明图像的更多细节. 已知限制: 对包含了 ListView 的 Tab 控件中的其他控件, BackgroundTrans 可能无法正确应用.

-Background(即负 Background): 使用标准的背景颜色代替 Gui Color 命令设置的那个颜色. 此选项常用于让 Tab 控件使用其标准颜色代替窗口颜色. 以后可以使用 `GuiControl +background` 移除此选项.

Border: 为控件增加一个细边框. 对于大多数控件不需要使用此选项, 因为它们已经含有特定于类型的边框. 添加一个边框到 现有 控件时, 可能需要给控件的宽度和高度增加 1 个像素.

Hwnd OutputVar [v1.0.46.01+]: 在 Gui Add 中使用时, 此选项保存新建控件的窗口句柄(HWND) 到 OutputVar. 例如: `Gui, Add, Edit, vMyEdit HwndMyEditHwnd`. 如果在函数中使用, MyEditHwnd 会被视为函数动态变量. 控件的 HWND 常用于 PostMessage, SendMessage 和 DllCall(). 它还可以直接用在 ahk_id WinTitle(即使 DetectHiddenWindows 设置关闭时, 这样对于隐藏控件也是有效的) 或在 [ v1.1.04+] 中 GuiControl 和 GuiControlGet 的 ControlID 参数. 相关提示, 父窗口的 HWND 可以使用 Gui MyGui:+HwndOutputVar 获取.

Theme: 使用此选项可以让新建的控件忽略窗口当前的主题设置. 它对于现有控件没有效果; 不过, 这种情况可能在将来的版本中改变. 请参阅 Gui +/-Theme 了解详情.

(未命名样式): 在十进制或十六进制的样式编号前加上加号或减号表示添加或删除此样式. 如果省略了符号, 则默认为加号.

(未命名扩展样式): 在字母 E 和十进制或十六进制的扩展样式编号前加上加号或减号表示添加或删除此扩展样式. 如果省略了符号, 则默认为加号. 例如, `E0x0200` 表示添加 WS_EX_CLIENTEDGE 样式, 它可以为图片和其他控件增加一个下沉的边框样式. 尽管这里没有列出其他的扩展样式编号(因为它们极少使用), 不过可以通过在 www.microsoft.com 中搜索 WS_EX_CLIENTEDGE 找到它们.

## 窗口事件

如果在脚本中存在下列的标签(子程序) 时, 它们会自动和 GUI 窗口关联:

- GuiClose
- GuiEscape
- GuiSize
- GuiContextMenu
- GuiDropFiles

[v1.1.20+]: 如果事件处理标签不存在, 那么相同名称的函数将替代标签响应. 函数可选择接收 GUI 的 HWND 作为第一个参数. 一些事件还有更多的参数.

对于非第一个窗口(多窗口的情况) , 窗口的名称或序号(如果有) 会被作为前面提到的特殊标签的前缀; 例如, 2GuiEscape 和 2GuiClose 将被作为第二窗口的默认标签, 当 MyGuiGuiEscape 和 MyGuiGuiClose 会作为 MyGui 的默认标签. 要自定义一个前缀, 请用 Gui +Label.

### GuiClose

使用下列其中一种方法关闭窗口时自动运行此子程序: 点击标题栏上的关闭按钮, 从标题栏中的系统菜单中选择 "关闭" 或使用 WinClose 关闭. 如果此标签不存在, 则关闭窗口只是简单地隐藏窗口, 与 Gui Cancel 的效果一样. 在 GuiClose 中一个最常用的动作是 ExitApp; 例如:

    GuiClose:
    ExitApp

[v1.1.20+]: 如果 GuiClose 是一个函数, GUI 默认将隐藏. 函数可以通过返回一个非零整数来防止这种情况, 如下面的例子:

    GuiClose(GuiHwnd) {  ; 这个参数声明是可选的.
        MsgBox 4,, Are you sure you want to hide the GUI?
        IfMsgBox No
            return true  ; true = 1
    }

### GuiEscape

用户在 GUI 窗口活动时按下 `Esc` 后自动运行此子程序. 如果此标签不存在, 则按下 `Esc` 没有效果. 已知限制: 如果窗口中首个控件是禁用的(可能与控件类型有关), 则按下 `Esc` 时 GuiEscape 子程序不会运行. 产生这样的效果可能是受其他一些事件的影响.

### GuiSize

对窗口调整大小, 最小化, 最大化或还原时自动运行此子程序. 内置变量 A_GuiWidth 和 A_GuiHeight 分别包含了窗口工作区调整后的宽度和高度, 窗口工作区不包括标题栏, 菜单栏和边框. 此外, A_EventInfo 和 ErrorLevel 将同时包含下列数字的其中一个:

- 0 = 窗口被还原, 或正常的通过拖拉窗口边缘调节了大小.
- 1 = 窗口被最小化.
- 2 = 窗口被最大化.

脚本中可以使用 GuiSize 调整控件的大小和位置来响应用户对窗口大小的改变. 通过 AutoXYWH() by tmplinshi and toralf 可以让这种处理更容易些.

当窗口改变大小时(脚本发出的事件), GuiSize 不一定会立即响应. 类似其他窗口事件, 如果当前线程为不可中断的, GuiSize 直到线程变为可中断之前都不会响应. 如果脚本正在改变窗口大小, 下面的例子将确保 GuiSize 立即响应:

    Critical Off  ; 无论是否设置过 Critical On.
    Sleep -1

[v1.1.22.05+]: Gui Show 会自动延迟一秒 `Sleep -1`, 所以通常无需再次使用 Sleep .

[v1.1.20+]: 如果 GuiSize 为函数, 它的参数应为:

    GuiSize(GuiHwnd, EventInfo, Width, Height)

### GuiContextMenu

当用户在窗口上除标题栏和菜单栏外的其他地方点击右键时自动运行此子程序. 当用户按下 `Menu` 或 `Shift`+`F10` 时也会运行. 和其他多数 GUI 标签不同, GuiContextMenu 可以含有多个并发线程. 在 GuiContextMenu 子程序中可以引用下列内置变量:

1. A_GuiControl, 它包含了接收事件的控件的文本或变量名(如果没有则为空).
2. A_EventInfo: 当右键点击 ListBox, ListView 或 TreeView 时(可以由上面的 A_GuiControl 确定), A_EventInfo 包含了右键点击的控件项目:
   - ListBox 或 ListView: A_EventInfo 包含了当前焦点行的行号(如果没有则为 0).
   - TreeView: 右键点击时, A_EventInfo 包含了右击项目的 ID 编号(如果用户点击到项目外的其他地方则为 0). 对于 `Menu` 和 `Shift`+`F10`, A_EventInfo 包含了选择的项目的 ID 编号.
3. A_GuiX 和 A_GuiY, 包含了菜单显示位置的 X 和 Y 坐标(例如 `Menu, MyContext, Show, %A_GuiX%, %A_GuiY%`). 这里的坐标相对于窗口的左上角.
4. A_GuiEvent, 当用户右键点击时包含单词 RightClick, 当用户按下 `Menu` 或 `Shift`+`F10` 时包含单词 Normal.

注意: 由于 Edit 和 MonthCal 控件有它们自己的右键菜单, 所以右键点击这些控件时不会运行 GuiContextMenu.

[v1.1.20+]: 如果 GuiContextMenu 为函数, 它的参数应为:

    GuiContextMenu(GuiHwnd, CtrlHwnd, EventInfo, IsRightClick, X, Y)

CtrlHwnd 如果控件没有接收到事件则为空. IsRightClick 在 A_GuiEvent 为 RightClick 时返回 True.

### GuiDropFiles

拖放文件/文件夹到窗口上时运行此子程序(如果此子程序已经在运行中, 则忽略拖放事件). 在 GuiDropFiles 中可以引用下列内置变量:

1. A_GuiControl, 它包含了接收到释放文件的控件的文本或变量名(如果没有则为空).
2. A_EventInfo 和 ErrorLevel, 包含了释放文件的数目.
3. A_GuiX 和 A_GuiY, 包含了释放文件时的 X 和 Y 坐标(相对于窗口的左上角).
4. A_GuiEvent, 包含了被释放文件的名称, 文件名之间使用换行符(`n) 分隔.

要逐个提取每个文件, 请使用解析循环, 如下所示:

    ; 示例 #1:
    Loop, Parse, A_GuiEvent, `n
    {
        MsgBox, 4,, File number %A_Index% is:`n%A_LoopField%.`n`nContinue?
        IfMsgBox, No, break
    }

    ; 示例 #2: 只要提取首个文件, 请参照此例:
    Loop, Parse, A_GuiEvent, `n
    {
        FirstFile = %A_LoopField%
        break
    }

    ; 示例 #3: 要按照文件名的字母顺序处理文件, 请参照此例:
    FileList := A_GuiEvent
    Sort, FileList
    Loop, Parse, FileList, `n
        MsgBox File number %A_Index% is:`n%A_LoopField%.

要临时禁用窗口的拖放功能, 请使用 `Gui -E0x10` 移除 WS_EX_ACCEPTFILES 样式. 后面要重新启用, 请使用 `Gui +E0x10`.

[v1.1.20+]: 如果 GuiDropFiles 为函数, 它的参数应为下面例子中那样. CtrlHwnd 当文件在 GUI 上释放时为空. FileArray 为一个包含文件名称的数组(对象), 其中 `FileArray[1]` 为第一个文件, 而 `FileArray.MaxIndex()` 返回文件的数量. 使用 for-循环可迭代枚举其中的文件:

    GuiDropFiles(GuiHwnd, FileArray, CtrlHwnd, X, Y) {
        for i, file in FileArray
            MsgBox File %i% is:`n%file%
    }

### 其他事件

其他 GUI 事件可以使用 OnMessage() 来检测和响应. 例如, 当用户把鼠标移动到窗口中特殊的控件时脚本可以通过工具提示显示相关帮助. 请参阅演示 GUI 工具提示示例.

## 创建多个 GUI 窗口

要对非默认窗口进行操作, 需要在子命令前加上窗口名称或编号(在 [v1.1.03+] 中, 还可以使用 HWND) 和一个冒号, 例如:

    Gui, MyGui:Add, Text,, Text for about-box.
    Gui, MyGui:Show

使用 `Gui MyGui:Default` 后可以去除上面使用的 "MyGui:" 前缀. 此外, 在由窗口运行的 GUI 线程中对此窗口进行操作时可以不加前缀.

[v1.1.03+]: Gui 名称必须遵循和变量名相同的规则. 在 1 到 99 范围外或长于两个字符(例如 0x01) 的数字必须为现有 Gui 的 HWND, 否则命令执行失败. 可以创建的窗口数仅受系统可用资源的限制.

[v1.1.04+]: 使用 Gui, New 可以创建任何数目的未命名 GUI 窗口.

## GUI 事件, 线程和子程序

一个 GUI 线程是由 GUI 动作启动的. GUI 动作包括从 GUI 窗口的菜单栏中选择一个项目或触发其某个 g-标签(例如按下按钮).

GUI 线程的默认窗口名称是运行此线程的窗口名称. 非 GUI 线程的默认窗口编号为 1.

当一个 GUI 线程启动时, 此线程的上次找到的窗口初始为此 GUI 窗口自身. 这样可以让窗口和控件操作命令(例如 WinMove, WinHide, WinSet, WinSetTitle 和 ControlGetFocus) 对当前的 GUI 窗口进行操作时省略 WinTitle 和 WinText(即使窗口处于隐藏状态).

当一个控件的 g-标签由于之前的点击还在运行时, 点击此控件不会有效果并且此事件被丢弃. 要避免此问题, 请在子程序的首行使用 Critical(不过, 这样也将缓冲/延迟其他线程, 例如按下的热键).

内置变量 A_Gui 和 A_GuiControl 包含了运行当前线程的窗口编号和控件 ID. 要了解详情请参阅 A_Gui 和 A_GuiControl.

要让多个事件执行相同的子程序, 请在子程序上面连续指定这些标签. 例如:

    GuiEscape:
    GuiClose:
    ButtonCancel:
    ExitApp  ; 上面的所有标签都会执行这个语句.

所有的 GUI 线程都会以设置的默认值启动, 例如 SendMode. 这些默认值可以在自动执行段改变.

## 键盘导航

使用 `Tab` 可以在 GUI 窗口中导航, 它会移动键盘焦点到下一个可输入型控件中(跳过移除了 Tabstop 样式的控件). 导航的顺序由控件添加的顺序决定. 当首次显示一个窗口时, 键盘焦点将在首个具有 Tabstop 样式(默认情况下大多数类型的控件都具有) 的可输入型控件上.

可以在某些控件的名称中包含和符号(&) 来创建此控件的键盘快捷键, 在控件名称中的快捷键字母会加上下划线显示(取决于系统设置). 用户可以通过按下 `Alt` 和相应的字符来触发这样的快捷键. 对于按钮, 复选框和单选按钮, 按下相应的快捷键等于点击了按钮. 对于 GroupBox 和 Text 控件, 按下相应的快捷键则移动键盘焦点到此控件后(不是指位置, 是创建顺序) 首个具有 tabstop 样式的可输入型控件中. 然而, 如果多个控件含有相同的快捷键, 则按下此快捷键会让键盘焦点在这些控件中交替.

要在上面提及类型的控件中显示一个原义的和符号, 请指定两个连续的和符号, 例如: `Gui, Add, Button,, Save && Exit`.

## 窗口外观

GUI 窗口使用托盘图标作为其窗口图标是在窗口创建时生效. 因此, 如果要使用不同的图标, 需要在创建窗口前改变托盘图标. 例如: `Menu, Tray, Icon, MyIcon.ico`. 还可以让窗口拥有一个不同的大图标而不用这个小图标(大图标显示在 alt-tab 任务切换器中). 这个功能可以通过 LoadPicture() 和 SendMessage 来实现; 例如:

    iconsize := 32  ; alt-tab 任务切换器中图标的理想尺寸在不同版本的系统中有所不同.
    hIcon := LoadPicture("My Icon.ico", "Icon1 w" iconsize " h" iconsize, imgtype)
    Gui +LastFound
    SendMessage 0x0080, 1, hIcon  ; 0x0080 是 WM_SETICON; 1 表示 ICON_BIG(而 0 表示 ICON_SMALL).
    Gui Show

旧版使用 DllCall 的例子留做记录, 不推荐.

    hIcon := DllCall("LoadImage", uint, 0
        , str, "My Icon.ico"  ; 图标文件名(此文件可以包含多种尺寸的图标).
        , uint, 1  ; 图像类型: IMAGE_ICON
        , int, 32, int, 32  ; 想要的高度和宽度(可以让 LoadImage 确定哪个是最佳图标).
        , uint, 0x10)  ; Flags: LR_LOADFROMFILE
    Gui +LastFound
    SendMessage, 0x0080, 1, hIcon

由于操作系统的限制, 在 Windows XP 以及更高版本中, Checkbox, Radio 和 GroupBox 控件中的文本不是使用默认颜色时将显示为经典主题外观.

相关主题: 窗口边距.

## 一般说明

使用 GuiControl 和 GuiControlGet 可以单独对 GUI 窗口中的控件进行操作.

每个 GUI 窗口最多可以包含 11,000 个控件. 然而, 当控件数量超过 5000 时需要谨慎, 因为此时某些类型的控件可能让系统不稳定.

使用 GUI 命令的任何脚本会自动成为持续运行的(即使 GUI 命令实际从未执行过). 同时也会单实例运行, 除非使用 #SingleInstance 覆盖了默认设置.

## 相关

GuiControl, GuiControlGet, Menu, 控件类型, ListView, TreeView, Control, ControlGet, SplashImage, MsgBox, FileSelectFile, FileSelectFolder

## 示例

创建一个弹出窗口, 实现类似 SplashTextOn 的效果.

    Gui, +AlwaysOnTop +Disabled -SysMenu +Owner  ; +Owner 避免显示任务栏按钮.
    Gui, Add, Text,, Some text to display.
    Gui, Show, NoActivate, Title of Window  ; NoActivate 让当前活动窗口继续保持活动状态.

创建一个要求输入姓名的简单输入框.

    Gui, Add, Text,, First name:
    Gui, Add, Text,, Last name:
    Gui, Add, Edit, vFirstName ym  ; ym 选项开始一个新的控件列.
    Gui, Add, Edit, vLastName
    Gui, Add, Button, default, OK  ; ButtonOK(如果存在) 会在此按钮被按下时运行.
    Gui, Show,, Simple Input Example
    return  ; 自动运行段结束. 在用户进行操作前脚本会一直保持空闲状态.

    GuiClose:
    ButtonOK:
    Gui, Submit  ; 保存用户的输入到每个控件的关联变量中.
    MsgBox You entered "%FirstName% %LastName%".
    ExitApp

创建带有多个选项卡的选项卡控件, 每个选项卡包含不同的控件与之交互.

    Gui, Add, Tab2,, First Tab|Second Tab|Third Tab  ; Tab2 比起 Tab 需要 [v1.0.47.05+].
    Gui, Add, Checkbox, vMyCheckbox, Sample checkbox
    Gui, Tab, 2
    Gui, Add, Radio, vMyRadio, Sample radio1
    Gui, Add, Radio,, Sample radio2
    Gui, Tab, 3
    Gui, Add, Edit, vMyEdit r5  ; r5 表示 5 行的高度.
    Gui, Tab  ; 即后续添加的控件将不属于前面那个选项卡控件.
    Gui, Add, Button, default xm, OK  ; xm 把它放置在左下角.
    Gui, Show
    return

    ButtonOK:
    GuiClose:
    GuiEscape:
    Gui, Submit  ; 保存每个控件的内容到其关联变量中.
    MsgBox You entered:`n%MyCheckbox%`n%MyRadio%`n%MyEdit%
    ExitApp

显示一个目录中的文件的列表框.

    Gui, Add, Text,, Pick a file to launch from the list below.`nTo cancel, press ESCAPE or close this window.
    Gui, Add, ListBox, vMyListBox gMyListBox w640 r10
    Gui, Add, Button, Default, OK
    Loop, C:\*.*  ; 根据您的需要改变此文件和通配符模式.
    {
        GuiControl,, MyListBox, %A_LoopFileFullPath%
    }
    Gui, Show
    return

    MyListBox:
    if (A_GuiEvent != "DoubleClick")
        return
    ; 否则, 用户双击了列表中的项目, 所以把它和点击 OK 按钮进行相同的处理.
    ; 所以直接进入下一个标签.
    ButtonOK:
    GuiControlGet, MyListBox  ; 获取列表框中当前选择的项目.
    MsgBox, 4,, Would you you like to launch the file or document below?`n`n%MyListBox%
    IfMsgBox, No
        return
    ; 否则, 运行此文件:
    Run, %MyListBox%,, UseErrorLevel
    if (ErrorLevel = "ERROR")
        MsgBox Could not launch the specified file.  Perhaps it is not associated with anything.
    return

    GuiClose:
    GuiEscape:
    ExitApp

当鼠标移动到特定的控件上时显示相关帮助(使用工具提示).

    Gui, Add, Edit, vMyEdit
    MyEdit_TT := "This is a tooltip for the control whose variable is MyEdit."
    Gui, Add, DropDownList, vMyDDL, Red|Green|Blue
    MyDDL_TT := "Choose a color from the drop-down list."
    Gui, Add, Checkbox, vMyCheck, This control has no tooltip.
    Gui, Show
    OnMessage(0x0200, "WM_MOUSEMOVE")
    return

    WM_MOUSEMOVE()
    {
        static CurrControl, PrevControl, _TT  ; _TT 保持为空以便用于下面的 ToolTip 命令.
        CurrControl := A_GuiControl
        If (CurrControl != PrevControl and not InStr(CurrControl, " "))
        {
            ToolTip  ; 关闭之前的工具提示.
            SetTimer, DisplayToolTip, 1000
            PrevControl := CurrControl
        }
        return

        DisplayToolTip:
        SetTimer, DisplayToolTip, Off
        ToolTip % %CurrControl%_TT  ; 前导的百分号表示要使用表达式.
        SetTimer, RemoveToolTip, 3000
        return

        RemoveToolTip:
        SetTimer, RemoveToolTip, Off
        ToolTip
        return
    }

    GuiClose:
    ExitApp

使用透明窗口进行屏幕显示(OSD).

    CustomColor := "EEAA99"  ; 可以为任意 RGB 颜色(在下面会被设置为透明).
    Gui +LastFound +AlwaysOnTop -Caption +ToolWindow  ; +ToolWindow 避免显示任务栏按钮和 alt-tab 菜单项.
    Gui, Color, %CustomColor%
    Gui, Font, s32  ; 设置大字体 (32 磅).
    Gui, Add, Text, vMyText cLime, XXXXX YYYYY  ; XX & YY 用来自动调整窗口大小.
    ; 让此颜色的所有像素透明且让文本显示为半透明 (150):
    WinSet, TransColor, %CustomColor% 150
    SetTimer, UpdateOSD, 200
    Gosub, UpdateOSD  ; 立即进行第一次更新而不等待计时器.
    Gui, Show, x0 y400 NoActivate  ; NoActivate 让当前活动窗口继续保持活动状态.
    return

    UpdateOSD:
    MouseGetPos, MouseX, MouseY
    GuiControl,, MyText, X%MouseX%, Y%MouseY%
    return

创建一个在背景图像上移动的进度条.

    Gui, Color, White
    Gui, Add, Picture, x0 y0 h350 w450, %A_WinDir%\system32\ntimage.gif
    Gui, Add, Button, Default xp+20 yp+250, Start the Bar Moving
    Gui, Add, Progress, vMyProgress w416
    Gui, Add, Text, vMyText wp  ; wp 表示 "使用之前的宽度".
    Gui, Show
    return

    ButtonStartTheBarMoving:
    Loop, %A_WinDir%\*.*
    {
        if A_Index > 100
            break
        GuiControl,, MyProgress, %A_Index%
        GuiControl,, MyText, %A_LoopFileName%
        Sleep 50
    }
    GuiControl,, MyText, Bar finished.
    return

    GuiClose:
    ExitApp

创建一个简单的图像查看器.

    Gui, +Resize
    Gui, Add, Button, default, &Load New Image
    Gui, Add, Radio, ym+5 x+10 vRadio checked, Load &actual size
    Gui, Add, Radio, ym+5 x+10, Load to &fit screen
    Gui, Add, Pic, xm vPic
    Gui, Show
    return

    ButtonLoadNewImage:
    FileSelectFile, file,,, Select an image:, Images (*.gif; *.jpg; *.bmp; *.png; *.tif; *.ico; *.cur; *.ani; *.exe; *.dll)
    if not file
        return
    Gui, Submit, NoHide ; 保存单选按钮的值.
    if (Radio = 1)  ; 按实际大小显示图像.
    {
        Width := 0
        Height := 0
    }
    else ; 选择了第二个单选按钮: 按照屏幕的大小显示图像.
    {
        Width := A_ScreenWidth - 28  ; 减去的 28 是用来显示边框和内边缘的空间.
        Height := -1  ; "保持高宽比" 应该是最好的.
    }
    GuiControl,, Pic, *w%width% *h%height% %file%  ; 载入图像.
    Gui, Show, xCenter y0 AutoSize, %file%  ; 调整窗口以适合图片尺寸.
    return

    GuiClose:
    ExitApp

创建一个带有菜单栏的简单文本编辑器.

    ; 为菜单栏创建子菜单:
    Menu, FileMenu, Add, &New, FileNew
    Menu, FileMenu, Add, &Open, FileOpen
    Menu, FileMenu, Add, &Save, FileSave
    Menu, FileMenu, Add, Save &As, FileSaveAs
    Menu, FileMenu, Add  ; 分隔线.
    Menu, FileMenu, Add, E&xit, FileExit
    Menu, HelpMenu, Add, &About, HelpAbout

    ; 创建用来附加子菜单的菜单栏:
    Menu, MyMenuBar, Add, &File, :FileMenu
    Menu, MyMenuBar, Add, &Help, :HelpMenu

    ; 添加菜单栏到窗口:
    Gui, Menu, MyMenuBar

    ; 创建主编辑控件并显示窗口:
    Gui, +Resize  ; 让用户可以调整窗口的大小.
    Gui, Add, Edit, vMainEdit WantTab W600 R20
    Gui, Show,, Untitled
    CurrentFileName :=""  ; 表示当前没有文件.
    return

    FileNew:
    GuiControl,, MainEdit  ; 清空编辑控件.
    return

    FileOpen:
    Gui +OwnDialogs  ; 强制用户响应 FileSelectFile 对话框后才能返回到主窗口.
    FileSelectFile, SelectedFileName, 3,, Open File, Text Documents (*.txt)
    if not SelectedFileName   ; 没有选择文件.
        return
    Gosub FileRead
    return

    FileRead:  ; 调用者已经设置了 SelectedFileName 变量.
    FileRead, MainEdit, %SelectedFileName%  ; 读取文件的内容到变量中.
    if ErrorLevel
    {
        MsgBox Could not open "%SelectedFileName%".
        return
    }
    GuiControl,, MainEdit, %MainEdit%  ; 在控件中显示文本.
    CurrentFileName := SelectedFileName
    Gui, Show,, %CurrentFileName%   ; 在标题栏显示文件名.
    return

    FileSave:
    if not CurrentFileName   ; 还没有选择文件, 所以执行另存为操作.
        Goto FileSaveAs
    Gosub SaveCurrentFile
    return

    FileSaveAs:
    Gui +OwnDialogs  ; 强制用户响应 FileSelectFile 对话框后才能返回到主窗口.
    FileSelectFile, SelectedFileName, S16,, Save File, Text Documents (*.txt)
    if not SelectedFileName ; 没有选择文件.
        return
    CurrentFileName := SelectedFileName
    Gosub SaveCurrentFile
    return

    SaveCurrentFile:  ; 调用者已经确保了 CurrentFileName 不为空.
    if FileExist(CurrentFileName)
    {
        FileDelete %CurrentFileName%
        if ErrorLevel
        {
            MsgBox The attempt to overwrite "%CurrentFileName%" failed.
            return
        }
    }
    GuiControlGet, MainEdit  ; 获取编辑控件的内容.
    FileAppend, %MainEdit%, %CurrentFileName%  ; 保存内容到文件.
    ; 成功时在标题栏显示文件名 (以防 FileSaveAs 调用时的情况):
    Gui, Show,, %CurrentFileName%
    return

    HelpAbout:
    Gui, About:+owner1  ; 让主窗口 (Gui #1) 成为 "关于对话框" 的父窗口.
    Gui +Disabled  ; 禁用主窗口.
    Gui, About:Add, Text,, Text for about box.
    Gui, About:Add, Button, Default, OK
    Gui, About:Show
    return

    AboutButtonOK:  ; 上面的 "关于对话框" 需要使用这部分.
    AboutGuiClose:
    AboutGuiEscape:
    Gui, 1:-Disabled  ; 重新启用主窗口 (必须在下一步之前进行).
    Gui Destroy  ; 销毁关于对话框.
    return

    GuiDropFiles:  ; 对拖放提供支持.
    Loop, Parse, A_GuiEvent, `n
    {
        SelectedFileName := A_LoopField  ; 仅获取首个文件 (如果有多个文件的时候).
        break
    }
    Gosub FileRead
    return

    GuiSize:
    if (ErrorLevel = 1)  ; 窗口被最小化了. 无需进行操作.
        return
    ; 否则, 窗口的大小被调整过或被最大化了. 调整编辑控件的大小以匹配窗口.
    NewWidth := A_GuiWidth - 20
    NewHeight := A_GuiHeight - 20
    GuiControl, Move, MainEdit, W%NewWidth% H%NewHeight%
    return

    FileExit:     ; 用户在 File 菜单中选择了 "Exit".
    GuiClose:  ; 用户关闭了窗口.
    ExitApp

dftg