Dear ImGui学习:使用 WantCaptureMouse 检查鼠标消息
2024-03-17 17:33:41

WantCaptureMouse是类ImGuiIO的成员方法,源码中对于WantCaptureMouse的注释是这么写的:

Set when Dear ImGui will use mouse inputs, in this case do not dispatch them to your main game/application (either way, always pass on mouse inputs to imgui). (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.).

简单地说就是可以用来它判断鼠标是否在 imgui 窗口内,大部分使用场景是用来覆盖游戏引擎自身的鼠标数据。
比如我在游戏内show出窗口时,默认情况下鼠标在窗口上的点击都会传递给游戏处理,而此时我需要避免将 imgui 的鼠标事件传递给游戏处理,那么就可以通过WantCaptureMouse来判断

1
2
3
4
5
6
7
8
9
10
11
12
13
LRESULT WINAPI MyWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam)) {
return ERROR_SUCCESS;
}

const ImGuiIO& io = ImGui::GetIO();
if (io.WantCaptureMouse && (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP || uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP || uMsg == WM_MOUSEWHEEL || uMsg == WM_MOUSEMOVE)) {
return ERROR_SUCCESS;
}

return CallWindowProcW(g_pOldWindowProc, hWnd, uMsg, wParam, lParam);
}

鼠标在 imgui 窗口外时,imgui 默认会渲染指针样式,再加上游戏引擎渲染的指针样式,就出现了游戏内同时有两个指针的问题,所以我们在渲染时也可以通过WantCaptureMouse来检查,避免在 imgui 窗口外二次渲染指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();

// 鼠标不在imgui窗口内就不要渲染指针了
const ImGuiIO& io = ImGui::GetIO();
if (!io.WantCaptureMouse) {
ImGui::SetMouseCursor(ImGuiMouseCursor_None);
}

ImGui::Begin("Demo");
ImGui::Text("FPS:%.1f", io.Framerate);
ImGui::End();

ImGui::Render();

注意,永远不要手动去设置 WantCaptureMouse。


参考

io.WantCaptureMouse is not working. So im using an alternative bool. But i still want to understand what im doing wrong.
How to use imgui in an existing win32 dx11 application properly.
Mouse input going through ImGui window