環境:Windows 11 筆記本,其它環境未測試
根據其它部落格的直接在視窗 nativeEvent
中監聽 WM_WTSSESSION_CHANGE
會話訊息和 WM_POWERBROADCAST
電源訊息發現不起作用,查閱嘗試後找到可行方法如下:
會話事件和電源訊息都需要先用Windows API註冊視窗控制代碼
void MainWindow::registerSysNotification()
{
#ifdef Q_OS_WINDOWS
// 註冊指定視窗以接收會話更改通知,獲取鎖屏,解鎖,登入,登出等訊息
bool ret = WTSRegisterSessionNotification((HWND)this->winId(), NOTIFY_FOR_THIS_SESSION);
qDebug() << "會話事件通知註冊" << (ret ? "成功" : "失敗");
// 註冊以便在系統暫停或恢復時接收通知,最低支援 win8
HPOWERNOTIFY res = RegisterSuspendResumeNotification((HWND)this->winId(), DEVICE_NOTIFY_WINDOW_HANDLE);
qDebug() << "電源事件通知註冊" << (res != NULL ? "成功" : "失敗");
#endif
}
注意:根據MSDN文件,WTSRegisterSessionNotification
和 RegisterSuspendResumeNotification
函式都只能用在 win8 及以上桌面系統中,不支援 win7。
然後在 nativeEvent
中處理訊息
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
#ifdef Q_OS_WIN32
MSG* msg = (MSG*)message;
switch (msg->message) {
case WM_WTSSESSION_CHANGE://判斷登入、登出、鎖屏等
{
switch (msg->wParam) {
case WTS_SESSION_LOCK:
qDebug() << "鎖屏";
isScreenLock = true;
break;
case WTS_SESSION_UNLOCK:
qDebug() << "解鎖";
isScreenLock = false;
break;
case WTS_SESSION_LOGON:
qDebug() << "登入";
break;
case WTS_SESSION_LOGOFF:
qDebug() << "登出";
break;
case WTS_SESSION_REMOTE_CONTROL:
qDebug() << "被遠端控制";
break;
default:
break;
}
case WM_POWERBROADCAST:
{
switch (msg->wParam) {
case PBT_APMSUSPEND:
qDebug() << "系統進入休眠狀態";
isPowerSleep = true;
break;
case PBT_APMRESUMEAUTOMATIC:
qDebug() << "系統從休眠狀態恢復";
isPowerSleep = false;
break;
case PBT_APMPOWERSTATUSCHANGE:
qDebug() << "系統電源狀態更改";
break;
default:
break;
}
}
}
default:
break;
}
#endif
return QMainWindow::nativeEvent(eventType, message, result);
}