使用DWM實現Aero Glass效果
從Windows Vista開始,Aero Glass效果被應用在了Home Premium以上的系統中(Home Basic不具有該效果)。這種效果是由DWM(Desktop Window Manager)來控制的。對於一般的程式,預設將在視窗邊框應用這種效果。但如果我們想要更多的控制,比如讓客戶區的一部分也呈現這種效果,那也非常的簡單。不需要我們在程式裡做任何複雜的演算法,我們只需要調API,交給DWM去做就可以了。
DWM相關操作的MSDN說明:Desktop Window Manager (DWM) APIs.
http://msdn.microsoft.com/en-us/library/aa969527(v=VS.85).aspx
Header Dwmapi.h
Library Dwmapi.lib
DLL Dwmapi.dll
一、Composition(視窗合成) and Non-client Rendering(非客戶區渲染)
非客戶區通常包括視窗標題欄和視窗邊框。預設狀態下,非客戶區會被渲染成毛玻璃效果,這也稱為Compostion。有幾個函式可以控制系統和當前視窗的渲染方式。同時也有Windows訊息用於接受渲染模式的改變。
1.檢測系統是否開啟Aero Glass。使用函式DwmIsCompositionEnabled檢測系統當前是否開啟了Aero Glass特效。它接受一個BOOL引數,並將當前狀態儲存到其中。函式原型:HRESULT DwmIsCompositionEnabled(BOOL *pfEnabled);
2.開啟/關閉Aero Glass。使用函式DwmEnableComposition開啟或關閉系統Aero Glass效果,傳入DWM_EC_ENABLECOMPOSITION開啟,傳入DWM_EC_DISABLECOMPOSITION關閉。
3.開啟/關閉當前視窗的非客戶區渲染。函式DwmSetWindowAttribute用於設定視窗屬性,屬性DWMWA_NCRENDERING_POLICY控制當前視窗是否使用非客戶區渲染。DWMNCRP_ENABLED開啟,DWMNCRP_DISABLED關閉。當系統的Aero Glass關閉時,設定無效。與之對應,使用函式DwmGetWindowAttribute可以檢測當前視窗屬性。
4.響應系統Aero Glass的開啟或關閉。當Aero Glass被開啟或關閉時,Windows會傳送訊息WM_DWMCOMPOSITIONCHANGED,使用函式DwmIsCompositionEnabled檢測狀態。
5.響應視窗非客戶區渲染的開啟或關閉。當前視窗的非客戶區渲染開啟或關閉時,Windows會傳送訊息WM_DWMNCRENDERINGCHANGED,wParam指示當前狀態。
二、Transition(視窗動畫) and ColorizationColor(主題顏色)
Transition控制是否以動畫方式顯示視窗的最小化和還原。通過使用函式DwmSetWindowAttribute,設定屬性DWMWA_TRANSITIONS_FORCEDISABLED,開啟或關閉視窗動畫。該設定只對當前視窗有效。
當使用者通過控制皮膚修改主題顏色時,Windows將傳送訊息WM_DWMCOLORIZATIONCOLORCHANGED,程式中通過函式DwmGetColorizationColor取得當前主題顏色,以及是否透明。通過響應顏色的變更,可以讓程式的顏色風格隨主題風格而變化。
三、開啟客戶區域Aero Glass效果
函式DwmEnableBlurBehindWindow開啟客戶區的Aero Glass效果,第一個引數為視窗控制程式碼,第二個引數為一個DWM_BLURBEHIND結構。其中fEnable設定是否開啟客戶區Glass效果。hRgnBlur設定Glass效果的區域,該項設定為NULL將使整個客戶區呈現Glass效果,設定為一個正確的區域後,該區域將呈現Glass效果, 而區域以外為完全透明。要呈現透明效果需要客戶區原始的顏色為黑色,可以在WM_PAINT訊息中繪製客戶區,下面的程式碼使用GDI+,在Aero Glass開啟時將整個視窗繪製為黑色,Aero Glass關閉時繪製為灰色:
GDI+的初始化和關閉仍然是必須的:
下面程式碼將整個客戶區設定為Glass效果:
下面程式碼將客戶區中心一個橢圓的區域設定為Glass效果:
四、視窗邊框向客戶區擴充套件
上面的方式中,非客戶區和客戶區之間仍然有界限。如何增大Glass效果的範圍,並且消除界限呢?那就是使視窗邊框向客戶區擴充套件,利用函式DwmExtendFrameIntoClientArea實現。函式接受一個視窗控制程式碼和一個MARGINS型別的引數。MARGINS指定了在上下左右4個方向上擴充套件的範圍。如果4個值均為-1,則擴充套件到整個客戶區。
五、在視窗上繪製圖形
PNG圖片帶有alpha通道,可以與Aero Glass很好的配合。利用GDI+顯示PNG圖片非常方便,下面的程式碼將一張PNG圖片載入到記憶體中:
在WM_PAINT訊息處理中,將整個客戶區繪製為黑色以後,利用GDI+將圖片繪製到視窗客戶區:
六、文字的繪製
當視窗大範圍的透明之後,視窗上的文字的閱讀成了一個問題。Windows的解決辦法是為文字加上發光效果(Glowing),標題欄的文字使用的就是這種方式。我們在自己的程式中可以使用DrawThemeTextEx函式來繪製發光的文字。該函式的原型定義如下:
hTheme是一個主題控制程式碼,可以使用OpenThemeData獲得,OpenThemeData函式接受一個視窗控制程式碼,和主題類的名稱。iPartId和iStateId分別代表主題類中的Part和State,所有可用的主題類、Part和state在SDK的幫助文件中可以檢視到。pszText是要繪製的文字。iCharCount為文字個數,-1代表繪製全部文字。dwFlags指定文字格式。pRect為文字繪製區域。pOptions中可以設定文字的發光、陰影等效果。HDC是一個裝置上下文控制程式碼,為了實現類似於標題欄中文字的發光效果,這裡不能使用由BeginPaint得到的控制程式碼,而是要使用CreateCompatibleDC建立一個記憶體中的控制程式碼,並且要建立一張點陣圖,通過記憶體控制程式碼將文字繪製到點陣圖上。然後再將點陣圖轉移到視窗上。下面的函式封裝了繪製發光文字的過程:
在繪製了圖形後,加入下面程式碼繪製一段文字:
因為字型發光的緣故,在文字左側留下一個空格看起來會舒服一些。效果如下:
七、縮圖關聯
DWM API中還有一個功能,即縮圖關聯。它允許我們將一個視窗的縮圖顯示到自己視窗的客戶區。縮圖不同於截圖,它是實時更新的。下面的程式碼將在視窗客戶區顯示QQ影音播放器的縮圖:
首先通過視窗標題查詢到源視窗控制程式碼,然後使用DwmRegisterThumbnail註冊縮圖關聯,註冊成功後,通過DwmUpdateThumbnailProperties更新縮圖屬性,其中設定了是否可視、透明度以及目標繪製區域。得到下面的效果:
相關文章
- 使用 CSS 實現透明效果CSS
- win10系統開啟aero效果的方法Win10
- 使用 CSS 實現漸變效果CSS
- 使用BottomSheetBehavior實現美團拖拽效果
- 教你如何使用MvcPager實現分頁效果MVC
- 使用Glide快速實現毛玻璃效果IDE
- 使用 Sass mixin 實現 CSS 的居中效果CSS
- 實現聚焦效果
- RecyclerView使用指南(五)—— 實現吸頂效果View
- 使用純 CSS 實現滾動陰影效果CSS
- 使用CSS background實現炫酷懸停效果CSS
- 使用 CoordinatorLayout 實現複雜聯動效果
- 使用UICollectionView實現首頁的滾動效果UIView
- Unity使用DOTween實現金幣飛入效果Unity
- ArchLinux-dwmLinux
- 【譯】使用CSS Transitions實現圓形懸停效果CSS
- 使用CSS實現逼真的水波紋點選效果CSS
- 使用 jquery 實現 css hover 長期維持效果jQueryCSS
- 如何使用CCMenuItemImage實現CCMenuItemToggle的開關效果UI
- webgl實現故障效果Web
- webgl實現火焰效果Web
- css 實現打分效果CSS
- js實現打字效果JS
- canvas實現波浪效果Canvas
- React實現動畫效果React動畫
- iOS全景效果實現iOS
- Javascript實現動畫效果JavaScript動畫
- 如何實現倒影效果
- 使用rust編寫dwm status-bar應用程式Rust
- 使用Unity著色器實現精靈(Sprite)塗鴉效果Unity
- 使用CSS的clip-path實現圖片剪下效果CSS
- 直播平臺開發,使用swiper實現輪播效果
- 使用純 CSS 實現超酷炫的粘性氣泡效果CSS
- Android中使用RecyclerView + SnapHelper實現類似ViewPager效果AndroidViewpager
- 使用html5實現的繪製直線效果HTML
- 使用ViewPager和TabLayout來實現滑動切換效果ViewpagerTabLayout
- Flutter——實現閃爍效果Flutter
- Axure實現輪播效果