Qt——鼠标拖动调整窗口大小

要求:鼠标移到界面边角时,鼠标样式相应地发生改变。

实现方法一:

重写mouseMoveEvent,如果鼠标没有按下,则根据鼠标在界面上的位置设置鼠标样式,如果鼠标按下,则根据位置判断该怎样调整界面大小,或者是拖动界面。思路如上,实现起来很简单。但是存在一个问题,如果界面中放了一些其它控件,比如listWidget,此时鼠标在界面边缘移动速度稍微快一些,mouseMoveEvent就会被子控件截获了,鼠标样式不会改变,对于该方法的这个问题,我还没想到好的解决办法。

 

实现方法二:

在Qt中处理windows事件,具体实现如下,参考网上一些内容,我顺便修改优化了一下,源代码如下:

#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);
	bool winEvent(MSG *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;
}

//处理windows事件,在QT5中,被函数nativeEvent取代
bool MBaseWidget::winEvent(MSG *message, long *result)
{
	switch (message->message)
	{
	case WM_NCHITTEST:
		int iPosX = GET_X_LPARAM(message->lParam) - this->frameGeometry().x();//鼠标位置x
		int iPosY = GET_Y_LPARAM(message->lParam) - this->frameGeometry().y();//鼠标位置y

		*result = HTCAPTION;

		if (!m_bCanResize)
		{
			return true;//返回为真,此时仍可拖动,但无法改变大小
		}
		
		if (iPosX >= 0 && iPosX <= m_iMarginWidth)
		{
			*result = HTLEFT;//左
			int iHeight = this->height();
			if (iPosY >= 0 && iPosY <= m_iMarginWidth)
			{
				*result = HTTOPLEFT;//左上
			}
			if (iPosY >= iHeight - m_iMarginWidth && iPosY <= iHeight)
			{
				*result = HTBOTTOMLEFT;//左下
			}
			return true;
		}

		int iWidth = this->width();
		int iHeight = this->height();
		if (iPosX >= iWidth - m_iMarginWidth && iPosX <= iWidth)
		{
			*result = HTRIGHT;//右
			if (iPosY >= 0 && iPosY <= m_iMarginWidth)
			{
				*result = HTTOPRIGHT;//右上
				return true;
			}
			if (iPosY >= iHeight - m_iMarginWidth && iPosY <= iHeight)
			{
				*result = HTBOTTOMRIGHT;//右下
				return true;
			}
			return true;
		}
		if (iPosY >= 0 && iPosY <= m_iMarginWidth)
		{
			*result = HTTOP;//上
			return true;
		}
		if (iPosY >= iHeight - m_iMarginWidth && iPosY <= iHeight)
		{
			*result = HTBOTTOM;//下
			return true;
		}
		return true;
	}
	return false;
}

bool MBaseWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
	return winEvent((MSG*)message, result);
}

这种方法是借助windows来实现的,所以受系统的限制,比如,拖动放大到与屏幕一样大时,就不能继续放大了,而且其它类直接继承这个类可能会出现问题。

 

实现方法三:

既然通过mouseMoveEvent不能解决鼠标的样式问题,那么可以考虑通过其它事件来实现,下面是我实现的一个类,包括头文件、dll和lib文件。

在VS中项目属性-链接器中进行相关配置即可。

点击下载

posted @ 2016-01-01 15:28  去冰三分糖  阅读(4972)  评论(0编辑  收藏  举报