• qt 拖拽 修改大小


    写次篇文章之前,qt窗口的放大缩小和拖拽我都是通过setGeometry方法实现的,但是作为windows程序,windows支持橡 皮筋式(拖拽时有一个虚框)拖拽和拉伸。通过setGeometry方式实现功能是没有这种效果,幸好qt5中提供了一个本地事件处理接口 nativeEvent,具体功能可以看帮助文档,本文只讲述用该接口实现窗口放大、缩小和拖拽,具体实现代码如下:

      1 virtual bool nativeEvent(const QByteArray &, void *, long *) Q_DECL_OVERRIDE;
      2 
      3 {
      4 
      5     Q_UNUSED(eventType);
      6 
      7     MSG* msg = reinterpret_cast(message);
      8 
      9     if (winEvent(msg, result))
     10 
     11     {
     12 
     13         return true;
     14 
     15     }
     16 
     17     else
     18 
     19     {
     20 
     21         return QWidget::nativeEvent(eventType, message, result);
     22 
     23     }
     24 
     25 }
     26 
     27 如下方法是在qt事件循环之前调用的,如果返回值为true,则该事件循环不进入qt事件循环,否则进入,result是一个输出型参数,我们可以通过赋值给result不同的值,来控制鼠标的状态
     28 
     29 HTCAPTION:鼠标可以拖拽
     30 
     31 HTLEFT / HTRIGHT:鼠标可以左右拖拽
     32 
     33 HTTOP / HTBOTTOM:鼠标可以上下拖拽
     34 
     35 HTTOPLEFT / HTBOTTOMRIGHT:鼠标可以左上或者右下拖拽
     36 
     37 HTTOPRIGHT / HTBOTTOMLEFT:鼠标可以右上或者左下拖拽
     38 
     39 bool CCailianMainWindow::winEvent(MSG *message, long *result)
     40 
     41 {
     42 
     43     static int width = 4;//可检测到鼠标状态的宽度
     44 
     45     bool res = false;
     46 
     47     if (isMaximized())
     48 
     49     {
     50 
     51         return res;
     52 
     53     }
     54 
     55     switch (message->message)
     56 
     57     {
     58 
     59     case WM_NCHITTEST:
     60 
     61         int xPos = GET_X_LPARAM(message->lParam) - this->frameGeometry().x();
     62 
     63         int yPos = GET_Y_LPARAM(message->lParam) - this->frameGeometry().y();
     64 
     65         if (QWidget * childW = this->childAt(xPos, yPos))
     66 
     67         {
     68 
     69             if (childW == m_WindowTitle)//我自己的窗口头,支持鼠标拖拽
     70 
     71             {
     72 
     73                 *result = HTCAPTION;
     74 
     75                 res = true;
     76 
     77             }
     78 
     79         }
     80 
     81         else
     82 
     83         {
     84 
     85             return res;
     86 
     87         }
     88 
     89         if (xPos >= 0 && xPos < width)
     90 
     91         {
     92 
     93             *result = HTLEFT;
     94 
     95             res = true;
     96 
     97         }
     98 
     99         if (xPos > (this->width() - width) && xPos < this->width())
    100 
    101         {
    102 
    103             *result = HTRIGHT;
    104 
    105             res = true;
    106 
    107         }
    108 
    109         if (yPos >= 0 && yPos < width)
    110 
    111         {
    112 
    113             *result = HTTOP;
    114 
    115             res = true;
    116 
    117         }
    118 
    119         if (yPos > (this->height() - width) && yPos < this->height())
    120 
    121         {
    122 
    123             *result = HTBOTTOM;
    124 
    125             res = true;
    126 
    127         }
    128 
    129         if (xPos >= 0 && xPos < width && yPos >= 0 && yPos < width)
    130 
    131         {
    132 
    133             *result = HTTOPLEFT;
    134 
    135             res = true;
    136 
    137         }
    138 
    139         if (xPos > (this->width() - width) && xPos < this->width() && yPos >= 0 && yPos < width)
    140 
    141         {
    142 
    143             *result = HTTOPRIGHT;
    144 
    145             res = true;
    146 
    147         }
    148 
    149         if (xPos >= 0 && xPos < width && yPos >(this->height() - width) && yPos < this->height())
    150 
    151         {
    152 
    153             *result = HTBOTTOMLEFT;
    154 
    155             res = true;
    156 
    157         }
    158 
    159         if (xPos > (this->width() - width) && xPos < this->width() && yPos >(this->height() - width) && yPos < this->height())
    160 
    161         {
    162 
    163             *result = HTBOTTOMRIGHT;
    164 
    165             res = true;
    166 
    167         }
    168 
    169     }
    170 
    171     return res;
    172 
    173 }
    View Code
    图1 拖拽
    图2 修改大小 

    如上图所示,红色箭头指的就是拖拽和改变大小时出现的白色框

    这样处理后的标题栏(m_WindowTitle)不能接受到mouseDoubleClickEvent事件,因此还需要自己手动修改窗口大小,代码如下,添加到上述swtich语句中

     1 case WM_NCLBUTTONDBLCLK:
     2 
     3 {
     4 
     5     HWND hWnd = (HWND)this->winId();
     6 
     7     if (::IsZoomed(hWnd))
     8 
     9     {
    10 
    11         ShowWindow(hWnd, SW_RESTORE);
    12 
    13     }
    14 
    15     else
    16 
    17     {
    18 
    19         ShowWindow(hWnd, SW_MAXIMIZE);
    20 
    21     }
    22 
    23     res = false;
    24 
    25 }
    26 
    27 break;
    View Code

    注意:要支持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实现效果相同

    图3 QSizeGrip实例
  • 相关阅读:
    SQL游标的小知识
    SQL游标的小知识
    SQL游标的小知识
    为什么程序员发现不了自己的BUG
    为什么程序员发现不了自己的BUG
    为什么程序员发现不了自己的BUG
    为什么程序员发现不了自己的BUG
    为什么程序员发现不了自己的BUG
    ACM1998
    Leetcode 946. Validate Stack Sequences 验证栈序列
  • 原文地址:https://www.cnblogs.com/swarmbees/p/5621543.html
Copyright © 2020-2023  润新知