当前位置:   article > 正文

Qt自定义标题栏(可拖动标题栏编辑修改窗口大小)_qt 重写标题栏

qt 重写标题栏


前言

记录下Qt的自定义标题栏。

提示:以下是本篇文章正文内容,下面案例可供参考

效果

自定义标题栏演示

请添加图片描述
![请添加图片描述](https://img-blog.csdnimg.cn/direct/56fa22671ce04ddc9faf37a2f5eab9da.png
请添加图片描述
在这里插入图片描述

请添加图片描述
请添加图片描述

1.titlebar.h

代码如下(示例):

#ifndef TITLEBAR_H
#define TITLEBAR_H

#include <QLabel>
#include <QFrame>
#include <QMovie>
#include <QFont>
#include <QIcon>
#include <QStyle>
#include <QDebug>
#include <QFrame>
#include <QTimer>
#include <QObject>
#include <QListView>
#include <QShortcut>
#include <QComboBox>
#include <QPushButton>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QVBoxLayout>
#include <QMessageBox>
#include <QApplication>
#include <QDesktopWidget>
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
#include <QGraphicsDropShadowEffect>
#include "windows.h"

#define PADDING 5

#ifndef SAFEDELETE
#define SAFEDELETE(pointer) \
{                           \
    if(pointer)             \
    {                       \
        delete pointer;     \
    }                       \
    pointer = NULL;         \
}
#endif

namespace TITLEBAR
{
    enum WIDGETBYTTONTYPE
    {
        MAXWIDGET,      //去掉最大化按钮
        MINWIDGET,      //去掉最小化按钮
        CloseWIDGET,    //去掉关闭按钮
        ALLWIDGET,      //去掉除关闭按钮外的所有按钮
		NOBUTTON,		//去除所有按钮
    };
}

class TitleBar : public QFrame
{
    Q_OBJECT

public:
    explicit TitleBar(QWidget *parentWidget = nullptr);

	enum Direction { UP = 0, LEFT, RIGHT, LEFTTOP, RIGHTTOP, NONE };

	void initData();
    void initBotton();                              //初始化按钮
	void initConnect();                             //初始化值
    void setWindowTitle(const QString &title);      //设置标题
    void setWindowIcon(const QString &icon);        //设置图标(为空时隐藏图标)
    void subWindowButton(const int &type);          //设置按钮
    void Shadow_Warning();                          //设置阴影
    void RemoveMaxMinButton();                      //移除最大最小按钮
    void Set_MaximizeFlag();                        //设置双击标题栏是否可以最大、最小化
	void Set_MouseShapeFlag(bool MouseShape);		//设置标题栏是否可以改变大小
    bool FileIsExist(QString strFile);              //文件是否存在
	void SetTitleLabelTextColor(int R,int G,int B);	//修改标题显示文字颜色

    const static int TITLEBARHEIGHT = 30;           //标题栏高度
    const static int CONTROLWIDTH   = 30;           //控件宽度

	QRectF boundingRect() const;
	QRectF leftBorder() const;
	QRectF rightBorder() const;
	QRectF topBorder() const;
	QRectF bottomBorder() const;
	void setMousePressCursorShape(const QPointF& pt, bool isShow = true);

public slots:
    void showMax();                                 //最大化窗口
    void showMin();                                 //最小化窗口
    void showClose();                               //关闭窗口
    void set_ChildWindowColor(int R,int G,int B);   //设置标题栏背景色
    void ModifyTitleBarTip();						//修改标题栏按钮提示语言

signals:
    void send_close();								//发送关闭信号
    void send_showToolbar();                        //发送显示/隐藏工具栏信号

private slots:


private:
    QPushButton     *maxButton;                     //最大化按钮
    QPushButton     *minButton;                     //最小化按钮
    QPushButton     *closeButton;                   //关闭按钮
    QLabel          *imgLabel;                      //图片框
    QLabel          *titleLabel;                    //标题名
	QWidget         *parentWidget;                  //父窗口
	bool            mousePress;                     //按钮点击标志位
	QPoint          movePoint;                      //鼠标移动需要记住的点

    int             switchFlag;
    int             MaximizeFlag;                   //双击是否最大化
    int             IsShow_Toolbar;                 //显示隐藏工具栏
    int             Original_window_x;              //窗口x坐标
    int             Original_window_y;              //窗口y坐标
    int             Original_window_Mywidth;        //窗口宽度
    int             Original_window_Myheight;       //窗口高度
	bool			isTitleBarResize;				//标题栏是否可以改变大小

	bool			isLeftPressDown;				//判断左键是否按下
	Direction		dir;							//窗口大小改变时,记录改变方向

private:
    void mousePressEvent(QMouseEvent * event);      //鼠标点击事件
    void mouseReleaseEvent(QMouseEvent *event);     //鼠标释放事件
    void mouseMoveEvent(QMouseEvent * event);       //鼠标移动事件
    void mouseDoubleClickEvent(QMouseEvent *event); //鼠标双击事件
	bool eventFilter(QObject *obj, QEvent *event);
	void paintEvent(QPaintEvent *event);			//绘制事件
};

#endif // TITLEBAR_H



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134

2.titlebar.cpp

代码如下(示例):

#include "titlebar.h"

#include <QSizeGrip>


/***************************            构造函数              ***************************/
TitleBar::TitleBar(QWidget *parent) : QFrame(parent)
{
	//设置父类窗口
	parentWidget = parent;
	//初始化参数
	initData();
    //初始化按钮
	initBotton();
	//初始化
	initConnect();
	//设置标题栏背景色
	set_ChildWindowColor(70, 70, 70);
	//设置标题栏显示文字颜色
	SetTitleLabelTextColor(255, 255, 255);
	//重置窗口大小
	resize(parent->width(), TITLEBARHEIGHT);
	setFixedHeight(TITLEBARHEIGHT);
    //设置阴影
    //Shadow_Warning();
}

void TitleBar::initData()
{
	switchFlag = 1;
	MaximizeFlag = 0;
	isTitleBarResize = true;
	IsShow_Toolbar = 1;
	this->setMouseTracking(true);
	this->setAttribute(Qt::WA_Hover, true);
	this->installEventFilter(this);
	isLeftPressDown = false;
	this->dir = NONE;
}
void TitleBar::initBotton()
{
    //最大化按钮设置图标
    maxButton = new QPushButton(this);
	maxButton->setFocusPolicy(Qt::NoFocus);
	maxButton->setIcon(QPixmap("style/icons/max.png"));

    //最小化按钮设置图标
    minButton = new QPushButton(this);
	minButton->setFocusPolicy(Qt::NoFocus);
	minButton->setIcon(QPixmap("style/icons/min.png"));

    //关闭按钮设置图标
    closeButton = new QPushButton(this);
	closeButton->setShortcut(tr("Ctrl+w"));
	closeButton->setFocusPolicy(Qt::NoFocus);
	closeButton->setIcon(QPixmap("style/icons/close.png"));

    //设置标签
    imgLabel = new QLabel(this);
    titleLabel = new QLabel(this);
    titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    //设置控件大小
    imgLabel->setFixedSize(CONTROLWIDTH - 5, CONTROLWIDTH - 5);
    imgLabel->setScaledContents(true);
	titleLabel->setMinimumSize(120, TITLEBARHEIGHT);
    minButton->setFixedSize(CONTROLWIDTH, CONTROLWIDTH);
    maxButton->setFixedSize(CONTROLWIDTH, CONTROLWIDTH);
    closeButton->setFixedSize(CONTROLWIDTH, CONTROLWIDTH);

	//设置控件图标大小
	minButton->setIconSize(QSize(CONTROLWIDTH, CONTROLWIDTH));
	maxButton->setIconSize(QSize(CONTROLWIDTH, CONTROLWIDTH));
	closeButton->setIconSize(QSize(CONTROLWIDTH, CONTROLWIDTH));

    //设置鼠标移至按钮上的提示信息
	ModifyTitleBarTip();

    //设置布局
    QHBoxLayout *hBoxLayout = new QHBoxLayout;
    hBoxLayout->addSpacing(5);
    hBoxLayout->addWidget(imgLabel);
    hBoxLayout->addSpacing(5);
    hBoxLayout->addWidget(titleLabel);
	hBoxLayout->addStretch();
    hBoxLayout->addSpacing(5);
    hBoxLayout->addWidget(minButton);
    hBoxLayout->addWidget(maxButton);
    hBoxLayout->addWidget(closeButton);
    hBoxLayout->setSpacing(0);
    hBoxLayout->setContentsMargins(0, 0, 2, 0);
    this->setLayout(hBoxLayout);
}

/***************************            设置标题              ***************************/
void TitleBar::setWindowTitle(const QString &title)
{
    QFont myFont;
    //设置文字大小
    myFont.setPointSize(12);
    //设置文字字体
    myFont.setFamily(qApp->font().family());
    titleLabel->setFont(myFont);
    titleLabel->setText(title);
}

/***************************            设置图标              ***************************/
void TitleBar::setWindowIcon(const QString &icon)
{
	if (icon.isEmpty())
		imgLabel->hide();
	else
		imgLabel->setPixmap(QPixmap(icon));
}

/***************************            设置标题栏不需要显示的按钮              ***************************/
void TitleBar::subWindowButton(const int &type)
{
    if(type == TITLEBAR::MINWIDGET)
    {
        SAFEDELETE(minButton);
    }
    else if(type == TITLEBAR::MAXWIDGET)
    {
        SAFEDELETE(maxButton);
    }
    else if(type == TITLEBAR::CloseWIDGET)
    {
        SAFEDELETE(closeButton);
    }
    else if(type == TITLEBAR::ALLWIDGET)
    {
        SAFEDELETE(minButton);
        SAFEDELETE(maxButton);
    }
	else if (type == TITLEBAR::NOBUTTON)
	{
		SAFEDELETE(minButton);
		SAFEDELETE(maxButton);
		SAFEDELETE(closeButton);
	}
}

void TitleBar::Shadow_Warning()
{
    //窗口添加阴影效果
    QGraphicsDropShadowEffect *shadow_effect = new QGraphicsDropShadowEffect;
    shadow_effect->setOffset(0, 4);
    shadow_effect->setColor(Qt::gray);
    shadow_effect->setBlurRadius(6);
    this->setGraphicsEffect(shadow_effect);

#if 0
	//实现毛玻璃效果
	QGraphicsBlurEffect* ef = new QGraphicsBlurEffect;
	ef->setBlurRadius(1.5);
	ef->setBlurHints(QGraphicsBlurEffect::AnimationHint);
	this->setGraphicsEffect(ef);
#endif
}

//移除最大最小按钮
void TitleBar::RemoveMaxMinButton()
{
    subWindowButton(TITLEBAR::ALLWIDGET);
}

//设置双击标题栏是否可以最大、最小化
void TitleBar::Set_MaximizeFlag()
{
    MaximizeFlag = 1;
}
//文件是否存在
bool TitleBar::FileIsExist(QString strFile)
{
    QFile tempFile(strFile);
    return tempFile.exists();
}
//修改标题显示文字颜色
void TitleBar::SetTitleLabelTextColor(int R,int G,int B)
{
	titleLabel->setStyleSheet(QString("QLabel{background-color:transparent;color:rgb(%1,%2,%3);outline: none;border:none;qproperty-alignment: 'AlignVCenter | AlignLeft';}").arg(R).arg(G).arg(B));
}

/***************************            初始化              ***************************/
void TitleBar::initConnect()
{
    //设置样式表
    minButton->setStyleSheet("QPushButton{background-color:transparent;outline: none;border:none;}QPushButton:hover{padding-left:6px;padding-top:6px;}");
    maxButton->setStyleSheet("QPushButton{background-color:transparent;outline: none;border:none;}QPushButton:hover{padding-left:6px;padding-top:6px;}");
	closeButton->setStyleSheet("QPushButton{background-color:transparent;outline: none;border:none;border-radius: 0px;}QPushButton:hover{padding-left:6px;padding-top:6px;background-color:rgb(237,28,36);}");
	//连接信号与槽
    connect(minButton,              SIGNAL(clicked(bool)), this, SLOT(showMin()));
    connect(maxButton,              SIGNAL(clicked(bool)), this, SLOT(showMax()));
    connect(closeButton,            SIGNAL(clicked(bool)), this, SLOT(showClose()));
}


/***************************            最大化              ***************************/
void TitleBar::showMax()
{
    if(parentWidget->geometry() == QApplication::desktop()->availableGeometry()) //判断是否是全屏
    {
		maxButton->setIcon(QPixmap("style/icons/max.png"));
        //退出全屏时设置为原窗口的坐标位置和尺寸大小
        parentWidget->setGeometry(Original_window_x, Original_window_y, Original_window_Mywidth, Original_window_Myheight);
    }
    else
    {
        //但不是全屏时获取原窗口的坐标和尺寸
        Original_window_x           = parentWidget->geometry().x();
        Original_window_y           = parentWidget->geometry().y();
        Original_window_Mywidth     = parentWidget->geometry().width();
        Original_window_Myheight    = parentWidget->geometry().height();
		maxButton->setIcon(QPixmap("style/icons/normal.png"));
        parentWidget->setGeometry(QApplication::desktop()->availableGeometry());            //这种设置不会全屏遮挡任务栏
    }
}

/***************************            最小化              ***************************/
void TitleBar::showMin()
{
    parentWidget->showMinimized();
}

/***************************      发送关闭信号给主窗口        ***************************/
void TitleBar::showClose()
{
    emit send_close();
}

void TitleBar::set_ChildWindowColor(int R,int G,int B)
{
    //设置背景色
	setStyleSheet(QString("QFrame{background-color:rgb(%1,%2,%3);outline: none;border:none;}").arg(R).arg(G).arg(B));
}

//修改标题栏按钮提示语言
void TitleBar::ModifyTitleBarTip()
{
    //设置鼠标移至按钮上的提示信息
    minButton->setToolTip(tr(u8"最小化"));
    maxButton->setToolTip(tr(u8"最大化"));
    closeButton->setToolTip(tr(u8"关闭"));
}


/***************************           鼠标点击             ***************************/
void TitleBar::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
		isLeftPressDown = true;
		if (isTitleBarResize)
			setMousePressCursorShape(event->pos());
		if (dir != NONE) {
			this->mouseGrabber();
		}
		else {
			movePoint = event->globalPos() - parentWidget->pos();
		}
    }
}

/**************************             鼠标释放              ***************************/
void TitleBar::mouseReleaseEvent(QMouseEvent *event)
{
	if (event->button() == Qt::LeftButton) {
		isLeftPressDown = false;
		if (dir != NONE) {
			dir = NONE;
			this->releaseMouse();
			this->setCursor(QCursor(Qt::ArrowCursor));
		}
	}
}

/**************************             鼠标移动              **************************/
void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
    if(parentWidget->geometry() == QApplication::desktop()->availableGeometry())
    {
        //判断当前是全屏就不允许拖动窗口
    }
	else
	{
		//当前不是全屏可以拖动窗口
		QPoint gloPoint = event->globalPos();
		QRect rect = parentWidget->rect();
		QPoint tl = mapToGlobal(rect.topLeft());
		QPoint rb = mapToGlobal(rect.bottomRight());

		if (!isLeftPressDown) {
			if (isTitleBarResize)
				setMousePressCursorShape(gloPoint);
		}
		else {

			if (dir != NONE) {
				QRect rMove(tl, rb);

				switch (dir) {
				case LEFT:
					if (rb.x() - gloPoint.x() <= parentWidget->minimumWidth())
						rMove.setX(tl.x());
					else
						rMove.setX(gloPoint.x());
					break;
				case RIGHT:
					rMove.setWidth(gloPoint.x() - tl.x());
					break;
				case UP:
					if (rb.y() - gloPoint.y() <= parentWidget->minimumHeight())
						rMove.setY(tl.y());
					else
						rMove.setY(gloPoint.y());
					break;
				case LEFTTOP:
					if (rb.x() - gloPoint.x() <= parentWidget->minimumWidth())
						rMove.setX(tl.x());
					else
						rMove.setX(gloPoint.x());
					if (rb.y() - gloPoint.y() <= parentWidget->minimumHeight())
						rMove.setY(tl.y());
					else
						rMove.setY(gloPoint.y());
					break;
				case RIGHTTOP:
					rMove.setWidth(gloPoint.x() - tl.x());
					if (rb.y() - gloPoint.y() <= parentWidget->minimumHeight())
						rMove.setY(tl.y());
					else
						rMove.setY(gloPoint.y());
					break;
				default:
					break;
				}
				parentWidget->setGeometry(rMove);
			}
			else {
				QPoint movePos = event->globalPos();
				parentWidget->move(movePos - movePoint);
				if(parentWidget->pos().y() <= 0) parentWidget->move(parentWidget->x(), 0);
            	if(parentWidget->pos().y() + this->height() >= QApplication::desktop()->availableGeometry().height())
                	parentWidget->move(parentWidget->x(), QApplication::desktop()->availableGeometry().height() - this->height());
				event->accept();
			}
		}
	}
}

/**************************            鼠标双击               **************************/
void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        if(MaximizeFlag == 1)
        {
            int x = event->x();
            int y = event->y();
            if((x > 0 && x < parentWidget->width()) && (y > 0 && y < TITLEBARHEIGHT)) //如果双击的范围在标题栏的范围之内
            {
                showMax(); //调用全屏、退出全屏函数
            }
        }
    }
}

bool TitleBar::eventFilter(QObject * obj, QEvent * event)
{
	if (obj == this)
	{
		if (event->type() == QMouseEvent::HoverEnter)
		{
			QMouseEvent *_mouseEvent = static_cast<QMouseEvent *>(event);
			if (isTitleBarResize)
				setMousePressCursorShape(_mouseEvent->pos(), false);
		}
		if (event->type() == QMouseEvent::HoverMove)
		{
			QMouseEvent *_mouseEvent = static_cast<QMouseEvent *>(event);
			if (!isLeftPressDown)
			{
				if (isTitleBarResize)
					setMousePressCursorShape(_mouseEvent->pos(), false);
			}
		}
		if (event->type() == QMouseEvent::HoverLeave)
		{
			if (isTitleBarResize)
				unsetCursor();
		}
	}
	return QFrame::eventFilter(obj, event);
}

void TitleBar::Set_MouseShapeFlag(bool MouseShape)
{
	isTitleBarResize = MouseShape;
}

QRectF TitleBar::boundingRect() const
{
	return QRectF(QPointF(0, 0), geometry().size());
}

QRectF TitleBar::leftBorder() const
{
	return QRectF(0, 0, PADDING, boundingRect().height());
}

QRectF TitleBar::rightBorder() const
{
	return QRectF(boundingRect().width() - PADDING, 0, PADDING, boundingRect().height());
}

QRectF TitleBar::topBorder() const
{
	return QRectF(0, 0, boundingRect().width(), PADDING);
}

QRectF TitleBar::bottomBorder() const
{
	return QRectF(0, boundingRect().height() - PADDING, boundingRect().width(), PADDING);
}

void TitleBar::setMousePressCursorShape(const QPointF& pt, bool isShow)
{
	QCursor cursor = Qt::ArrowCursor;
	if (rightBorder().contains(pt) && topBorder().contains(pt))        // 右上角
	{
		if(isShow)
			dir = RIGHTTOP;
		this->setCursor(QCursor(Qt::SizeBDiagCursor));
	}
	else if (leftBorder().contains(pt) && topBorder().contains(pt))         // 左上角
	{
		if (isShow)
			dir = LEFTTOP;
		this->setCursor(QCursor(Qt::SizeFDiagCursor));
	}
	else if (rightBorder().contains(pt))        // 右边
	{
		if (isShow)
			dir = RIGHT;
		this->setCursor(QCursor(Qt::SizeHorCursor));
	}
	else if (leftBorder().contains(pt))         // 左边
	{
		if (isShow)
			dir = LEFT;
		this->setCursor(QCursor(Qt::SizeHorCursor));
	}
	else if (topBorder().contains(pt))          // 上边
	{
		if (isShow)
			dir = UP;
		this->setCursor(QCursor(Qt::SizeVerCursor));
	}
	else
	{
		if (isShow)
			dir = NONE;
		this->setCursor(QCursor(isLeftPressDown ? Qt::SizeAllCursor : Qt::ArrowCursor));
	}
}

// 绘制事件中设置标题栏宽度跟随父窗口宽度变化尺寸
void TitleBar::paintEvent(QPaintEvent *event)
{
	if (this->width() != parentWidget->width())
	{
		this->setFixedWidth(parentWidget->width());
	}
	QFrame::paintEvent(event);
}



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479

应用

//自定义标题栏
	{
		Main_InterfaceTitleBar = new TitleBar(this);										//在.h头文件中TitleBar *Main_InterfaceTitleBar
		setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint
		| Qt::WindowMinimizeButtonHint| Qt::WindowMaximizeButtonHint);						//设置为无边框
		connect(Main_InterfaceTitleBar, &TitleBar::send_close, this, [=]() {close();});		//一般窗口就是关闭,主界面或登录界面就是退出软件
		Main_InterfaceTitleBar->Set_MaximizeFlag();											//设置是否有最大最小化按钮
		Main_InterfaceTitleBar->setFixedHeight(40);											//设置标题栏高度
		Main_InterfaceTitleBar->Set_MouseShapeFlag(true);									//设置是否可以改变窗口大小
		Main_InterfaceTitleBar->setWindowIcon(":/trayIcon.png");							//这里根据自己的图标路径填写
		Main_InterfaceTitleBar->setWindowTitle(tr("图像拼接处理器"));						//设置标题栏标题
	}
	//布局情况很多种,标题栏只是显示在父窗口最上面的位置,具体怎么调整根据自己的布局来设置
	QVBoxLayout *vlayout = new QVBoxLayout;
	vlayout->addWidget(LargeScreenTitleBar);
	vlayout->addLayout(...);
	vlayout->addWidget(...);
	vlayout->addWidget(...);
	vLayout->setContentsMargins(0, 0, 0, 0);
	setLayout(vlayout);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

补充

去掉标题栏和边框后是比较方便,但是却失去了系统标题栏自带的属性,下面是网上找的使用nativeEventFilter函数捕获截取系统消息实现窗口移动缩放,还带有贴边等效果。原文链接QT无边框窗体——拦截windows消息实现

#ifndef WINMSGFILTER_H
#define WINMSGFILTER_H
#include <QAbstractNativeEventFilter>
#include <QDebug>
#include <Windows.h>
#pragma comment(lib, "dwmapi")
#pragma comment(lib,"user32.lib")
#include <dwmapi.h>
#include <windowsx.h>

class WinMsgFilter :public QAbstractNativeEventFilter
{
public:
    //过滤掉消息返回true,否则返回false
    bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override
    {
        int boundarySize = 7;
        MSG* pMsg = reinterpret_cast<MSG*>(message);
        switch (pMsg->message)
        {
            //去掉边框(这样比较setWindowFlags(Qt::Window | Qt::FramelessWindowHint)去掉标题栏好一些,但是高DPI下显示会有虚线)
            case WM_NCCALCSIZE:
            {
                *result = 0;
                return true;
                break;
            }
            //阴影
            case WM_ACTIVATE:
            {
                MARGINS margins = { 1,1,1,1 };
                HRESULT hr = S_OK;
                hr = DwmExtendFrameIntoClientArea(pMsg->hwnd, &margins);
                *result = hr;
                return true;
            }
            case WM_NCHITTEST:
            {
                //处理resize
                //标记只处理resize
                bool isResize = false;
                //鼠标点击的坐标
                POINT ptMouse = { GET_X_LPARAM(pMsg->lParam), GET_Y_LPARAM(pMsg->lParam) };
                //窗口矩形
                RECT rcWindow;
                GetWindowRect(pMsg->hwnd, &rcWindow);
                RECT rcFrame = { 0,0,0,0 };
                AdjustWindowRectEx(&rcFrame, WS_OVERLAPPEDWINDOW & ~WS_CAPTION, FALSE, NULL);
                USHORT uRow = 1;
                USHORT uCol = 1;
                bool fOnResizeBorder = false;
                //确认鼠标指针是否在top或者bottom,顺带说一下屏幕坐标原点是左上角,窗体坐标原点也是左上角
                if (ptMouse.y >= rcWindow.top && ptMouse.y < rcWindow.top + boundarySize)
                {
                    fOnResizeBorder = (ptMouse.y < (rcWindow.top - rcFrame.top));
                    uRow = 0;
                    isResize = true;
                }
                else if (ptMouse.y < rcWindow.bottom && ptMouse.y >= rcWindow.bottom - boundarySize)
                {
                    uRow = 2;
                    isResize = true;
                }
                //确认鼠标指针是否在left或者right
                if (ptMouse.x >= rcWindow.left && ptMouse.x < rcWindow.left + boundarySize)
                {
                    uCol = 0; // left side
                    isResize = true;
                }
                else if (ptMouse.x < rcWindow.right && ptMouse.x >= rcWindow.right - boundarySize)
                {
                    uCol = 2; // right side
                    isResize = true;
                }
                int interval = 217;
                //检测是不是在标题栏上,右边预留出了217的宽度,是留给关闭按钮、最大化、最小化和自定义按钮的宽度。
                //这个范围设置为HTCAPTION后,鼠标按在这个区域内只会执行标题栏功能,高DPI下坐标会变,
                //可能会导致区域覆盖部分自定义按钮,导致按钮按下无法响应。
                if (ptMouse.x >= rcWindow.left + boundarySize && ptMouse.x <= rcWindow.right - interval && ptMouse.y > rcWindow.top + boundarySize && ptMouse.y <= rcWindow.top+40)
                {
                    *result = HTCAPTION;
                    return true;
                }
                LRESULT hitTests[3][3] =
                {
                    { HTTOPLEFT,    fOnResizeBorder ? HTTOP : HTCAPTION,    HTTOPRIGHT },
                    { HTLEFT,       HTNOWHERE,     HTRIGHT },
                    { HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
                };
                if (isResize == true)
                {
                    *result = hitTests[uRow][uCol];
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        //这里一定要返回false,否则是屏蔽所有消息了
        return false;
    }
};
#endif // WINMSGFILTER_H

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106

使用

可以在main.cpp中注册使用也可以单独在窗口类中重写这个nativeEventFilter函数

#include "mainwindow.h"
#include "winmsgfilter.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    WinMsgFilter wmf;
    QCoreApplication::instance()->installNativeEventFilter(&wmf);
    MainWindow w;
    w.show();
    return a.exec();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

总结

可根据自己需求添加删除按钮,调整标题栏大小。

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号