Win8,win10都出来了,为了迎合系统的扁平化风格,项目要求窗体是无边框,看了一下QT的主要Widget,没有现成的,好吧,那就只有自己写了。
在网上也看到了一些代码,进行小结了一下,无边框窗体大小的改变,移动都需要自己处理,不在像有边框的窗体一样自动处理,处理起来目前有两种方法:
一、完全自己处理窗体的鼠标事件;
二、接收鼠标事件,连接到系统消息,由系统来处理;
先介绍第一种方法:
1.首先大家要了解各九宫格的概念
一个窗体可以被划分为上、下、左、右、左上、左下、右上、右下、中间,除了中间部分,其他都需要写程序处理。Padding其实就是鼠标放上去后需要改变鼠标的手势为改变大小形状。
在程序中定义Padding 为2,可定义枚举类型。
2.定义一个方法,参数为鼠标目前的全局位置。目的是获取窗体在屏幕上的位置区域
3.在对话框类中定义几个私有成员变量
boolisLeftPressDown; // 判断左键是否按下
QPoint dragPosition; // 窗口移动拖动时需要记住的点
Direction dir; // 窗口大小改变时,记录改变方向
在窗体的构造函数中初始化变量,并设置窗体为无边框窗体:
isLeftPressDown = false;
this->dir= NONE;
this->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowSystemMenuHint);// 设置成无边框对话框
this->setMouseTracking(true); // 追踪鼠标,如果使用的是QMainWindow此处应该修改为:ui. Centralwidget->setMouseTracking(true);
4.重载鼠标事件函数
voidmouseReleaseEvent(QMouseEvent *event);
voidmouseMoveEvent(QMouseEvent *event);
voidmousePressEvent(QMouseEvent *event);
一个无边框窗体的可移动可改变大小的功能就完成了,总结起来,这个算法其实并不复杂,就看有几个点能不能想到:
1)窗体矩形区域要转换成在屏幕上的区域,采取的方式就是取TopLeft和RightBottom两个点来确定这个区域。
2)鼠标移动要去全局的坐标。
3)region函数中判断坐标区间,然后改变鼠标形状
这种方法实现的优点的流程简单,代码简洁,基本上没有什么难点,但缺点是明显的,
1) 如果在窗体上使用了其他的控件那么鼠标的形状似乎就变得不那么好控制了;
2) 如果使用的控件跟窗口同样大小,那么你写的功能将失效,或者需要你安装事件过滤器来处理父子窗口之间的事件才能获得你需要的功能;
3) 窗口抖动的厉害,因为窗体一直在resize;
4) 处理的鼠标事件太多;
那么再来看看第二种方法:
第二种方法是利用QT处理windows消息来实现的,
同样在窗体的构造函数中也需要设置窗体的无边框的属性:
this->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowSystemMenuHint);// 设置成无边框对话框
注意,这个不需要设置鼠标跟随。
然后重载:
void paintEvent(QPaintEvent* event);
1. bool nativeEvent(const QByteArray&eventType, void *message, long *result);// QT 5.0版本以下是bool MainWindow::winEvent(MSG *message, long *result)
剩下的就交给系统来完成吧。
这个方法的好处是弥补了第一种方法的不足,是我推荐的使用方法,代码量也比较小。
方法一完整代码:https://github.com/thewarlocker/NoFrameWidget/
方法二完整代码:https://github.com/thewarlocker/NoFrameWindow/