在消息循環(huán)模式下,腳本大部分時間都在執(zhí)行一個周期非常短的循環(huán),這個循環(huán)通知GUI使用 GUIGetMsg (截獲消息)函數(shù)。當某個事件發(fā)生時 GUIGetMsg 函數(shù)把消息作為返回數(shù)值返回(比如某個按鈕被按下、GUI被關(guān)閉,等等)。
這一模式最適合用于那些以 GUI 為重點的腳本中,并且您最關(guān)心的就是等待用戶事件。
消息循環(huán)模式是AutoIt GUI 默認的模式。另外還有一種模式是 OnEvent 模式。
在此模式下,只有當我們頻繁地使用 GUIGetMsg 函數(shù)時才有可能接收到事件,因此您必須確保在每一秒內(nèi)都有數(shù)次調(diào)用該函數(shù),否則您的 GUI 將無法響應(yīng)事件。
下面是 消息循環(huán) 的基本結(jié)構(gòu):
While 1
$msg = GUIGetMsg() ; 截獲消息
... ; 處理消息
...
WEnd
像上面這種循環(huán)周期非常短的腳本通常會把CPU占用推到高達 100%,幸運的是 GUIGetMsg 函數(shù)可在無事件等待時自動閑置CPU。另外千萬 不要 因為怕增加CPU壓力而自己添加休眠語句(Sleep)到腳本中,這么做只會讓GUI響應(yīng)遲鈍。
GUIGetMsg 返回的事件消息有以下三種:
無事件
沒有截獲任何事件時 GUIGetMsg 的返回值為 0。這也是 最常發(fā)生的事件。
控件事件
當某個控件被點擊或該控件有其它變化時將發(fā)送控件事件。這些事件代碼都是正數(shù)并且關(guān)聯(lián)發(fā)送事件消息的 控件ID(也即使用 GUICtrlCreate... 函數(shù)創(chuàng)建該控件時的返回值)。
系統(tǒng)事件
系統(tǒng)事件包括GUI(窗口)被關(guān)閉等在內(nèi),它們的值都是 負數(shù)。下面列出了各種系統(tǒng)事件(在 GUIConstants.au3 中有定義):
$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)在我們來嘗試使用 消息循環(huán) 以及上面描述的事件消息來完成全部代碼。為了腳本的可讀性考慮我們使用條件選擇語句。
#include <GUIConstants.au3>
GUICreate("您好", 200, 100)
GUICtrlCreateLabel("最近過得怎樣?", 30, 10)
$okbutton = GUICtrlCreateButton("還OK吧", 70, 50, 60)
GUISetState(@SW_SHOW)
While 1
$msg = GUIGetMsg()
Select
Case $msg = $okbutton
MsgBox(0, "GUI 事件", "您按下了“還OK吧”按鈕!")
Case $msg = $GUI_EVENT_CLOSE
MsgBox(0, "GUI 事件", "您選擇了關(guān)閉!正在退出...")
ExitLoop
EndSelect
WEnd
很簡單,對吧?很明顯創(chuàng)建的窗口及控件越多則腳本越復雜,但基本結(jié)構(gòu)都是類似上面的這個示例。
即使有很多窗口存在,控件 ID 也是唯一的,因此上面的腳本可以正常工作。但是在處理如 $GUI_EVENT_CLOSE 或 $GUI_MOUSEMOVE 等消息時您還必須知道究竟是哪個窗口引發(fā)的事件。為了解決這個問題,您可以參考下面這個語句來調(diào)用 GUIGetMsg 函數(shù):
$msg = GUIGetMsg(1)
在函數(shù) GUIGetMsg 中指定1作為參數(shù)調(diào)用時它將返回一個數(shù)組。這個數(shù)組不僅包括被截獲的事件(保存在$array[0]中),還包括其它信息如窗口句柄等(保存在$array[1]中)。假設(shè)我們要創(chuàng)建兩個窗口,則相應(yīng)的腳本代碼如下:
#include <GUIConstants.au3>
$mainwindow = GUICreate("您好", 200, 100)
GUICtrlCreateLabel("最近過得怎樣?", 30, 10)
$okbutton = GUICtrlCreateButton("還OK吧", 70, 50, 60)
$dummywindow = GUICreate(" 這只是測試用的虛設(shè)窗口,并不會被顯示 ", 200, 100)
GUISwitch($mainwindow)
GUISetState(@SW_SHOW)
While 1
$msg = GUIGetMsg(1)
Select
Case $msg[0] = $okbutton ; 注意這里的$msg[0]和后面的$msg[1]
MsgBox(0, "GUI 事件", "您按下了“還OK吧”按鈕!")
Case $msg[0] = $GUI_EVENT_CLOSE And $msg[1] = $mainwindow
MsgBox(0, "GUI 事件", "您選擇了關(guān)閉主窗口!正在退出...")
ExitLoop
EndSelect
WEnd
第一個需要注意的變動是上面的腳本增加了一個 GUISwitch 函數(shù)的調(diào)用,當新的窗口被創(chuàng)建之后該窗口即變成后面所有GUI操作(包括創(chuàng)建控件在內(nèi))的“默認”窗口,也就是說這些GUI操作的對象都會是這個默認窗口。但我們希望顯示的是主窗口(首先被創(chuàng)建的窗口)而不是那個測試窗口,這時就要使用 GUISwitch 函數(shù)來切換操作對象。某些GUI函數(shù)允許您在調(diào)用它們時使用窗口句柄(參數(shù))來指定操作目標,同時也將自動切換該目標窗口為“默認窗口”。所以在這個示例中,我們還可以改用這樣的語句:
GUISetState(@SW_SHOW, $mainwindow)
另外要注意的就是 GUIGetMsg 函數(shù)的用法以及事件是如何被截獲并處理的,注意 $msg[0] 和 $msg[1] 的用法,現(xiàn)在我們就可以確保在窗口的關(guān)閉按鈕被點擊 而且 消息是從主窗口發(fā)送的時候才退出GUI了。