WM_NCHITTEST和HTTRANSPARENT阻止来自消息循环的输入

时间:2015-11-10 11:29:30

标签: multithreading user-interface winapi mfc

我们有一个用户可定义的“仪表板”。可以在此窗口中添加多个组件。一些窗口是浏览器控件(使用CLSID_WebBrowser创建的ActiveX控件)。此浏览器控件可以显示内部Web中不同来源的内容。

为避免阻止应用程序,每个浏览器控件都托管在自己的线程中。这里的原因是ActiveX Webbrowser控件托管在STA中,只在消息循环运行时加载和显示数据,这可能会阻止UI的其他部分。

因此,我们有一个父窗口,其中包含类型列表控件,树控件,静态和组框的子窗口,以及一些浏览器控件。除浏览器控件外,所有控件都属于同一UI线程。但线程使用一个输入队列,并为每个线程执行AttachThreadInput以将其附加到主线程。

现在我们面临以下问题:

当用户使用组合框和网页控件设计他的屏幕时。当用户将鼠标移到浏览器控件上并单击或使用鼠标滚轮时,应用程序会锁定。应用程序锁定并不接受任何进一步的输入。如果您最小化应用程序并再次激活它,您可以继续工作并再次接受输入。

原因

使用我们发现的调试器和spy ++,任何鼠标事件都会导致WM_NCHITTEST被发送到组框。组框返回HTTRANSPARENT。但底层窗口是一个不同的线程。我们可以看到无限循环发生WM_NCHITEST消息被触发到组框,输入被阻塞,直到这个循环被中断(通过显示桌面最小化)。

我们可以在文档中读到WM_NCHITTEST和HTTRANSPARENT仅限于同一线程的窗口。我可以在网上找到另外两篇描述相同或类似问题的文章。

简单的解决方案

简单的解决方案只是要注意浏览器控件永远不会被组框或静态控件所覆盖。因此,更改Z顺序很简单并且有效(groupbox必须遵循Z顺序中不同线程的窗口)

问题

如果有其他方法可以解决这个问题,我会感兴趣。或者,如果有办法防止此类输入队列死锁。或者,当这个WM_NCHITTEST必须处理来自不同线程的窗口时,有人知道内部发生了什么。

0 个答案:

没有答案