目錄
- 一、概述
- 二、效果展示
- 三、功能實作
- 四、相關文章
原文鏈接:Qt無邊框表單-模擬模態表單抖動效果
一、概述
用Qt開發windows客戶端界面確實是一大利器,兼顧性能的同時,速度相對來說也不錯,再加上qss的輔助,那么一個漂亮的界面就不在話下了,
想要做出漂亮的界面,重寫一個標題欄是必不可少的,那么我們肯定是需要使用Qt給我們提供的一個無邊框Qt::FramelessWindowHint表單屬性,但是設定了這個屬性以后,隨之而來的就是一系列的問題,比如說標題欄拖拽需要我們自己搞;視窗放大縮小需要自己實作;最要命的是一些模態表單原生的抖動效果沒有了,
既然出現問題,那么我們就得想辦法解決,
視窗放大縮小和拖拽在Qt的早期版本是提供了一個類檔案支持的,作者本人也對這個檔案進行了二次開發,可以提供更為豐富的功能,由于拖拽和縮放跟本篇文章關系不大,因此這里不做說明,感興趣的同學可以到Qt無邊框表單-最大化時支持拖拽還原這里查看
本篇文章我們就來說一說當模態表單彈出來時,如果點擊了非模態表單以外的應用程式界面,怎么實作一個閃動的效果,
閃動只是一個對外的資訊互動,如果大家想要一些其他互動效果,可以自行實作,
二、效果展示
如效果圖所示,做了一個簡單的效果
- 點擊主應用程式時,彈出的模態表單邊框顏色發生了變動,實作了一個抖動的效果,
- 點擊桌面時,模態表單也有一個失去焦點時的狀態變化,
三、功能實作
實作視窗抖動效果,首先需要了解windows的訊息ID,知道我們要接受哪個windows訊息來完成閃動效果,其次就是Qt怎么接收這樣的原生windows訊息,
windowws訊息
了解windows訊息ID,隨手打開一個搜索引擎,輸入關鍵字Windows訊息ID,然后就能找到大量的文章專門講述windwos訊息,博主這里找了一篇整理windows訊息串列的文章Windows訊息ID說明,文章中的訊息基本上都有中文注釋,因此閱讀起來比較容易,
然后我們就會發現有這樣一個訊息,可能是我們需要的,如下圖所示,
第130條內容,ID為86的WM_NCACTIVATE訊息,訊息觸發的實際是當某個視窗它的非客戶區需要被改變來顯示是激活還是非激活狀態時, 聽著有點兒意思,好像是我們需要的,然后就試唄,
Qt接收原生訊息
既然鎖定了訊息ID,那么接下來就是接收這個訊息,然后實作回應的UI互動效果即可,
那么問題來了,Qt視窗怎么接收windows原生訊息呢!
這個問題當然難不倒我們了,Qt為啥這么火,可不僅僅是因為庫封裝的好,而是它幫助檔案更全,下一步大家應該知道該干什么了吧,打開幫助檔案,然后搜索關鍵字nativeEv,如果不知道函式的具體名字或者功能名字,最好進行模糊搜索,
不搜不知道,一搜嚇一跳,原來還有不少接收原生訊息的函式,如下不所示,
上圖中總共有如下幾個函式
- filterNativeEvent:安裝事件過濾器的回呼函式
- installNativeEventFilter:安裝事件過濾器,回呼函式是第4個函式
- nativeEvent:視窗原生事件回呼
- nativeEventFilter:事件過濾器回呼函式,使用方法2安裝
看到這里大家卡能會有些迷茫,好像都差不多呀!其實不然,還是有卻別的,感興趣的同學可以看看我之前寫的幾篇相關文章,都使用了接收全域windows訊息來實作先關功能,具體一點來說就是使用上述的方法2+方法4來完成,
- Qt之自定義QLineEdit右鍵選單
- qt捕獲全域windows訊息
- Qt之股票組件-股票檢索--支持搜索結果預覽、滑鼠、鍵盤操作
除過方法2和方法4搭配起來使用外,方法1和方法2也可以一起搭配使用,言外之意就是方法2是按照事件過濾器的,方法1和方法4只是事件過濾器的回呼處理介面而已,
為什么這么說呢,大家可以來驗證一下,還是打開幫助檔案,我們輸入關鍵字installNativeEventFilter,回車就會發現,事件過濾器可以被安裝到兩個物件上,一個是我們熟知的QCoreApplication,另外一個看著好像也會牛逼的樣子,好像還是一個全域的抽象事件派發器,恭喜你,答對了,這兩個物件都很牛逼,都能優先處理到Qt的全域事件,
本篇文章我們只是要實作一個模態表單的抖動而已,因此就不需要大材小用了,我們使用QWidget的nativeEvent函式即可,同樣能達到我們的目的,
大方向都定了,那么還等什么
打開vs,新建了一個demo,哐哐哐,就是一頓干,,,,
發現還真好使,竊喜中,,,
下面是實作的核心代碼,由于是demo,所以寫的比較粗糙,大家在寫到專案里時最好能規范下代碼,
bool XXX::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
if ("windows_generic_MSG" == eventType)
{
MSG * pMsg = reinterpret_cast<MSG *>(message);
if (pMsg->message == WM_NCACTIVATE)
{
bool active = (bool)(pMsg->wParam);
if (active)
{
setStyleSheet("border:2 solid blue;background:gray;");
}
else
{
setStyleSheet("border:2 solid red;background:gray;");
}
style()->unpolish(this);
style()->polish(this);
}
}
return QDialog::nativeEvent(eventType, message, result);
}
重點強調
這里還需要說一點,有些同學按照檔案操作了,除錯時代碼也走到相關位置了,但是發現沒有效果,然后就開始懷疑人生了,
這里博主重點說幾個可能出現錯誤的地方
- 我們的模態表單一定要指定模態的父表單是誰
- 表單一定要設定上Qt::Dialog屬性
第二點是非常關鍵的,很多同學都是沒有設定這個屬性,導致失去了效果,
四、相關文章
- Qt自定義的無邊框Dialog 在點擊其他視窗時處理閃爍效果
- Qt無邊框表單-最大化時支持拖拽還原
- Qt之自定義QLineEdit右鍵選單
- qt捕獲全域windows訊息
- Qt之股票組件-股票檢索--支持搜索結果預覽、滑鼠、鍵盤操作
值得一看的優秀文章:
- 財聯社-產品展示
- 廣聯達-產品展示
- Qt定制控制元件串列
- 牛逼哄哄的Qt庫
如果您覺得文章不錯,不妨給個打賞,寫作不易,感謝各位的支持,您的支持是我最大的動力,謝謝!!!
![]() |
![]() |
很重要--轉載宣告
-
本站文章無特別說明,皆為原創,著作權所有,轉載時請用鏈接的方式,給出原文出處,同時寫上原作者:朝十晚八 or Twowords
-
如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時通過修改本文達到有利于轉載者的目的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/103657.html
標籤:C++
下一篇:最好的重試是指數后退和抖動


