Domanda

I'm trying to communicate with a native library that uses an HWND to pass messages back to the caller as follows:

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;
}

Even when the call the the native library is omitted, I only ever receive the following messages (in order):

  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

After this I can drag the window corresponding to the HwndSource around but am unable to resize or close it. Furthermore the operating system claims that this window is not responding.

Why does this window stop responding and how can I continue to intercept messages?

È stato utile?

Soluzione 2

As both @HansPassant and @HassanBoutougha pointed out the issue is with the following segment of code:

while (true) { }

While this may look like it's innocently keeping the application alive what it's really doing is preventing the dispatcher from processing messages. The messages that I was seeing was because they were being called directly from within the thread executing Example() by the HwndSource constructor. After construction the application enters the loop and runs around in circles. Unfortunately this is the thread that's suppose to be processing the messages!

Essentially the correct solution here was to tell the dispatcher to put the current call stack on the back burner and process events until we tell it to stop.

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

Essentially the call to Dispatcher.PushFrame this tells the dispatcher to suspend execution and continue listening to messages. At some point in the future if you decide that you want to resume execution where you left of just do the following:

frame.Continue = false;

And that's it! The call to Dispatcher.PushFrame will now return and resume execution

Kent Boggart has a great example here: http://kentb.blogspot.ca/2008/04/dispatcher-frames.html Unfortunately Kent's blog is no longer available however a snapshot of the page from Google's cache may be found here.

Altri suggerimenti

I think that when you try to retrieve the next message from the windows queue, it freezes your original thread that's waiting for the response from WndProc.

Try intercepting messages through Application.AddMessageFilter as was done in this other question

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top