Windows 2000+ 引入 WS_EX_LAYERED 擴充樣式與 SetLayeredWindowAttributes API,可輕鬆實現視窗整體透明或色鍵透明。但舊版 VC6 SDK 未包含此 API 宣告,導致編譯錯誤「未定義識別項」。
視作「未公開 API」,透過 LoadLibrary + GetProcAddress 取得函數指標呼叫。
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 0x00000001
#define LWA_ALPHA 0x00000002
BOOL CMyDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// 1. 加入 WS_EX_LAYERED 擴充樣式
LONG exStyle = GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE);
SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
// 2. 動態載入 user32.dll 並取得函數指標
HINSTANCE hUser32 = LoadLibrary(_T("User32.dll"));
if (hUser32)
{
typedef BOOL (WINAPI *PFN_SetLayeredWindowAttributes)(
HWND hwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);
PFN_SetLayeredWindowAttributes pFunc =
(PFN_SetLayeredWindowAttributes)GetProcAddress(hUser32,
"SetLayeredWindowAttributes");
if (pFunc)
{
// 參數說明:
// hwnd: 目標視窗
// crKey: 色鍵顏色 (dwFlags 包含 LWA_COLORKEY 時生效)
// bAlpha: 透明度 0(全透明)~255(不透明) (dwFlags 包含 LWA_ALPHA 時生效)
// dwFlags: LWA_ALPHA | LWA_COLORKEY
//
// 範例:整體 50% 透明 (Alpha=128)
pFunc(GetSafeHwnd(), 0, 128, LWA_ALPHA);
// 範例:指定白色 (RGB(255,255,255)) 為透明色
// pFunc(GetSafeHwnd(), RGB(255,255,255), 0, LWA_COLORKEY);
}
FreeLibrary(hUser32);
}
return TRUE;
}
| dwFlags | crKey | bAlpha | 效果 |
|---|---|---|---|
| LWA_ALPHA | 忽略 | 0~255 | 整體透明度,0=隱形, 255=實體 |
| LWA_COLORKEY | RGB 色值 | 忽略 | 指定顏色像素全透明,其餘不透明 |
| LWA_ALPHA | LWA_COLORKEY | RGB 色值 | 0~255 | 先色鍵透明,再整體 Alpha 混合 |
void CMyDialog::FadeIn(int durationMs = 500)
{
SetTimer(1, 20, NULL); // 20ms 間隔
m_fadeStart = GetTickCount();
m_fadeDuration = durationMs;
m_fadingIn = TRUE;
}
void CMyDialog::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == 1)
{
DWORD elapsed = GetTickCount() - m_fadeStart;
if (elapsed >= m_fadeDuration)
{
KillTimer(1);
BYTE finalAlpha = m_fadingIn ? 255 : 0;
SetLayeredAlpha(finalAlpha);
return;
}
BYTE alpha = (BYTE)(255.0 * elapsed / m_fadeDuration);
if (!m_fadingIn) alpha = 255 - alpha;
SetLayeredAlpha(alpha);
}
CDialog::OnTimer(nIDEvent);
}
void CMyDialog::SetLayeredAlpha(BYTE alpha)
{
HINSTANCE h = LoadLibrary(_T("User32.dll"));
if (h)
{
auto pFunc = (BOOL(WINAPI*)(HWND,COLORREF,BYTE,DWORD))
GetProcAddress(h, "SetLayeredWindowAttributes");
if (pFunc) pFunc(GetSafeHwnd(), 0, alpha, LWA_ALPHA);
FreeLibrary(h);
}
}
UpdateLayeredWindow 繪製自訂介面。#include <windows.h> 使用,無需動態載入。動態載入 SetLayeredWindowAttributes 讓舊版 VC6 專案也能輕鬆擁有現代透明視窗效果,配合計時器即可實現優雅的淡入淡出動畫。