zoukankan      html  css  js  c++  java
  • 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中项目属性-链接器中进行相关配置即可。

    点击下载

  • 相关阅读:
    【Spring Framework】10、代理模式
    【Spring Framework】8、使用注解开发
    Codeforces 516E
    AtCoder Grand Contest 055 题解
    Codeforces 1606F
    贪心/构造/DP 杂题选做
    整数拆分最大乘积
    CSP-S2021 被碾压记
    洛谷 P2791
    LCT 小记
  • 原文地址:https://www.cnblogs.com/hellovenus/p/5093362.html
Copyright © 2011-2022 走看看