Windows 2000 引入分層視窗,透過 SetLayeredWindowAttributes() 可輕鬆實現視窗整體透明、淡入淡出、色鍵透明等效果。但舊版 SDK(VC6 預設)缺少此 API 宣告。本文展示如何以動態載入 User32.dll 取得函數指標的方式繞過 SDK 限制,在 VC6 環境下實現視窗透明效果。
BOOL SetLayeredWindowAttributes(
HWND hwnd, // 分層視窗控制代碼
COLORREF crKey, // 色鍵(LWA_COLORKEY 時使用)
BYTE bAlpha, // Alpha 值 0-255(LWA_ALPHA 時使用)
DWORD dwFlags // LWA_ALPHA(0x2) | LWA_COLORKEY(0x1)
);
WS_EX_LAYERED = 0x80000; // 擴充視窗風格
需求:Windows 2000/XP/2003/Vista/7/8/10/11 支援;Windows 95/98/Me 不支援。
// 在 OnInitDialog() 或 OnCreate() 中
// 1. 加入 WS_EX_LAYERED 擴充風格
SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE,
GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE) ^ WS_EX_LAYERED);
// 2. 動態載入 User32.dll 並取得函數指標
HINSTANCE hInst = LoadLibrary(_T("User32.DLL"));
if (hInst) {
typedef BOOL (WINAPI *PFN_SETLAYEREDWINDOWATTRS)(HWND, COLORREF, BYTE, DWORD);
PFN_SETLAYEREDWINDOWATTRS pfn = (PFN_SETLAYEREDWINDOWATTRS)
GetProcAddress(hInst, "SetLayeredWindowAttributes");
if (pfn) {
// 設定 50% 透明度 (Alpha = 128)
pfn(GetSafeHwnd(), 0, 128, LWA_ALPHA);
}
FreeLibrary(hInst);
}
| dwFlags | bAlpha / crKey | 效果 |
|---|---|---|
| LWA_ALPHA (0x2) | bAlpha = 0-255 | 整體透明度:0 完全透明,255 不透明 |
| LWA_COLORKEY (0x1) | crKey = RGB 值 | 指定顏色變透明(如綠幕抠圖) |
| LWA_ALPHA | LWA_COLORKEY | 兩者皆用 | 混合效果 |
注意:
bAlpha勿設太小(如 < 50),視窗幾乎不可見將難以操作關閉。
// 淡入:0 → 255
for (BYTE alpha = 0; alpha <= 255; alpha += 10) {
pfn(hWnd, 0, alpha, LWA_ALPHA);
Sleep(10);
}
// 淡出:255 → 0
for (BYTE alpha = 255; alpha >= 0; alpha -= 10) {
pfn(hWnd, 0, alpha, LWA_ALPHA);
Sleep(10);
}
SetLayeredWindowAttributes 宣告,可直接呼叫Window.Opacity / UIElement.Opacity 更簡單UpdateLayeredWindow() 配合 32 位元 DIBCS_OWNDC,或使用 UpdateLayeredWindow
動態載入 SetLayeredWindowAttributes 是在舊版開發環境(VC6 + 老舊 SDK)實現視窗透明的經典技巧。雖現代 SDK 已內建此 API,但動態載入技術對於相容舊系統、插件式架構、運行時功能檢測仍具參考價值。配合 WS_EX_LAYERED 即可用幾行代碼賦予應用程式現代化的視覺效果。