如何在没有任何内容的情况下拦截来自HwndSource的WndProc消息

时间:2012-08-30 18:34:21

标签: c# .net wpf interop hwnd

我正在尝试与使用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
  23. 在此之后我可以拖动与HwndSource对应的窗口,但无法调整大小或关闭它。此外,操作系统声称此窗口没有响应。

    为什么此窗口停止响应,如何继续拦截消息?

2 个答案:

答案 0 :(得分:1)

我认为当您尝试从Windows队列中检索下一条消息时,它会冻结等待WndProc响应的原始主题。

尝试通过Application.AddMessageFilter

中的{{1}}拦截邮件

答案 1 :(得分: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缓存的页面快照here