### 使用 WS_EX_LAYERED 样式设置透明或图层窗口
在 Windows API 中,`WS_EX_LAYERED` 是一个扩展窗口样式,允许窗口实现透明效果或使用颜色键值[^1]。通过设置此样式,可以调用 `SetLayeredWindowAttributes` 函数来指定窗口的透明级别或颜色键。
#### 设置窗口为 Layered 属性
要将窗口设置为 Layered 属性,需要使用以下代码:
```c
SetWindowLongPtr(hWnd, GWL_EXSTYLE, GetWindowLongPtr(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
```
这段代码通过 `SetWindowLongPtr` 函数修改窗口的扩展样式,将 `WS_EX_LAYERED` 添加到现有样式中。
#### 调用 SetLayeredWindowAttributes 函数
设置窗口为 Layered 属性后,可以通过 `SetLayeredWindowAttributes` 函数进一步配置透明效果。以下是函数原型和参数说明:
```c
BOOL SetLayeredWindowAttributes(
HWND hwnd, // 窗口句柄
COLORREF crKey, // 颜色键值
BYTE bAlpha, // 透明级别
DWORD dwFlags // 透明类型标志
);
```
- `crKey`: 指定颜色键值,所有与该颜色匹配的像素将变为透明。
- `bAlpha`: 指定窗口的全局透明度,范围从 0(完全透明)到 255(完全不透明)。
- `dwFlags`: 指定透明类型的标志,可以是 `LWA_COLORKEY`、`LWA_ALPHA` 或它们的组合。
例如,以下代码将窗口的透明度设置为 50%:
```c
SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 128, LWA_ALPHA);
```
这里,`RGB(0, 0, 0)` 表示颜色键值未被使用,`128` 表示透明度为 50%,`LWA_ALPHA` 表示仅应用透明度[^1]。
#### 使用 UpdateLayeredWindow 函数
对于更复杂的场景,可以使用 `UpdateLayeredWindow` 函数更新分层窗口的内容和属性。以下是函数原型和参数说明:
```c
BOOL UpdateLayeredWindow(
HWND hWnd, // 窗口句柄
HDC hdcDst, // 目标设备上下文
POINT *pptDst, // 窗口相对于屏幕的位置
SIZE *psize, // 显示窗口大小
HDC hdcSrc, // 源设备上下文
POINT *pptSrc, // 窗口绘图表面在设备上下文中的位置
COLORREF crKey, // 颜色键值
BLENDFUNCTION *pblend, // 透明混合参数
DWORD dwFlags // 更新标志
);
```
`UpdateLayeredWindow` 提供了更大的灵活性,允许开发者手动控制窗口的绘制过程[^3]。
#### 示例代码:创建透明窗口
以下是一个完整的示例代码,展示如何使用 `WS_EX_LAYERED` 创建一个透明窗口:
```c
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
const char CLASS_NAME[] = "TransparentWindowClass";
WNDCLASS wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(
WS_EX_LAYERED,
CLASS_NAME,
"Transparent Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 128, LWA_ALPHA);
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
```
#### 注意事项
- 在使用 `WS_EX_LAYERED` 样式时,必须确保窗口已正确注册并创建。
- 如果需要动态调整透明度或颜色键值,可以在消息循环中重新调用 `SetLayeredWindowAttributes` 函数。