如何在Qt托盘应用程序中处理会话更改通知?

时间:2017-04-11 14:30:02

标签: c++ qt winapi qt5

我在Qt托盘应用程序中处理会话状态通知(如用户登录/注销/锁定等)时遇到问题。在通常的Qt应用程序中,我可以使用WTSRegisterSessionNotification致电hWnd=effectiveWinId()并重新实施nativeEvent,如下所示:

bool EventListener::nativeEvent(const QByteArray &eventType, void *message, long *result)
{    
    MSG* msg = reinterpret_cast<MSG*>(message);
    switch(msg->message)
    {
        case WM_WTSSESSION_CHANGE:
            ...
    }

    ...
}

但是在托盘应用程序中它是不可能的,因为QSystemTrayIcon并不是从QWidget继承而且我没有任何窗口句柄。

是否可以在不创建假隐形窗口的情况下解决问题?

1 个答案:

答案 0 :(得分:1)

我用WinAPI函数创建了一个假的不可见窗口,用于通知处理。这是一个简短的示例:

QObject *ni = reinterpret_cast<QObject*>(QGuiApplication::platformNativeInterface() );

// Register window class in the platform plugin.
QString className;
void *wndProc = reinterpret_cast<void *>(msgWndProc);
QMetaObject::invokeMethod(ni, "registerWindowClass", Qt::DirectConnection,
                               Q_RETURN_ARG(QString, className),
                               Q_ARG(QString, QStringLiteral("MessageFakeWindowClass")),
                               Q_ARG(void *, wndProc));

const wchar_t windowName[] = L"MessageFakeWindow";
HWND msgWindow_ = CreateWindowEx(0, (wchar_t*)className.utf16(),
                      windowName, WS_OVERLAPPED,
                      0, 0,
                      0, 0,
                      HWND_DESKTOP, nullptr, (HINSTANCE)GetModuleHandle(0), nullptr);

WTSRegisterSessionNotification(msgWindow_, NOTIFY_FOR_THIS_SESSION);