# OnEvent

注册一个函数或方法, 当 GUI 窗口或控件发生给定事件时, 该函数或方法将被调用.

    Gui.OnEvent(EventName, Callback , AddRemove)
    GuiCtrl.OnEvent(EventName, Callback , AddRemove)

## 参数

EventName

  类型: 字符串

  事件的名称. 请参阅下面的 Events.

Callback

  类型: 字符串或函数对象

  事件发生时要调用的函数, 方法或对象.

  如果 GUI 有事件接收器(即, 如果指定了 Gui() 的 EventObj 参数), 那么这个参数可能是属于事件接收器的方法的名称.

  否则, 这个参数必须是一个函数对象.

AddRemove

  类型: 整数

  如果省略, 则默认为 1(在任何先前注册的回调之后调用回调). 否则, 指定下列数字之一:

  - 1 = 在任何先前注册的回调之后调用回调.
  - -1 = 在任何先前注册的回调之前调用回调.
  - 0 = 不调用该回调.

## Callback 参数

如果回调是按名称注册的方法, 其隐藏的 this 参数无缝事件接收器对象(即该方法所属的对象). 这个参数在本文档的参数列表中没有显示.

由于 Callback 可以是一个对象, 它可以是一个 BoundFunc 对象, 在参数列表的开头插入额外的参数, 然后调用另一个函数. 这是一种通用的技术, 不是 OnEvent 所特有的, 所以一般被本文档的其他部分忽略.

回调的第一个显式参数是触发事件的 Gui 或 GuiControl 对象. 唯一的例外是, 当 Gui 处理自己的事件时, this 参数会被省略, 因为 `this` 已经包含了对 Gui 的引用.

许多事件都传递了关于事件的附加参数, 每个事件都有描述.

与所有动态调用的方法或函数一样, 回调不需要声明回调本身不需要的参数, 但在这种情况下, 必须指定一个星号作为最终参数. 如果一个事件的参数多于回调声明的参数, 那么这些参数将被忽略(除非回调是可变参数的).

回调可以声明比事件提供的参数更多的参数, 如果(而且只有当) 额外的参数被声明为可选参数. 然而, 不建议使用可选参数, 因为未来的程序版本可能会用额外的参数来扩展一个事件, 在这种情况下, 可选参数将停止接收它们的默认值.

## Callback 返回值

如果一个事件已经注册了多个回调, 回调可以返回一个非空值, 以防止任何剩余的回调被调用.

对于特定的事件, 返回值可能有额外的意义. 例如, Close 回调可以返回一个非零的数字(例如 `true`) 来防止 GUI 窗口关闭.

## Callback 名称

按照惯例, 为了清晰起见, 下面每个事件的语法都用 `ObjectType_EventName` 这种形式的函数名来显示. 脚本不需要遵循这个惯例, 可以使用任何有效的函数名.

## 线程

每个事件回调都是在一个新的线程中调用的, 因此会以诸如 SendMode 等设置的默认值重新开始. 这些默认值可以在脚本启动时更改.

每当一个 GUI 线程被启动时, 该线程的上次找到的窗口都会作为 GUI 窗口本身启动. 这使得窗口和控件的函数 -- 如 WinGetStyle, WinSetTransparent 和 ControlGetFocus -- 在对 GUI 窗口本身进行操作时可以省略 WinTitle 和 WinText(即使它是隐藏的).

除非另有说明, 每个事件被限制为每个对象一次只能有一个线程. 如果一个事件在由该事件启动的前一个线程结束之前被触发, 则该事件通常会被丢弃. 为了防止这种情况发生, 请使用 Critical 作为回调的第一行(然而, 这也将缓冲/延迟其他线程, 例如按下热键).

## 销毁 GUI

当 GUI 被销毁时, 所有的事件回调都被释放. 因此, 如果 GUI 在事件被派发时被销毁, 那么后续的事件回调就不会被调用. 为了清晰起见, 在销毁 GUI 后, 回调应该返回一个非空值.

## 事件

Gui 对象支持以下事件:

事件 | 当...时触发
--- | ---
Close | 关闭窗口.
ContextMenu | 用户在窗口内右键单击或按下 `Menu` 或 `Shift`+`F10`.
DropFiles | 文件/文件夹被拖放到窗口上.
Escape | 当 GUI 窗口处于活动状态时, 用户按下 `Esc`.
Size | 窗口被调整大小, 最小化, 最大化或还原.

根据控件类型, GuiControl 对象支持以下事件:

事件 | 当...时触发
--- | ---
Change | 控件的值发生变化.
Click | 控件被点击.
DoubleClick | 控件被双击.
ColClick | ListView 的一个列头被点击.
ContextMenu | 当控件具有键盘焦点时, 用户右键单击控件或按下 `Menu` 或 `Shift`+`F10`.
Focus | 控件获得键盘焦点.
LoseFocus | 控件失去键盘焦点.
ItemCheck | ListView 或 TreeView 的项目被选中或取消选中.
ItemEdit | 用户编辑 ListView 或 TreeView 项的标签.
ItemExpand | TreeView 项目被展开或折叠.
ItemFocus | ListView 中改变聚焦的项目.
ItemSelect | ListView 或 TreeView 项目被选中, 或者一个 ListView 项目被取消选择.

## 窗口事件

### Close

当用户或其他程序试图关闭窗口时, 如按下标题栏中的 X 按钮, 从系统菜单中选择 "关闭", 或调用 WinClose, 则启动该函数.

    Gui_Close(GuiObj)

默认情况下, 回调返回后或者没有注册回调, 窗口会自动隐藏. 回调可以通过返回 1(或 `true`) 来阻止这种情况, 这也将阻止任何剩余的回调被调用. 回调可以通过调用 Gui.Hide 立即隐藏窗口, 或者通过调用 Gui.Destroy 销毁窗口.

例如, 这个 GUI 在关闭前会显示一个确认提示:

    myGui := Gui()
    myGui.AddText("", "Press Alt+F4 or the X button in the title bar.")
    myGui.OnEvent("Close", myGui_Close)
    myGui_Close(thisGui) {  ; 声明中 this 参数是可选的.
        if MsgBox("Are you sure you want to close the GUI?",, "y/n") = "No"
            return true  ; true = 1
    }
    myGui.Show

### ContextMenu

每当用户在窗口中除标题栏和菜单栏外的任何地方单击右键时就会启动. 当按下 `Menu` 或 `Shift`+`F10` 时, 也会启动.

    Gui_ContextMenu(GuiObj, GuiCtrlObj, Item, IsRightClick, X, Y)

GuiCtrlObj

  类型: GuiControl 或 字符串(空值)

  接收事件的控件的 GuiControl 对象(如果没有则为空白).

Item

  类型: 整数

  当 ListBox, ListView 或 TreeView 是上下文菜单的目标时(由 GuiCtrlObj 决定), Item 指定控件的哪个项目是目标.

  ListBox: 当前焦点行的编号. 请注意, 标准的 ListBox 在右键单击时不会聚焦一个项目, 所以这可能不是被单击的项目.

  ListView 和 TreeView: 对于右键点击, Item 包含被点击的项目的 ID 或行号(如果用户点击的不是项目, 则为 0). 对于 AppsKey 和 Shift-F10, Item 包含所选项目的 ID 或行号.

IsRightClick

  类型: 整数(布尔值)

  如果用户点击了鼠标右键, 则为 `True`.
  如果用户按下了 `Menu` 键或 `Shift`+`F10`, 则为 `False`.

X, Y

  类型: 整数

  脚本应该显示菜单的 X 和 Y 坐标(例如 `MyContextMenu.Show X, Y`). 坐标是相对于窗口客户端区域的左上角.

与大多数其他 GUI 事件不同, ContextMenu 事件可以有一个以上的并发线程.

每个控件都可以有自己的 ContextMenu 事件回调, 该回调在为 Gui 对象注册的任何回调之前被调用. 特定于控件的回调省略了 GuiObj 参数, 但所有其他参数都是一样的.

注意: 由于 Edit 和 MonthCal 控件有自己的上下文菜单, 所以在其中一个控件中右击不会启动 ContextMenu 事件.

### DropFiles

每当文件/文件夹作为拖放操作的一部分被放置到窗口时, 就会启动该回调(但如果该回调已经运行, 则忽略拖拽事件).

    Gui_DropFiles(GuiObj, GuiCtrlObj, FileArray, X, Y)

GuiCtrlObj

  类型: GuiControl 或 字符串(空值)

  文件被拖拽到的控件的 GuiControl 对象(如果没有则为空白).

FileArray

  类型: 字符串的数组

  一个文件名的数组(对象), 其中 `FileArray[1]` 是第一个文件, `FileArray.Length` 返回文件的数量. 可以使用 for-loop 来迭代文件:

      Gui_DropFiles(GuiObj, GuiCtrlObj, FileArray, X, Y) {
          for i, DroppedFile in FileArray
              MsgBox "File " i " is:`n" DroppedFile
      }

X, Y

  类型: 整数

  文件拖拽位置的 X 和 Y 坐标, 相对于窗口客户端区域的左上角.

### Escape

当用户在 GUI 窗口处于活动状态时按下 `Esc` 时启动.

    Gui_Escape(GuiObj)

默认情况下, 按下 `Esc` 没有效果. 已知限制: 如果窗口中的第一个控件被禁用(可能取决于控件类型), Escape 事件将不会启动. 可能有其他情况会产生这种效果.

### Size

当窗口被调整大小, 最小化, 最大化或还原时启动.

    Gui_Size(GuiObj, MinMax, Width, Height)

MinMax

  类型: 整数

  以下数值之一:

  - 0: 窗口既没有最小化也没有最大化.
  - 1: 窗口已最大化.
  - -1: 窗口被最小化.

  请注意, 已最大化的窗口可以在不恢复/取消最大化的情况下调整大小, 因此值为 1 并不一定意味着该事件是在用户最大化窗口的情况下发生的.

Width, Height

  类型: 整数

  窗口客户端区域的新宽度和高度, 即不包括标题栏, 菜单栏和边框的区域.

脚本可以使用 Size 事件来重新定位和调整控件的大小, 以响应用户对窗口的大小调整.

当窗口被调整大小时(即使是由脚本调整), Size 事件可能不会立即被触发. 与其他窗口事件一样, 如果当前线程是不可中断的, 那么在线程变得可中断之前, Size 事件不会被触发. 如果脚本刚刚调整了窗口的大小, 请按照这个例子来确保 Size 事件立即被触发:

    Critical "Off"  ; 即使从未使用 Critical "On".
    Sleep -1

Gui.Show 会自动 `Sleep -1`, 所以在这种情况下一般不需要调用 Sleep.

## 控件事件

### Change

控件的值发生变化时触发该事件.

    Ctrl_Change(GuiCtrlObj, Info)

Info

  类型: 整数

  对于 Slider 控件, Info 是一个数值, 表示滑块如何移动. 有关详情, 请参阅检测变化(Slider).

  对于所有其他控件, Info 目前没有任何意义.

要获取控件的新值, 请使用 GuiCtrlObj.Value.

适用于: DDL, ComboBox, ListBox, Edit, DateTime, MonthCal, Hotkey, UpDown, Slider, Tab.

### Click

控件被点击时触发该事件.

    Ctrl_Click(GuiCtrlObj, Info)
    Link_Click(GuiCtrlObj, Info, Href)

Info

  类型: 整数

  ListView: 点击的项目的行号, 如果鼠标没有在项目上, 则为 0.

  TreeView: 点击的项目的 ID, 如果鼠标没有放在项目上, 则为 0.

  Link: 如果有的话, 链接的 ID 属性(字符串), 否则为链接的索引(整数).

  StatusBar: 点击的部分的编号(然而, 如果用户点击在栏右边的大小抓手附近, 编号可能是一个很大的整数).

  对于所有其他控件, Info 目前没有任何意义.

Href

  类型: 字符串

  Link: 链接的 HREF 属性. 注意, 如果注册了 Click 事件回调, HREF 属性不会自动执行.

适用于: Text, Pic, Button, CheckBox, Radio, ListView, TreeView, Link, StatusBar.

### DoubleClick

当控件被双击时触发该事件.

    Ctrl_DoubleClick(GuiCtrlObj, Info)

Info

  类型: 整数

  ListView, TreeView 和 StatusBar: 与 Click 事件相同.

  ListBox: 聚焦项的位置. 双击最后一个项目下面的空白处, 通常会聚焦最后一个项目, 并保持原样.

适用于: Text, Pic, Button, CheckBox, Radio, ComboBox, ListBox, ListView, TreeView, StatusBar.

### ColClick

当 ListView 的一个列头被点击时触发该事件.

    Ctrl_ColClick(GuiCtrlObj, Info)

Info

  类型: 整数

  被点击的以 1 开始的列号. 这是创建列时分配的原始编号; 也就是说, 它不反映用户对列的任何拖放.

适用于: ListView.

### ContextMenu

当控件具有键盘焦点时, 用户右键单击控件或按下 `Menu` 或 `Shift`+`F10` 时触发该事件.

    Ctrl_ContextMenu(GuiCtrlObj, Item, IsRightClick, X, Y)

有关详情, 请参阅 ContextMenu.

适用于: 除了 Edit 和 MonthCal(以及 ComboBox 内的 Edit 控件)(他们都有自己的标准上下文菜单) 外的所有控件,.

### Focus / LoseFocus

控件获得或失去键盘焦点时触发该事件.

    Ctrl_Focus(GuiCtrlObj, Info)
    Ctrl_LoseFocus(GuiCtrlObj, Info)

Info

  保留.

适用于: Button, CheckBox, Radio, DDL, ComboBox, ListBox, ListView, TreeView, Edit, DateTime.

不支持: Hotkey, Slider, Tab 和 Link. 注意 Text, Pic, MonthCal, UpDown 和 StatusBar 控件不接受键盘焦点.

### ItemCheck

当 ListView 或 TreeView 项目被选中或取消选中时触发该事件.

    Ctrl_ItemCheck(GuiCtrlObj, Item, Checked)

适用于: ListView, TreeView.

### ItemEdit

用户编辑 ListView 或 TreeView 项的标签时触发该事件.

    Ctrl_ItemEdit(GuiCtrlObj, Item)

只有在控件的选项中使用了 `-ReadOnly`, 才能编辑项目的标签.

适用于: ListView, TreeView.

### ItemExpand

TreeView 项目被展开或折叠时触发该事件.

    Ctrl_ItemExpand(GuiCtrlObj, Item, Expanded)

适用于: TreeView.

### ItemFocus

当 ListView 中的焦点项目发生变化时触发该事件.

    Ctrl_ItemFocus(GuiCtrlObj, Item)

适用于: ListView.

### ItemSelect

当 ListView 或 TreeView 项目被选中或 ListView 项目被取消选择时触发该事件.

    ListView_ItemSelect(GuiCtrlObj, Item, Selected)
    TreeView_ItemSelect(GuiCtrlObj, Item)

适用于: ListView, TreeView.

ListView: 该事件对每一个被取消选择或选择的项目都会被触发一次, 所以可以对用户的一个动作进行多次响应.

## 其他事件

其他类型的 GUI 事件可以通过 OnNotify, OnCommand 或 OnMessage 来检测和处理. 例如, 每当用户将鼠标移动到窗口中的特定控件上时, 脚本可以通过 ToolTip 显示上下文相关的帮助. 这在 GUI ToolTip 的例子中进行了演示.

dftg