homeman |
2020-06-01 17:04 |
Qt 5.15 窗口换肤(QML)
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,使用简单,易于扩展,请参考附件代码[attachment=21643],或通过https://github.com/afarcat/QtSkinWindow 下载。 [attachment=21642] |
|