如何在单击通知后强制将 Qt 窗口置于前台

问题描述 投票:0回答:1

我正在开发使用 Qt5 的消息应用程序。收到新消息时会显示 Windows 通知。当我单击通知时,它应该打开应用程序窗口,它实际上是这样做的。但打开的窗口不是前景,因此当我开始输入时,窗口失去焦点并且没有任何反应。我需要先点击窗口,然后开始输入。

我目前使用以下代码打开应用程序窗口:

appWindow->setWindowState(static_cast<Qt::WindowState>(appWindow->windowState() & ~Qt::WindowMinimized));

    const auto winId = appWindow->winId();

#ifdef Q_OS_WIN
    QWindowsWindowFunctions::setWindowActivationBehavior(QWindowsWindowFunctions::AlwaysActivateWindow);
    appWindow->requestActivate();

    // Setting rights for the process to move window to foreground
    // They get reset after user input
    AllowSetForegroundWindow(ASFW_ANY);

    // Getting window handles for QApp and currently active process
    HWND  appWinHandle   = HWND(winId);
    HWND  curWinHandle   = GetForegroundWindow();
    DWORD appWinThreadID = GetCurrentThreadId();
    DWORD curWinThreadID = GetWindowThreadProcessId(curWinHandle, NULL);

    // Forcing qWindow raise by setting it to be topmost and releasing right after
    SetWindowPos(appWinHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
    SetWindowPos(appWinHandle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);

    AllowSetForegroundWindow(curWinThreadID);


    // Moving input thread from current process to qApp
    // Simulate Alt press and release to ensure qApp process got focus
    keybd_event(VK_MENU, 0, 0, 0);
    SetForegroundWindow(appWinHandle);
    keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
    AttachThreadInput(curWinThreadID, appWinThreadID, FALSE);
    SetFocus(appWinHandle);
    SetActiveWindow(appWinHandle);

但它仍然没有在前台打开应用程序窗口。有什么方法可以打开它的前台吗?顺便说一句,我听说 Windows 10 对在前台打开窗口有一些限制,但某些应用程序(例如 OutLook)按照我想要的方式工作。

c++ windows qt qt5
1个回答
0
投票

我在 Windows 应用程序中使用以下代码:

void forceSetForegroundWindow(HWND hWnd)
{
    if(!hWnd || !::IsWindow(hWnd)) return;

    HWND  hCurrWnd = ::GetForegroundWindow();
    DWORD dwThisTID = ::GetCurrentThreadId(),
          dwCurrTID = ::GetWindowThreadProcessId(hCurrWnd, NULL);

    if(dwThisTID != dwCurrTID)
        ::AttachThreadInput(dwThisTID, dwCurrTID, TRUE);

    ::BringWindowToTop(hWnd);
    ::SetForegroundWindow(hWnd);

    if(dwThisTID != dwCurrTID)
        ::AttachThreadInput(dwThisTID, dwCurrTID, FALSE);
}
© www.soinside.com 2019 - 2024. All rights reserved.