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

运行ImGui+DirectX11 Overlay的.exe时无法渲染显示红点

问题描述

我正在实现一个基于ImGui和DirectX11的Overlay程序,将测试用红点替换为实际GUI前,运行编译生成的.exe文件后界面完全无显示。已确认依赖库及头文件配置正确,编写的Visual Studio C++代码如下:

#include <Windows.h>

#include <dwmapi.h>
#include <d3d11.h>
#include <imgui.h>
#include <imgui_impl_dx11.h>
#include <imgui_impl_win32.h>

extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

LRESULT CALLBACK window_procedure(HWND window, UINT message, WPARAM w_param, LPARAM l_param) {
    if (ImGui_ImplWin32_WndProcHandler(window, message, w_param, l_param)) {
        return 0L;
    }

    if (message == WM_DESTROY) {
        PostQuitMessage(0);
        return 0L;
    }

    return DefWindowProc(window, message, w_param, l_param);

}

INT APIENTRY WinMain(HINSTANCE instance, HINSTANCE, PSTR, INT cmd_show) {
    WNDCLASSEXW wc{};
    wc.cbSize = sizeof(WNDCLASSEXW);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = window_procedure;
    wc.hInstance = instance;
    wc.lpszClassName = L"External Overlay Class";

    RegisterClassExW(&wc);

    const HWND window = CreateWindowExW(
        WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED,
        wc.lpszClassName,
        L"Overlay",
        NULL,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        1920,
        1080,
        nullptr,
        nullptr,
        wc.hInstance,
        nullptr
    );

    SetLayeredWindowAttributes(window, RGB(255, 0, 0), BYTE(255), LWA_ALPHA);
    
    {
        RECT client_area{};
        GetClientRect(window, &client_area);

        RECT window_area{};
        GetWindowRect(window, &window_area);

        POINT diff{};
        ClientToScreen(window, &diff);

        const MARGINS margins{
            window_area.left + (diff.x - window_area.left),
            window_area.top + (diff.y - window_area.top),
            client_area.right,
            client_area.bottom
        };

        DwmExtendFrameIntoClientArea(window, &margins);
    }

    DXGI_SWAP_CHAIN_DESC sd{};
    sd.BufferDesc.RefreshRate.Numerator = 60U;
    sd.BufferDesc.RefreshRate.Denominator = 1U;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.SampleDesc.Count = 1U;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.BufferCount = 2U;
    sd.OutputWindow = window;
    sd.Windowed = TRUE;
    sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

    constexpr D3D_FEATURE_LEVEL levels[2]{
        D3D_FEATURE_LEVEL_11_1,
        D3D_FEATURE_LEVEL_10_0
    };

    ID3D11Device* device{ nullptr };
    ID3D11DeviceContext* device_context{ nullptr };
    IDXGISwapChain* swap_chain{ nullptr };
    ID3D11RenderTargetView* render_target_view{ nullptr };
    D3D_FEATURE_LEVEL level{};

    D3D11CreateDeviceAndSwapChain(
        nullptr,
        D3D_DRIVER_TYPE_HARDWARE,
        nullptr,
        0U,
        levels,
        2U,
        D3D11_SDK_VERSION,
        &sd,
        &swap_chain,
        &device,
        &level,
        &device_context
    );

    ID3D11Texture2D* back_buffer{ nullptr };
    swap_chain->GetBuffer(0U, IID_PPV_ARGS(&back_buffer));

    if (back_buffer) {
        device->CreateRenderTargetView(back_buffer, nullptr, &render_target_view);
        back_buffer->Release();
    }
    else {
        return 1;
    }

    ShowWindow(window, cmd_show);
    UpdateWindow(window);

    ImGui::CreateContext();
    ImGui::StyleColorsDark();

    ImGui_ImplWin32_Init(window);
    ImGui_ImplDX11_Init(device, device_context);

    bool running = true;

    while (running) {
        MSG msg;
        while (PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);

            if (msg.message = WM_QUIT) {
                running = false;
            }
        }

        if (!running) {
            break;
        }

        ImGui_ImplDX11_NewFrame();
        ImGui_ImplWin32_NewFrame();

        ImGui::NewFrame();

        ImGui::GetBackgroundDrawList()->AddCircleFilled({500, 500}, 20.f, ImColor (1.f, 0.f, 0.f, 0.5f));

        ImGui::Render();

        constexpr float color[4]{0.f, 0.f, 0.f, 0.f};
        device_context->OMSetRenderTargets(1U, &render_target_view, nullptr);
        device_context->ClearRenderTargetView(render_target_view, color);

        ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

        swap_chain->Present(0U, 0U);
    }

    ImGui_ImplDX11_Shutdown();
    ImGui_ImplWin32_Shutdown();

    ImGui::DestroyContext();

    if (swap_chain) {
        swap_chain->Release();
    }
    if (device_context) {
        device_context->Release();
    }
    if (device) {
        device->Release();
    }

    if (render_target_view) {
        render_target_view->Release();
    }

    DestroyWindow(window);
    UnregisterClassW(wc.lpszClassName, wc.hInstance);

    return 0;
}
问题排查与修复方案
  • 消息循环赋值错误:消息循环中if (msg.message = WM_QUIT)是赋值操作而非比较,会导致程序异常退出或无法正常运行。修改为:
    if (msg.message == WM_QUIT) {
        running = false;
    }
    
  • 分层窗口属性配置冲突:当前SetLayeredWindowAttributes参数逻辑矛盾,窗口设为不透明但渲染目标被清除为全透明,导致显示异常。调整为:
    SetLayeredWindowAttributes(window, 0, 255, LWA_ALPHA);
    
    若需颜色键透明,可改为:
    SetLayeredWindowAttributes(window, RGB(0,0,0), 0, LWA_COLORKEY);
    
    同时保持渲染目标清除为黑色,黑色区域会透明,红点正常显示。
  • Dwm扩展框架参数错误:当前计算的margins会导致渲染区域被框架遮挡,简化为:
    const MARGINS margins = { -1 };
    DwmExtendFrameIntoClientArea(window, &margins);
    
    确保客户端区域覆盖整个窗口。
  • 窗口样式缺失:CreateWindowExW中窗口样式设为NULL,添加WS_POPUP样式避免标题栏等元素干扰:
    const HWND window = CreateWindowExW(
        WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED,
        wc.lpszClassName,
        L"Overlay",
        WS_POPUP,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        1920,
        1080,
        nullptr,
        nullptr,
        wc.hInstance,
        nullptr
    );
    
  • Present参数优化:将swap_chain->Present(0U, 0U)改为swap_chain->Present(1U, 0U),确保画面按刷新率刷新,避免显示异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 06:15:55