便利に使う‎ > ‎

Windowsのイベントを拾う

イベントの検知方法

AutoHotkeyで常駐型のスクリプトを利用している場合、アクティブウィンドウやキー入力フォーカスが切り替わったりしたときなどに、何らかの処理をしたいということを思ったことは無いだろうか?

これらは WinWaitActive コマンドや SetTimer で定期監視することで実現出来なくもない。しかし、前者はスレッドが止まったままになる問題があるし、後者は実際にイベントが起きた時とのタイムラグを減らすためにタイマー間隔を短くしなければいけない一方、殆どの処理が空振りに終わるという問題がある。

Windows自体はイベント駆動型のOSなので、実際は各種イベントが起きたかどうかはOSに任せて、発生した時だけ通知してもらうという方法を利用することが可能だ。

これにはいくつかの方法がある

  1. グローバルフックを利用してウィンドウ間に飛び交うメッセージを拾う
  2. イベントフック専用APIを利用する

(1) は非常に汎用的だが外部DLLを必要とするなど、AHKだけで完結することが出来ない。(2)は限られたイベントの種類しか取得出来ないがAHKだけで実現することが可能だ。


WinEventの種類

イベントの種類は多くここに一覧がある。

ウィンドウなど一般的なイベントは以下、
  • 音声が鳴るとき
  • 警告が発生するとき
  • アクティブウィンドウが切り替わったとき
  • メニューを開いた/閉じたとき
  • ポップアップメニューを開いた/閉じたとき
  • ウィンドウの移動・リサイズを開始/終了したとき
  • ドラッグ&ドロップの開始/終了したとき
  • ダイアログが開いた/閉じたとき
  • Alt+Tabを開始/終了したとき
  • ウィンドウの最小化を開始/終了した時
  • UACの管理ウィンドウなど異なるデスクトップに切り替わった時
ウィンドウ内のオブジェクトに関するイベントは以下、
  • オブジェクトが作成/破棄されたとき
  • オブジェクトが表示/非表示されたとき
  • オブジェクトがフォーカスを得たとき
  • オブジェクト内のアイテムを選択したとき
  • オブジェクト内のテキスト選択が変化したとき

実際に使ってみる

これは Windows API をDllCall 経由で呼び出す。とはいってもそれほど難しくない。SetWInEventHookというAPIを利用する。

このAPIはイベントを処理する関数を要求する。従って、AHKの組み込み関数 RegisterCallback() を利用することでAPIに引き渡す関数を作成することが出来る。コールバック関数の引数や戻り値は APIのリファレンスを見て決めることになる。

ここではアクティブウィンドウが切り替わった時に、指定の関数が呼ばれるようにしてみる。ウィンドウが切り替わるときのイベント識別子は "EVENT_SYSTEM_FOREGROUND" となる。スクリプトは以下の通り。

#Persistent

myFunc := RegisterCallback("WinActivateHandler")

myHook := DllCall("SetWinEventHook"
, "UInt", 0x00000003 ; eventMin      : EVENT_SYSTEM_FOREGROUND
, "UInt", 0x00000003 ; eventMax      : EVENT_SYSTEM_FOREGROUND
, "UInt", 0          ; hModule       : self
, "UInt", myFunc     ; hWinEventProc : 
, "UInt", 0          ; idProcess     : All process
, "UInt", 0          ; idThread      : All threads
, "UInt", 0x0003     ; dwFlags       : WINEVENT_SKIPOWNTHREAD | WINEVENT_SKIPOWNPROCESS
, "UInt")

WinActivateHandler(hWinEventHook, event, hwnd, idObject, idChild, thread, time) {
WinGetTitle, title, ahk_id %hwnd%
WinGetClass, class, ahk_id %hwnd%
Tooltip, 「%title% ahk_class %class%」がアクティブになった
}

尚、他のイベント識別子はこのページの最後に定数を貼って置いたので参考にされたし。







付録: 定数一覧

イベント識別番号

EVENT_MIN                         = 0x00000001
EVENT_SYSTEM_SOUND                = 0x00000001
EVENT_SYSTEM_ALERT                = 0x00000002
EVENT_SYSTEM_FOREGROUND           = 0x00000003
EVENT_SYSTEM_MENUSTART            = 0x00000004
EVENT_SYSTEM_MENUEND              = 0x00000005
EVENT_SYSTEM_MENUPOPUPSTART       = 0x00000006
EVENT_SYSTEM_MENUPOPUPEND         = 0x00000007
EVENT_SYSTEM_CAPTURESTART         = 0x00000008
EVENT_SYSTEM_CAPTUREEND           = 0x00000009
EVENT_SYSTEM_MOVESIZESTART        = 0x0000000a
EVENT_SYSTEM_MOVESIZEEND          = 0x0000000b
EVENT_SYSTEM_CONTEXTHELPSTART     = 0x0000000c
EVENT_SYSTEM_CONTEXTHELPEND       = 0x0000000d
EVENT_SYSTEM_DRAGDROPSTART        = 0x0000000e
EVENT_SYSTEM_DRAGDROPEND          = 0x0000000f
EVENT_SYSTEM_DIALOGSTART          = 0x00000010
EVENT_SYSTEM_DIALOGEND            = 0x00000011
EVENT_SYSTEM_SCROLLINGSTART       = 0x00000012
EVENT_SYSTEM_SCROLLINGEND         = 0x00000013
EVENT_SYSTEM_SWITCHSTART          = 0x00000014
EVENT_SYSTEM_SWITCHEND            = 0x00000015
EVENT_SYSTEM_MINIMIZESTART        = 0x00000016
EVENT_SYSTEM_MINIMIZEEND          = 0x00000017

EVENT_OBJECT_CREATE               = 0x00008000
EVENT_OBJECT_DESTROY              = 0x00008001
EVENT_OBJECT_SHOW                 = 0x00008002
EVENT_OBJECT_HIDE                 = 0x00008003
EVENT_OBJECT_REORDER              = 0x00008004
EVENT_OBJECT_FOCUS                = 0x00008005
EVENT_OBJECT_SELECTION            = 0x00008006
EVENT_OBJECT_SELECTIONADD         = 0x00008007
EVENT_OBJECT_SELECTIONREMOVE      = 0x00008008
EVENT_OBJECT_SELECTIONWITHIN      = 0x00008009
EVENT_OBJECT_STATECHANGE          = 0x0000800a
EVENT_OBJECT_LOCATIONCHANGE       = 0x0000800b
EVENT_OBJECT_NAMECHANGE           = 0x0000800c
EVENT_OBJECT_DESCRIPTIONCHANGE    = 0x0000800d
EVENT_OBJECT_VALUECHANGE          = 0x0000800e
EVENT_OBJECT_PARENTCHANGE         = 0x0000800f
EVENT_OBJECT_HELPCHANGE           = 0x00008010
EVENT_OBJECT_DEFACTIONCHANGE      = 0x00008011
EVENT_OBJECT_ACCELERATORCHANGE    = 0x00008012

; XP or lator
EVENT_CONSOLE_CARET               = 0x00004001
CONSOLE_CARET_SELECTION           = 0x00000001
CONSOLE_CARET_VISIBLE             = 0x00000002
EVENT_CONSOLE_UPDATE_REGION       = 0x00004002
EVENT_CONSOLE_UPDATE_SIMPLE       = 0x00004003
EVENT_CONSOLE_UPDATE_SCROLL       = 0x00004004
EVENT_CONSOLE_LAYOUT              = 0x00004005
EVENT_CONSOLE_START_APPLICATION   = 0x00004006
CONSOLE_APPLICATION_16BIT         = 0x00000001
EVENT_CONSOLE_END_APPLICATION     = 0x00004007

EVENT_MAX                         = 0x7fffffff

; Vista or lator
EVENT_SYSTEM_DESKTOPSWITCH        = 0x00000020
EVENT_OBJECT_INVOKED              = 0x00008013
EVENT_OBJECT_TEXTSELECTIONCHANGED = 0x00008014
EVENT_OBJECT_CONTENTSCROLLED      = 0x00008015

オブジェクトID

OBJID_WINDOW      = 0x00000000
OBJID_SYSMENU     = 0xFFFFFFFF
OBJID_TITLEBAR    = 0xFFFFFFFE
OBJID_MENU        = 0xFFFFFFFD
OBJID_CLIENT      = 0xFFFFFFFC
OBJID_VSCROLL     = 0xFFFFFFFB
OBJID_HSCROLL     = 0xFFFFFFFA
OBJID_SIZEGRIP    = 0xFFFFFFF9
OBJID_CARET       = 0xFFFFFFF8
OBJID_CURSOR      = 0xFFFFFFF7
OBJID_ALERT       = 0xFFFFFFF6
OBJID_SOUND       = 0xFFFFFFF5



Comments