MFC 应用程序中的 Qt DLL - 如何使 QDialog *真正* 模态?

Posted

技术标签:

【中文标题】MFC 应用程序中的 Qt DLL - 如何使 QDialog *真正* 模态?【英文标题】:Qt DLL in MFC app - How to make QDialog *really* modal? 【发布时间】:2018-02-07 16:01:23 【问题描述】:

目前我正在使用 Qt 5.9.2(MSVC 2015 编译器)开发一个 Windows DLL,它应该由现有的商业 MFC 应用程序加载。应此应用程序的请求,应显示QDialog 的模态实例。 由于QApplication::exec() 会阻塞整个应用程序,我使用以下代码“模拟”事件循环:

void Core::createQApplicationInstance()

    // Check, if there's already a 'QApplication' instance running (unlikely)
    if (!QApplication::instance())
    
        int argc = 1;

        // Create a new 'QApplication' instance
        m_app = new QApplication(argc, nullptr);

        // Create a 'QTimer' instance to call 'processEvents' periodically:
        // We can't run 'm_app->exec()' because it would block everything,
        // so we'll use this 'hacky-whacky' method here
        m_timer = new QTimer;

        // Connect the timer's timeout to the app's 'processEvents' via a lambda
        QObject::connect(
            m_timer,
            &QTimer::timeout,
            [&]()
            
                m_app->processEvents();
            
        );

        // Start the timer with the fixed 'message' interval
        m_timer->start(kMsgInterval);
    

如果我的 DLL 现在应该显示一个模式对话框,它(部分)使用以下代码:

...
        case eUserIGeneral:
        
            qDebug() << "<< eUserIGeneral";

            QDialog w;

            w.setModal(true);

            w.exec();

            // --> Code here is executed AFTER the dialog has been closed
        
        break;
        //-------------------------------------------------------------------

...

w.exec() 之后的代码实际上将在对话框关闭后执行(如预期的那样)。但是,主应用程序仍然保持响应,并且不受我的对话框模式的影响,这与我预期的不一样。

如何确保在调用模态 DLL 对话框时锁定主应用程序中的输入?

【问题讨论】:

M... 除了在自己的新线程上创建 Qt 应用程序实例并旋转事件循环之外,我无法清楚地看到其他方式。这将如何与 MFC UI 线程对话是另一回事和有趣的效果。 您基本上只是在显示对话框之前禁用所有者窗口。例如。 EnableWindow(hWndOwner, FALSE); 并在模态结束后再次启用它。 【参考方案1】:

虽然我对您的问题没有真正的答案,但您的代码有太多错误,无法在评论中正确解释。因此,我写这个作为答案。

QApplication::exec():我强烈建议修改反对它的决定。如果您希望窗口是模态的,为什么“阻止整个应用程序”直到它关闭是错误的?请注意,您不会阻塞应用程序的 Qt 部分,只会阻塞调用 exec 的部分。

QTimer: 定时器只能在事件循环中运行。所以m_app-&gt;processEvents() 要么永远不会执行,要么你已经有一个事件循环在运行。无论哪种方式,计时器都没有用。

w.setModal():如果这对您不正确,请查看setWindowModality()

w.exec():忽略setModal() 的值。阅读setModal()exec() 的文档以了解更多信息。

w.exec():执行事件循环。如果这有点符合您的要求,QApplication::exec() 也应该可以工作。只要确保完成后退出主事件循环即可。

w.exec(): 对话框关闭后不执行。它在显示对话框时执行。它会一直阻塞,直到对话框关闭。所以你将开始执行它,显示对话框,关闭对话框,然后从它返回。阅读exec() 的文档以了解更多信息。

【讨论】:

以上是关于MFC 应用程序中的 Qt DLL - 如何使 QDialog *真正* 模态?的主要内容,如果未能解决你的问题,请参考以下文章

Qt/MFC 迁移框架工具:正确退出 DLL?

MFC生成的DLL导出类的函数,在Qt中如何调用

QT跟MFC的区别?QT可以调用MFC的东西吗?

包装 MFC 应用程序(目标移动设备)以创建 dll 以在 c#.NET 中使用以进行互操作

QT跟MFC的区别?QT可以调用MFC的东西吗?

点击MFC界面按钮,就可以调出来一个已经编译好的Qt界面。如何实现?