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 下载。