关于 QML 程序置顶的问题
如果你直接这么写:
import QtQuick.Window 2.15
import QtQuick 2.7
import QtQuick.Controls 2.0
Window {
id: window
width: 840
height: 480
visible: true
title: qsTr("HelloWorld")
flags: Qt.WindowStaysOnTopHint | Qt.Window // 直接设置置顶
}
你会发现,此时窗口的标题栏莫名其妙的缩小了一截。
解决办法
话不多说,直接上代码:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QIcon>
#include <QQmlContext>
#include "ImageManager.h"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
app.setWindowIcon(QIcon(":/image/logo.ico"));
QQmlApplicationEngine engine;
ImageManager* mgr = new ImageManager;
engine.rootContext()->setContextProperty("$ImageManager", mgr);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
// 重点就在这里,在 engine.load(url) 后,获取顶层元素,转为 QWindow* 。拿到 Wid
QList<QObject*> objectList = engine.rootObjects();
if(objectList.size() > 0)
{
QObject* rootObject = objectList[0];
if(rootObject)
{
QWindow *window = qobject_cast<QWindow *>(rootObject);
if(window)
{
mgr->setWId(window->winId()); // 设置给你需要的类
}
}
}
return app.exec();
}
然后:
// 窗口 WId
WId m_winId;
// 设置 WId
inline void setWId(WId winid) { m_winId = winid; }
// 在置顶和取消置顶之间切换
void ImageManager::toggleTopState(bool topState)
{
if(topState)
{
::SetWindowPos((HWND)(/*this->winId()*/m_winId),
HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
}
else
{
::SetWindowPos((HWND)(/*this->winId()*/m_winId),
HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
}
}
效果
下面的这个 GIF ,一开始我没有设置置顶,点击空白处,窗口就下沉了;当我设置了置顶,再点空白处,就能置顶了。
参考链接
必须是 stackoverflow:
QML get the winId of a loaded qml window
有读者想知道具体网站你的话,是这个:
https://stackoverflow.com/questions/42490280/qml-get-the-winid-of-a-loaded-qml-window
为防止没梯子的人看不到,截图下吧: