Alright, it took me a bit more than I wanted but here is how it went:
Created a TTimer with Timeout slot to indicate a request for closing the window.
Subclassed QPrintDialog into TPrintDialog.
For QT5.7 I've connected the TTimer::Timeout signal to TPrintDialog::close. This is not necessary in QT>=6, this is because for some reason the close method is not invoked when destroying the window in QT5.7.
Overridden the TPrintDialog::closeEvent - this is where the "hacking" begins - inside I find a HWND handle to a PrintDlg with GetWindow((HWND)this->winId(), GW_HWNDPREV) , which gets the window that is before the this->winId() in Z axis on the screen, and then send a WM_CLOSE message to the handle with PostMessage(handle, WM_CLOSE, 0, 0),
and set the handle to nullptr;
Feel free to lecture me if you see something concerning about that or something that could be done better :)
Here is a source code for the tests, I tried to make it as compact as possible:
app.hpp
#pragma once
#include <QMainWindow>
#include <QTime>
#include <QPrintDialog>
class TAutoLogoff : public QObject
{
Q_OBJECT
public:
explicit TAutoLogoff(QObject* parent);
~TAutoLogoff();
virtual void timerEvent(QTimerEvent* e) override;
void StopTimer();
public: signals:
void Timeout();
private:
ULONGLONG m_interval;
ULONGLONG m_begin_tick;
int m_timer_id;
};
class TMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit TMainWindow(QWidget* parent = nullptr);
~TMainWindow();
void Process();
public slots:
void OnTimerExit();
private:
TAutoLogoff* m_auto_logoff;
};
class TPrintDialog : public QPrintDialog
{
Q_OBJECT
public:
explicit TPrintDialog(QWidget* parent = nullptr);
~TPrintDialog();
virtual void closeEvent(QCloseEvent* e) override;
};
app.cpp
#include "app.hpp"
#include <QApplication>
#include <QTimer>
#include <windows.h>
static TAutoLogoff* g_auto_logoff = nullptr;
TAutoLogoff::TAutoLogoff(QObject* parent)
: QObject{ parent }
, m_begin_tick{ GetTickCount64() }
, m_interval{ 2500 }
, m_timer_id{ -1 }
{
m_timer_id = QObject::startTimer(m_interval, Qt::CoarseTimer);
}
TAutoLogoff::~TAutoLogoff()
{
qDebug() << "TAutoLogoff::~TAutoLogoff";
}
void TAutoLogoff::timerEvent(QTimerEvent* e)
{
if (m_begin_tick + m_interval < GetTickCount64())
{
StopTimer();
emit Timeout();
}
}
void TAutoLogoff::StopTimer()
{
if (m_timer_id != -1)
{
QObject::killTimer(m_timer_id);
m_timer_id = QObject::startTimer(m_interval, Qt::CoarseTimer);
}
}
TMainWindow::TMainWindow(QWidget* parent)
: QMainWindow{ parent }
, m_auto_logoff{ new TAutoLogoff{ this } }
{
g_auto_logoff = m_auto_logoff;
connect(m_auto_logoff, &TAutoLogoff::Timeout, this, &TMainWindow::OnTimerExit, Qt::QueuedConnection);
QTimer::singleShot(0, this, &TMainWindow::Process);
}
TMainWindow::~TMainWindow()
{
qDebug() << "TMainWindow::~TMainWindow";
g_auto_logoff = nullptr;
}
void TMainWindow::Process()
{
TPrintDialog pd{ this };
if (pd.exec() != QPrintDialog::Accepted)
return;
}
void TMainWindow::OnTimerExit()
{
qDebug() << "TMainWindow::OnTimerExit";
close();
}
TPrintDialog::TPrintDialog(QWidget* parent)
: QPrintDialog{ parent }
{
connect(g_auto_logoff, &TAutoLogoff::Timeout, this, &TPrintDialog::close);
}
TPrintDialog::~TPrintDialog()
{
qDebug() << "TPrintDialog::~TPrintDialog";
}
void TPrintDialog::closeEvent(QCloseEvent* e)
{
qDebug() << "TPrintDialog::closeEvent";
auto* handle = GetWindow((HWND)this->winId(), GW_HWNDPREV);
if (handle != nullptr)
{
PostMessage(handle, WM_CLOSE, 0, 0);
handle = nullptr;
}
QPrintDialog::closeEvent(e);
}
main.cpp
#include <QApplication>
#include "app.hpp"
int main(int argc, char *argv[])
{
QApplication app{ argc, argv };
TMainWindow window{};
window.show();
return app.exec();
}