• 5356阅读
  • 2回复

Qt 5.15 窗口换肤(QML) [复制链接]

上一主题 下一主题
离线homeman
 

只看楼主 倒序阅读 楼主  发表于: 2020-06-01
Qt 5.15 窗口换肤(QML)

一、前言
    Qt窗口换肤都是需要设置FramelessWindowHint窗口标志,去掉宿主窗口的原生显示,然后用客户区的部分区域来实现标题栏和边框,并且模拟非客户区的动作行为,比如拖拉边框改变窗口大小,拖拉边框时改变鼠标形状,双击标题栏等。

    之前看过一些QML窗口的换肤实现,都是在C++端派生QWindow来实现,使用宏定义对不同平台来实现上述功能。

    在Qt 5.15中,Qt从库的角度提供了这些功能,参见Custom client-side window decorations in Qt 5.15 ,这就简化了前端开发的难度,可以专注于UI功能的开发。

二、Qt实现
    在Qt 5.15中,Qt提供了2个函数:startSystemResize和startSystemMove,来模拟非客户区的动作行为。在Windows平台,它们是这么实现的:

    bool QWindowsWindow::startSystemResize(Qt::Edges edges)
    {
        if (Q_UNLIKELY(window()->flags().testFlag(Qt::MSWindowsFixedSizeDialogHint)))
            return false;

        ReleaseCapture();
        PostMessage(m_data.hwnd, WM_SYSCOMMAND, edgesToWinOrientation(edges), 0);
        setFlag(SizeGripOperation);
        return true;
     }

    bool QWindowsWindow::startSystemMove()
    {
        ReleaseCapture();
        PostMessage(m_data.hwnd, WM_SYSCOMMAND, 0xF012 /*SC_DRAGMOVE*/, 0);
        return true;
    }

三、QML实现
    在QML Window里,需要将设置窗口标志为Qt.Window | Qt.FramelessWindowHint。

    可以使用Page对象作为Window的contentItem,Page提供了header/footer以及Layout的功能,这样就可以使用header来实现标题栏功能,Page的margin来实现边框功能。这取决于界面的业务需求而定。

    在Window里放置一个MouseArea,用来处理窗口边框功能:拖拉边框改变窗口大小,拖拉边框时改变鼠标形状,这个需要调用startSystemResize来实现。

    在Window标题栏的标题位置也放置一个MouseArea,用来处理鼠标双击、鼠标拖动移动窗口功能,这个需要调用startSystemMove来实现。

    基于QML的强大表现能力,可以很丰富的实现标题栏,取决于业务需求,比如:可以放置MenuBar/TextField/ComboBox,可以支持动画的Image/Video,标题可以使用richtext,按钮可以使用多种效果等等。

四、QML样例
    样例实现了一个标准的Window,使用简单,易于扩展,请参考附件代码 QtSkinWindow.zip (12 K) 下载次数:50 ,或通过https://github.com/afarcat/QtSkinWindow 下载
    
离线listen342325

只看该作者 1楼 发表于: 2020-07-09
qt5.15 在线安装很麻烦,有没有人编译好的。
Qt 不错的选择
离线reghtml

只看该作者 2楼 发表于: 2021-08-27
  下载学习下
快速回复
限100 字节
 
上一个 下一个