11

Win32 C ++アプリケーションでは、キューからメッセージをフェッチし、それらを変換してからディスパッチするメッセージループを開始します。最終的に、各メッセージはWndProcに到達し、そこで関連するイベントを処理できます。

私はその部分を理解しています。私が理解していないのは、進行の合間です。具体的には:

  1. さまざまな種類のOS割り込みハンドラーが、前述の「メッセージキュー」にメッセージを配置する必要がありますが、このキューはプロセスアドレス空間内のどこにありますか?割り込みハンドラコードにどのように公開されますか?
  2. メッセージを「翻訳」するとはどういう意味ですか?呼び出しはTranslateMessage()実際に何をしますか?
  3. によってディスパッチされるDispatchMessage()と、メッセージはWndProcに到達する前にどの場所でスイングしますか(つまり、OSはそれをどのように処理しますか)?

上記の答えをご存知の方がいらっしゃいましたら、好奇心を満たしてください。ありがとう。

4

5 に答える 5

6

OSはメッセージキューを維持し、そこでイベントを配置します(たとえば、割り込みまたは他のソースから)。次に、メッセージに応じて、そのキューからすべてのウィンドウにメッセージを送信します(たとえば、フォーカスのないウィンドウにキーメッセージを送信しません)。

アプリケーションは、メッセージを処理するための独自のキューを持つことができます。これらのキューは、要求に応じて作成されます(必要な場合のみ)。

メッセージの翻訳は、「実際の」イベントではないメッセージを作成するために使用されます。たとえば、WM_CONTEXTMENUメッセージは、マウスの右クリック、コンテキストメニューキー、またはShift-F10のいずれかから「変換」されます。WM_CHARは、WM_KEYDOWNメッセージから変換されます。そしてもちろん、他の多くのメッセージはそのように「翻訳」されます。

メッセージは、それを受信する必要があるすべてのウィンドウに投稿されます。OSは、メッセージのタイプに応じて、ウィンドウがそのメッセージを受信するかどうかを決定します。ほとんどのメッセージはシステムによって待機されます。つまり、メッセージはウィンドウによって処理されるまで別のウィンドウに投稿されません。これはブロードキャストメッセージに大きな影響を与えます。そのメッセージを処理するときに1つのウィンドウが戻らない場合、キューはブロックされ、他のウィンドウはメッセージを受信しなくなります。

于 2009-04-19T14:19:59.473 に答える
6

メッセージの送信方法と処理方法によって異なります。

SendMessageを呼び出すときに、ターゲットウィンドウが現在のスレッドによって所有されている場合、呼び出しはウィンドウのメッセージキューをバイパスし、ウィンドウマネージャーはターゲットウィンドウのwindowprocを直接呼び出します。ターゲットウィンドウが別のスレッドによって所有されている場合、ウィンドウマネージャーはPostMessageを効果的に呼び出し、ターゲットウィンドウがウィンドウプロシージャから戻るまでウィンドウメッセージをポンピングします。

PostMessageを呼び出すと、ウィンドウマネージャはメッセージパラメータをマーシャリングし、対応するオブジェクトをターゲットウィンドウのメッセージキューに挿入します。次にGetMessageを呼び出すと、メッセージはメッセージキューから削除されます。

ウィンドウマネージャーは、入力デバイス(キーボードやマウス)からの生の入力イベントも登録し、それらの入力イベントのメッセージを生成します。次に、それらのメッセージを必要に応じてキューに挿入します(入力イベントの処理は、ウィンドウのメッセージキューに既に存在するメッセージに依存するため複雑です)。

Stefanが示したように、TranslateMessageはアクセラレータキーを変換するだけです。たとえば、キーシーケンスをWM_COMMANDメッセージに変換します。

于 2009-04-19T22:16:07.610 に答える
4

さまざまな種類のOS割り込みハンドラーが、前述の「メッセージキュー」にメッセージを配置する必要がありますが、このキューはプロセスアドレス空間内のどこにありますか?割り込みハンドラコードにどのように公開されますか?

Windowsはスレッドに関連付けられています。ウィンドウのある各スレッドには、プロセスのアドレス空間にスレッドキューがあります。OSには、ハードウェアで生成されたイベント用に、独自のアドレス空間に内部キューがあります。OSは、イベントの詳細とその他の状態情報(たとえば、どのウィンドウにフォーカスがあるか)を使用して、ハードウェアイベントをメッセージに変換し、適切なスレッドキューに配置します。

投稿されたメッセージは、ターゲットウィンドウのスレッドキューに直接配置されます。

送信されるメッセージは通常、直接処理されます(キューをバイパスします)。

細部が毛むくじゃらになります。たとえば、スレッドキューはメッセージのリスト以上のものであり、いくつかの状態情報も保持します。一部のメッセージ(WM_PAINTなど)は実際にはキューに入れられていませんが、キューを照会して空になったときに追加の状態情報から合成されます。他のスレッドが所有するウィンドウに送信されたメッセージは、直接処理されるのではなく、実際には受信者のキューに投稿されますが、システムは、呼び出し元の観点からは通常のブロッキング送信のように見せます。これがデッドロックを引き起こす可能性がある場合(循環が元のスレッドに送り返されるため)、陽気さが続きます。

ジェフリー・リッチターの本には、多くの(すべて?)残酷な詳細があります。私のエディションは古いです(高度なウィンドウ)。現在のエディションは、C /C++経由でWindowsと呼ばれているようです。

OSは、メッセージストリームを呼び出し元に合理的(かつ比較的単純)に見せるために多くの作業を行います。

メッセージを「翻訳」するとはどういう意味ですか?TranslateMessage()の呼び出しは実際に何をしますか?

仮想キーメッセージを監視し、キーダウン/キーアップの組み合わせを認識すると、文字メッセージを追加します。TranslateMessageを呼び出さないと、WM_CHARのような文字メッセージを受信できません。

(投稿するのではなく)戻る直前にキャラクターメッセージを送信しているのではないかと思います。チェックしたことはありませんが、WM_CHARメッセージがWM_KEYUPの直前に到着したことを思い出しているようです。

DispatchMessage()によってディスパッチされると、WndProcに到達する前にメッセージはどの場所でスイングしますか(つまり、OSはそれをどのように処理しますか)?

DispatchMessageは、ターゲットウィンドウのWndProcにメッセージを渡します。途中で、いくつかのフックがメッセージを見る機会を得るかもしれません(そしておそらくそれを妨害するかもしれません)。

于 2009-05-13T22:56:26.217 に答える
1

これについて絶対的に肯定的ではありませんが、私の最善の推測は次のように述べています。

  1. キューは、Win32API呼び出しでアクセスするシステムオブジェクトです。プロセスのアドレス空間にはまったくありません。したがって、割り込みハンドラーはそれにアクセスできます(おそらくカーネルのHAL(ハードウェアアブストラクションレイヤー)を介して)。

  2. Win16では、その呼び出しは、より大きなメッセージのさまざまなサブパートを取り、それらを全体にマッシュアップしました。したがって、TranslateMessageは、対応するWM_KEYDOWN WM_KEYUPシーケンスが見つかったときに、WM_KEYPRESSを追加します。また、内部設定とメッセージのタイムスタンプに基づいて、さまざまなボタンクリックメッセージをダブルクリックメッセージに変換します。Win32でもこれができるかどうかはわかりません。

  3. DispatchMessageは、おそらくウィンドウメッセージフックが処理される場所です。したがって、ウィンドウにフックがある場合は、ここで呼び出されるか、GetMessageが呼び出されたときに呼び出されます。わからない。それ以外は、DispatchMessageはウィンドウに関連付けられているWndProcアドレスを検索して呼び出します。それがすることは他にあまりありません。

お役に立てば幸いです。

于 2009-04-19T14:12:07.760 に答える
1

最後のサブ質問に対処するために、ディスパッチされたメッセージは、すべてのフックを介してパイプ処理された後、WindowProcに送信されます(WH_CALLWNDPROC)

于 2009-04-20T11:31:48.603 に答える