You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让GDI+窗口仅背景透明而非整体透明?

实现GDI+窗口背景透明(仅背景,图像不透明)

原代码使用SetLayeredWindowAttributes的LWA_ALPHA会让整个窗口(包括绘制的图像)都半透明。要实现仅窗口背景透明、绘制的图像保持不透明,应该采用颜色键(Color Key)透明方案:指定窗口背景为一个唯一的、不会出现在目标图像中的颜色,让系统自动将该颜色区域设为透明。

解决方案步骤

  • 注册窗口类时,将窗口背景色设为一个特定的专属颜色(确保你的图像中没有该颜色)。
  • 创建窗口时必须使用WS_EX_LAYERED扩展样式,这是分层窗口透明的前提。
  • 在窗口创建完成(WM_CREATE消息)时,调用SetLayeredWindowAttributes指定颜色键,仅启用LWA_COLORKEY标志,不使用LWA_ALPHA。
  • 在WM_PAINT中先填充窗口背景为该专属颜色,再绘制图像,这样未被图像覆盖的背景区域会被系统透明化,图像保留原本的不透明度。

修改后的完整代码

#include <windows.h>
#include <gdiplus.h>

LRESULT CALLBACK WindowProcessMessages(HWND hwnd, UINT msg, WPARAM param, LPARAM lparam);
void draw(HDC hdc, RECT clientRect);

// 定义用于透明的专属背景色(确保图像中没有这个颜色,可根据需求替换)
#define TRANSPARENT_BG_COLOR RGB(0, 0, 0)

int WINAPI WinMain(HINSTANCE currentInstance, HINSTANCE previousInstance, PSTR cmdLine, INT cmdCount) {
    // 初始化GDI+
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);

    // 注册窗口类
    const char* CLASS_NAME = "myWin32WindowClass";
    WNDCLASS wc{};
    wc.hInstance = currentInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wc.hbrBackground = CreateSolidBrush(TRANSPARENT_BG_COLOR); // 设置背景刷为透明专属色
    wc.lpfnWndProc = WindowProcessMessages;
    RegisterClass(&wc);

    // 创建分层窗口(可选WS_EX_TOPMOST让窗口置顶)
    HWND hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST,
        CLASS_NAME, "Drawing Image",
        WS_POPUP | WS_VISIBLE,
        CW_USEDEFAULT, CW_USEDEFAULT,
        800, 600,
        nullptr, nullptr, currentInstance,
        nullptr);

    // 消息循环
    MSG msg{};
    while (GetMessage(&msg, nullptr, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    Gdiplus::GdiplusShutdown(gdiplusToken);
    return 0;
}

LRESULT CALLBACK WindowProcessMessages(HWND hwnd, UINT msg, WPARAM param, LPARAM lparam) {
    HDC hdc;
    PAINTSTRUCT ps;
    RECT clientRect;

    switch (msg) {
    case WM_CREATE:
        // 设置分层窗口属性:仅TRANSPARENT_BG_COLOR颜色的区域会被透明化
        SetLayeredWindowAttributes(hwnd, TRANSPARENT_BG_COLOR, 0, LWA_COLORKEY);
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &clientRect);
        
        // 先填充整个客户区为透明专属色,确保空白区域都是该颜色
        FillRect(hdc, &clientRect, (HBRUSH)GetClassLongPtr(hwnd, GCLP_HBRBACKGROUND));
        
        // 绘制图像
        draw(hdc, clientRect);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        return DefWindowProc(hwnd, msg, param, lparam);
    }
}

void draw(HDC hdc, RECT clientRect) {
    Gdiplus::Graphics gf(hdc);
    // 加载图像(确保图像中没有TRANSPARENT_BG_COLOR,否则对应区域也会被透明)
    Gdiplus::Bitmap bmp(L"image.png");
    
    // 绘制图像到窗口(示例在(10,10)位置绘制,可自行调整坐标)
    gf.DrawImage(&bmp, 10, 10);
}

关键改动说明

  1. 专属透明色:TRANSPARENT_BG_COLOR可替换为如RGB(255,0,255)(品红色)这类极少出现在普通图像中的颜色,避免误透明图像内容。
  2. 分层属性设置:仅在WM_CREATE中调用一次SetLayeredWindowAttributes,仅启用LWA_COLORKEY,确保只有背景色区域透明,图像不受影响。
  3. 背景填充:在WM_PAINT中先填充窗口背景,保证所有未被图像覆盖的区域都是专属透明色,最终被系统处理为透明。

内容的提问来源于stack exchange,提问作者joeymalvinni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 15:55:20