C/C++实现透明窗口程序

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

一、透明窗口实现

1. 方式一

通过 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;
}

2. 方式二

使用 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;
}

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绘图总结篇

你可能感兴趣的:(#,C语言,#,C++,c++,c语言,windows)