移動無邊框窗體(設置標志位更流暢,或者發送WM_SYSCOMMAND和SC_MOVE + HTCAPTION消息)


移動無邊框窗體的代碼網上很多,其原理都是一樣的,但是是有問題的,我這里只是對其修正一下

網上的代碼僅僅實現了兩個事件

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. void EditDialog::mousePressEvent(QMouseEvent *event)  
  2. {  
  3.     if (event->button() == Qt::LeftButton) {  
  4.         m_DragPosition = event->globalPos() - this->pos();  
  5.         event->accept();  
  6.     }  
  7. }  
  8.   
  9. void EditDialog::mouseMoveEvent(QMouseEvent *event)  
  10. {  
  11.     if (event->buttons() && Qt::LeftButton) {  
  12.         move(event->globalPos() - m_DragPosition);  
  13.         event->accept();  
  14.     }  
  15. }  

但是這樣就會有一個問題,就是當鼠標在一個實現了mousePressEvent的類上點擊時(比如QPushButton)會被該類優先處理此事件

而不會將事件傳遞到窗體的mousePressEvent中。繼續,當移動鼠標到這個按鈕外時(假設點在了QPushButton上)會觸發窗體的mouseMoveEvent

從而導致計算坐標時發生錯誤,此時你就會看到窗體閃了一下,變動了位置,鼠標也沒有停在前面按下的按鈕之上。

解決辦法也很簡單,就是再多聲明一個bool變量來判斷,並實現mouseReleaseEvent即可

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. void EditDialog::mousePressEvent(QMouseEvent *event)  
  2. {  
  3.     if (event->button() == Qt::LeftButton) {  
  4.         m_Drag = true;  
  5.         m_DragPosition = event->globalPos() - this->pos();  
  6.         event->accept();  
  7.     }  
  8. }  
  9.   
  10. void EditDialog::mouseMoveEvent(QMouseEvent *event)  
  11. {  
  12.     if (m_Drag && (event->buttons() && Qt::LeftButton)) {  
  13.         move(event->globalPos() - m_DragPosition);  
  14.         event->accept();  
  15.     }  
  16. }  
  17.   
  18. void EditDialog::mouseReleaseEvent(QMouseEvent *)  
  19. {  
  20.     m_Drag = false;  
  21. }  


這樣,就完成了無邊框窗體的拖動。可是,這樣做的效率並不高,因為鼠標每次move時都會觸發事件,計算位置,移動窗口,重繪窗口……

當窗體上有QWebView部件時,特別是網頁中有圖片,Flash時,你就會發現用上面的方案去移動窗體時會非常不流暢。

 

如果不考慮跨平台,只針對Windows平台,那么我建議用Windows下的標准方法,模擬標題欄移動消息,既簡單又高效

[cpp]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. void MainWindow::mousePressEvent(QMouseEvent *event)  
  2. {  
  3.     if (ReleaseCapture())  
  4.         SendMessage(HWND(this->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);  
  5.     event->ignore();  
  6. }  

 這樣,在拖動窗體時只會在松開鼠標時才將窗體移動過去,這樣就避免了第一種方法的低效率問題

http://blog.csdn.net/aqtata/article/details/8902889


免責聲明!

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



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