OnEventモードでは、何が起きているか知るためにGUIをポーリングする代わりにGUIにスクリプトの一時停止と事前に定義した関数の呼び出しをおこなわせます。例えば、ユーザーがボタン1を押すとGUIはメインスクリプトを停止して事前に定義したボタン1用のユーザー関数を呼び出します。関数が終了するとメインスクリプトが再開します。このモードはVisualBasicの形式と同じものです。
GUIが実行されている間、メインスクリプトは通常のスクリプト処理をおこないます。しかし簡単のために例ではメインスクリプトはWhileによる無限ループで「アイドリング」させておくことにしましょう。
デフォルトのモードはMessageLoopモードなのでOnEventモードを使う前にOpt("GUIOnEventMode", 1)を使わなければいけません。
一般的なOnEventコードの書き方は次の通りです。
While 1
Sleep(1000) ; 単なるアイドリング
WEnd
Func Event1()
; ここにイベント処理用コードを書く
EndFunc
Func Event2()
; ここにイベント処理用コードを書く
EndFunc
OnEventモードではGUIで次の「イベント」を発生させなければいけません。
両タイプのイベントはそれぞれGUI(GUISetOnEvent)とコントロール(GUICtrlSetOnEvent)に設定されたユーザー定義関数を呼びます。もしイベントに対して関数が定義されていない場合は単純に無視されます。この呼ばれる関数内でイベントを処理するためにさまざまなマクロの値が設定されます。
Macro | Details |
@GUI_CTRLID | メッセージを送信したコントロールのコントロールIDまたはシステムイベントID |
@GUI_WINHANDLE | メッセージを送信したGUIのハンドル |
@GUI_CTRLHANDLE | メッセージを送信したコントロールのコントロールハンドル(利用できる場合) |
注意:同じ関数を複数のイベント処理に使用することはまったく問題ありません。その場合必要なことは@GUI_CTRLIDマクロに基づいて動作を決定することです。例えば全てのシステムイベントに同じ関数を登録することができます。
コントロールイベント
コントロールがクリックされたりコントロールに変化があった場合、コントロールイベントが送信されます。イベントはGUICtrlSetOnEventで定義された関数に送られます。ユーザー定義関数内では@GUI_CTRLIDがGUICtrlCreate...でコントロールを作成したときに返されるコントロールIDに設定されます。
システムイベント
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("Hello World", 200, 100)
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
GUICtrlCreateButton("OK", 70, 50, 60)
GUISetState(@SW_SHOW)
Sleep(2000)
さて、OnEventsと上で述べたイベントメッセージを使ってコードを完成させましょう。
#include <GUIConstantsEx.au3>
Opt("GUIOnEventMode", 1) ; Change to OnEvent mode
$mainwindow = GUICreate("Hello World", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")
GUISetState(@SW_SHOW)
While 1
Sleep(1000) ; Idle around
WEnd
Func OKButton()
;Note: at this point @GUI_CTRLID would equal $okbutton,
;and @GUI_WINHANDLE would equal $mainwindow
MsgBox(0, "GUI Event", "You pressed OK!")
EndFunc
Func CLOSEClicked()
;Note: at this point @GUI_CTRLID would equal $GUI_EVENT_CLOSE,
;and @GUI_WINHANDLE would equal $mainwindow
MsgBox(0, "GUI Event", "You clicked CLOSE! Exiting...")
Exit
EndFunc
とても単純です。たくさんのウィンドウとコントロールがある場合はより複雑になります。しかしその場合も上に示したものが基本です。
複数のウィンドウを作った場合でも コントロールIDはユニークです。しかしどのように複数のウィンドウを取り扱うのでしょうか?
次に上の例と機能は同じで、もう1つの「ダミー」ウィンドウをもつ例を示します。
#include <GUIConstantsEx.au3>
Opt("GUIOnEventMode", 1) ; Change to OnEvent mode
$mainwindow = GUICreate("Hello World", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
GUICtrlSetOnEvent($okbutton, "OKButton")
$dummywindow = GUICreate("Dummy window for testing ", 200, 100)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUISwitch($mainwindow)
GUISetState(@SW_SHOW)
While 1
Sleep(1000) ; Idle around
WEnd
Func OKButton()
;Note: at this point @GUI_CTRLID would equal $okbutton
MsgBox(0, "GUI Event", "You pressed OK!")
EndFunc
Func CLOSEClicked()
;Note: at this point @GUI_CTRLID would equal $GUI_EVENT_CLOSE,
;@GUI_WINHANDLE will be either $mainwindow or $dummywindow
If @GUI_WINHANDLE = $mainwindow Then
MsgBox(0, "GUI Event", "You clicked CLOSE in the main window! Exiting...")
Exit
EndIf
EndFunc
最初の大きな違いはGUISwitch関数が呼ばれていることです。新しいウィンドウが作られるとそれが次回以降のGUI操作の「デフォルト」ウィンドウになります(コントロール作成もそうです)。 今回の場合、動かしたいのはメインの「Hello World」ウィンドウで、テストウィンドウではないので「switch」をおこないます。 いくつかのGUI関数では関数呼び出しにウィンドウハンドルが使えます。これらの関数は自動で切り替えをおこなってくれます。 先ほどの例に使うと次のようになります。
GUISetState(@SW_SHOW, $mainwindow)
また両方のウィンドウで同じOnEvent関数を使って「終了」を処理していることがわかります。@GUI_WINHANDLEを使用してどのウィンドウからメッセージが送られたのかを決定し、クローズボタンが押され、かつメッセージがメインウィンドウから送信された場合のみGUIを終了しています。 簡単のためにそれぞれのウィンドウ用に関数を分けることもできます。