天天看點

windows api實作視窗透明整理1. 實作視窗徹底透明2.實作背景透明控件不透明一3.實作背景透明控件不透明正式方案4.動圖顯示異常分析

  • 1. 實作視窗徹底透明
  • 2.實作背景透明控件不透明一
  • 3.實作背景透明控件不透明正式方案
  • 4.動圖顯示異常分析

1. 實作視窗徹底透明

實作這種效果的方案網上介紹很多,基本原理都一樣,在這裡還是重複記錄一次。

效果圖:

windows api實作視窗透明整理1. 實作視窗徹底透明2.實作背景透明控件不透明一3.實作背景透明控件不透明正式方案4.動圖顯示異常分析

這種透明效果整個視窗的所有内容全部透明,可以看到圖中紅色箭頭所指,從這個視窗可以看到底層的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.實作背景透明控件不透明一

這種方案其實是實作毛玻璃效果用的,隻是偶然發現勉強能夠實作透明效果,效果差強人意,如果發現在某些環境下不起作用,那也算正常現象。

效果:

windows api實作視窗透明整理1. 實作視窗徹底透明2.實作背景透明控件不透明一3.實作背景透明控件不透明正式方案4.動圖顯示異常分析

可以看到左側透出來的代碼,有一種朦胧的感覺,這可能就是毛玻璃效果吧。

代碼實作:

(1) 包含頭檔案

(2) 添加編譯連結

(3) 設定視窗的背景顔色

備注:視窗背景顔色設定為某些顔色無法透明,上圖效果是設定為灰色時實作的。

(4) 在視窗初始化時加上如下代碼

MARGINS m = { - };
    DwmExtendFrameIntoClientArea(main_window_, &m);

    ::ShowWindow(main_window_, nCmdShow);
    ::UpdateWindow(main_window_);
           

第一個代碼塊是實作這種效果的關鍵所在,這兩個代碼塊的相對位置可以調整。

3.實作背景透明控件不透明正式方案

效果:

windows api實作視窗透明整理1. 實作視窗徹底透明2.實作背景透明控件不透明一3.實作背景透明控件不透明正式方案4.動圖顯示異常分析

可以看到,這種背景透明的效果還是比較正常的,看到底層的文字很清晰。

代碼實作:

(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.動圖顯示異常分析

效果

windows api實作視窗透明整理1. 實作視窗徹底透明2.實作背景透明控件不透明一3.實作背景透明控件不透明正式方案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);
           

在開始顯示第一幀圖檔之前,強制重新整理視窗,之後即可恢複正常。

繼續閱讀