【发布时间】:2017-02-16 12:00:09
【问题描述】:
我确实需要让我的窗口在 Windows 上保持在顶部,但 Windows 本身似乎 willing to allow me 无法做到这一点。
我无法使用解决方法来设置注册表值,因为我无法要求用户注销/登录。
此外,我使用 QML,QWidget::raise() and QApplication::setActiveWindow() 的解决方案似乎也不起作用,因为我还没有设法使用以下代码将 QML 根对象作为 QWidget 指针:
QWidget* mainWin = qobject_cast<QWidget*>(engine.rootObjects().at(0));
if (mainWin)
{
mainWin->raise();
QApplication::setActiveWindow(mainWin);
mainWin->activateWindow();
}
我还尝试从 QML 直接激活窗口:
window.raise()
window.requestActivate()
但也没有运气。
有没有一种方法可以在不更改注册表的情况下将窗口置于 Windows 之上,最好是纯粹从 QML 中?
编辑: 当前使用的窗口标志是:
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。
这是我的 mcve,正如@derM 所问:
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
flags: Qt.WindowStaysOnTopHint
width: 100
height: 100
visible: true
}
它是在 Windows 10 x64 下使用 MinGW x32 编译的。
更简单的方法重现:在命令提示符下运行
timeout 5 && debug\Test.exe
其中 debug\Test.exe 是 mcve 二进制文件的路径,然后打开文件资源管理器并导航到某个位置。当窗口打开时,它不会在前台。
更难的方式:如果您只是运行它,窗口将按原样保持在顶部。 但是,如果您在 Qt Creator 中按下 Run 按钮并将焦点(我想应该更改鼠标焦点,只需按 Alt+Tab 不会有帮助)切换到另一个进程(在我的情况下 - 文件资源管理器),则会显示窗口在当前活动的文件资源管理器窗口下,即使我将通过单击将其调出,只要我选择任何其他应用程序,它也会进入后台。
真正的应用程序是从服务启动的,所以当我的应用程序启动时,经常会有一个应用程序保持鼠标焦点。我想Qt将窗口带到前台的能力是使用SetForegroundWindow API调用实现的,它在它的注释中指出了以下限制:
- 该进程是前台进程。
- 进程由前台进程启动。
- 进程收到最后一个输入事件。
- 没有前台进程。
- 正在调试进程。
- 前台进程不是现代应用程序或开始屏幕。
- 前景未锁定(请参阅 LockSetForegroundWindow)。
- 前台锁定超时已过期(请参阅 SystemParametersInfo 中的 SPI_GETFOREGROUNDLOCKTIMEOUT)。
- 没有处于活动状态的菜单。
所以我想知道如果进程是由服务而不是用户启动的(即进程在启动期间不是活动进程),是否有可能将窗口置于前台。
【问题讨论】:
-
只是为了确保:您说的是 QML 而不是 QtWidgets,对吧?
-
@derM 没错,但我认为 QML 类型和 QWidgets 内部有一个共同的机制,这就是我关注与 QWidgets 相关的错误的原因。除了 Qt.WindowStaysOnTopHint 标志之外,我什么也没找到,它可以帮助解决纯 QML 方面的问题。
-
好吧,好像确实有bug。我会发布一些为我规避它的黑客。