在OnEvent模式下, 脚本并不需要频繁地要求 GUI 检查是否有任何事件发生(并根据返回信息处理事件),
而是仅当某个事件发生时, GUI 才临时性暂停脚本, 并调用一个用户预定义的函数来处理该事件.
例如, 假定用户点击了按钮1, 则 GUI 将暂停主脚本并调用某个预定义的用户函数来处理按钮1事件.
当该函数完成处理操作后才回到主脚本继续执行.这个模式比较类似 Visual Basic 的窗体方法.
当GUI被执行时, 主脚本还可以做其它一般性工作,
但为了演示方便, 我们只是让主脚本“闲置”在一个无限 While 循环里.
因为消息循环是默认的模式,所以在应用 OnEvent 模式之前我们应该先使用 Opt("GUIOnEventMode", 1) 语句切换默认模式
OnEvent 代码的常规格结构:
While 1
Sleep(1000) ; 闲置,不做任何事
WEnd
Func Event1()
; 这里放置事件 1 的处理代码
EndFunc
Func Event2()
; 这里放置事件 2 的处理代码
EndFunc
在 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 概论 页面上我们曾编写过一个简单的窗口:
#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) |