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中項目屬性-鏈接器中進行相關配置即可。

點擊下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM