1

我正在尝试与使用 anHWND将消息传递回调用者的本机库进行通信,如下所示:

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 回答