蓝色星晨|C/C++编程笔记:无边框窗口橡皮筋拉伸效果

序有时候UI设计的风格 , 并不需要系统默认的标题栏;如QQ、微信电脑版等等 。
这时候就需要我们实现对窗口的拖动和拉伸进行实现 。
由于拖动比较简单 , 就此略过 。
本文将以Qt做示例介绍我实现的拉伸功能 , 并封装成类 。
当然思路是相同的 , 其他UI也可按此方法实现 。
蓝色星晨|C/C++编程笔记:无边框窗口橡皮筋拉伸效果使用方法秉持实用至上主义 , 集成使用尽可能的方便 , 具体操作如下:只需要在无边框的窗体添加 CFrameForm 对象 , 将它叠放在窗体上就行 。 例如:
#ifndef FORM_H#define FORM_H#include #include "cframeform.h"// 包含头文件namespace Ui {class Form;}class Form : public QWidget{Q_OBJECTpublic:explicit Form(QWidget *parent = 0);~Form();private:Ui::Form *ui;CFrameForm *m_frame;// 创建对象};#endif // FORM_H类实现如下:
#include "form.h"#include "ui_form.h"Form::Form(QWidget *parent) :QWidget(parent),ui(new Ui::Form){ui->setupUi(this);setWindowFlags(windowFlags() | Qt::FramelessWindowHint);m_frame = new CFrameForm(this);// 创建对象}Form::~Form(){delete ui;}设计思路

  • 如图所示 , 一般鼠标移动到窗口的四个角落(黑色区域)和四个边缘(红色区域)的时候 , 就可以进行拖拽了;我们只要对这个几个区域进行监听处理 , 在不同位置时 , 鼠标移动到上面就处于不同的状态 , 这样可以给用户更好的体验 。
  • 当点击鼠标左键后开始 , 监听鼠标移动消息;
  • 然后只要根据窗口和鼠标的位置 , 进行动态计算 , 确定窗口不动的角、边与拉动的角、边 , 便可以计算出拉伸的区域大小 。
  • 再然后对区域大小进行边框标记 , 就可以看到大小;在来回拉动的过程中实时刷新下 , 即可看到橡皮筋的效果了 。
  • 等到鼠标是否 , 移到了其他区域如白色区域或者窗口以外的地方 , 鼠标恢复箭头状态 。

蓝色星晨|C/C++编程笔记:无边框窗口橡皮筋拉伸效果拖拽区域为每个区域创建一个窗口 , 实现对响应鼠标的点击和释放 , 以及类型的管理 , 知道每个窗口显示什么样的光标 , 以及区域位置;我们创建一个简单的区域操作类:
class CHandel : public QWidget{Q_OBJECTpublic:CHandel(int type, CFrameForm*frm):QWidget(frm), m_type(type), m_frm(frm){}int type() {return m_type;}private:void mousePressEvent(QMouseEvent *e){m_frm->setType(m_type);QWidget::mousePressEvent(e);}void mouseReleaseEvent(QMouseEvent *e){m_frm->setType(9);QWidget::mouseReleaseEvent(e);}private:int m_type;CFrameForm*m_frm;};橡皮筋为每个边框设计一个窗口 , 实现4条线组成的方框 , 实现橡皮筋的显示效果 。 (问:为啥不是用一个窗口 , 然后绘制四边?)为了对4条线的管理 , 我们创建一个简单的区域类:
class CRubberBand{public:explicit CRubberBand();void setRect(const QRectQRect rect();bool isVisible();void show();void hide();void clear();private:QRect m_rect;QListm_lines;};类的实现部分:
/// class CRubberBandCRubberBand::CRubberBand()// 构造4条线的属性和颜色{for (int i = 0; i < 4; i++) {QWidget *l = new QWidget;l->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);l->setStyleSheet("background:rgb(133,132,131)");l->raise();m_lines.append(l);}}void CRubberBand::setRect(const QRectm_lines[0]->setGeometry(QRect(r.topLeft(), r.topRight()+QPoint(0,2)));m_lines[1]->setGeometry(QRect(r.bottomLeft(), r.bottomRight()+QPoint(0,2)));m_lines[2]->setGeometry(QRect(r.topLeft(), r.bottomLeft()+QPoint(2,0)));m_lines[3]->setGeometry(QRect(r.topRight(), r.bottomRight()+QPoint(2,0)));foreach (auto l, m_lines)l->raise();}QRect CRubberBand::rect(){return m_rect;}bool CRubberBand::isVisible() // 判断是否可见{return m_lines[0]->isVisible();}void CRubberBand::show()// 显示4条线{foreach (auto l, m_lines)l->show();}void CRubberBand::hide() // 隐藏4条线{foreach (auto l, m_lines)l->hide();}void CRubberBand::clear() // 删除四条线{foreach (auto l, m_lines)l->deleteLater();m_lines.clear();}