Как обнаружить выключение или выход Windows в Qt

Я портирую приложение Linux на Windows, написанное на Qt. Приложение должно сохранить некоторые настройки перед закрытием. В Linux мы можем сделать это обработчиками сигналов для SIGTERM и т. д. Как я могу реализовать то же самое в Windows.

5 ответов


Если вы используете цикл событий Qt, вы можете поймать следующий сигнал:

void QCoreApplication::aboutToQuit() [сигнал]

этот сигнал посылается, когда приложение собирается выйти из основного цикла событий, например, когда цикл обработки событий падает до нуля. Это может произойти либо после вызова quit () из приложения, либо когда пользователи завершают весь сеанс рабочего стола. Сигнал особенно полезен, если ваше приложение должно сделай последнюю уборку. Обратите внимание, что в этом состоянии взаимодействие с пользователем невозможно.

кроме этого, вы можете искать следующие сообщения ниже, если вышеупомянутые сигнал не подходит для вашего варианта использования:

WM_QUIT: http://msdn.microsoft.com/en-us/library/windows/desktop/ms632641(v=vs. 85).aspx

WM_CLOSE: http://msdn.microsoft.com/en-us/library/windows/desktop/ms632617(v=vs. 85).aspx

WM_QUERYENDSESSION:http://msdn.microsoft.com/en-US/library/windows/desktop/aa376890.aspx

WM_ENDSESSION:http://msdn.microsoft.com/en-US/library/windows/desktop/aa376889.aspx


Я думаю, что другие ответы полностью упустить момент: когда вы принудительно заканчиваете приложение, это похоже на SIGKILL в Unix. нет никакого способа справиться с этим-кроме как раньше времени. что я имею в виду, обрабатывая его раньше времени, убедитесь, что вы сохраняете настройки каждый раз, когда они изменяются. Конечно, вы можете оптимизировать это поведение, например, сохранять настройки каждые несколько секунд, если они загрязнены, если вы хотите минимизировать количество дисков доступ (подумайте о потреблении энергии на мобильных устройствах).

многое из этого обрабатывается QSettings для вас. Пока вы используете QSettings, вы получите разумное поведение. Если вы сами сохраняете файлы, используйте QSaveFile как это касается промывки файла и аппроксимации замены атомарного файла, так что вы не потеряете настройки, если убийство (принудительное завершение) приходит в середине вас делать запись.

на aboutToQuit сигнал, излучаемый QCoreApplication это то, что вы хотите реагировать, если вы хотите просто сделать что-то когда приложения просят уйти. Это эквивалентно обработке WM_QUIT сообщении или иметь дело с SIGTERM на Unix. Поэтому делать это специфичным для платформы способом бессмысленно, поскольку Qt уже делает это для вас. нет никакого смысла в обращении WM_CLOSE так как это сообщение, которое получает только windows, и снова Qt уже обрабатывает его для вас.

вы также можете участвовать в процессе выхода / выключения, установив QAbstractNativeEventFilter и обработке WM_ENDSESSION и WM_QUERYENDSESSION. Это имеет смысл только в том случае, если вы хотите заранее знать, что приложение будет закрыто. Если вы явно не хотите остановить выключение / выход из системы, вам не нужно беспокоиться об этом.


Я думаю, что было бы лучше справиться с от QApplication::commitDataRequest сигнал (или QGuiApplication::commitDataRequest в Qt5) вместо aboutToQuit. Просто подключите сигнал к вашей функции для сохранения настроек.

вот некоторые связанные обсуждения:http://qt-project.org/forums/viewthread/33329


выход из сеанса будет излучать aboutToQuit

case WM_ENDSESSION: {
    sm_smActive = false;
    sm_blockUserInput = false;
    bool endsession = (bool) wParam;

    // we receive the message for each toplevel window included internal hidden ones,
    // but the aboutToQuit signal should be emitted only once.
    QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
    if (endsession && !qAppPriv->aboutToQuitEmitted) {
        qAppPriv->aboutToQuitEmitted = true;
        int index = QApplication::staticMetaObject.indexOfSignal("aboutToQuit()");
        qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0);
        // since the process will be killed immediately quit() has no real effect
        QApplication::quit();
    }

    RETURN(0);
}

Я не знаю Qt. Если вы можете позволить себе быть только Windows WM_QUERYENDSESSION и WM_ENDSESSION сообщения могут быть правильным решением.