今さらAutoHotKeyのすごさを知る
AutoHotKeyというツールの存在は以前から知っていたけど,実際に試してみるまでそのすごさを全然わかっていなかった.これはすごいものだ.デスクトップユーティリティ系のツールがいとも簡単に作れてしまう.
基本的にはahkの拡張子を持つというスクリプトを1つ書いて,そいつを常駐しているAutoHotKey本体に読み込ませて動かすんだけど,このahkスクリプトを実行ファイル(exeファイル)にしてくれるというのだから驚愕だ.
UWSCといったスクリプトを用いるユーティリティは自分の環境をちょっとカスタマイズするには便利だけど,誰かが作ったスクリプトを使おうとしたらUWSC本体も導入しなければならない.
AutoHotKeyは実行ファイルまで作れてしまうので,本来自分専用のスクリプト系ユーティリティがアプリケーションの開発環境にまでなってしまうってんだから脱帽である.
とっかかりはあまり良くないけど,実は簡単に書けるのがうれしい.ユーティリティ系でよく使いそうな機能はたいてい用意されているし,用意されていなくてもDLLから直接APIをコールできるので実質ほとんどの操作ができる.
サンプルスクリプト
僕もちょっと書いてみたので公開.画面端にマウスを持って行ったときに指定したウィンドウをアクティブにして,画面上部に持って行ったときは最小化するというもの.よくありそうなツールである.
画面下をファイラ(X-Finder),画面左をブラウザ(Firefox)としている.ちなみに右はランチャー(nrLaunch)が出てくるのでここでは指定していない.
下半分は配列の簡単な実装.これだけ気合いが入ったツールなのに配列が無いのはちょっと意外.そして,配列やハッシュのライブラリを誰か作っていないかとググってみたけど見つからない.これまた意外.
; スクリプト概要 ; - マウスカーソルが画面端から一定の距離になったときウィンドウをアクティブ化 ; 履歴 ; - 2008/04/13 作成 ; ; 永続的に動かす #Persistent ; MouseGetPosの座標をスクリーン座標にする CoordMode,Mouse,Screen ; スクリーンのサイズを取得 ;WinGetPos, , , screen_width, screen_height , Program Manager screen_width := A_ScreenWidth screen_height := A_ScreenHeight ; ウィンドウを探すときのマッチの方法を「指定した文字列を含む」に変更 SetTitleMatchMode,2 ; 複数のウィンドウを同時にチェックするための配列作成 window_list := array("window_list") margin_list := array("margin_list") direct_list := array("direct_list") ; 画面上部に持って行ったときに対象ウィンドウを最小化する top_margin := 5 xfinder := FindWindow("X-Finder", "Firefox") firefox := FindWindow("- Mozilla Firefox", "") ; ウィンドウハンドル,画面端からの距離,方向(1:右,2:下,3:左) SetWatchWindow(xfinder, 5, 2) SetWatchWindow(firefox, 5, 3) ; 100ミリ秒ごとにマウス座標をチェックする SetTimer, WatchCursor, 100 FindWindow(window_text, exclude_text){ window := WinExist(window_text,"",exclude_text) if(window == 0) MsgBox, %window_text% が見つかりません return window } SetWatchWindow(window_id, margin, direct){ global arrpush(window_list, window_id) arrpush(margin_list, margin) arrpush(direct_list, direct) return } WatchCursor: MouseGetPos,x,y,id,control,3 SendMessage,0x84,0,%lp%,,ahk_id %control% If ErrorLevel=4294967295 MouseGetPos,,,,control,2 Loop, %window_list@length% { index := A_Index - 1 window := window_list[%index%] direct := direct_list[%index%] margin := margin_list[%index%] CheckWindow(x,y,window,direct,margin) } CheckHide(x,y) return CheckWindow(x, y, window, direct, margin){ global screen_width global screen_height global last_activated if(direct == 1 && x > screen_width - margin || direct == 2 && y > screen_height - margin || direct == 3 && x < margin) { WinActivate, ahk_id %window% } return } CheckHide(x, y){ global if(y < top_margin){ Loop, %window_list@length% { local index := A_Index - 1 local window := arrget(window_list, index) WinMinimize, ahk_id %window% } } return } ; ここから配列操作関係 array(var_name){ global %var_name%@length := 0 return %var_name% } arrpop(var_name){ global local length := 0 local value := if(%var_name%@length > 0){ %var_name%@length := %var_name%@length - 1 length := %var_name%@length value := %var_name%[%length%] } return value } arrpush(var_name, value){ global local next := %var_name%@length %var_name%[%next%] := value %var_name%@length += 1 return next } arrget(var_name, index){ global return %var_name%[%index%] } arrlen(var_name){ global return %var_name%@length } arrbegin(var_name){ global ; 要素が存在しないときは空文字が返る return %var_name%[0] } arrend(var_name){ global ; 要素が存在しないときは空文字が返る endpos := %var_name%@length - 1 return %var_name%[%endpos%] }