SetLayeredWindowAttributes函數:
hwnd是透明窗體的句柄,
crKey爲顏色值,
bAlpha是透明度,取值範圍是[0,255],
dwFlags是透明方式,能夠取兩個值:
當取值爲LWA_ALPHA時,crKey參數無效,bAlpha參數有效;
當取值爲LWA_COLORKEY時,bAlpha參數有效而窗體中的全部顏色爲crKey的地方將變爲透明。
LWA_ALPHA = 0x2 LWA_COLORKEY=0x1
要使使窗體擁有透明效果,首先要有WS_EX_LAYERED擴展屬性 (舊的sdk沒有定義這個屬性,因此能夠直接指定爲0x80000). WS_EX_LAYERED = 0x80000
Windows 2000操做系統不管是在品質上仍是在用戶界面上都有了很大的改善與提升,用戶對系統的操做變的更加簡單、方便,感受也更加舒
適。若是用戶在使用時留意一下,不難發現其中界面上的一些新特性。例如,Windows 2000提供了對帶陰影阿爾法混合光標的支持、提供對菜單
、提示框淡入淡出效果的支持以及在外殼拖拽具備阿爾法混合效果圖片等透明特效。全部這些特效看似不一樣但實際都是經過對Windows 2000新提
供的一個分層窗口API函數的調用而實現的。 既然是Windows 2000系統提供的API函數,那麼也就意味着在本身的應用程序中一樣可以實現該函
數作作支持的各類特效。
在程序設計時,有時一些微小的改善就足以加強用戶界面的顯示效果。例如,使用一個具備阿爾法混合效果的光標顯然要比一隻普通光標的
感受要好的多,尤爲是在大屏幕顯示器或多顯示器系統下這種光標也更容易找到。更進一步,顯示器的屏幕大小是有限的,若是想同時查看多個
窗口的內容顯然是不太方便的,儘管採起大屏幕顯示器或多顯示器系統能在必定程度上緩解但遠不如將這些應用程序窗體設置爲透明或半透明來
的完全和方便。下圖顯示的兩個應用程序雖然存在覆蓋,但位於前臺的程序窗體顯然沒有影響後臺Word文檔內容的顯示。鑑於分層窗口函數在程
序設計中的實用做用,本文將對其做具體的介紹以充分挖掘其潛力並將其應用到程序設計中去。
分層窗口
在介紹分層窗口函數以前,首先要介紹一下WS_EX_LAYERED擴展窗口風格。該窗口風格也是Windows 2000新增長的,若是使用了該屬性,窗
體將具有複合形狀、動畫、阿爾法混合等方面的視覺特效。
窗口經過被其餘窗口的裁剪而在屏幕上以矩形出現。爲了實現一個圓形窗體,僅僅簡單繪製一個圓形窗體是不夠的,這樣的話系統還會把窗
體按原矩形進行點擊檢測,並且位於該窗體下的窗口仍將被該窗體矩形所裁剪。或許能夠考慮在園形窗體顯示出來前取得位於該窗體矩形下可視
區域的快照,並在稍後窗體顯示完畢後將其繪製到當前窗體。但因爲其餘窗口可以繪製該窗體覆蓋下的區域,而前臺程序沒法獲知這種繪製將於
什麼時候發生而不會及時獲取下面可視區域的新的快照,所以這種解決方法並不能在多進程、多任務環境下很正常的工做。對於這種狀況,在
Windows 95/98和Windows NT 4.0下的正確作法是經過SetWindowRgn()API函數指出須要的窗體形狀,可是這種處理在頻繁更改窗體形狀或是在
屏幕上拖拽時仍有缺陷存在:前臺窗體將要求位於其下的窗體重繪整個區域,這將生過多的消息和計算量。並且使用SetWindowRgn()只能實現
窗體的全透明而沒法實現半透明效果。或許這也正是分層窗口被提出的緣由。
分層窗口真正實現了兩個大相徑庭的概念:分層和重定向。爲了可以去除任何一個層,WS_EX_LAYERED標誌位必需要設置,這能夠在窗體創
建時設置也能夠在建立後經過以GWL_EXSTYLE標誌調用SetWindowLong()來進行設置。接下來,能夠經過UpdateLayeredWindows()函數來更新
分層窗口。在具體使用時,須要在位圖中繪製出可視區域,並將其與關鍵色、阿爾法混合參數等一塊兒提供給UpdateLayeredWindows()函數。需
要注意的是,在使用UpdateLayeredWindows()函數時,應用程序並不須要響應WM_PAINT或其餘繪製消息。
除此以外,還可使用傳統的Win32繪製機制來實現,這須要調用另外一個API函數SetLayeredWindowAttributes()來完成對關鍵色或阿爾法
混合參數值的設定。一旦該函數被調用,系統將開始爲分層窗口重定向全部的繪製並自動應用指定的特效。
窗體半透明特效的實現
前面已經對分層窗口作了較爲詳細的介紹。這裏將對SetLayeredWindowAttributes()函數及其使用方法作具體的介紹,並在此基礎上實現
窗體半透明特效。首先給出SetLayeredWindowAttributes()原形:
BOOL SetLayeredWindowAttributes(
HWND hwnd, // handle to the layered window 透明窗體的句柄
COLORREF crKey, // specifies the color key 顏色值
BYTE bAlpha, // value for the blend function 透明度,取值範圍是[0,255]
DWORD dwFlags // action 透明方式,能夠取兩個值:
當取值爲LWA_ALPHA時,crKey參數無效,bAlpha參數有效;
當取值爲LWA_COLORKEY時,bAlpha參數有效,而窗體中的全部顏色爲crKey的地方將變爲透明。
LWA_ALPHA = 0x2
LWA_COLORKEY=0x1
);
其中dwFlags有LWA_ALPHA(值爲2)和LWA_COLORKEY(值爲1)兩種設置,若是LWA_ALPHA被設置的話,經過bAlpha參數指定窗體的透明度;
若是LWA_COLORKEY標誌被設置的話,則指定關鍵色爲crKey,該顏色所覆蓋的區域將從窗體去除,去除後的區域將再也不進行點擊檢測,其餘顏色
則正常顯示。若是阿爾法混合值設置爲0,其窗口區域一樣不進行點擊檢測。
前面說過,SetLayeredWindowAttributes()函數是Windows 2000新增的一個API函數,它所在的模塊爲USER32.DLL。在用GetModuleHandle
()裝載USER32.DLL模塊並調用GetProcAddress()獲得函數 SetLayeredWindowAttributes()在User32.dll中的指針後就能夠經過
SetLayeredWindowAttributes()函數將窗體設置爲半透明瞭:
// 全局變量
typedef BOOL (WINAPI *lpfn) (HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags);
lpfn g_pSetLayeredWindowAttributes;
……
// 獲取函數 SetLayeredWindowAttributes 在User32.dll中的指針
HMODULE hUser32 = GetModuleHandle(_T("USER32.DLL"));
g_pSetLayeredWindowAttributes = (lpfn)GetProcAddress(hUser32, "SetLayeredWindowAttributes");
if (g_pSetLayeredWindowAttributes == NULL)
::PostQuitMessage(0);
這段代碼一般在程序初始化時運行以及時將USER32.DLL模塊裝載到內存並獲取獲得SetLayeredWindowAttributes()函數指針。在程序退出
前須要經過FreeLibrary()函數釋放先前加載的模塊:
// 卸載模塊
if (m_hUser32 != NULL)
FreeLibrary(m_hUser32);
在將窗體設置爲半透明時,首先要獲取獲得該窗體的窗口句柄,以指明要操做的是哪個窗口。若是是對本應用程序中的某個窗口進行設置
,能夠經過傳遞窗口句柄或是用GetSafeHwnd()來動態獲取。若是要對本程序外的某個程序窗口進行設置,通常的作法是經過對FindWindow(
)函數的調用來獲取指定窗口標題的窗口句柄。在獲得窗口句柄以後並不能直接調用SetLayeredWindowAttributes()進行設置,須要在
GetWindowLong()獲取獲得當前窗口風格設置後在其基礎之上添加WS_EX_LAYERED擴展風格,並經過SetWindowLong()函數將其設置:
// 半透明
HWND hWnd = GetSafeHwnd();
LONG lWindowLong = GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED;
::SetWindowLong(hWnd, GWL_EXSTYLE, lWindowLong);
g_pSetLayeredWindowAttributes(hWnd, 0, (BYTE)m_sldAlpha.GetPos(), 2);
::RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
爲了可以使用該函數,還必須在上述語句以前添加預約義語句:
#define WS_EX_LAYERED 0x00080000
異形窗體特效的實現
使用SetLayeredWindowAttributes()建立異形窗體是很是簡單的,具體過程與半透明窗體的實現極爲相似,所不一樣的只是將標誌設置爲
LWA_COLORKEY並指定須要透明顯示的關鍵色:
// 指定關鍵色
HWND hWnd = GetSafeHwnd();
LONG lWindowLong = GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED;
::SetWindowLong(hWnd, GWL_EXSTYLE, lWindowLong);
g_pSetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 0, 1);
::RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
小結
本文經過對Windows 2000新增API函數SetLayeredWindowAttributes()的使用很是簡單的實現了窗體的半透明設置和異形窗體的建立。除
了SetLayeredWindowAttributes()函數,Windows 2000還提供了其餘許多相似的特效函數好比用於窗體動態滑動顯示的AnimateWindow()。
因爲這些函數是系統提供的API函數,所以不會受編程語言的制約,也就是說,並不僅在VC++下能夠實現上述特效。在C++ Builder、Delphi等其
他開發環境下也是能夠用相似的方法來實現的。本文所述程序代碼在Windows 2000 Professional下由Microsoft Visual C++ 6.0編譯經過編程