【QT】实现无边框窗口+可拖动+可调整大小

QT无边框

// 在widget构造中添加如下即可实现无边框
setWindowFlags(Qt::FramelessWindowHint);  //设置无边框

可拖动

当实现无边框之后,你会发现无法拖动了。
或许我们需要了解下窗口是怎么被拖动的

  1. 通过标题栏拖动窗口
  2. move窗口位置
    因此有两种方案可以解决无法拖动
// 1. 通过定位到标题栏拖动窗口
// 重写nativeEvent事件,是QT用于处理原生系统事件
bool Widget::nativeEvent(const QByteArray& eventType, void* message, long* result)
{
	MSG* msg = (MSG*)message;
	switch (msg->message)
	{
	case WM_NCHITTEST:
		int xPos = GET_X_LPARAM(msg->lParam) - this->frameGeometry().x();
		int yPos = GET_Y_LPARAM(msg->lParam) - this->frameGeometry().y();
		if (xPos && xPos < width() && yPos && yPos < height())
			*result = HTCAPTION;
		else
			return false;

		return true;
	}
	return false;
}

PS:
GET_X_LPARAM(msg->lParam)获取鼠标在屏幕中坐标,原点为屏幕左上角
this->frameGeometry().x()获取窗口左上角x坐标
通过计算,可将鼠标坐标系换算成窗口坐标系中
HTCAPTION是一个常量,表示鼠标在窗口的标题栏上
此种处理有缺陷,会导致无法点击窗口中控件

// 2. move窗口位置
// 通过重写mousePressEvent、mouseMoveEvent事件
protected:
	void mousePressEvent(QMouseEvent* event);
	void mouseMoveEvent(QMouseEvent* event);
private:
	QPoint m_dragPosition;  // 用于窗口移动的临时变量

void Widget::mousePressEvent(QMouseEvent* event)
{
    // 当鼠标左键按下时记录鼠标的全局坐标与窗口左上角的坐标差
    if (event->button() == Qt::LeftButton) {
        m_dragPosition = event->pos();
        event->accept();
    }
}

void Widget::mouseMoveEvent(QMouseEvent* event)
{

    // 当鼠标左键被按下时移动窗口
    if (event->buttons() & Qt::LeftButton) {
        move(event->globalPos() - m_dragPosition);
        event->accept();
    }
}

PS:
pos()获取鼠标在窗口坐标系中位置
globalPos()获取鼠标在屏幕坐标系中位置
原理:
通过鼠标移动中,计算窗口左上角位置,实现移动

可调整大小

同上,重写nativeEvent即可

bool Widget::nativeEvent(const QByteArray& eventType, void* message, long* result)
{
	MSG* msg = (MSG*)message;
	switch (msg->message)
	{
	case WM_NCHITTEST:
		int xPos = GET_X_LPARAM(msg->lParam) - this->frameGeometry().x();
		int yPos = GET_Y_LPARAM(msg->lParam) - this->frameGeometry().y();
		if (xPos && xPos < width() && yPos && yPos < height())
			*result = HTCAPTION;
        else if (xPos < boundaryWidth && yPos < boundaryWidth)                    //左上角
            *result = HTTOPLEFT;
        else if (xPos >= width() - boundaryWidth && yPos < boundaryWidth)          //右上角
            *result = HTTOPRIGHT;
        else if (xPos < boundaryWidth && yPos >= height() - boundaryWidth)         //左下角
            *result = HTBOTTOMLEFT;
        else if (xPos >= width() - boundaryWidth && yPos >= height() - boundaryWidth)//右下角
            *result = HTBOTTOMRIGHT;
        else if (xPos < boundaryWidth)                                     //左边
            *result = HTLEFT;
        else if (xPos >= width() - boundaryWidth)                              //右边
            *result = HTRIGHT;
        else if (yPos < boundaryWidth)                                       //上边
            *result = HTTOP;
        else if (yPos >= height() - boundaryWidth)                             //下边
            *result = HTBOTTOM;
		else
			return false;
	}
	return false;
}

头文件

#include <QMouseEvent>
#include <windows.h>
#include <windowsx.h>

参考文章

  1. QT实现完美无边框窗口(可拖动,可调整大小)
  2. Qt无边框窗口实现拖动和改变大小(修改)
  3. Qt::FramelessWindowHint无边框化,移动,大小调整
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值