2

Windows メッセージは、Windows OS 上のアプリケーションに通知する良い方法のようです。実際にはうまく機能しますが、いくつかの質問が頭に浮かびます。

SendMessage ルーチンのlparamに構造化データを指定する方法(多くのメッセージ コードと同様)。つまり...もちろん、パラメーターはポインターですが、プロセスはどのようにアクセスするのでしょうか? メッセージを送受信するプロセスによってロードされたDLLによって割り当てられているのでしょうか?

メッセージの構造化パラメーターを (送信者と受信者の間で) 共有することは可能ですか? それらは、送信操作とピーク操作の間でマーシャリングされますか? この場合、構造化パラメーターを変更することで、呼び出し元からデータを返すことは可能ですか? これは、PostMessage ルーチンの代わりに同期的に実行されるため、SendMessage で役立ちます。

他にも疑問...

PostMessageやSendNotifyMessageとの違いは何ですか?

メッセージ ポンプの処理中に、アプリケーションがそれ自体に SendMessage を呼び出した場合、デッドロックが発生する可能性はありますか?

4

2 に答える 2

4

メッセージが標準ウィンドウのメッセージの 1 つである場合 (通常はメッセージ ID が 0 ~ WM_USER の場合)、システム ウィンドウ メッセージ ディスパッチ ロジックには、メッセージがディスパッチされるプロセスに構造体をマーシャリングするコードが含まれます。

WM_USER より上のメッセージはそのような扱いを受けません - これには Windows 95 で導入されたすべての共通コントロール メッセージが含まれます - LVM_* (リスト ビュー メッセージ) または他の新しいコントロール メッセージを別のプロセスでコントロールに終了させて​​結果を取得することはできません。戻る。

WM_COPYDATA は、ユーザー コードがプロセス間で任意のデータをマーシャリングするための汎用メカニズムとして具体的に導入されました。WM_COPYDATA の外部 (または他の Windows 標準メッセージを再利用) では、メッセージ キュー メカニズムを使用して構造化データを別のプロセスに自動的にマーシャリングするウィンドウを取得する方法はありません。 .

メッセージの送信と受信を行う独自のコードである場合は、ポインターを送信する代わりに、dll を使用して共有メモリ セクションを定義できます (dll はプロセスごとに異なるベースになっている可能性があります)。共有メモリ ブロックにオフセットを送信します。

データをマーシャリングしない外部アプリケーションと構造化データを交換する場合 (たとえば、リストまたはツリー ビューからデータを抽出する場合)、dll インジェクションを実行して、「インプロセス」からメッセージを送信および処理できるようにする必要があります。 .


SendNofityMessage は PostMessage とは異なります。PostMessage は常にメッセージをメッセージ キューに入れるのに対し、SendNotifyMessage は同じプロセス内のウィンドウの SendMessage のように機能します。次に、ターゲット ウィンドウが別のプロセスにある場合でも、メッセージは、GetMessage または PeekMessage を介して取得するためにポストされたメッセージ キューに配置されていないウィンドウ プロシージャに直接ディスパッチされます。


最後に、デッドロックを引き起こす可能性がありますが、「ブロッキング」 sendmessage が別のスレッドの応答を待っている間、SendMessage は他のスレッドから送信された (ポストされていない) メッセージをディスパッチして、デッドロックを防ぎます。これにより、潜在的なデッドロックのほとんどが軽減されますが、他のブロッキング API を呼び出したり、モーダル メッセージ処理ループに入ったりすることで、デッドロックが発生する可能性があります。

于 2010-06-29T19:36:47.377 に答える
0

あなたの懸念は、主にプロセス間で送信されるメッセージの場合に当てはまります。プロセス内では、ポインターを送信するだけでよく、送信者は受信者がデータの使用を終了するまでデータが有効であることを確認する必要があります。

HGLOBAL一部のインタープロセス メッセージでは、 (クリップボード メッセージなど)を操作する必要があります。明示的なブロック サイズを必要とするものもあります (たとえば、 を使用WM_COPYDATA)。さらに、マーシャリングをサポートするために、事前に指定された構造 (ゼロで終わる文字列など) でデータを送信するものもあります。

一般的に言えば、受け取ったブロックを変更して値を返すことはできません。値を返すには、(たとえば) 返信メッセージを送信する必要があります。

SendMessageデッドロックを防ぐための (かなり複雑な) ロジックがありますが、それでも注意が必要です。

于 2010-06-29T19:38:22.117 に答える