[MFC] WS_EX_LAYERED 实现透明异形窗口(酷狗歌词、360加速球、窗口边缘阴影)

本文介绍如何使用WS_EX_LAYERED属性及UpdateLayeredWindow函数创建透明的异形窗口,并通过GDI+实现特殊视觉效果,如渐变和轮廓。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关键词:WS_EX_LAYERED、 UpdateLayeredWindow 


PC应用不少都有透明的异形窗口  比如以下程序的效果:

酷狗音乐播放器的歌词窗口(窗口除了歌词内容 其他都是透明的)


360桌面加速球

窗口边缘阴影(窗口四周有一圈渐变阴影 这个不是WINDOWS系统的阴影 是自己实现的)



这类窗口的实现 可以采用WS_EX_LAYERED属性(详情请MSDN)。将窗口设置WS_EX_LAYERED和WS_EX_TRANSPARENT属性  并使用函数UpdateLayeredWindow更新界面(注意不是在OnPaint中渲染界面) 即可实现该功能。渲染时如果需要特殊效果 比如歌词的渐变、轮廓、设置透明度  可以使用GDI+来画界面


附带一个高手的demo:

酷狗异形按钮 http://blog.youkuaiyun.com/cometnet/article/details/6561912

### 使用 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` 函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值