Windows 上的 QML:使窗口保持在顶部 [英] QML on Windows: make the window to stay on top

查看:163
本文介绍了Windows 上的 QML:使窗口保持在顶部的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我确实需要让我的窗口在 Windows 上保持在顶部,但 Windows 本身似乎没有 愿意让我这样做.

I do really need to make my window to stay on top on Windows, but Windows itself does not seem willing to allow me to do this.

我无法使用设置注册表值的解决方法,因为我无法要求用户注销/登录.

I cannot use the workaround with setting registry values because I am not able to ask the user to log-out/log-in.

此外,我使用 QML 和 QWidget::raise() 和 QApplication::setActiveWindow() 似乎也不起作用,因为我还没有设法获得 QML 根对象带有以下代码的 QWidget 指针:

Besides, I use QML and the solution with QWidget::raise() and QApplication::setActiveWindow() does not seem to work also because I have not managed to get the QML root object as a QWidget pointer with the following code:

QWidget* mainWin = qobject_cast<QWidget*>(engine.rootObjects().at(0));
if (mainWin)
{
    mainWin->raise();
    QApplication::setActiveWindow(mainWin);
    mainWin->activateWindow();
}

我还尝试从 QML 直接激活窗口:

I have also tried to make the window active right from the QML:

window.raise()
window.requestActivate()

但也没有运气.

是否有任何一种方法可以在不更改注册表的情况下将窗口置于 Windows 的顶部,最好是纯粹从 QML 中?

Is there, either way to bring the window on top on Windows without changing the registry and, preferably, from the QML purely?

编辑:当前使用的窗口标志是:

Edit: currently used window flags are:

Qt.Popup
Qt.FramelessWindowHint
Qt.WindowStaysOnTopHint
Qt.CustomizeWindowHint
Qt.BypassWindowManagerHint
Qt.MSWindowsFixedSizeDialogHint

我正在 Windows 10 x64 机器上部署 Qt 5.7 应用程序.我发现了这两个错误修正:

I am deploying Qt 5.7 app on the Windows 10 x64 machine. I have found this two bugfixes:

从中我可以得出结论,QWidget::activateWindow() 和 QWindow::requestActive() 应该适用于 Windows XP 和 Windows 7.

from which I can conclude that QWidget::activateWindow() and QWindow::requestActive() should work on Windows XP and Windows 7.

这是我的 mcve,正如 @derM 所问:

Here is my mcve, as @derM asked:

import QtQuick 2.7
import QtQuick.Window 2.2

Window {
    flags: Qt.WindowStaysOnTopHint

    width: 100
    height: 100
    visible: true
}

它是在 Windows 10 x64 下用 MinGW x32 编译的.

It was compiled under Windows 10 x64 with MinGW x32.

更简单的方法重现:在命令提示符下运行

Easier way to reproduce: run in the command prompt

timeout 5 && debug\Test.exe

其中 debug\Test.exe 是 mcve 二进制文件的路径,然后打开文件资源管理器并导航到某个地方.当窗口打开时,它不会在前台.

where debug\Test.exe is a path to the mcve binary, then open File Explorer and navigate somewhere. When the window opens, it won`t be in the foreground.

更难的方法:如果您只是运行它,窗口将保持在它应该的顶部.但是,如果您按下 Qt Creator 中的运行按钮并将焦点(我想应该更改鼠标焦点,只需按 Alt+Tab 将无济于事)切换到另一个进程(在我的情况下 - 文件资源管理器),将显示该窗口在当前活动的文件资源管理器窗口下,即使我通过单击将其调出,只要我选择任何其他应用程序,它就会进入后台.

Harder way: If you just run it, the window will stay on top as it should. But if you press Run button in the Qt Creator and switch the focus (I suppose, mouse focus should be changed, just pressing Alt+Tab won`t help) to another process (in my case - File Explorer), the window is displayed under the current active File Explorer window, and even if I will bring it up by clicking, it will go background as soon as I choose any other application.

真正的应用程序是从一个服务启动的,所以我的应用程序启动时经常会有一个应用程序保持鼠标焦点.我想 Qt 将窗口置于前台的能力是使用 SetForegroundWindow API 调用,在其备注中注明以下限制:

The real application is started from a service, so there often will be an app holding mouse focus when my app is started. I suppose that Qt ability to bring the window to foreground is implemented using SetForegroundWindow API call, which notes the following restrictions in it`s remarks:

  • 进程是前台进程.
  • 该进程由前台进程启动.
  • 进程收到最后一个输入事件.
  • 没有前台进程.
  • 正在调试进程.
  • 前台进程不是现代应用程序或开始屏幕.
  • 前景未锁定(请参阅 LockSetForegroundWindow).
  • 前台锁超时已过期(请参阅 - SystemParametersInfo 中的 SPI_GETFOREGROUNDLOCKTIMEOUT).
  • 没有菜单处于活动状态.

所以我想知道如果进程是由服务而不是用户启动的(即进程在启动期间不是活动进程),是否有可能将窗口置于前台.

So I wonder is it possible at all to bring the window to foreground if the process has been started by a service, not a user (i. e. the process has not been an active process during startup).

推荐答案

正如您所发布的:如果窗口是从前台进程创建的,我们将在创建窗口之前确保我们的进程是前台进程.

As you have posted: If the window is created from the foreground process, we will just make sure, that our process is the foreground process before we create the window.

import QtQuick 2.7
import QtQuick.Window 2.2

Item {
    id: root

    Component { // Like a splash screen: Claim to be foreground process,
                // then create main window.
        id: winInit
        Window {
            flags: Qt.WindowStaysOnTopHint
            width: 1
            height: 1
            Component.onCompleted: {
                requestActivate()
                mainWin.createObject(root)
            }
        }
    }

    Component {
        id: mainWin
        Window {
            flags: Qt.WindowStaysOnTopHint
            width: 100
            height: 100
            visible: true
        }
    }

    Component.onCompleted: {
        var w1 = winInit.createObject(null)
        w1.destroy()
    }
}

这篇关于Windows 上的 QML:使窗口保持在顶部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆