本文介绍几种在Windows环境下通过C/C++使用WIN32API实现透明窗口的方法。如有问题,请私信或者在评论区评论。
通过 SetLayeredWindowAttributes
函数实现,需要添加以下代码:
// 设置窗口透明度
SetLayeredWindowAttributes(
hWnd, // 窗口句柄
0, // 需要透明化的颜色值,0表示不使用颜色值
128, // 透明度,取值为0-255
LWA_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-255
LWA_ALPHA //
);
// 显示窗口
ShowWindow(hWnd, nCmdShow);
// 消息循环
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
使用 SetWindowLong()
和 SetLayeredWindowAttributes()
函数实现透明窗口。
完整示例代码如下:
#include
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE: // 多用于窗口的初始化
// 设置窗口扩展样式为WS_EX_LAYERED
SetWindowLong(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;
}
使用 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;
}
窗口透明,绘图不透明的实现:
#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;
}
#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绘图总结篇