(AutoHotkey)(API関数の SetTimerで コールバック関数を使った タイマー処理をしたい 編)

この記事『API関数の SetTimerで コールバック関数を使った タイマー処理をしたい 編』に一部間違いがあるので
その事を訂正している 関連記事:『AutoHotkeyのタイマーについて 編』
http://d.hatena.ne.jp/morakana/20080222/1203656671
もあわせて ご覧になってください


 AutoHotkeyには 最初から SetTimerコマンドが用意されています
これは 気軽に使えて便利なのですが ひとつのスクリプトの中で 一つしか使えません
まぁ 普通の場合は 一つあれば十分かもしれませんが
明らかに違うタイミングで発動させたい複数個のタイマーを動かしたいと思った時はお手上げになります
ということで それを解決するには API関数を使う事になるわけですね

 ただし API関数で タイマー処理をする場合 「コールバック関数」が必要になる場合がありますね
もちろん AutoHotkeyの関数のアドレスを いきなり API関数に渡しても上手くは動かないでしょう
そこで AutoHotkeyでは API関数から呼び出されても きちんと通用する コールバック関数を生成して
その コールバック関数から AutoHotkeyの関数 を 呼び出せるようになっています
つまり 「コールバック関数のつもり の AutoHotkeyの関数」 を 呼び出す ラッパー関数を 用意しているわけですね

 というわけで 以下は シンプルなサンプルの例ですが
実行すると 3秒おきに MsgBoxで メッセージを出してきます
OK を押して 閉じなければ 次々に メッセージが出てきて 大変です 笑)
このままでは メモリを食い尽くしてしまう!! と 心配してしまいそうですが
AutoHotkey が 一定数以上の MsgBoxが開くのを拒否してくれているようなので 一安心です 笑)
以下の例では マウスの 真ん中ボタンを押すと スクリプトを終了させます
[]; コールバック関数の ラッパー関数のアドレスを pOnTimer変数 に代入しています[]
[]pOnTimer := RegisterCallback("On_Timer", "Fast")[]

[]; 第1引数 は 今回は 明確な ウインドウのハンドルは存在しないので NULL値(0) をセットします[]
[]; 第2引数 は 本来タイマーのIDをセットするはずですが 今回は ハンドルを渡していないので 無視されます[]
[]; 第3引数 は セットするインターバルは 3000msとします、 3秒に一回呼び出される事になります[]
[]; 第4引数 は コールバック関数のラッパー関数のアドレスをセットします[]
[]; 戻り値   は 今回 ハンドルを渡していないので 新しいタイマーのID が 返ってきます[]
[];             KillTimerの時に必要なので NewID変数 に 代入しておきます[]
[]NewID := DllCall("user32.dll\SetTimer", "UInt", 0, "UInt", 0, "UInt", 3000, "UInt", pOnTimer)[]

[]; この例では マウスの 真ん中ボタンを押すと タイマー と ラッパー関数 を開放して スクリプトを終了させます[]
[]MButton::[]
	[]; タイマーを開放します、 ハンドルは NULL値、 IDは さっき取得したものをセットします[]
	DllCall("user32.dll\KillTimer", "UInt", 0, "UInt", NewID)
	[]; コールバック関数のラッパー関数を開放します[]
	[]DllCall("kernel32\GlobalFree", "UInt", pOnTimer)[]
	[]; スクリプトを終了させます[]
	[]ExitApp[]
	[]Return[]

[]On_Timer()[]
[]{[]
	[]; ここに 一定時間ごとに処理する内容を書きます[]
	[]MsgBox, OnTimer[]
[]	Return[]
[]}[]

 タイマーが二個必要な場合ならこんな感じですかね
[]pOnTimer1 := RegisterCallback("On_Timer1", "Fast")[]
[]pOnTimer2 := RegisterCallback("On_Timer2", "Fast")[]

[]NewID1 := DllCall("user32.dll\SetTimer", "UInt", 0, "UInt", 0, "UInt", 3000, "UInt", pOnTimer1)[]
[]Sleep, 1500[]
[]NewID2 := DllCall("user32.dll\SetTimer", "UInt", 0, "UInt", 0, "UInt", 3000, "UInt", pOnTimer2)[]

[]MButton::[]
[]	DllCall("user32.dll\KillTimer", "UInt", 0, "UInt", NewID1)[]
[]	DllCall("user32.dll\KillTimer", "UInt", 0, "UInt", NewID2)[]
[]	DllCall("kernel32\GlobalFree", "UInt", pOnTimer1)[]
[]	DllCall("kernel32\GlobalFree", "UInt", pOnTimer2)[]
[]	ExitApp[]
[]	Return[]

[]On_Timer1()[]
[]{[]
[]	MsgBox, OnTimer1[]
[]	Return[]
[]}[]

[]On_Timer2()[]
[]{[]
[]	MsgBox, OnTimer2[]
[]	Return[]
[]}[]