PostMessage / SendMessage チュートリアルby Rajat

このページでは、PostMessageSendMessageを使ってウィンドウやそのコントロールにメッセージを送る方法を説明し、以下のような質問に答える:

必要条件:Winspector Spy(ここにある

最初の例として、MenuSelectがOutlook Expressの "New Message "ウィンドウのメニューバーで動作しないことに注意してください。つまり、このコードは機能しない:

MenuSelect "New Message",, "&Insert", "&Picture..."

しかし、PostMessageは仕事をこなすことができる:

PostMessage 0x0111, 40239, 0, , "New Message"

魅力的に機能する!でも、あれは一体何なんだ?0x0111はwm_commandメッセージの16進コードであり、40239はこの特定のウィンドウがメニュー項目の'Insert Picture'選択として理解するコードである。では、40239のような値を見つける方法を説明しよう:

  1. Winspector Spyと "New Message"ウィンドウを開きます。
  2. Winspector Spyのウィンドウから十字線を "New Message"ウィンドウのタイトルバー(Winspector Spyのオーバーレイで覆われていない部分)にドラッグする。
  3. 左側のリストで選択したウィンドウを右クリックし、「メッセージ」を選択します。
  4. 空白のウィンドウを右クリックし、「Edit message filter」を選択する。
  5. 'filter all'ボタンを押して、左のリストにある'wm_command'をダブルクリックする。こうすることで、このメッセージだけを監視することができる。
  6. 「新規メッセージ」ウィンドウに移動し、メニューバーから選択する:Insert > Picture。
  7. ウィンスペクター・スパイに戻り、信号ボタンを押して監視を一時停止する。
  8. 溜まっているwm_commandメッセージを展開する(もしあれば他のものは忘れる)。
  9. 探したいのは(通常は)コード0のメッセージだ。時々、wm_commandに'win activated'とか'win destroyed'とかいうメッセージが出る。You'll find that there's a message saying 'Control ID: 40239' ...that's it!
  10. これを上記の関数に入れれば完成です!wParamの値です。

次の例ではペイントを取り上げる。ここで、AutoHotkeyを使ってツールバーからツールを選択するアプリを考えてみよう。

どうするつもりだ?おそらく、ツールバーのボタンをマウスでクリックしたんだろう?しかし、ツールバーは動かしたり隠したりできる!こちらも移動/非表示が可能。そのため、ターゲット・ユーザーがこのいずれかを行った場合、スクリプトはその時点で失敗する。しかし、次の関数はまだ機能する:

ポストメッセージ 0x0111, 639,,, "無題 - ペイント"

PostMessageのもう一つの利点は、ウィンドウをバックグラウンドにできることである。対照的に、マウスクリックを送信するには、ウィンドウをアクティブにする必要がある。

以下はその例である。注:私はWinXP Pro (SP1)を使っています...もし違うOSを使っているなら、パラメータが変わるかもしれません(ワードパッドやメモ帳のようなウィンドウズ付属のアプリにのみ適用されます):

;makes writing color teal in Wordpad
PostMessage 0x0111, 32788, 0, , "Document - WordPad"
;opens about box in Notepad
PostMessage 0x0111, 65, 0, , "Untitled - Notepad"
;toggles word-wrap in Notepad
PostMessage 0x0111, 32, 0, , "Untitled - Notepad"
;play/pause in Windows Media Player
PostMessage 0x0111, 32808, 0, , "Windows Media Player"
;suspend the hotkeys of a running AHK script
DetectHiddenWindows True
; Use 65306 to Pause and 65303 to Reload instead of Suspend. (see FAQ)
PostMessage 0x0111, 65305,,, "MyScript.ahk - AutoHotkey"
; Press CapsLock and Numpad2 to reload all AutoHotkey scripts
CapsLock & Numpad2::
ReloadAllAhkScripts(ThisHotkey)
{
    DetectHiddenWindows True
    for hwnd in WinGetList("ahk_class AutoHotkey")
    {
        if (hwnd = A_ScriptHwnd)  ; ignore the current window for reloading
            continue
        PostMessage 0x0111, 65303,,, hwnd
    }
    Reload
}

これはPostMessage用である。SendMessageも同じように動作するが、さらに戻り値を待つ。この戻り値は、Winampで現在再生中のトラックを取得する場合などに使用できる(例としてWinampの自動化を参照)。

以下はそのメモである:

注:このテクニックが使えないアプリもある。VBとDelphiのアプリには、いろいろな運があった。このテクニックは、CやC++のアプリで使うのが最適だ。VBアプリでは、同じ関数の'LParam'が実行ごとに変わり続ける。Delphiアプリでは...いくつかのアプリのGUIはwm_commandすら使わない。おそらくマウスのポーズとクリックを使っているのだろう。

そしてAutoHotkeyフォーラムであなたの経験を共有してください。フィードバックは大歓迎だ!

このチュートリアルは全くの初心者向けではありません(悪意はありません)。だから、上記を読んでもさっぱり理解できないなら、もう忘れてほしい。

-Rajat