在 OnEvent(事件驅(qū)動)模式下,腳本并不需要頻繁地要求GUI檢查是否有任何事件發(fā)生(并根據(jù)返回信息處理事件),而是僅當(dāng)某個事件發(fā)生時GUI才臨時性暫停腳本并調(diào)用一個用戶預(yù)定義的函數(shù)來處理該事件。例如,假定用戶點擊了按鈕1則GUI將暫停主腳本并調(diào)用某個預(yù)定義的用戶函數(shù)來處理按鈕1事件。當(dāng)該函數(shù)完成處理操作后才回到主腳本繼續(xù)執(zhí)行。這個模式比較類似 Visual Basic 的窗體方法。
當(dāng)GUI被執(zhí)行時,主腳本還可以做其它一般性工作,但為了演示方便我們只是讓主腳本在一個無限While循環(huán)里“睡眠”一下。
因為消息循環(huán)是默認(rèn)的模式,所以在應(yīng)用 OnEvent 模式之前我們應(yīng)該先使用 Opt("GUIOnEventMode", 1) 語句。
下面是 OnEvent 的基本結(jié)構(gòu):
While 1
Sleep(1000) ; 閑置工作,不做任何事
WEnd
Func Event1()
; 處理事件的代碼放在這里
EndFunc
Func Event2()
; 處理事件的代碼放在這里
EndFunc
在 OnEvent 模式下會產(chǎn)生兩種“事件”:
這兩種事件類型發(fā)生時都將調(diào)用用戶預(yù)先定義的函數(shù),這些函數(shù)可以是為GUI(窗口)設(shè)置的(GUISetOnEvent)或者為控件設(shè)置的(GUICtrlSetOnEvent)。如果某事件并沒有預(yù)先定義相應(yīng)的處理函數(shù)則該事件將被忽略。在這些被調(diào)用的函數(shù)內(nèi)部可使用各種 宏 以助處理事件:
宏 |
說明 |
@GUI_CTRLID | 發(fā)送消息的控件ID 或者 系統(tǒng)事件ID |
@GUI_WINHANDLE | 發(fā)送消息的GUI(窗口)句柄 |
@GUI_CTRLHANDLE | 發(fā)送消息的控件句柄(如果適用) |
注意:使用同一個函數(shù)來響應(yīng)多種事件是完全合法的,記住要靈活使用 @GUI_CTRLID 這個宏。比如說,您可以注冊所有系統(tǒng)事件到同一個函數(shù)。
控件
當(dāng)某個控件被點擊或該控件有其它變化時將發(fā)送控件事件。該事件將被傳遞到由 GUICtrlSetOnEvent 定義的函數(shù)中。在這個函數(shù)里,@GUI_CTRLID 的值是發(fā)送消息的 控件ID(也即使用 GUICtrlCreate... 函數(shù)創(chuàng)建該控件時的返回值)。
系統(tǒng)事件
系統(tǒng)事件包括GUI(窗口)被關(guān)閉等在內(nèi),它們以類似于控件事件的方式被發(fā)送出去,而事件類型(ID)則由 @GUI_CTRLID 指示。系統(tǒng)事件將被傳遞到由 GUISetOnEvent 定義的函數(shù)中。可能的系統(tǒng)事件包括:
$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 相關(guān) 的頁面上我們曾編寫過一個簡單的窗口:
#include <GUIConstants.au3>
GUICreate("您好", 200, 100)
GUICtrlCreateLabel("最近過得怎樣?", 30, 10)
GUICtrlCreateButton("還OK吧", 70, 50, 60)
GUISetState(@SW_SHOW)
Sleep(2000)
現(xiàn)在我們來嘗試使用 OnEvent 以及上面描述的事件消息來完成全部代碼:
#include <GUIConstants.au3>
Opt("GUIOnEventMode", 1) ; 切換為 OnEvent 模式
$mainwindow = GUICreate("您好", 200, 100) ; 創(chuàng)建窗口并返回窗口句柄
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked") ; 設(shè)置窗口關(guān)閉事件
GUICtrlCreateLabel("最近過得怎樣?", 30, 10)
$okbutton = GUICtrlCreateButton("還OK吧", 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 事件", "您按下了“還OK吧”按鈕!")
EndFunc
Func CLOSEClicked()
;注意:此時 @GUI_CTRLID 的值將等價于 $GUI_EVENT_CLOSE,
;而 @GUI_WINHANDLE 則等價于 $mainwindow
MsgBox(0, "GUI 事件", "您選擇了關(guān)閉!正在退出...")
Exit
EndFunc
很簡單,對吧?很明顯創(chuàng)建的窗口及控件越多則腳本越復(fù)雜,但基本結(jié)構(gòu)都是類似上面的這個示例。
即使有很多窗口存在,控件 ID 也是唯一的,但是我們?nèi)绾翁幚矶啻翱谀兀?/p>
下面這個示例腳本和上面的很像,但多出了一個“dummy(虛設(shè)的)”窗口。
#include <GUIConstants.au3>
Opt("GUIOnEventMode", 1) ; 切換為 OnEvent 模式
$mainwindow = GUICreate("您好", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("最近過得怎樣?", 30, 10)
$okbutton = GUICtrlCreateButton("還OK吧", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")
$dummywindow = GUICreate(" 這只是測試用的虛設(shè)窗口,并不會被顯示 ", 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 事件", "您按下了“還OK吧”按鈕!")
EndFunc
Func CLOSEClicked()
;注意:此時 @GUI_CTRLID 的值將等價于 $GUI_EVENT_CLOSE,
;而 @GUI_WINHANDLE 則等價于 $mainwindow 或 $dummywindow
If @GUI_WINHANDLE = $mainwindow Then
MsgBox(0, "GUI 事件", "您選擇了關(guān)閉主窗口!正在退出...")
Exit
EndIf
EndFunc
第一個需要注意的變動是上面的腳本增加了一個 GUISwitch 函數(shù)的調(diào)用,當(dāng)新的窗口被創(chuàng)建之后該窗口即變成后面所有GUI操作(包括創(chuàng)建控件在內(nèi))的“默認(rèn)”窗口,也就是說這些GUI操作的對象都會是這個默認(rèn)窗口。但我們希望顯示的是主窗口(首先被創(chuàng)建的窗口)而不是那個測試窗口,這時就要使用 GUISwitch 函數(shù)來切換操作對象。某些GUI函數(shù)允許您在調(diào)用它們時使用窗口句柄(參數(shù))來指定操作目標(biāo),同時也將自動切換該目標(biāo)窗口為“默認(rèn)窗口”。所以在這個示例中,我們還可以改用這樣的語句:
GUISetState(@SW_SHOW, $mainwindow)
另外要注意的就是我們使用了同一個 OnEvent 函數(shù)來處理兩個窗口的“關(guān)閉”事件,為了識別被關(guān)閉的窗口究竟是哪一個我們還使用了 @GUI_WINHANDLE 來檢查發(fā)送消息的窗口句柄。這樣處理之后我們就可以確保在窗口的關(guān)閉按鈕被點擊 而且 消息是從主窗口發(fā)送的時候才退出GUI了。當(dāng)然了,您也可以為每個窗口指定不同的事件處理函數(shù)。