【QT入门】 设计实现无边框窗口拉伸的公用类

往期回顾:

【QT入门】 QScrollArea实际运用之滑动Widget设计-CSDN博客

【QT入门】QWidget类的简单介绍-CSDN博客

【QT入门】 鼠标按下和移动事件实现无边框窗口拖动-CSDN博客

 【QT入门】 设计实现无边框窗口拉伸的公用类

我们想要做的就是把实现无边框窗口边框拉伸这一功能抽象出来,设计为一个公用类,这样需要的时候我们直接派生这个类就可以了。

一、如何派生

只需要在主类的.h文件和.cpp文件里简单修改一下派生的类就行,这个基础要知道。

 1、MainWidget.h

class MainWidget : public CFrameLessWidgetBase
{
    Q_OBJECT

public:
    MainWidget(QWidget *parent = Q_NULLPTR);
    MainWidget();

};

 2、MainWidget.cpp

MainWidget::MainWidget(QWidget *parent)
    : CFrameLessWidgetBase(parent)
{
    initUI();
}

二、 公用类实现

这一块的逻辑实现我也写了注释,大家可以看一看,看不明白也没事,先会用。

1、CFrameLessWidgetBase.h

#pragma once
#include <QWidget>

class CFrameLessWidgetBase :
    public QWidget
{
public:
    CFrameLessWidgetBase(QWidget* p = nullptr);
    ~CFrameLessWidgetBase() {}

protected:
    bool nativeEvent(const QByteArray& eventType, void* message, long* result) override;

private:
    int m_nBorderWidth = 5;
};

2、CFrameLessWidgetBase.cpp

#include "CFrameLessWidgetBase.h"
#include <qt_windows.h>
#include <windows.h>
#include <windowsx.h>
#include <QDebug>

#pragma comment(lib, "user32.lib")
#pragma comment(lib,"dwmapi.lib")

CFrameLessWidgetBase::CFrameLessWidgetBase(QWidget* p)
 :QWidget(p)
{
 //this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
  setAttribute(Qt::WA_Hover);   //避免因多个部件无法识别
}

bool CFrameLessWidgetBase::nativeEvent(const QByteArray& eventType, void* message, long* result)
{
 MSG* param = static_cast<MSG*>(message);//将void*类型的message转换为MSG*类型,以便获取消息参数。

 switch (param->message) //根据消息类型进行分支处理。
 {
 case WM_NCHITTEST: //处理鼠标在非客户区的命中测试消息。
 {
  //计算鼠标相对于窗口左上角的坐标。
  int nX = GET_X_LPARAM(param->lParam) - this->geometry().x();
  int nY = GET_Y_LPARAM(param->lParam) - this->geometry().y();

  /*if (childAt(nX, nY) != nullptr)
   return QWidget::nativeEvent(eventType, message, result);*/

  //检查鼠标是否在窗口的边框内部区域,如果在内部区域,
  if (nX > m_nBorderWidth && nX < this->width() - m_nBorderWidth &&
   nY > m_nBorderWidth && nY < this->height() - m_nBorderWidth)
  {
   qDebug() << "in the title ";
   //检查鼠标位置是否在子控件上,如果是,则调用QWidget的nativeEvent函数进行处理。
   if (childAt(nX, nY) != nullptr)
    return QWidget::nativeEvent(eventType, message, result);
  }

  //根据鼠标位置的不同,设置*result为对应的窗口调整消息
  if ((nX > 0) && (nX < m_nBorderWidth))
   *result = HTLEFT;

  if ((nX > this->width() - m_nBorderWidth) && (nX < this->width()))
   *result = HTRIGHT;

  if ((nY > 0) && (nY < m_nBorderWidth))
   *result = HTTOP;

  if ((nY > this->height() - m_nBorderWidth) && (nY < this->height()))
   *result = HTBOTTOM;

  //根据鼠标位置的不同,设置*result为对应的窗口角落调整消息
  if ((nX > 0) && (nX < m_nBorderWidth) && (nY > 0)
   && (nY < m_nBorderWidth))
   *result = HTTOPLEFT;

  if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
   && (nY > 0) && (nY < m_nBorderWidth))
   *result = HTTOPRIGHT;

  if ((nX > 0) && (nX < m_nBorderWidth)
   && (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
   *result = HTBOTTOMLEFT;

  if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
   && (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
   *result = HTBOTTOMRIGHT;

  //返回true表示已经处理了该消息
  return true;
 }
 }

 //如果没有匹配到特定消息类型,会执行return false; ,表示未处理该消息
 return false;
}

后面大家在需要实现无边框窗口拉伸功能的时候,直接把CFrameLessWidgetBase类添加进去,并派生就行。

都看到这里了,点个赞再走呗朋友~

加油吧,预祝大家变得更强!

  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值