2012-02-11 32 views
4

私はWin32上でいくつかのことを読んで、メッセージループがどのように機能するのか、まだわかりません。メッセージキューには正確に何が格納されていますか?メッセージ(WM_COMMANDWM_CREATEなど)またはMSG構造体へのポインタに対応する整数値。wParam,lParamなどのメッセージ整数値と他のものを含む構造体?Win32でメッセージキューはどのように機能しますか?

+1

これはどうしてですか?どのような問題を解決しようとしていますか?どのコードが機能していないのですか?入手するにはどのような情報が必要ですか? –

+3

@CodyGrayあなたの疑問に対する回答は、 です。a)彼は好奇心を持っていたからです。 b)この顕著な質問の存在。 c)なし。 d)質問で要求された情報(「メッセージキューに正確に格納されているものは何ですか?」 –

+0

@Jon問題は問題と同じではありません。誰も彼の好奇心に疑問を投げかけたり反対したりするのではなく、むしろこの好奇心の背後にあるモチベーション*について問いかける。彼がWin32の内部について興味があるだけなら、問題をデバッグしたり、何かを回避したり、メッセージキューを使ってアプリケーションを動作させたりする場合とは、非常に異なる答えを書いています。[[ XY問題](http://meta.stackexchange.com/questions/66377/)?人々がWin32の詳細について質問するとき、私はそのようなことをたくさん見ます。 –

答えて

8

あなたのように、メッセージコード

  • 、少なくとも、

    • 、狭義のwParamとlParamにはメッセージが向けられているウィンドウハンドルをキュー店で各メッセージをあなたの質問に答えるためにメッセージはが掲載されたとき、すでに正常にメッセージが投稿された時間は、を参照してください(、UIメッセージのため
    • 、あなたはGetMessageTime()で取得することを、
    • 、カーソルの位置を指摘しました。

    実際にすべてのメッセージがキューに格納されているわけではありません。ウィンドウを所有するスレッドからウィンドウにSendMessage()で送信されたメッセージは保存されません。代わりに、受信側ウィンドウのメッセージ関数が直接呼び出されます。他のスレッドから送信されたメッセージは、処理されるまで格納され、送信スレッドは、ウィンドウ関数を終了するか、ReplyMessage()の呼び出しで明示的にメッセージが返されるまでブロックします。 API関数InSendMessage()は、ウィンドウ機能が別のスレッドから送信されたメッセージを処理しているかどうかを判断するのに役立ちます。

    あなたやシステムが投稿したメッセージは、いくつかの例外を除いてキューに格納されます。 WM_TIMERメッセージは実際にはに格納されません。;代わりに、GetMessage()は、キューに他のメッセージがなく、タイマーが成熟している場合、タイマーメッセージを構成します。これは、まず、タイマーメッセージのデキュー優先順位が最も低く、短時間タイマーからの複数のメッセージは、GetMessage()がしばらく呼び出されていなくても、決してオーバーフローしないことを意味します。同様に、WM_QUITも格納されず、フラグが立てられます。 GetMessage()は、キューが使い果たされた後にWM_QUITを取得したふりをしており、これが最後に取得したメッセージです。おそらく、他にも例外と内部最適化があります。

    メッセージが投稿されたウィンドウを所有するスレッドのキューに、PostMessage()というメッセージが投稿されました。

    メッセージが内部的にどのような形式で保存されているかわかりませんが、気にしません。 Windows APIはそれを完全に抽象化します。 MSG構造体は、GetMessage()またはPeekMessage()に渡すメモリに格納されます。 Windows SDKのガイドに記載されているものを超えて、内部実装の詳細を知る必要はなく、心配する必要はありません。

  • +0

    私は参照してください。したがって、SendMessage()によって送信された別のメッセージがすでに処理/処理されているときにSendMessage()でメッセージを送信するとどうなりますか?どこにも保存されていないので、何が起こるのでしょうか? – user1091856

    +0

    単一のスレッドを考えてみましょう。スレッドは、(SendMessage()を介して)メッセージ関数を入力し、その関数がまだ返されていない場合に限り、「メッセージの処理」を行います。メッセージ関数内からSendMessage()を呼び出すと、同じ呼び出しスタック上で別のメッセージ関数が呼び出されます(または同じものが実際に再帰的に呼び出されます)。メッセージを処理した後、SendMessage()から制御が戻ります。 SendMessage()は、* call *メッセージ関数の方法と考えることができます。これは、hWndに基づいて追加のファンシーディスパッチを行うということだけです。 – kkm

    +0

    'WM_TIMER'と同様に、' WM_PAINT'は別の例外です。実際にはキューに格納されていないメッセージです。もちろん、質問に対する実際の答えは最後の段落にあります。これはすべて実装の詳細なので、プログラマーにとってはまったく関係ありません。開発者は、SDKで文書化されている内容のみに関心を持ち、実装の詳細を変更する必要はありません。 –

    0

    MSDNには、メッセージとメッセージキューのすべてを説明する素敵な記事hereがあります。

    質問に答えるために、キューは各ウィンドウに存在し、MSGのキューが実装定義されているかどうかに関係なく、メッセージとその関連パラメータを一時的に保存しますが、 )。すべてのメッセージがキューに入るわけではなく、即時処理が必要なメッセージもあることにも注意してください。

    +0

    すべての点を考慮すると、ウィンドウごとのキューに関する文は正しくありません。キューはスレッドごとに作成されるか、 ':: AttachThreadInput()'によって複数のスレッドによって共有されます。ナンシーの古いが良い記事を見てください:http://msdn.microsoft.com/en-us/library/ms810439.aspx – kkm

    6

    Windowsのメッセージキューは、抽象です。それをキューと考えるのは非常に便利ですが、実際の実装ははるかに詳細です。 Windowsでは、4つの異なるメッセージソースがあります。

    • SendMessage()によって配信されるメッセージ。 Windowsは直接ウィンドウプロシージャを呼び出し、メッセージはPeek/GetMessage()によって返されませんが、ディスパッチするにはその関数への呼び出しが必要です。はるかに多くのメッセージがこの方法で配信されます。 WM_COMMANDは、TranslateAccelerator()のようなキーダウンイベントを変換するコードによって直接送信されます。キューのような振る舞いはありません。

    • ウィンドウ状態から合成されたメッセージ。最も良い例は、WM_PAINTであり、「ウィンドウが汚れた矩形を有する」状態フラグがセットされたときに送出される。そして、WM_TIMERは、 "タイマー満了"状態フラグがセットされたときに配信される。これらは「低優先度」のメッセージで、メッセージキューが空の場合にのみ配信されます。 GetMessage()によって配信されますが、それ以外の場合はキューには存在しません。

    • キーボードとマウスのイベントメッセージを入力します。これらは本当にキューのような振る舞いを持つメッセージです。キーボードの場合、これは先行入力が機能することを保証し、プログラムがキーストロークを受け入れる準備ができていないときにキーストロークが失われることはありません。それは状態の束に関連付けられ、キーボードの状態全体がコピーされます。マウスの状態はそれ以外はほぼ同じです。 WM_MOUSEMOVEメッセージは興味深いコーナーケースです。キューはではありません。は、カーソルが移動するすべての単一ピクセルを格納します。位置の変化は1つのメッセージに蓄積され、必要に応じて格納または配信されます。

    • メッセージは明示的なPostMessage()呼び出しによってキューに格納されます。これはプログラムコードに完全に従っています。コールの引数とコールの時間を保存するだけで、GetMessage()時に正確に再生できるようになります。

    +0

    "Windowsは直接ウィンドウプロシージャを呼び出しますが、メッセージはPeek/GetMessage()によって返されませんが、ディスパッチするにはその関数への呼び出しが必要です。ディスパッチビットは、クロススレッドメッセージに対してのみ真です。それ以外の場合は関数呼び出しです。 – arx

    関連する問題