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

如何在Windows任意窗口上层显示透明的GPU/CPU状态文本?

实现全局透明悬浮的CPU/GPU使用率显示

原代码的问题分析

  • 直接操作桌面窗口DC无效:GetDesktopWindow()获取的桌面窗口不支持WS_EX_LAYERED扩展风格,调用SetLayeredWindowAttributes无法实现透明效果。
  • DrawText默认填充背景:该函数会用当前DC的背景色填充文本所在矩形,导致出现不透明背景块。
  • 绘制内容会被覆盖:直接在桌面绘制的文本会被其他窗口遮挡,无法实现“所有窗口右上角显示”的需求。

WinAPI 实现方案

正确的做法是创建一个分层透明的顶层悬浮窗口,而非直接操作桌面窗口。以下是完整实现代码:

#include <windows.h>
#include <stdio.h>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

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

    // 注册窗口类
    WNDCLASSEX wc = {0};
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.lpfnWndProc   = WindowProc;
    wc.hInstance     = hInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);

    RegisterClassEx(&wc);

    // 获取屏幕分辨率,定位窗口到右上角
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
    int overlayWidth = 220;
    int overlayHeight = 60;
    int xPos = screenWidth - overlayWidth - 15;
    int yPos = 15;

    // 创建分层、顶层、穿透鼠标的窗口
    HWND hwnd = CreateWindowEx(
        WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TRANSPARENT,
        CLASS_NAME,
        L"",
        WS_POPUP,
        xPos, yPos, overlayWidth, overlayHeight,
        NULL, NULL, hInstance, NULL
    );

    if (!hwnd) return 0;

    // 设置黑色为透明色,仅显示非黑色内容(文本)
    SetLayeredWindowAttributes(hwnd, RGB(0,0,0), 0, LWA_COLORKEY);
    ShowWindow(hwnd, nCmdShow);

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

    return (int)msg.wParam;
}

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

            // 设置文本背景透明,避免填充底色
            SetBkMode(hdc, TRANSPARENT);
            // 设置文本颜色为白色
            SetTextColor(hdc, RGB(255,255,255));

            // 替换为实际获取CPU/GPU数据的逻辑
            const wchar_t text[] = L"CPU: 45% | GPU: 32%";
            RECT rect;
            GetClientRect(hwnd, &rect);
            // 居中绘制文本
            DrawText(hdc, text, -1, &rect, DT_CENTER | DT_VCENTER);

            EndPaint(hwnd, &ps);
            return 0;
        }
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}

关键细节说明

  • WS_EX_TOPMOST:确保窗口始终在所有其他窗口上方。
  • WS_EX_TRANSPARENT:窗口不拦截鼠标事件,底层窗口可正常操作。
  • LWA_COLORKEY模式:指定黑色为透明色,窗口中黑色区域完全透明,仅文本可见。
  • 可添加SetTimer实现定时刷新CPU/GPU数据(比如每秒更新一次)。

SFML 实现方案

如果觉得WinAPI过于繁琐,SFML库可以更简洁地实现需求,代码如下:

#include <SFML/Graphics.hpp>
#include <iostream>

int main()
{
    // 获取屏幕参数,定位窗口到右上角
    sf::VideoMode desktop = sf::VideoMode::getDesktopMode();
    const int overlayW = 220, overlayH = 60;
    int x = desktop.width - overlayW - 15;
    int y = 15;

    // 创建无边框、顶层、透明窗口
    sf::RenderWindow window(
        sf::VideoMode(overlayW, overlayH),
        "",
        sf::Style::None | sf::Style::Topmost
    );
    window.setPosition(sf::Vector2i(x, y));
    window.setFramerateLimit(30);

    // 加载系统Arial字体
    sf::Font font;
    if (!font.loadFromFile("C:/Windows/Fonts/arial.ttf")) {
        std::cerr << "字体加载失败" << std::endl;
        return 1;
    }

    // 配置文本
    sf::Text text;
    text.setFont(font);
    text.setString("CPU: 45% | GPU: 32%");
    text.setCharacterSize(19);
    text.setFillColor(sf::Color::White);
    // 居中文本
    sf::FloatRect textBounds = text.getLocalBounds();
    text.setOrigin(textBounds.width/2, textBounds.height/2);
    text.setPosition(overlayW/2.f, overlayH/2.f);

    // 主循环
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed || 
                (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape))
                window.close();
        }

        // 此处添加CPU/GPU数据更新逻辑,修改text.setString()内容

        window.clear(sf::Color::Transparent);
        window.draw(text);
        window.display();
    }

    return 0;
}

SFML 优势

  • 无需手动处理WinAPI窗口注册、消息循环等底层细节,代码更简洁易读。
  • 内置文本渲染、窗口透明等功能,快速实现需求。
  • 跨平台兼容,若后续需要移植到其他系统也无需大幅修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:14:53