简体   繁体   English

SendInput() 鼠标移动计算?

[英]SendInput() mouse movement calculation?

I'm playing around with SendInput() for mouse movement, and it wants INPUT structures.我正在使用SendInput()来移动鼠标,它需要INPUT结构。 I'm using relative movement, and in the docs about this struct, in the Remarks it says:我正在使用相对运动,在关于这个结构的文档中,在备注中它说:

Relative mouse motion is subject to the effects of the mouse speed and the two-mouse threshold values.相对鼠标运动受鼠标速度和两鼠标阈值的影响。

So my question is, what and how exactly is this calculated (what is the formula)?所以我的问题是,这是什么以及如何计算的(公式是什么)? It is not specified.未指定。

I tried searching about it, but with no luck.我尝试搜索它,但没有运气。 Hope someone knows.希望有人知道。

I need this information because I'm trying to make the mouse movement be independant of the actual Windows cursor speed.我需要这些信息,因为我试图使鼠标移动独立于实际的 Windows 光标速度。 And in the docs it clearly says this is affected by those values.在文档中,它清楚地表明这受这些值的影响。

  • Relative value相对价值

Relative mouse motion is subject to the effects of the mouse speed and the two-mouse threshold values.相对鼠标运动受鼠标速度和两鼠标阈值的影响。 So my question is, what and how exactly is this calculated (what is the formula)?所以我的问题是,这是什么以及如何计算的(公式是什么)? It is not specified.未指定。

How to calculate is stated in remarks of MOUSEINPUT structure document as below:如何计算在MOUSEINPUT结构文件的备注中说明如下:

The system applies two tests to the specified relative mouse movement.系统对指定的相对鼠标移动应用两个测试。 If the specified distance along either the x or y axis is greater than the first mouse threshold value, and the mouse speed is not zero, the system doubles the distance.如果沿 x 或 y 轴的指定距离大于第一个鼠标阈值,并且鼠标速度不为零,则系统将距离加倍。 If the specified distance along either the x or y axis is greater than the second mouse threshold value, and the mouse speed is equal to two, the system doubles the distance that resulted from applying the first threshold test.如果沿 x 或 y 轴的指定距离大于第二个鼠标阈值,并且鼠标速度等于 2,则系统将应用第一个阈值测试产生的距离加倍。 It is thus possible for the system to multiply specified relative mouse movement along the x or y axis by up to four times.因此,系统可以将指定的沿 x 或 y 轴的相对鼠标移动最多乘以四倍。

To prevent system from doubling the distance or multiply specified relative mouse movement along the x or y axis by up to four times, for example, you can keep the specified relative mouse movement less than or equal to the the first mouse threshold value, and set the mouse speed to zero.为防止系统将距离加倍或将指定的鼠标沿 x 或 y 轴的相对移动最多乘以四倍,例如,您可以保持指定的鼠标相对移动小于或等于第一个鼠标阈值,并设置鼠标速度归零。 Please test to see if this meets your requirement.请测试看看这是否符合您的要求。

As for UIPI limitation, since your application already runs as admin rights, it has the high mandatory level, so this will not be a problem unless your target application runs as system integrity level .至于 UIPI 限制,由于您的应用程序已经以管理员权限运行,因此它具有较高的强制级别,因此除非您的目标应用程序以系统完整性级别运行,否则这不会成为问题。

  • Absolute values绝对值

And without UIPI limitation, you can also use absolute values which is not subject to the effects of the mouse speed and the two-mouse threshold values.并且不受 UIPI 限制,也可以使用不受鼠标速度和两鼠标阈值影响的绝对值

From the documentation for mouse_event function :mouse_event函数的文档中:

Relative mouse motion is subject to the settings for mouse speed and acceleration level.鼠标相对运动受鼠标速度和加速度级别的设置影响。 An end user sets these values using the Mouse application in Control Panel.最终用户使用控制面板中的鼠标应用程序设置这些值。 An application obtains and sets these values with the SystemParametersInfo function.应用程序使用SystemParametersInfo函数获取和设置这些值。

I believe these refer to the following two queries:我相信这些是指以下两个查询:

  • SPI_GETMOUSE ( = 0x0003 ), SPI_GETMOUSE ( = 0x0003 ),

    Retrieves the two mouse threshold values and the mouse acceleration.检索两个鼠标阈值和鼠标加速度。 The pvParam parameter must point to an array of three integers that receives these values. pvParam参数必须指向接收这些值的三个整数的数组。

    The three values are the first threshold, second threshold, and acceleration.这三个值是第一阈值、第二阈值和加速度。

  • SPI_GETMOUSESPEED ( = 0x0070 ), SPI_GETMOUSESPEED ( = 0x0070 ),

    Retrieves the current mouse speed.检索当前鼠标速度。 The mouse speed determines how far the pointer will move based on the distance the mouse moves.鼠标速度根据鼠标移动的距离确定指针移动的距离。 The pvParam parameter must point to an integer that receives a value which ranges between 1 (slowest) and 20 (fastest). pvParam参数必须指向一个整数,该整数接收一个介于 1(最慢)和 20(最快)之间的值。 A value of 10 is the default.默认值为 10。

    This seems to follow a somewhat strange formula to scale the movement.这似乎遵循一个有点奇怪的公式来缩放运动。

The system applies two tests to the specified relative mouse motion when applying acceleration.系统在应用加速度时对指定的相对鼠标运动应用两个测试。 If the specified distance along either the x or y axis is greater than the first mouse threshold value, and the mouse acceleration level is not zero, the operating system doubles the distance.如果沿 x 或 y 轴的指定距离大于第一个鼠标阈值,并且鼠标加速级别不为零,则操作系统将距离加倍。 If the specified distance along either the x- or y-axis is greater than the second mouse threshold value, and the mouse acceleration level is equal to two, the operating system doubles the distance that resulted from applying the first threshold test.如果沿 x 轴或 y 轴的指定距离大于第二个鼠标阈值,并且鼠标加速度级别等于 2,则操作系统将应用第一个阈值测试产生的距离加倍。 It is thus possible for the operating system to multiply relatively-specified mouse motion along the x- or y-axis by up to four times.因此,操作系统可以将沿 x 轴或 y 轴的相对指定的鼠标移动最多乘以四倍。

Unfortunately I have not been able to crack this one out (it applies when "enhance pointer precision" is enabled in the "mouse properties").不幸的是,我无法破解这个问题(它适用于在“鼠标属性”中启用“增强指针精度”时)。 It definitely does not seem to just double the value.它绝对不似乎只是使价值翻倍。

For values three times as high as the threshold, the scaling seems accurate (it doubles your input), but beyond that the factor of 2 keeps growing.对于三倍于阈值的值,缩放似乎是准确的(它会使您的输入加倍),但除此之外,因子 2 会不断增长。 These were tested with a mouse speed of 10:这些是用 10 的鼠标速度测试的:

  • For your input of 20, the final distance traveled is 40.对于您的输入 20,最终行驶距离为 40。
  • For 40, the final distance is 93 and not 80 (~1.16 higher).对于 40,最终距离是 93 而不是 80(约高 1.16)。
  • For 80, the final distance is 201 and not 160 (~1.25 higher).对于 80,最终距离是 201 而不是 160(约高 1.25)。
  • For 160, the final distance is 416 and not 320 (~1.30 higher).对于 160,最终距离是 416 而不是 320(约高 1.30)。
  • For 320, the final distance is 846 and not 640 (~1.32 higher).对于 320,最终距离是 846 而不是 640(约高 1.32)。
  • For higher values the ratio actual / expected hardly grows.对于更高的值,实际/预期的比率几乎不会增长。

To make matters worse, with a speed of 20 (assuming the speed scaling as described later is the same):更糟糕的是,在速度为 20 的情况下(假设后面描述的速度缩放是相同的):

  • For your input of 20, the final distance traveled is 66.对于您输入的 20,最终行驶距离为 66。
  • For 40, the final distance is 173 and not 280 (~0.62 lower).对于 40,最终距离是 173 而不是 280(约低 0.62)。
  • For 80, the final distance is 388 and not 560 (~0.69 lower).对于 80,最终距离是 388 而不是 560(约低 0.69)。
  • For 160, the final distance is 416 and not 320 (~0.73 lower).对于 160,最终距离是 416 而不是 320(约低 0.73)。
  • For 320, the final distance is 1677 and not 2240 (~0.75 higher).对于 320,最终距离是 1677 而不是 2240(约高 0.75)。
  • For higher values, my monitor is not large enough.对于更高的值,我的显示器不够大。

Once acceleration has been applied, the system scales the resultant value by the desired mouse speed.应用加速度后,系统会按所需的鼠标速度缩放结果值。 Mouse speed can range from 1 (slowest) to 20 (fastest) and represents how much the pointer moves based on the distance the mouse moves.鼠标速度的范围可以从 1(最慢)到 20(最快),并表示指针根据鼠标移动的距离移动了多少。 The default value is 10, which results in no additional modification to the mouse motion.默认值为 10,不会对鼠标移动进行额外修改。

From my testing, it appears 10 means no scaling (scale of 1).从我的测试来看,10 表示没有缩放(比例为 1)。 Every value above 10 seems to increase the scale factor by 1/4, and every value below 10 decreases it by 1/8 (except for the value of 2 where it would have reached 0, so the scaling is 1/16, and the scaling at 1 unit seems to be 0/32).每个高于 10 的值似乎都会将比例因子增加 1/4,而低于 10 的每个值都会将比例因子减少 1/8(除了值 2 会达到 0,因此比例为 1/16,并且以 1 个单位缩放似乎是 0/32)。 The following algorithm (Python) predicts where the mouse ends if "enhance pointer precision" is disabled:如果禁用“增强指针精度”,以下算法 (Python) 会预测鼠标的结束位置:

import ctypes

speed = ctypes.c_int()
ctypes.windll.user32.SystemParametersInfoA(0x0070, 0, ctypes.byref(speed), 0)  # SPI_GETMOUSESPEED
speed = out.value

# x is how much you want to move the mouse in the x axis (the same is true for the y axis)

if speed == 1:
    predict_x = x // 32
elif speed == 2:
    predict_x = x // 16
elif speed <= 10:
    predict_x = (x * (speed - 2)) // 8
else:
    predict_x = (x * (speed - 6)) // 4

If you wanted to move the mouse exactly x , you would need the reverse code:如果您想精确移动鼠标x ,则需要反向代码:

if speed == 1:
    used_x = x * 32
elif speed == 2:
    used_x = x * 16
elif speed <= 10:
    used_x = int(round((x * 8) / (speed - 2)))
else:
    used_x = int(round((x * 4) / (speed - 6)))

My conclusion is it's not worth it to use relative movement for accurate mouse movements.我的结论是使用相对移动来进行精确的鼠标移动是不值得的。 You are better off querying the current position, adding your delta, and setting the absolute position.您最好查询当前位置,添加增量并设置绝对位置。 Otherwise you have to query mouse configuration which can change any time and is designed to feel good, not be exact in a single movement.否则,您必须查询可以随时更改的鼠标配置,并且旨在让您感觉良好,而不是在单个动作中精确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM