1
votes

At the moment I am developing a Windows DLL with Qt 5.9.2 (MSVC 2015 compiler), which should be loaded by an existing, commercial MFC application. Upon request of this application a modal instance of QDialog should be displayed. Since QApplication::exec() would block the entire application, I "simulate" the event loop using the following code:

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);
    }
}

If my DLL should now display a modal dialog, it works (partially) with the following code:

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

            QDialog w;

            w.setModal(true);

            w.exec();

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

{...}

The code after w.exec() will actually be executed AFTER the dialog was closed (as intended). However, the main application still remains responsive and is not affected by the modality of my dialog, which Is not as I expected it to behave.

How can I make sure that inputs in the main application are locked when calling a modal DLL dialog?

1
M... Except creating Qt application instance on its own new thread and spinning the event loop I cannot clearly see the other way. How that will talk to MFC UI thread is the other matter and interesting effects as well.Alexander V
You basically just disable the owner window before showing your dialog. E. g. EnableWindow(hWndOwner, FALSE); and after the modality ends, enable it again.zett42

1 Answers

0
votes

Although I don't have a real answer to your question, there too much stuff wrong with your code to be properly explained in a comment. Therefore I am writing this as an answer.

QApplication::exec(): I strongly recommend revising the decision against it. If you want the window to be modal, why would it be wrong to "block the entire application" until it is closed? Note that you will not block the Qt part of the application, only the one that calls exec.

QTimer: A timer can only run inside an event loop. So the m_app->processEvents() either never executes, or you already have an event loop running. Either way, there is no use for the timer.

w.setModal(): If what this does is not correct for you, check out setWindowModality().

w.exec(): Ignores the value of setModal(). Read the documentation of setModal() and exec() to find out more.

w.exec(): Executes an event loop. If this somewhat does what you want, QApplication::exec() should work too. Just make sure to exit the main event loop when done.

w.exec(): Is not executed after the dialog was closed. It is executes while the dialog is shown. It blocks until the dialog is closed. So you will start executing it, show the dialog, close the dialog, and then return from it. Read the documentation of exec() to find out more.