1

HWND次のように、を使用してメッセージを発信者に返すネイティブライブラリと通信しようとしています。

private void Example()
{
    using (
        var hwnd = new HwndSource(
            new HwndSourceParameters("I sense a disturbance in the force...") {HwndSourceHook = WndProc}
            )
        )
    {
        //send hwnd.handle to native library
        while (true) { }
    }
}

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool ishandled)
{
    ishandled = false;
    Console.WriteLine("Intercepted message: 0x{0:X}", msg);
    return IntPtr.Zero;
}

ネイティブライブラリの呼び出しが省略されている場合でも、次のメッセージのみを(順番に)受信します。

  1. 0x0001:WM_CREATE
  2. 0x0018:WM_SHOWWINDOW
  3. 0x0046:WM_WINDOWPOSCHANGING
  4. 0x0046:WM_WINDOWPOSCHANGING
  5. 0x001C:WM_ACTIVATEAPP
  6. 0x0086:WM_NCACTIVATE
  7. 0x007F:WM_GETICON
  8. 0x007F:WM_GETICON
  9. 0x007F:WM_GETICON
  10. 0x0006:WM_ACTIVATE
  11. 0x0281:WM_IME_SETCONTEXT
  12. 0x0282:WM_IME_NOTIFY
  13. 0x0007:WM_SETFOCUS
  14. 0x0085:WM_NCPAINT
  15. 0x0014:WM_ERASEBKGND
  16. 0x0047:WM_WINDOWPOSCHANGED
  17. 0x0083:WM_NCCALCSIZE
  18. 0x0085:WM_NCPAINT
  19. 0x0014:WM_ERASEBKGND
  20. 0x0005:WM_SIZE
  21. 0x0003:WM_MOVE
  22. 0x000D:WM_GETTEXT

この後、HwndSource周囲に対応するウィンドウをドラッグできますが、サイズを変更したり閉じたりすることはできません。さらに、オペレーティングシステムは、このウィンドウが応答していないと主張します。

このウィンドウが応答を停止するのはなぜですか。また、メッセージを傍受し続けるにはどうすればよいですか。

4

2 に答える 2

1

Windowsキューから次のメッセージを取得しようとすると、からの応答を待機している元のスレッドがフリーズすると思いますWndProc

この他の質問Application.AddMessageFilterで行われたように、メッセージを傍受してみてください

于 2012-08-30T19:02:11.153 に答える
0

@HansPassantと@HassanBoutoughaの両方が指摘したように、問題は次のコードセグメントにあります。

while (true) { }

これは無邪気にアプリケーションを存続させているように見えるかもしれませんが、実際に行っていることは、ディスパッチャがメッセージを処理するのを妨げています。私が見たメッセージは、コンストラクターによって実行Example()されているスレッド内から直接呼び出されていたためです。HwndSource構築後、アプリケーションはループに入り、円を描いて走り回ります。残念ながら、これはメッセージを処理していると思われるスレッドです。

ここでの基本的に正しい解決策は、ディスパッチャに現在のコールスタックをバックバーナーに配置し、停止するように指示するまでイベントを処理するように指示することでした。

DipatcherFrame frame = new DispatcherFrame();
Dispatcher.PushFrame(frame);

基本的に、Dispatcher.PushFrameこれを呼び出すと、ディスパッチャは実行を一時停止してメッセージのリッスンを続行するように指示されます。将来のある時点で、実行を再開したい場合は、次の手順を実行します。

frame.Continue = false;

以上です!の呼び出しDispatcher.PushFrameが戻り、実行が再開されます

Kent Boggartの良い例がここにあります:http://kentb.blogspot.ca/2008/04/dispatcher-frames.html 残念ながら、Kentのブログは利用できなくなりましたが、Googleのキャッシュからのページのスナップショットがここにあります。

于 2012-08-31T20:24:53.607 に答える