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

如何在C++透明窗口中为文本设置黑色背景

问题分析与解决方案

你的代码出现绿色文字+白色背景的原因是窗口扩展样式和分层窗口透明设置冲突:

  • 你给窗口加了WS_EX_TRANSPARENT样式,这个样式会让窗口忽略背景绘制并允许鼠标穿透;同时你用SetLayeredWindowAttributes把黑色设为透明色,导致双缓冲里画的黑色背景被系统完全透明化,显示出来的是窗口底层的白色内容(可能是桌面或其他窗口)。
  • 另外,注册窗口类时未设置hbrBackground,默认会使用白色背景刷,进一步加剧了问题。

修改步骤

  1. 调整窗口扩展样式:移除WS_EX_TRANSPARENT,该样式与你需要的不透明黑色背景需求冲突;若需窗口置顶,保留WS_EX_TOPMOST即可。
  2. 移除黑色透明设置:删除SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY);,你不需要将黑色转为透明。
  3. 设置窗口类背景刷:注册窗口类时给wc.hbrBackground赋值为黑色刷,确保窗口默认背景为黑色,避免白色残留。

修改后的完整代码

#include <windows.h>
#include <string>

int frameCounter = 0; // 全局帧计数器

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        // 获取客户区尺寸
        RECT rect;
        GetClientRect(hwnd, &rect);
        int width = rect.right - rect.left;
        int height = rect.bottom - rect.top;

        // 创建双缓冲DC和位图
        HDC hdcBuffer = CreateCompatibleDC(hdc);
        HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
        HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcBuffer, hBitmap);

        // 设置文本颜色为绿色
        SetTextColor(hdcBuffer, RGB(0, 255, 0));
        // 绘制黑色背景
        HBRUSH hBackgroundBrush = CreateSolidBrush(RGB(0, 0, 0));
        FillRect(hdcBuffer, &rect, hBackgroundBrush);
        DeleteObject(hBackgroundBrush);

        // 绘制帧计数文本
        wchar_t frameText[32];
        swprintf_s(frameText, L"Frame: %d", frameCounter);
        DrawText(hdcBuffer, frameText, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

        // 将缓冲内容复制到窗口DC
        BitBlt(hdc, 0, 0, width, height, hdcBuffer, 0, 0, SRCCOPY);

        // 清理资源
        SelectObject(hdcBuffer, hBitmapOld);
        DeleteObject(hBitmap);
        DeleteDC(hdcBuffer);

        EndPaint(hwnd, &ps);
        return 0;
    }

    case WM_ERASEBKGND:
        return 1; // 阻止系统默认擦除背景

    case WM_CLOSE:
        DestroyWindow(hwnd);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    const wchar_t CLASS_NAME[] = L"TransparentWindowClass";

    WNDCLASS wc = {};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0)); // 设置窗口类默认背景为黑色

    RegisterClass(&wc);

    // 创建窗口:移除WS_EX_TRANSPARENT,保留WS_EX_TOPMOST(如果需要置顶)
    HWND hwnd = CreateWindowEx(
        WS_EX_TOPMOST,
        CLASS_NAME,
        NULL,
        WS_POPUP,
        0, 0, 200, 200,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if (hwnd == NULL)
        return 0;

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    MSG msg;
    while (true)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
                return msg.wParam;

            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        ++frameCounter;
        RedrawWindow(hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
    }

    return 0;
}

额外说明

如果需要窗口整体半透明效果,可以保留WS_EX_LAYERED,并改用LWA_ALPHA设置透明度,示例:

SetLayeredWindowAttributes(hwnd, 0, 200, LWA_ALPHA); // 200为透明度值(范围0-255)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:06:56