GUI 参考 - OnEvent 事件模式

在OnEvent模式下, 脚本并不需要频繁地要求 GUI 检查是否有任何事件发生(并根据返回信息处理事件),

而是仅当某个事件发生时, GUI 才临时性暂停脚本, 并调用一个用户预定义的函数来处理该事件.

例如, 假定用户点击了按钮1, 则 GUI 将暂停主脚本并调用某个预定义的用户函数来处理按钮1事件.

当该函数完成处理操作后才回到主脚本继续执行.这个模式比较类似 Visual Basic 的窗体方法.

当GUI被执行时, 主脚本还可以做其它一般性工作,

但为了演示方便, 我们只是让主脚本“闲置”在一个无限 While 循环里.

因为消息循环是默认的模式,所以在应用 OnEvent 模式之前我们应该先使用 Opt("GUIOnEventMode", 1) 语句切换默认模式

 

基本 OnEvent 结构

OnEvent 代码的常规格结构:

While 1
  Sleep(1000)   ; 闲置,不做任何事
WEnd
  
Func Event1()
  ; 这里放置事件 1 的处理代码
EndFunc

Func Event2()
  ; 这里放置事件 2 的处理代码
EndFunc

 

GUI 事件

在 OnEvent 模态中, GUI 将会产生下列"事件":

 

这两种类型事件发生时, 都将调用用户预先定义的函数.

这些函数可以是为 GUI 定义的 (GUISetOnEvent); 也可以是为控件定义的 (GUICtrlSetOnEvent).

如果某事件没有预先定义相应的处理函数, 则该事件被忽略. 这些被调用的函数内部可使用各种以帮助处理事件.

宏指令 描述
@GUI_CTRLID 发送消息的控件 ID 或系统事件 ID.
@GUI_WINHANDLE 发送消息的 GUI 句柄.
@GUI_CTRLHANDLE 发送消息的控件句柄(如果适用).

注意: 使用同一函数响应多种事件是完全合法的,记住要灵活使用 @GUI_CTRLID 这个宏.

例如您可以注册所有系统事件到同一个用户处理函数.

 

控件事件

当控件被点击或该控件有其它变化时将发送控件事件. 该事件将被发送到 GUICtrlSetOnEvent 定义的函数中.

在用户自定义函数内部, @GUI_CTRLID 为设定为返回控件 ID 值.

也就是使用 GUICtrlCreate... 函数创建该控件时的返回值.

 

系统事件

包括 GUI 关闭等的系统事件, 以类似控件事件的方式发送,但事件类型则由 @GUI_CTRLID 定义.

系统事件发送到 GUISetOnEvent 定义的函数中. 系统事件的可能值如下所示(与消息模式完全相同):

$GUI_EVENT_CLOSE ---------- 窗口关闭
$GUI_EVENT_MINIMIZE ------- 窗口最小化
$GUI_EVENT_RESTORE -------- 窗口还原
$GUI_EVENT_MAXIMIZE ------- 窗口最大化
$GUI_EVENT_PRIMARYDOWN ---- 鼠标左键按下
$GUI_EVENT_PRIMARYUP ------ 鼠标左键释放
$GUI_EVENT_SECONDARYDOWN -- 鼠标右键按下
$GUI_EVENT_SECONDARYUP ---- 鼠标右键释放
$GUI_EVENT_MOUSEMOVE ------ 鼠标移动
$GUI_EVENT_RESIZED -------- 调整大小
$GUI_EVENT_DROPPED -------- 拖动操作

GUI 示例

GUI 概论 页面上我们曾编写过一个简单的窗口:

#include <GUIConstantsEx.au3>

GUICreate("您好,世界", 200, 100)
GUICtrlCreateLabel("您好,世界! 你过得怎么样?", 30, 10)
GUICtrlCreateButton("确定", 70, 50, 60)
GUISetState(@SW_SHOW)
Sleep(2000)

 

现在我们来尝试使用 OnEvent 以及上面描述的事件来完成全部代码.

#include <GUIConstantsEx.au3>

Opt("GUIOnEventMode", 1)  ; 切换到 OnEvent 模式
$mainwindow = GUICreate("您好,世界", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("您好,世界! 你过得怎么样?", 30, 10)
$okbutton = GUICtrlCreateButton("确定", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")
GUISetState(@SW_SHOW)

While 1
  Sleep(1000)  ; 闲置,不做任何事
WEnd

Func OKButton()
  ;注意: 此时 @GUI_CTRLID 的值等于 $okbutton,
  ;而 @GUI_WINHANDLE 则等于 $mainwindow
  MsgBox(0, "GUI 事件", "你点击了 '确定'!")
EndFunc

Func CLOSEClicked()
  ;注意: 此时 @GUI_CTRLID 等于 $GUI_EVENT_CLOSE,
  ;而 @GUI_WINHANDLE 等于 $mainwindow
  MsgBox(0, "GUI 事件", "您选择了关闭窗口!正在退出...")
  Exit
EndFunc

就这么简单. 很明显的, 创建的窗口及控件越多则脚本越复杂, 但基本结构都是类似上面的这个示例.

 

高级操作及多窗口

即使有很多窗口存在, 控件 ID 也是唯一的. 但是我们如何处理多窗口呢?

下面这个示例脚本和上面的很像, 但多出了一个"dummy"(虚拟)窗口. 

#include <GUIConstantsEx.au3>

Opt("GUIOnEventMode", 1)  ; 切换到 OnEvent 模式
$mainwindow = GUICreate("您好,世界", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("您好,世界! 你过得怎么样?", 30, 10)
$okbutton = GUICtrlCreateButton("确定", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")

$dummywindow = GUICreate("用于测试的虚拟窗口,不会显示 ", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")

GUISwitch($mainwindow)
GUISetState(@SW_SHOW)

While 1
  Sleep(1000)  ; 闲置,不做任何事
WEnd

Func OKButton()
  ;注意: 此时 @GUI_CTRLID 等于 $okbutton
  MsgBox(0, "GUI 事件", "你点击了 '确定'!")
EndFunc

Func CLOSEClicked()
  ;注意: 此时 @GUI_CTRLID 等于 $GUI_EVENT_CLOSE,
  ;@GUI_WINHANDLE 则可能等于 $mainwindow, 也可能等于 $dummywindow
  If @GUI_WINHANDLE = $mainwindow Then
    MsgBox(0, "GUI 事件", "您选择了关闭主窗口!正在退出...")
    Exit
  EndIf
EndFunc

 

第一个主要变化是 GUISwitch 函数的调用.

当新的窗口被创建之后, 该窗口即成为后面所有 GUI 操作(包括创建控件)的“默认”工作窗口,

也就是说这些 GUI 操作的对象都会是这个默认窗口.

现在要处理的是"您好,世界"的窗口, 而不是那个虚拟测试窗口, 这时就要使用 GUISwitch 函数来切换操作对象.

某些 GUI 函数允许调用时使用窗口句柄指定操作目标, 同时也将自动切换该目标窗口为"默认窗口".

所以在这个示例中, 我们可以改用这样的语句:

GUISetState(@SW_SHOW, $mainwindow)

 

另外要注意, 我们使用了同一个 OnEvent 函数来处理两个窗口的 "close" 关闭事件,

然后使用 @GUI_WINHANDLE 来检查发送消息的窗口句柄.

这样处理之后, 可以确保窗口关闭事件是主窗口发送的时候才退出 GUI.

当然, 您也可以为每个窗口指定不同的事件处理函数.

 

provider with jb51.net (unicode)