Qt無邊框窗體-模擬模態窗體抖動效果

原文連接:Qt無邊框窗體-模擬模態窗體抖動效果windows

1、概述

用Qt開發windows客戶端界面確實是一大利器,兼顧性能的同時,速度相對來講也不錯。再加上qss的輔助,那麼一個漂亮的界面就不在話下了。less

想要作出漂亮的界面,重寫一個標題欄是必不可少的,那麼咱們確定是須要使用Qt給咱們提供的一個無邊框Qt::FramelessWindowHint窗體屬性。可是設置了這個屬性之後,隨之而來的就是一系列的問題,好比說標題欄拖拽須要咱們本身搞;窗口放大縮小須要本身實現;最要命的是一些模態窗體原生的抖動效果沒有了。函數

既然出現問題,那麼咱們就得想辦法解決。性能

窗口放大縮小和拖拽在Qt的早期版本是提供了一個類文件支持的,做者本人也對這個文件進行了二次開發,能夠提供更爲豐富的功能。因爲拖拽和縮放跟本篇文章關係不大,所以這裏不作說明,感興趣的同窗能夠到Qt無邊框窗體-最大化時支持拖拽還原這裏查看this

本篇文章咱們就來講一說當模態窗體彈出來時,若是點擊了非模態窗體之外的應用程序界面,怎麼實現一個閃動的效果。搜索引擎

閃動只是一個對外的信息交互,若是你們想要一些其餘交互效果,能夠自行實現。spa

2、效果展現

如效果圖所示,作了一個簡單的效果.net

  1. 點擊主應用程序時,彈出的模態窗體邊框顏色發生了變更,實現了一個抖動的效果。
  2. 點擊桌面時,模態窗體也有一個失去焦點時的狀態變化。

3、功能實現

實現窗口抖動效果,首先須要瞭解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,若是不知道函數的具體名字或者功能名字,最好進行模糊搜索。

不搜不知道,一搜嚇一跳,原來還有很多接收原生消息的函數,以下不所示。

上圖中總共有以下幾個函數

  1. filterNativeEvent:安裝事件過濾器的回調函數
  2. installNativeEventFilter:安裝事件過濾器,回調函數是第4個函數
  3. nativeEvent:窗口原生事件回調
  4. nativeEventFilter:事件過濾器回調函數,使用方法2安裝

看到這裏你們卡能會有些迷茫,好像都差很少呀!其實否則,仍是有卻別的,感興趣的同窗能夠看看我以前寫的幾篇相關文章,都使用了接收全局windows消息來實現先關功能,具體一點來講就是使用上述的方法2+方法4來完成。

  1. Qt之自定義QLineEdit右鍵菜單
  2. qt捕獲全局windows消息
  3. 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);
}

重點強調

這裏還須要說一點,有些同窗按照文檔操做了,調試時代碼也走到相關位置了,可是發現沒有效果,而後就開始懷疑人生了。

這裏博主重點說幾個可能出現錯誤的地方

  1. 咱們的模態窗體必定要指定模態的父窗體是誰
  2. 窗體必定要設置上Qt::Dialog屬性

第二點是很是關鍵的,不少同窗都是沒有設置這個屬性,致使失去了效果。

4、相關文章

  1. Qt自定義的無邊框Dialog 在點擊其餘窗口時處理閃爍效果
  2. Qt無邊框窗體-最大化時支持拖拽還原
  3. Qt之自定義QLineEdit右鍵菜單
  4. qt捕獲全局windows消息
  5. Qt之股票組件-股票檢索--支持搜索結果預覽、鼠標、鍵盤操做

值得一看的優秀文章:

  1. 財聯社-產品展現
  2. 廣聯達-產品展現
  3. Qt定製控件列表
  4. 牛逼哄哄的Qt庫





若是您以爲文章不錯,不妨給個 打賞,寫做不易,感謝各位的支持。您的支持是我最大的動力,謝謝!!!














很重要--轉載聲明

  1. 本站文章無特別說明,皆爲原創,版權全部,轉載時請用連接的方式,給出原文出處。同時寫上原做者:朝十晚八 or Twowords

  2. 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時經過修改本文達到有利於轉載者的目的。

相關文章
相關標籤/搜索