[英]How to intercept WndProc messages from a HwndSource without any content
I'm trying to communicate with a native library that uses an HWND
to pass messages back to the caller as follows: 我正在尝试与使用
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;
}
Even when the call the the native library is omitted , I only ever receive the following messages (in order): 即使省略了对本机库的调用 ,我也只会(按顺序)收到以下消息:
WM_CREATE
WM_CREATE
WM_SHOWWINDOW
WM_SHOWWINDOW
WM_WINDOWPOSCHANGING
WM_WINDOWPOSCHANGING
WM_WINDOWPOSCHANGING
WM_WINDOWPOSCHANGING
WM_ACTIVATEAPP
WM_ACTIVATEAPP
WM_NCACTIVATE
WM_NCACTIVATE
WM_GETICON
WM_GETICON
WM_GETICON
WM_GETICON
WM_GETICON
WM_GETICON
WM_ACTIVATE
WM_ACTIVATE
WM_IME_SETCONTEXT
WM_IME_SETCONTEXT
WM_IME_NOTIFY
WM_IME_NOTIFY
WM_SETFOCUS
WM_SETFOCUS
WM_NCPAINT
WM_NCPAINT
WM_ERASEBKGND
WM_ERASEBKGND
WM_WINDOWPOSCHANGED
WM_WINDOWPOSCHANGED
WM_NCCALCSIZE
WM_NCCALCSIZE
: WM_NCCALCSIZE
WM_NCPAINT
WM_NCPAINT
WM_ERASEBKGND
WM_ERASEBKGND
WM_SIZE
WM_SIZE
WM_MOVE
WM_MOVE
WM_GETTEXT
WM_GETTEXT
After this I can drag the window corresponding to the HwndSource
around but am unable to resize or close it. 此后,我可以拖动与
HwndSource
对应的窗口,但是无法调整大小或关闭它。 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? 为什么此窗口停止响应,如何继续拦截消息?
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
. 我认为,当您尝试从Windows队列中检索下一条消息时,它将冻结等待
WndProc
响应的原始线程。
Try intercepting messages through Application.AddMessageFilter
as was done in this other question 尝试像上述其他问题一样通过
Application.AddMessageFilter
拦截消息
As both @HansPassant and @HassanBoutougha pointed out the issue is with the following segment of code: 正如@HansPassant和@HassanBoutougha指出的那样,问题在于以下代码段:
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. 我看到的消息是因为
HwndSource
构造函数直接从执行Example()
的线程中调用了它们。 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. 本质上,对
Dispatcher.PushFrame
的调用告诉调度程序暂停执行并继续侦听消息。 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 现在,对
Dispatcher.PushFrame
的调用将返回并恢复执行
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 . 肯特·博格(Kent Boggart)在这里有一个很好的例子: http ://kentb.blogspot.ca/2008/04/dispatcher-frames.html不幸的是,肯特的博客不再可用,但是可以在此处找到Google缓存中页面的快照。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.