如何在STA中抽取COM消息而不抽取WM_PAINT?

如何在STA中抽取COM消息而不抽取WM_PAINT?

问题描述:

我需要在等待事件修复死锁时抽取COM消息。尽可能少地输入消息来处理该COM调用会更好。该角色的最佳人选是CoWaitForMultipleHandles,但starting from Vista除了COM消息外,还会泵送WM_PAINT。对于我来说,重新导入WM_PAINT对我来说太危险了,我不想安装一个自定义填充数据库作为这个问题的解决方案。如何在STA中抽取COM消息而不抽取WM_PAINT?

我试图泵送COM消息手动发送到隐藏的消息窗口。

我发现两种方式来获得隐藏窗口的HWND:

  1. ((SOleTlsData *) NtCurrentTeb()->ReservedForOle)->hwndSTA使用ntinfo.h从.NET的核心。就未来的变化而言,这似乎没有证据,也不是可靠的解决方案。
  2. 按照this question中的建议查找OleMainThreadWndClass的窗口。问题是CoInitialize不会创建该窗口。它是在第一次跨公寓呼叫后创建的,可能会或可能不会在我的应用程序中发生。每次我需要HWND时运行搜索循环从性能角度来看是不好的,但是缓存HWND似乎是不可能的,因为我不知道它是什么时候创建的。

有没有办法确定是否为当前公寓创建了隐藏窗口?我想它会比循环更便宜,然后我可以找到并缓存HWND。

有没有更好的方法来泵送COM消息而不抽水WM_PAINT?

更新:您可以通过调用CoMarshalInterThreadInterfaceInStream来强制窗口创建任何接口。然后调用Co­Release­Marshal­Data来释放流指针。这就是我最终在搜索OleMainThreadWndClass时所做的事情。

+1

如果你想去黑暗的路线,你应该能够调整AppCompatFlags直接通过内存PEB:https://social.msdn.microsoft.com/Forums/sqlserver/en-US/5a28a9f5-5711-4efa -843e-e98927fa2b92/dcom-in-vista-specific-processing-wmpaint-messages?forum = windowsgeneraldevelopmentissues。我认为你可以禁用WM_PAINT泵,如果你的二进制和当前AppCompatFlags标志值为0x100000。注意从PEB开始的AppCompatFlags偏移量与x64和x32不同。 –

+0

我想不出处理WM_PAINT消息的唯一好理由。如果WM_PAINT处理程序中的某些内容是“危险的”,我会猜测你在WM_PAINT中做了一些你不应该做的事情。 WM_PAINT处理程序应该只读取状态(任何必要的变量来弄清楚画什么),而不是修改状态。 –

+0

@MichaelGunter,虚拟网格在WM_PAINT处理程序中做了很多有趣的事情。 –

WM_PAINT是在消息队列中没有其他消息并执行GetMessage或使用PeekMessage时生成的。

WM_PAINT只发送,如果你调度它。也没有新的WM_PAINT消息,直到窗口再次失效。

因此,如果您发送WM_PAINT消息,则取决于您。但请注意,还有其他的再入机会,例如WM_TIMER消息。

有关详细信息,请参阅WM_PAINT的文档。

从我的角度来看,最好的解决方案是将应用程序设置为“等待”模式,甚至可以在这个未定义的等待状态下处理WM_PAINT。你知道你什么时候重新进入。它总是在WM_PAINT之后...或者像其他输入消息一样到达的类似消息。所以我在这里没有看到任何问题。 STA有一个线程,并且您始终处理消息到结束,直到您执行GetMessage,启动模态对话框或显示MessageBox。当你在一些消息处理中时,什么都不会打扰你。

也许其他解决方案是在第二个线程内等待此事件。这个线程可能没有任何窗口,您可以将事件转换为您的应用程序中需要的任何内容。

所以你的问题可能没有足够的信息如何真正出现这个死锁。所以这个答案可能不够。

写完后,我倾向于认为这是一个XY问题。