Skip to content

MS_SendMessage

nishi_74322014 edited this page Aug 21, 2026 · 1 revision

SendMessage

概要

WndProc をサブルーチン的に呼び出す(イベントの実装に使用する)

  • スレッド跨ぎか否かで動作が大きく異なる。
  • スレッド跨ぎなら送信・応答にメッセージキューを使用。
  • なお、処理の優先度は、ポストメッセージより高い。

API

  • SendMessage

  • FindWindow

  • SendMessageTimeout

  • SendMessageCallback

  • SendNotifyMessage

  • ReplyMessage(InSendMessage → スレッド内メッセージ?)

  • ,etc.

移行メモ(誤字・体裁): 移行元の「SendMessageTimeOut」を
正しい API 名「SendMessageTimeout」に修正した。
また FindWindow の直後に全角スペースが入っていたため削除した。

補足(SendMessagePostMessage の決定的な違い): 概要の
3 行を図で補強しておく。この違いを理解していないとデッドロックする

【SendMessage(同期)】★
   呼び出し元 ──→ WndProc を実行 ──→ 戻り値を返す
               (処理が終わるまで【戻ってこない】)

   ・同一スレッド → 【ただの関数呼び出し】
                    キューを経由しない ★
   ・別スレッド   → 送信メッセージキューに積み、
                    相手の【メッセージ ループが回るまで待つ】

【PostMessage(非同期)】
   呼び出し元 ──→ キューに積む ──→ すぐ戻る(TRUE/FALSE)
                実行は【後で】
【デッドロックの典型パターン】★★
   スレッドA ──SendMessage──→ スレッドB
   スレッドB ──SendMessage──→ スレッドA
     → 双方が相手の応答を待って【永久に停止】

   ・より地味な形
     スレッドA が SendMessage で B を待つ
     B は重い処理中で【メッセージ ループを回していない】
     → A が固まる
     → A が UI スレッドなら【アプリ全体が「応答なし」】★

   【対策】
     ・【SendMessageTimeout】を使う ★
       → SMTO_ABORTIFHUNG を指定すると
         相手がハングしていれば即座に失敗する
     ・応答が要らないなら【PostMessage】
     ・【SendNotifyMessage】
       → 別スレッド宛なら非同期、同一スレッドなら同期
     ・【SendMessageCallback】
       → 非同期に送り、完了時にコールバックを受ける
【ReplyMessage / InSendMessage について】★
   原文の疑問符(「スレッド内メッセージ?」)に答えると、

   ・InSendMessage()
       → 今処理中のメッセージが
         【別スレッドからの SendMessage か】を判定する
   ・ReplyMessage(result)
       → WndProc の処理を続けたまま、
         【送信元に先に応答を返す】★
       → 送信元のブロックを早く解ける
       → 「時間のかかる処理だが、
         相手を待たせたくない」場合に使う

   → いずれも【別スレッドからの SendMessage】が前提
     (同一スレッドなら単なる関数呼び出しなので意味がない)

補足(FindWindow が並んでいる理由と、その危うさ): 送信系 API の中に
FindWindow があるのは、他プロセスのウィンドウを操作するという
用途を前提にしているためである。

【典型的な使い方(他アプリの自動操作)】★
   HWND h = FindWindow("Notepad", NULL);
   HWND edit = FindWindowEx(h, NULL, "Edit", NULL);
   SendMessage(edit, WM_SETTEXT, 0, (LPARAM)"hello");

【この手法の問題点】
 ① 【ウィンドウ クラス名は実装詳細】★
     → アプリの更新で変わる
     → Windows 11 のメモ帳は WinUI 化され
       従来の "Edit" が【存在しない】
 ② 【UIPI(Vista 以降)】
     → 低い整合性レベルのプロセスから
       高いプロセスへは【メッセージを送れない】
     → 管理者権限で動くアプリは操作できない
 ③ 同名ウィンドウが複数あると取り違える

【現在の推奨】★
   ・【UI Automation】(→ [UI Automation](MS_UIAutomation))
     → アクセシビリティ基盤の上に立つ公式 API
     → 要素の役割・名前で辿れる
   ・アプリが API / CLI を提供しているならそちらを使う
   ・[RPA (Robotic Process Automation)](MS_RPA) の
     製品も内部ではこれらを使っている

参考

移行メモ(リンク切れ): 移行元の msdn.microsoft.com/ja-jp/library/cc411022.aspx
MSDN ライブラリの廃止により到達しないため、
Microsoft Learn の現行ページに差し替えた。


Tags: 移行, Windows, ウィンドウ・システム, プログラミング

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally