Qt监听Windows锁屏、解锁、休眠、唤醒、登录、注销消息
环境: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);
}