运行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
相关产品推荐
相关产品推荐

