本文介绍几种在Windows环境下通过C/C++使用WIN32API实现透明窗口的方法。如有问题,请私信或者在评论区评论。

一、透明窗口实现

1. 方式一

通过 SetLayeredWindowAttributes 函数实现,需要添加以下代码:

// 设置窗口透明度SetLayeredWindowAttributes(hWnd, // 窗口句柄0,// 需要透明化的颜色值,0表示不使用颜色值128,// 透明度,取值为0-255LWA_ALPHA // 指定透明度效果);

以下为完整示例代码:

#include LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){switch (message){case WM_DESTROY:{PostQuitMessage(0);break;}default:return DefWindowProc(hWnd, message, wParam, lParam);}}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow){// 定义窗口类const wchar_t CLASS_NAME[] = L"MyWindowClass";WNDCLASSEX wc = { 0 };wc.cbSize = sizeof(wc); wc.lpfnWndProc = WindowProc;wc.lpszClassName = CLASS_NAME;wc.style = CS_HREDRAW | CS_VREDRAW;wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);wc.cbWndExtra = sizeof(LONG_PTR);wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);wc.hInstance = hInstance;wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);wc.cbClsExtra = 0;wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);// 注册窗口RegisterClassEx(&wc);// 创建窗口HWND hWnd = CreateWindowEx(WS_EX_LAYERED,CLASS_NAME, "透明窗口", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,NULL, NULL, hInstance,NULL);// 创建失败if (hWnd == NULL){return -1;}// 设置窗口透明度SetLayeredWindowAttributes(hWnd, // 窗口句柄0,// 颜色键128,// 透明度,取值为0-255LWA_ALPHA // );// 显示窗口ShowWindow(hWnd, nCmdShow);// 消息循环MSG msg = { 0 };while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}

2. 方式二

使用 SetWindowLong()SetLayeredWindowAttributes() 函数实现透明窗口。

完整示例代码如下:

#include LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){switch (msg){case WM_CREATE:// 多用于窗口的初始化// 设置窗口扩展样式为WS_EX_LAYEREDSetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);// 设置窗口透明度为50%(0-255,255为完全不透明)SetLayeredWindowAttributes(hWnd, 0, 128, LWA_ALPHA);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, msg, wParam, lParam);}return 0;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){const char *CLASS_NAME = "MyClass";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);MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}

3. 方式三

使用 UpdateLayeredWindow() 函数实现透明窗口,完整实例代码如下:

#include LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){switch (msg){case WM_CREATE:{// 创建窗口的设备上下文HDC hdc = GetDC(hWnd);// 创建透明位图int width = 400;int height = 300;HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);// 创建与位图相关联的设备上下文HDC hdcMem = CreateCompatibleDC(hdc);SelectObject(hdcMem, hBitmap);// 绘制透明背景BLENDFUNCTION blend = { 0 };blend.BlendOp = AC_SRC_OVER;blend.BlendFlags = 0;blend.AlphaFormat = AC_SRC_ALPHA;blend.SourceConstantAlpha = 128; // 透明度(0-255,255为完全不透明)RECT rcClient;GetClientRect(hWnd, &rcClient);FillRect(hdcMem, &rcClient, (HBRUSH)(COLOR_WINDOW + 1));// 使用UpdateLayeredWindow函数设置窗口为透明窗口POINT ptDst = { 0, 0 };SIZE sizeWnd = { width, height };POINT ptSrc = { 0, 0 };UpdateLayeredWindow(hWnd, hdc, NULL, &sizeWnd, hdcMem, &ptSrc, 0, &blend, ULW_ALPHA);// 释放资源DeleteDC(hdcMem);DeleteObject(hBitmap);ReleaseDC(hWnd, hdc);}break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, msg, wParam, lParam);}return 0;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){const char* CLASS_NAME = "MyClass";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);MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}

二、半透明窗口实现

1. 窗口透明绘图不透明

窗口透明,绘图不透明的实现:

#include // 窗口类名称#define CLASS_NAME "MyWindowClass"// 窗口标题#define WINDOW_TITLE "Transparent Window"// 窗口大小#define WINDOW_WIDTH 640#define WINDOW_HEIGHT 480// GDI 绘图颜色#define DRAW_COLOR RGB(0, 0, 255)// 窗口透明色#define TRANSPARENT_COLOR RGB(0, 0, 0)// 窗口过程函数LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch (msg){case WM_PAINT:{PAINTSTRUCT ps;HDC hdc = BeginPaint(hwnd, &ps);// 使用透明色创建一个画刷HBRUSH hBrush = CreateSolidBrush(TRANSPARENT_COLOR);// 用画刷填充背景RECT rect;GetClientRect(hwnd, &rect);FillRect(hdc, &rect, hBrush);// 绘制一个不透明的矩形HBRUSH hDrawBrush = CreateSolidBrush(DRAW_COLOR);RECT drawRect = { 50, 50, 200, 200 };FillRect(hdc, &drawRect, hDrawBrush);// 释放资源DeleteObject(hBrush);DeleteObject(hDrawBrush);EndPaint(hwnd, &ps);break;}case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){// 注册窗口类WNDCLASS wc = { 0 };wc.lpfnWndProc = WndProc;wc.hInstance = hInstance;wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);wc.lpszClassName = CLASS_NAME;RegisterClass(&wc);// 创建窗口HWND hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,CLASS_NAME, WINDOW_TITLE,WS_POPUP | WS_VISIBLE,0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,NULL, NULL, hInstance, NULL);// 设置透明色SetLayeredWindowAttributes(hwnd, TRANSPARENT_COLOR, 0, LWA_COLORKEY);// 消息循环MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return (int)msg.wParam;}

2. 窗口半透明绘图不透明

#include // 窗口类名称#define CLASS_NAME L"MyWindowClass"// 窗口标题#define WINDOW_TITLE L"Transparent Window"// 窗口大小#define WINDOW_WIDTH 640#define WINDOW_HEIGHT 480// 窗口透明度#define WINDOW_ALPHA 200// 窗口过程函数LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){switch (msg){case WM_DESTROY:{PostQuitMessage(0);break;}case WM_LBUTTONDBLCLK:{// 鼠标双击时关闭窗口DestroyWindow(hwnd);break;}case WM_LBUTTONDOWN:{// 鼠标左键按下时开始拖动窗口SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);break;}case WM_PAINT:{PAINTSTRUCT ps;HDC hdc = BeginPaint(hwnd, &ps);// 绘制一个不透明的矩形HBRUSH hDrawBrush = CreateSolidBrush(RGB(0, 0, 255));RECT drawRect = { 50, 50, 200, 200 };FillRect(hdc, &drawRect, hDrawBrush);// 释放资源DeleteObject(hDrawBrush);EndPaint(hwnd, &ps);break;}default:return DefWindowProc(hwnd, msg, wParam, lParam);}return 0;}int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){// 注册窗口类WNDCLASS wc = { 0 };wc.lpfnWndProc = WndProc;wc.hInstance = hInstance;wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);wc.lpszClassName = CLASS_NAME;wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;RegisterClass(&wc);// 创建窗口HWND hwnd = CreateWindowEx(WS_EX_LAYERED,CLASS_NAME, WINDOW_TITLE,WS_POPUP | WS_VISIBLE | WS_SYSMENU,0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,NULL, NULL, hInstance, NULL);// 设置窗口透明度SetLayeredWindowAttributes(hwnd, 0, WINDOW_ALPHA, LWA_ALPHA);// 消息循环MSG msg;while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}return 0;}

参考资料:
各种常用的 Win32Api 汇总
Win32窗口和Qt窗口部分透明实现
Win32 使用 SetLayeredWindowAttributes 制作透明窗体
使Win32窗口透明的几种方法
windows api实现窗口透明整理
win32去除窗体边框标题栏非客户区,保留阴影
[Win32SDK基本] 窗口详解(超详细)
(详解入门)Windows(Win32) 应用程序的 简单窗口创建以及关键函数详细解释( 一 )
Win32绘图总结篇