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