MessageLoopモードではスクリプトはほとんどの時間をループで使います。このループではGUIGetMsg関数を使って単純にGUIのポーリングがおこなわれます。イベントが起きるとGUIGetMsg関数の返し値がその詳細(ボタンが押された、GUIが閉じられたなど)を教えてくれます。
MessageLoopはAutoIt GUIのデフォルトのメッセージモードです。他のモードにはOnEventモードがあります。
MessageLoopモードではGUIGetMsg関数を使ってポーリングすることでイベントを受け取ります。従って1秒間に何度もGUIGetMsg関数を呼ばなければなりません。さもなければGUIは反応してくれません。
一般的なMessageLoopコードの書き方は次の通りです。
While 1
$msg = GUIGetMsg()
...
...
WEnd
通常上記のようなループはCPU使用率を100%にしてしまいますが、幸いGUIGetMsg関数はイベントが起きていないときには自動的にCPUをアイドリング状態にしてくれます。GUIが反応しなくなってしまうだけですからループ内でCPUの酷使を避けるための手書きのSleepをおこなわないでください 。
GUIGetMsgの返すイベントメッセージは3タイプあります。
イベント無し
イベントがない場合、GUIGetMsgは0を返します。GUIではこの場合がほとんどです。
コントロールイベント
コントロールがクリックされたりコントロールに変化があった場合、コントロールイベントが返されます。 これは正の数で、GUICtrlCreate...でコントロールを作成した時に返されるコントロールIDと対応しています。
システムイベント
システムイベントはGUIが閉じたときなどに返され、負の数です。具体的なイベントは下に示す通りでGUIConstantsEx.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_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)
さて、メッセージループと上で述べたイベントメッセージを使ってコードを完成させましょう。読みやすいようにSelect文を使ってメッセージの数値を処理するのが一般的です。
#include <GUIConstantsEx.au3>
GUICreate("Hello World", 200, 100)
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
GUISetState(@SW_SHOW)
While 1
$msg = GUIGetMsg()
Select
Case $msg = $okbutton
MsgBox(0, "GUI Event", "You pressed OK!")
Case $msg = $GUI_EVENT_CLOSE
MsgBox(0, "GUI Event", "You clicked CLOSE! Exiting...")
ExitLoop
EndSelect
WEnd
とても単純です。たくさんのウィンドウとコントロールがある場合はより複雑になります。しかしその場合も上に示したものが基本です。
コントロールIDは固有の値で、もし複数のウィンドウがある場合でも上記のコードはコントロール、ウィンドウ複数を正常に処理します。 ただし、$GUI_EVENT_CLOSEや$GUI_MOUSEMOVEといったイベントを処理する場合はどのGUIウィンドウがイベントを発生させたのかを知る必要があります。 そのためにはGUIGetMsgを次のように呼ばなければなりません。
$msg = GUIGetMsg(1)
1 をパラメータにして呼ぶと、単体のイベント値の代わりに配列が返されます。配列にはイベント($array[0]内)とウィンドウハンドルといった追加情報($array[1]内)が格納されています。 もし2つのウィンドウが作成された場合、先ほどの例は次のように書き直されます。
#include <GUIConstantsEx.au3>
$mainwindow = GUICreate("Hello World", 200, 100)
GUICtrlCreateLabel("Hello world! How are you?", 30, 10)
$okbutton = GUICtrlCreateButton("OK", 70, 50, 60)
$dummywindow = GUICreate("Dummy window for testing ", 200, 100)
GUISwitch($mainwindow)
GUISetState(@SW_SHOW)
While 1
$msg = GUIGetMsg(1)
Select
Case $msg[0] = $okbutton
MsgBox(0, "GUI Event", "You pressed OK!")
Case $msg[0] = $GUI_EVENT_CLOSE And $msg[1] = $mainwindow
MsgBox(0, "GUI Event", "You clicked CLOSE on the main window! Exiting...")
ExitLoop
EndSelect
WEnd
最初の大きな違いはGUISwitch関数が呼ばれていることです。新しいウィンドウが作られるとそれが次回以降のGUI操作の「デフォルト」ウィンドウになります(コントロール作成もそうです)。 今回の場合、動かしたいのはメインの「Hello World」ウィンドウで、テストウィンドウではないので「switch」をおこないます。 いくつかのGUI関数では関数呼び出しにウィンドウハンドルが使えます。これらの関数は自動で切り替えをおこなってくれます。 先ほどの例に使うと次のようになります。
GUISetState(@SW_SHOW, $mainwindow)
つぎの違いはGUIGetMsgの呼ばれ方とイベントのチェックの仕方です。$msg[0] と$msg[1] を見てください。クローズイベントが返され、かつそのイベントがメインウィンドウからの場合のみスクリプトを終了します。