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實例


免責聲明!

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



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