- 1. 實作視窗徹底透明
- 2.實作背景透明控件不透明一
- 3.實作背景透明控件不透明正式方案
- 4.動圖顯示異常分析
1. 實作視窗徹底透明
實作這種效果的方案網上介紹很多,基本原理都一樣,在這裡還是重複記錄一次。
效果圖:
這種透明效果整個視窗的所有内容全部透明,可以看到圖中紅色箭頭所指,從這個視窗可以看到底層的source tree的按鈕。
代碼實作:
(1)設定WS_EX_LAYERED屬性
::ShowWindow(main_window_, nCmdShow);
::UpdateWindow(main_window_);
LONG ret = ::GetWindowLong(main_window_, GWL_EXSTYLE);
ret = ret | WS_EX_LAYERED;
::SetWindowLong(main_window_, GWL_EXSTYLE, ret);
前面兩行代碼是建立視窗後重新整理用的,之後三行代碼是設定視窗的分層屬性WS_EX_LAYERED,隻有設定了這個屬性,才能實作上圖給出的透明效果,這幾行代碼的相對位置不可以更改,我試着把後三行代碼放到視窗重新整理操作之前,代碼無法正常運作。
(2)在視窗過程函數中響應WM_PAINT時加上
::SetLayeredWindowAttributes(main_window_, 0, 255, LWA_ALPHA);
2.實作背景透明控件不透明一
這種方案其實是實作毛玻璃效果用的,隻是偶然發現勉強能夠實作透明效果,效果差強人意,如果發現在某些環境下不起作用,那也算正常現象。
效果:
可以看到左側透出來的代碼,有一種朦胧的感覺,這可能就是毛玻璃效果吧。
代碼實作:
(1) 包含頭檔案
(2) 添加編譯連結
(3) 設定視窗的背景顔色
備注:視窗背景顔色設定為某些顔色無法透明,上圖效果是設定為灰色時實作的。
(4) 在視窗初始化時加上如下代碼
MARGINS m = { - };
DwmExtendFrameIntoClientArea(main_window_, &m);
::ShowWindow(main_window_, nCmdShow);
::UpdateWindow(main_window_);
第一個代碼塊是實作這種效果的關鍵所在,這兩個代碼塊的相對位置可以調整。
3.實作背景透明控件不透明正式方案
效果:
可以看到,這種背景透明的效果還是比較正常的,看到底層的文字很清晰。
代碼實作:
(1) 設定視窗背景顔色
這裡設定了一種我需要顯示的圖檔裡沒有的顔色作為背景顔色,後面将看到實作透明的原理是将指定的顔色設為透明。
(2) 初始化設定視窗的WS_EX_LAYERED屬性
這裡和第一種方案的設定方式是一樣,還是複制一次:
::ShowWindow(main_window_, nCmdShow);
::UpdateWindow(main_window_);
LONG ret = ::GetWindowLong(main_window_, GWL_EXSTYLE);
ret = ret | WS_EX_LAYERED;
::SetWindowLong(main_window_, GWL_EXSTYLE, ret);
(3)在視窗的過程函數中響應WM_PAINT消息,增加如下代碼
::SetLayeredWindowAttributes(main_window_, RGB(251, 255, 242), 0, LWA_COLORKEY);
注意這裡設定的是LWA_COLORKEY,而不是LWA_ALPHA,前面一種是将某種顔色(第二個參數)設定為透明,後一種是将視窗所有顔色均設定為指定透明度(第三個參數),具體差別網上搜尋一下就出來了。
4.動圖顯示異常分析
效果
圖中的gif圖檔顯示異常,很明顯錯位了。第一幀顯示位置,與後面的幀的顯示位置相差極大。
原因分析:
視窗去除邊框和标題欄是通過處理WM_SIZE消息實作的,第一幀顯示時很明顯是在有邊框和标題欄的情況下的,而後面的幀在顯示時邊框和标題欄已經消失了,是以後面的幀顯示位置就往左上移動了。也就是說去除視窗邊框和标題欄的時機過晚,需要在開始顯示gif圖檔之前通知視窗重新整理。
case WM_SIZE:
{
LONG_PTR Style = ::GetWindowLongPtr(hWnd, GWL_STYLE);
Style = Style & ~WS_CAPTION &~WS_SYSMENU &~WS_SIZEBOX;
::SetWindowLongPtr(hWnd, GWL_STYLE, Style);
return ;
}
解決辦法:
::InvalidateRect(hWnd, NULL, TRUE);
::UpdateWindow(hWnd);
在開始顯示第一幀圖檔之前,強制重新整理視窗,之後即可恢複正常。