我有一个Windows/LinuxQT4.3应用程序,它在QTreeView中使用拖放。我有两个非常相似的应用程序,它们使用相同的Qt库集。拖放在Linux上都能工作,但在Windows上只能在一个中工作。
在不工作的应用程序中,鼠标一移动,QDrag对象就会被删除。它由一个DeferredDelete事件从事件队列中删除,该事件队列在拖放期间仍然在Qt中处理。我不知道如何查看导致QDrag对象过早被删除的原因。
我想不出一个好办法来调试这个问题。我比较了来源,找不到任何明显的东西。我尝试使用另一个应用程序中的一个应用程序的代码。
有什么建议吗?
更新:
QDrag操作失败的原因是COM未成功初始化,因此QDrag::exec中对DoDragDrop的调用立即返回。QApplication试图通过在qt_init中调用OleInitialize来初始化COM,但失败了,错误是“设置之后不能更改线程模式”。
有趣的是,即使OleInitialize是在main中完成的第一件事,也会发生这种情况,因此线程模式最初是由某些外部依赖项设置的。在Windows上工作的应用程序之间的一个不同之处在于,失败的应用程序也包含.NET代码,所以这可能就是问题所在。
解决:
这个问题是COM/CLR互操作问题。CLR在初始化时将单元状态设置为MTA,然后当Qt尝试初始化COM时,它将失败。亚当·内森在使用STAThreadAttribute和托管C++捕获您中讨论了这个问题和一个旧的解决方案。在Visual 2005中,可以在Configuration > Linker > Advanced中设置/CLRTHREADATTRIBUTE:STA编译器选项,将线程属性设置为STA,而无需创建新的入口点。