
正文
qt 拖拽 修改大小
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
写次篇文章之前,qt窗口的放大缩小和拖拽我都是通过setGeometry方法实现的,但是作为windows程序,windows支持橡 皮筋式(拖拽时有一个虚框)拖拽和拉伸。通过setGeometry方式实现功能是没有这种效果,幸好qt5中提供了一个本地事件处理接口 nativeEvent,具体功能可以看帮助文档,本文只讲述用该接口实现窗口放大、缩小和拖拽,具体实现代码如下:
virtual bool nativeEvent(const QByteArray &, void *, long *) Q_DECL_OVERRIDE; { Q_UNUSED(eventType); MSG* msg = reinterpret_cast(message); if (winEvent(msg, result)) { return true; } else { return QWidget::nativeEvent(eventType, message, result); } } 如下方法是在qt事件循环之前调用的,如果返回值为true,则该事件循环不进入qt事件循环,否则进入,result是一个输出型参数,我们可以通过赋值给result不同的值,来控制鼠标的状态 HTCAPTION:鼠标可以拖拽 HTLEFT / HTRIGHT:鼠标可以左右拖拽 HTTOP / HTBOTTOM:鼠标可以上下拖拽 HTTOPLEFT / HTBOTTOMRIGHT:鼠标可以左上或者右下拖拽 HTTOPRIGHT / HTBOTTOMLEFT:鼠标可以右上或者左下拖拽 bool CCailianMainWindow::winEvent(MSG *message, long *result) { static int width = ;//可检测到鼠标状态的宽度 bool res = false; if (isMaximized()) { return res; } switch (message->message) { case WM_NCHITTEST: int xPos = GET_X_LPARAM(message->lParam) - this->frameGeometry().x(); int yPos = GET_Y_LPARAM(message->lParam) - this->frameGeometry().y(); if (QWidget * childW = this->childAt(xPos, yPos)) { if (childW == m_WindowTitle)//我自己的窗口头,支持鼠标拖拽 { *result = HTCAPTION; res = true; } } else { return res; } if (xPos >= && xPos < width) { *result = HTLEFT; res = true; } if (xPos > (this->width() - width) && xPos < this->width()) { *result = HTRIGHT; res = true; } if (yPos >= && yPos < width) { *result = HTTOP; res = true; } if (yPos > (this->height() - width) && yPos < this->height()) { *result = HTBOTTOM; res = true; } if (xPos >= && xPos < width && yPos >= && yPos < width) { *result = HTTOPLEFT; res = true; } if (xPos > (this->width() - width) && xPos < this->width() && yPos >= && yPos < width) { *result = HTTOPRIGHT; res = true; } if (xPos >= && xPos < width && yPos >(this->height() - width) && yPos < this->height()) { *result = HTBOTTOMLEFT; res = true; } if (xPos > (this->width() - width) && xPos < this->width() && yPos >(this->height() - width) && yPos < this->height()) { *result = HTBOTTOMRIGHT; res = true; } } return res; }
图1 拖拽
图2 修改大小如上图所示,红色箭头指的就是拖拽和改变大小时出现的白色框
这样处理后的标题栏(m_WindowTitle)不能接受到mouseDoubleClickEvent事件,因此还需要自己手动修改窗口大小,代码如下,添加到上述swtich语句中
case WM_NCLBUTTONDBLCLK: { HWND hWnd = (HWND)this->winId(); if (::IsZoomed(hWnd)) { ShowWindow(hWnd, SW_RESTORE); } else { ShowWindow(hWnd, SW_MAXIMIZE); } res = false; } break;
注意:要支持windows的这种特性,需要通过代码设置
showFullWindow:true代表拖动和改变大小时窗口实时变化;false代表橡皮筋式放大,如上图所示
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, showFullWindow ? TRUE : FALSE, NULL, 0);
================================================
时隔10几天,当我测试新功能时发现一个问题,特此记录:
在xp系统上qt程序没有任务栏菜单,但是win7和win10正常,给qt程序手动添加Qt::WindowSystemMenuHint属性后,3系统都有菜单,但是nativeEvent方法不能放大缩小了,解决办法暂时没找到
====================================
今儿突然想到QMainWindow,这个右下角有一个可以支持放大做小的功能,最后看了源码,发现由一个QSizeGrip类,这个类可以实现所在顶层 QWindow的放大和缩小,特此记录,此时结果如下图3。这个类支持橡皮筋放大缩小,和前文所述nativeEvent实现效果相同
图3QSizeGrip实例







