参考:Qt——鼠标拖动调整窗口大小 - 去冰三分糖 - 博客园 (cnblogs.com)
要求:鼠标移到界面边角时,鼠标样式相应地发生改变。
实现方法一:
重写mouseMoveEvent,如果鼠标没有按下,则根据鼠标在界面上的位置设置鼠标样式,如果鼠标按下,则根据位置判断该怎样调整界面大小,或者是拖动界面。思路如上,实现起来很简单。但是存在一个问题,如果界面中放了一些其它控件,比如listWidget,此时鼠标在界面边缘移动速度稍微快一些,mouseMoveEvent就会被子控件截获了,鼠标样式不会改变,对于该方法的这个问题,我还没想到好的解决办法。
ps:
类似参考:QT实现鼠标拖动调整窗口大小_Dawn丶的博客-CSDN博客
我这边就是遇到了这种鼠标样式不会变的情况,当时还很疑惑,明明逻辑对,但是就是不成功!所以,我这边因为系统只需要支持Windows,所以我就想找通过Windows方法实现此功能(也就是下面的方法二),然后就发现个这篇博客,美中不足的是:此博客的方法三的文件下载路径失效了,希望我有时间后,进行补充!
实现方法二:
此方法只适用于Windows系统,原作者的代码有些问题(信号槽无法响应),调试了半天才找到问题(应该是某个不是边缘的,返回的true,无法传给其他事件,比如信号槽);后续重新写的逻辑(也是参考网上已有的代码),这个应该没问题了 。
还有补充一下:Qt4用的是winEvent,Qt5用的是nativeEvent,因为我觉得我不会用到Qt4,所以以下代码也没有进行兼容操作。
#ifndef MBASEWIDGET_H
#define MBASEWIDGET_H
#include <QtWidgets/QWidget>
#include "windows.h"
class MBaseWidget : public QWidget
{
Q_OBJECT
public:
MBaseWidget(QWidget *parent);
~MBaseWidget();
void setMarginWidth(const int &); //设置鼠标可以在界面边缘多大范围内拖动改变界面大小
void serResizable(bool); //设置是否可以拖动改变大小
protected:
bool nativeEvent(const QByteArray & eventType, void * message, long * result);
private:
int m_iMarginWidth;
bool m_bCanResize;
};
#endif // MBASEWIDGET_H
#include "MBaseWidget.h"
#include "windowsx.h"
MBaseWidget::MBaseWidget(QWidget *parent)
: QWidget(parent)
{
m_iMarginWidth = 3;
m_bCanResize = true;
setWindowFlags(Qt::FramelessWindowHint);
}
MBaseWidget::~MBaseWidget()
{
}
void MBaseWidget::setMarginWidth(const int &iWidth)
{
m_iMarginWidth = iWidth;
}
void MBaseWidget::serResizable(bool bCanResize)
{
m_bCanResize = bCanResize;
}
bool MBaseWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
if (!m_bCanResize)
{
return QWidget::nativeEvent(eventType,message,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 < m_iMarginWidth && yPos<m_iMarginWidth) //左上角
*result = HTTOPLEFT;
else if(xPos>=width()-m_iMarginWidth&&yPos<m_iMarginWidth) //右上角
*result = HTTOPRIGHT;
else if(xPos<m_iMarginWidth&&yPos>=height()-m_iMarginWidth) //左下角
*result = HTBOTTOMLEFT;
else if(xPos>=width()-m_iMarginWidth&&yPos>=height()-m_iMarginWidth)//右下角
*result = HTBOTTOMRIGHT;
else if(xPos < m_iMarginWidth) //左边
*result = HTLEFT;
else if(xPos>=width()-m_iMarginWidth) //右边
*result = HTRIGHT;
else if(yPos<m_iMarginWidth) //上边
*result = HTTOP;
else if(yPos>=height()-m_iMarginWidth) //下边
*result = HTBOTTOM;
else //其他部分不做处理,返回false,留给其他事件处理器处理
return false;
return true;
}
return false; //此处返回false,留给其他事件处理器处理
}
这种方法是借助windows来实现的,所以受系统的限制,比如,拖动放大到与屏幕一样大时,就不能继续放大了。
实现方法三:
既然通过mouseMoveEvent不能解决鼠标的样式问题,那么可以考虑通过其它事件来实现,下面是我实现的一个类,包括头文件、dll和lib文件。
在VS中项目属性-链接器中进行相关配置即可。(此文件下载路径失效了~,好可惜,但是也提供了一条思路!)