Windows上的QML:使窗口保持在顶部

Windows上的QML:使窗口保持在顶部,windows,qml,Windows,Qml,我确实需要让我的窗口保持在窗口的顶部,但Windows本身似乎并没有做到这一点 我无法使用设置注册表值的解决方法,因为我无法要求用户注销/登录 此外,我使用QML,解决方案似乎也不起作用,因为我还没有使用以下代码将QML根对象作为QWidget指针: QWidget* mainWin = qobject_cast<QWidget*>(engine.rootObjects().at(0)); if (mainWin) { mainWin->raise(); QAp

我确实需要让我的窗口保持在窗口的顶部,但Windows本身似乎并没有做到这一点

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

此外,我使用QML,解决方案似乎也不起作用,因为我还没有使用以下代码将QML根对象作为QWidget指针:

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

是否有任何一种方法可以在不更改注册表的情况下(最好是从QML)将窗口置于Windows之上

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

Qt.Popup
Qt.FramelessWindowHint
Qt.WindowStaysOnTopHint
Qt.CustomizeWindowHint
Qt.BypassWindowManagerHint
Qt.MSWindowsFixedSizeDialogHint
我正在Windows 10 x64计算机上部署Qt 5.7应用程序。 我发现了以下两个错误修复:

从中我可以得出结论,QWidget::activateWindow()和QWindow::requestActive()应该可以在Windows XP和Windows 7上工作

这是@derM询问的我的mcve

import QtQuick 2.7
import QtQuick.Window 2.2

Window {
    flags: Qt.WindowStaysOnTopHint

    width: 100
    height: 100
    visible: true
}
它是在Windows10x64和MingWX32下编译的

更容易复制:在命令提示符下运行

timeout 5 && debug\Test.exe
其中debug\Test.exe是mcve二进制文件的路径,然后打开文件资源管理器并导航到某个位置。当窗口打开时,它将不在前景中

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

真正的应用程序是从一个服务启动的,所以当我的应用程序启动时,通常会有一个应用程序保持鼠标焦点。我认为Qt将窗口置于前台的功能是通过API调用实现的,它在备注中指出了以下限制:

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

因此,我想知道,如果进程是由服务启动的,而不是由用户启动的(即进程在启动过程中不是活动进程),是否有可能将窗口置于前台。

如您所述:如果窗口是从前台进程创建的,我们只需确保,在我们创建窗口之前,我们的进程是前台进程

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()
    }
}

只是为了确保:你说的是QML而不是qtwidts,对吗?@derM完全正确,但我认为QML类型和QWidgets内部有一个共同的机制,这就是为什么我关注与QWidgets相关的bug。除了Qt.WindowStaysOnTopHint标志之外,我没有发现任何东西可以从纯QML的角度帮助解决这个问题。我将为我发布一些绕过它的黑客。我必须注意我使用了这个标志,但在Windows上它什么也不做。对我来说,它在Win7和Qt5.7上工作。你使用哪个版本?你能提供一个例子吗?我在Windows10上使用Qt5.8。对于Windows 7,将窗口置于前台的问题似乎已得到解决:我添加了mcve,花了一些时间才找到如何重现我的问题。在测试过程中,我注意到winInit组件的visible属性不必为真,解决方法就可以工作。将visible更改为false将在应用程序启动期间删除闪烁。
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()
    }
}