mirror of
https://github.com/ocornut/imgui.git
synced 2026-11-12 19:14:43 +00:00
How to use imgui in an existing win32 dx11 application properly. #5061
Labels
No labels
accidentally closed
android
backends
bug
building
clipper
coloredit
color spaces
cplusplus
data types
demo
disabled
doc
docking
dpi
drag drop
drawing/drawlist
dropped
dx12
enhancement
focus
font/text
gallery
help wanted
idle/power saving
ime
in progress
inputs
inputtext
internals
label/id and id stack
language bindings
layout
linux/bsd
menus
multi-contexts
multi-threading
multi-viewports
nav
news/info
opengl
optimization
osx/ios
overlap
plot/graph
popups
question
scrolling
selection
settings
sliders/drags
style
tables/columns
tabs
test wanted
tools
tooltips
tree
tricks & tips
useful widgets
vulkan
web
window pos/depth
window sizing
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ocornut/imgui#5061
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Version/Branch of Dear ImGui:
Version: 1.88 WIP (18709)
Branch: master
Back-end/Renderer/Compiler/OS
Back-ends: imgui_impl_dx11_cpp + imgui_impl_win32.cpp
Compiler: Visual C++ 2022
Operating System: Windows 11
My Issue/Question:
I am trying to use imgui with an existing win32 DX11 application. I have done everything you have done in example_win32_directx11 when I hook into the dx11 "present" function to initialize imgui and, upon request, displaying the demo window, and I am able to get the imgui demo window to display and interact with its widgets. However, I am unable to drag the demo window around (it giggles a bit but stays put), and when I resize the platform window containing the imgui demo window, the imgui window scales up or down, becoming unreadable and difficult to interact with (mouse no longer seems to correlate to where widgets visually appear in the resized imgui window.) In the example application, neither of these situations occurs - I can drag the imgui window around freely, and when I resize the platform window, the imgui window retains their original aspect, both of which are the behaviors I want. Here is my WinProc:
It is almost the same as your example, with the main differences being handling a couple of keystrokes so I can toggle the demo window display or end my imgui usage, and passing the messages if needed to the original WinProc of the application.
So, I would appreciate some help in understanding why by imgui behavior is not the same as your example, and if perhaps there is something specific I must do to filter certain events from the platform window that is not needed in your demo application (since it is only doing default processing of window messages not needed by the example.) I tried to use io.WantCaptureMouse to do that, but it didn't change any behavior.
After playing around with this a bit more, I was able to get the imgui window dragging and resizing to work by making the following modification to my WinProc:
Interestingly, if instead of calling the DefWindowProc, I simply return 0, I am no longer able to interact with the imgui widgets at all. In any event, I still am still getting the imgui window scaling when I resize the platform window. I will keep digging, but any help with solving that issue would be appreciated, as would an explanation of why returning 0 vice returning DefWindowProc works so differently.
You don't need to the return value of
ImGui_ImplWin32_WndProcHandler()it'll always return 0.Beware when making statement like that, they tend to perpetuate not seeing a blind spot. 90% of the time it isn't a correct statement and there is a blind spot that you may have missed.
I don't know what
g_oWndProcis, that your own code. AFAIK you should always callDefWindowProc()if you want standard Windows behavior to function. And Dear ImGui only needs events passwed to ImGui_ImplWin32_WndProcHandler() + xxx_NewFrame() for the Renderer backend + xxx_NewFrame() for the Win32 backend + ImGui::NewFrame().There is this one case in there that doesn't return 0. Should I just pass WM_SETCURSOR on to the application regardless?
That is the application's wndproc - I am hooking it to run imgui on top of its main window.
In any event, I believe I figured out how to deal with the resize scaling. As it turns out, the application is resizing the swap chain buffers on window resize, and my imgui backend was unaware of that. So I hooked SwapChain::ResizeBuffers, reset the render target when that happens, and now it is working as expected - with one exception. As I resize the application window, the imgui windows all scale up or down until I stop resizing by releasing the mouse, then they snap back to their original size. I guess it is just a quirk of the windows resize operation, since it appears that as long as you are dragging the window corner, the swap chain buffers are not resized. If you have more information about how this works, I'd appreciate hearing it.
Oh, and just as a sanity check - to ensure I am not forwarding events to the application that imgui "wants", I made the following function to check for that situation - please let me know if it makes sense, or should there be other events (or maybe less?) than what I have grabbed from ImGui_ImplWin32_WndProcHandler.
Good point, let me investigate before I can give you an answer.
The win32 backend updates
io.DisplaySizein _NewFrame() based on the client area size so normally this would be automatic.In Win32 by default when using Windows resize/move is goes into a modal loop and doesn't return control to your application. So this is the "default" legacy behavior of Win32. The common workaround is to hook WM_PAINT and/or set a WM_TIMER and refresh inside that. The exact details of how it looks depends on details of how the swapchain is configured (e.g. on default examples it typically looks different in DX11 vs Vulkan).
I suppose that would work. I guess what people often do is that the use
io.WantCaptureMouseto alter higher-level data (e.g. clear/overwrite mouse data in your engine, or make high-level functions in your engine not return them).This is correct, ignore my previous comment about not testing return value. In fact I am going to add additional commentary around that function now.
Allrighty, thanks for your time. Got it working well now.