From 839067fda9e2ffa34c2e8bfc36be2c94fddcab53 Mon Sep 17 00:00:00 2001 From: Gargaj Date: Tue, 17 Oct 2017 12:37:21 +0200 Subject: [PATCH 1/4] Capture/release window in DX9 implementation This helps a lot when the user drags a slider but carries the cursor offscreen before releasing the button - without the capturing, the slider will "stick" to the mouse cursor even after the button has been released. (This should generally be added to all Windows implementations - I won't mind doing it if you think it's a good idea.) --- examples/directx9_example/imgui_impl_dx9.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 49012012..d1062560 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -177,21 +177,27 @@ IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LP switch (msg) { case WM_LBUTTONDOWN: + SetCapture( hWnd ); io.MouseDown[0] = true; return true; case WM_LBUTTONUP: + ReleaseCapture(); io.MouseDown[0] = false; return true; case WM_RBUTTONDOWN: + SetCapture( hWnd ); io.MouseDown[1] = true; return true; case WM_RBUTTONUP: + ReleaseCapture(); io.MouseDown[1] = false; return true; case WM_MBUTTONDOWN: + SetCapture( hWnd ); io.MouseDown[2] = true; return true; case WM_MBUTTONUP: + ReleaseCapture(); io.MouseDown[2] = false; return true; case WM_MOUSEWHEEL: From e03198bb0f636a4f997883b498125dee30f570db Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Oct 2017 09:08:12 +0200 Subject: [PATCH 2/4] Fixed compilation for #1375 + coding style fixes. --- examples/directx9_example/imgui_impl_dx9.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index d1062560..1d122adf 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -171,13 +171,13 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) d3d9_state_block->Release(); } -IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) +IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) { case WM_LBUTTONDOWN: - SetCapture( hWnd ); + SetCapture(hwnd); io.MouseDown[0] = true; return true; case WM_LBUTTONUP: @@ -185,7 +185,7 @@ IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LP io.MouseDown[0] = false; return true; case WM_RBUTTONDOWN: - SetCapture( hWnd ); + SetCapture(hwnd); io.MouseDown[1] = true; return true; case WM_RBUTTONUP: @@ -193,7 +193,7 @@ IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND, UINT msg, WPARAM wParam, LP io.MouseDown[1] = false; return true; case WM_MBUTTONDOWN: - SetCapture( hWnd ); + SetCapture(hwnd); io.MouseDown[2] = true; return true; case WM_MBUTTONUP: From 3e0765ee222a21bf801486f7a817d07569cada84 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Oct 2017 09:43:13 +0200 Subject: [PATCH 3/4] Examples: DirectX9: Using SetCapture/ReleaseCapture to get correct behavior (#1375) --- examples/directx9_example/imgui_impl_dx9.cpp | 34 +++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 1d122adf..0e94d3b8 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -171,34 +171,44 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) d3d9_state_block->Release(); } +static bool IsAnyMouseButtonDown() +{ + ImGuiIO& io = ImGui::GetIO(); + for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++) + if (io.MouseDown[n]) + return true; + return false; +} + +// We use Win32 SetCapture/ReleaseCapture() API to enable reading the mouse outside our Windows bounds. IMGUI_API LRESULT ImGui_ImplDX9_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) { case WM_LBUTTONDOWN: - SetCapture(hwnd); + if (!IsAnyMouseButtonDown()) ::SetCapture(hwnd); io.MouseDown[0] = true; return true; - case WM_LBUTTONUP: - ReleaseCapture(); - io.MouseDown[0] = false; - return true; case WM_RBUTTONDOWN: - SetCapture(hwnd); + if (!IsAnyMouseButtonDown()) ::SetCapture(hwnd); io.MouseDown[1] = true; return true; - case WM_RBUTTONUP: - ReleaseCapture(); - io.MouseDown[1] = false; - return true; case WM_MBUTTONDOWN: - SetCapture(hwnd); + if (!IsAnyMouseButtonDown()) ::SetCapture(hwnd); io.MouseDown[2] = true; return true; + case WM_LBUTTONUP: + io.MouseDown[0] = false; + if (!IsAnyMouseButtonDown()) ::ReleaseCapture(); + return true; + case WM_RBUTTONUP: + io.MouseDown[1] = false; + if (!IsAnyMouseButtonDown()) ::ReleaseCapture(); + return true; case WM_MBUTTONUP: - ReleaseCapture(); io.MouseDown[2] = false; + if (!IsAnyMouseButtonDown()) ::ReleaseCapture(); return true; case WM_MOUSEWHEEL: io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; From a96f095deb83f001498157bf10eed3a44d3ee96a Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Oct 2017 09:46:49 +0200 Subject: [PATCH 4/4] Examples: DirectX10, DirectX11: Using SetCapture/ReleaseCapture to get correct behavior (#1375) ps: DirectX 12 example (#302) may want to adopt that as well. --- .../directx10_example/imgui_impl_dx10.cpp | 29 ++++++++++++++----- .../directx11_example/imgui_impl_dx11.cpp | 29 ++++++++++++++----- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index f85edf9b..e0afa6f6 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -225,28 +225,43 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } -IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) +static bool IsAnyMouseButtonDown() +{ + ImGuiIO& io = ImGui::GetIO(); + for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++) + if (io.MouseDown[n]) + return true; + return false; +} + +IMGUI_API LRESULT ImGui_ImplDX10_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) { case WM_LBUTTONDOWN: + if (!IsAnyMouseButtonDown()) ::SetCapture(hwnd); io.MouseDown[0] = true; return true; + case WM_RBUTTONDOWN: + if (!IsAnyMouseButtonDown()) ::SetCapture(hwnd); + io.MouseDown[1] = true; + return true; + case WM_MBUTTONDOWN: + if (!IsAnyMouseButtonDown()) ::SetCapture(hwnd); + io.MouseDown[2] = true; + return true; case WM_LBUTTONUP: io.MouseDown[0] = false; - return true; - case WM_RBUTTONDOWN: - io.MouseDown[1] = true; + if (!IsAnyMouseButtonDown()) ::ReleaseCapture(); return true; case WM_RBUTTONUP: io.MouseDown[1] = false; - return true; - case WM_MBUTTONDOWN: - io.MouseDown[2] = true; + if (!IsAnyMouseButtonDown()) ::ReleaseCapture(); return true; case WM_MBUTTONUP: io.MouseDown[2] = false; + if (!IsAnyMouseButtonDown()) ::ReleaseCapture(); return true; case WM_MOUSEWHEEL: io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 49a4aa48..82c43f7e 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -232,28 +232,43 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } -IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) +static bool IsAnyMouseButtonDown() +{ + ImGuiIO& io = ImGui::GetIO(); + for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++) + if (io.MouseDown[n]) + return true; + return false; +} + +IMGUI_API LRESULT ImGui_ImplDX11_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) { case WM_LBUTTONDOWN: + if (!IsAnyMouseButtonDown()) ::SetCapture(hwnd); io.MouseDown[0] = true; return true; + case WM_RBUTTONDOWN: + if (!IsAnyMouseButtonDown()) ::SetCapture(hwnd); + io.MouseDown[1] = true; + return true; + case WM_MBUTTONDOWN: + if (!IsAnyMouseButtonDown()) ::SetCapture(hwnd); + io.MouseDown[2] = true; + return true; case WM_LBUTTONUP: io.MouseDown[0] = false; - return true; - case WM_RBUTTONDOWN: - io.MouseDown[1] = true; + if (!IsAnyMouseButtonDown()) ::ReleaseCapture(); return true; case WM_RBUTTONUP: io.MouseDown[1] = false; - return true; - case WM_MBUTTONDOWN: - io.MouseDown[2] = true; + if (!IsAnyMouseButtonDown()) ::ReleaseCapture(); return true; case WM_MBUTTONUP: io.MouseDown[2] = false; + if (!IsAnyMouseButtonDown()) ::ReleaseCapture(); return true; case WM_MOUSEWHEEL: io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;