Winapi 如何在不限制屏幕大小的情况下跟踪鼠标移动?

Winapi 如何在不限制屏幕大小的情况下跟踪鼠标移动?,winapi,mousemove,Winapi,Mousemove,我使用WM_MOUSEMOVE来改变鼠标位置。例如,当模拟“旋钮”时,需要让用户不受任何限制地使用鼠标上下移动。在这种情况下,我隐藏光标并使用SetCursorPos在用户每次移动光标时更改其位置,并检测与原始位置的差异 不幸的是,它似乎不工作-如果我设置鼠标位置,它有时工作,但有时是一个或多个像素的距离,这是错误的。更大的麻烦是,在调用之后,另一个WM_MOUSEMOVE似乎被传递,不幸的是,它做了同样的事情,因为它想再次将光标移回原始位置。因此,它以无限循环或设置鼠标位置和接收消息结束,直到

我使用WM_MOUSEMOVE来改变鼠标位置。例如,当模拟“旋钮”时,需要让用户不受任何限制地使用鼠标上下移动。在这种情况下,我隐藏光标并使用SetCursorPos在用户每次移动光标时更改其位置,并检测与原始位置的差异

不幸的是,它似乎不工作-如果我设置鼠标位置,它有时工作,但有时是一个或多个像素的距离,这是错误的。更大的麻烦是,在调用之后,另一个WM_MOUSEMOVE似乎被传递,不幸的是,它做了同样的事情,因为它想再次将光标移回原始位置。因此,它以无限循环或设置鼠标位置和接收消息结束,直到用户释放鼠标按钮


正确的方法是什么?问题是什么?

原始输入系统可以做到这一点-它允许您注册未被剪裁或限制在屏幕边界的原始鼠标输入

广义地说,您可以使用注册来注册原始输入。然后,您的窗口将接收您使用该函数处理的消息

有关示例,请参见

我隐藏光标并使用SetCursorPos在用户每次移动光标时更改其位置,并检测与原始位置的差异


这完全是错误的。相反,使用来捕获鼠标。所有移动都将被报告为带有相对于指定窗口的坐标的
WM_MOUSEMOVE
消息,即使鼠标在该窗口之外,直到您释放捕获。

要求用户连续移动鼠标,即使在光标到达屏幕限制后,在用户界面上也是一个非常糟糕的主意,伊姆霍

有些游戏有另一种方法:当鼠标达到“极限”时,游戏进入一种特殊模式:即使用户不移动鼠标,事情看起来就像鼠标在移动一样。当用户想要退出该模式时,他只需移动鼠标的极限


这样做需要一个计时器,当鼠标达到某个极限时,它会自动启动,并像鼠标移动一样周期性地执行代码。当真正的鼠标移动使计时器离开限制时,计时器将停止。

好的,伙计们,所以我找到了一个足够简单的解决方案:

主要问题是SetCursorPos可能无法准确设置坐标,我猜这是因为某些高分辨率处理,不过这可能是一个bug。无论如何,如果SetCursorPos没有正确设置坐标(但是x和/或y中的+-1),它也会将WM_MOUSEMOVE发送到目标窗口。因此,窗口将执行与以前完全相同的操作,并且这种操作将持续不断

因此,解决方案是在SetCursorPos之后立即删除所有WM_MOUSEMOVE消息:

MSG msg;
while (::PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) { };
然后使用::GetCursorPos检索当前鼠标光标位置。
这很难看,但似乎解决了问题。基本上,在鼠标的某个位置,系统总是在任一坐标中加或减1,这样,你就可以让系统做一些奇怪的事情,使用新的坐标,而不试图说服系统你的坐标是正确的:)。

你能用鼠标上的滚轮代替x/y吗?我想你可以用DirectX来获取原始的鼠标输入信息,这些信息只是“鼠标移动了这么远”而不是转换为(并限制为)屏幕坐标。尝试寻找DirectInput示例代码。恐怕鼠标滚轮太笨拙了,它也被使用了。DirectInput可能会工作,但我真的不想进入这些深渊,软件必须在非常旧的机器上工作,而DirectInput甚至可能不在这些机器上。更不用说所有的繁重工作只是为了让DX工作这么琐碎的(但显然不是)。而且,考虑到如果用户移动你的“旋钮”很长的距离,他们将不得不拿起鼠标并重新设置它,可能几次。你可以考虑让它们在圆圈中移动鼠标(转动旋钮)而不是直接向上或向下移动;这对用户来说可能更容易,并且可以避免屏幕边界的问题。我知道,但我认为不会那么糟糕。我个人认为使用“旋转角度”非常混乱和难以使用。捕获足够了,并且与标准UI保持一致。@RaymondChen即使捕获鼠标,它仍然会被剪裁到屏幕边界,不是吗?是的。我错过了那个细节,没错!问题出在屏幕上。我会检查原始输入,这不是问题所在。事实上,我使用鼠标捕捉。问题不在于窗口的限制,而在于屏幕的限制!假设你的旋钮在屏幕坐标中大约(50,50)。那么你只有50个垂直像素了!然后鼠标消息停止出现,因为坐标是负数。如果在捕获时保存起始屏幕坐标,则可以使用消息坐标(即使是负数),轻松计算鼠标从起始坐标移动的距离。但是,如果你说当你到达屏幕顶部时,消息就完全停止了,那就这样吧。正如Jonathan所建议的,你可能需要原始的输入来克服这一点。好吧,在我所从事的领域中,这是一种相当普遍的做法。我想在游戏中这是有道理的。@VojtěchMeldaMeluzín当鼠标在50厘米外时,用户会让它飞回原来的位置?嗯,这太夸张了,你不觉得吗?;)除了你可能只是运气不好,而且“旋钮”将比屏幕顶部低10个像素,使其实际上无法使用之外,我所在领域的许多人正在使用其他设备,如平板电脑等。。。