C# 低级鼠标钩子增量计算不稳定
我正在使用此处提供的示例: 加上我自己的代码来计算鼠标的delta 在任何人提到它之前,我知道在WPF和WF中有直接访问mouse.delta属性的方法,但我需要这是一个低级钩子 我对示例代码的修改如下:C# 低级鼠标钩子增量计算不稳定,c#,mouse-hook,C#,Mouse Hook,我正在使用此处提供的示例: 加上我自己的代码来计算鼠标的delta 在任何人提到它之前,我知道在WPF和WF中有直接访问mouse.delta属性的方法,但我需要这是一个低级钩子 我对示例代码的修改如下: private static Stopwatch CallbackTimestamp = new Stopwatch(); private static MSLLHOOKSTRUCT LastHook = new MSLLHOOKSTRUCT(); private static IntPtr
private static Stopwatch CallbackTimestamp = new Stopwatch();
private static MSLLHOOKSTRUCT LastHook = new MSLLHOOKSTRUCT();
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
mouseExtensions.instance.InputChannels["X"].Value = hookStruct.pt.x;
mouseExtensions.instance.InputChannels["Y"].Value = hookStruct.pt.y;
int timeDif = (int)CallbackTimestamp.ElapsedTicks;
if (timeDif > 0)
{
int xDif = hookStruct.pt.x - LastHook.pt.x;
int yDif = hookStruct.pt.y - LastHook.pt.y;
double xDelta = ((double)xDif / (double)timeDif) * 10000;
mouseExtensions.instance.InputChannels["dX"].Value = (int)Math.Round(xDelta);
}
LastHook = hookStruct;
CallbackTimestamp.Restart();
}
if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
mouseExtensions.instance.InputChannels["B1"].Value = true;
if (nCode >= 0 && MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
mouseExtensions.instance.InputChannels["B1"].Value = false;
if (nCode >= 0 && MouseMessages.WM_RBUTTONDOWN == (MouseMessages)wParam)
mouseExtensions.instance.InputChannels["B2"].Value = true;
if (nCode >= 0 && MouseMessages.WM_RBUTTONUP == (MouseMessages)wParam)
mouseExtensions.instance.InputChannels["B2"].Value = false;
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
它在大多数情况下工作得很好,但问题是我偶尔会得到不稳定的输出,例如,当将值绑定到滑块时,一致的鼠标移动将按预期移动滑块,但突然震动到极限最小值或最大值除外。我认为这可能是一个被零除的问题,因为在分离太快的情况下调用回调,在时间跨度上不会有任何差异,但是添加忽略0的逻辑似乎没有什么区别
我可以存储一个值列表,并用一个平均值来帮助消除错误,但是我宁愿把问题固定在一个创可贴上。
是的,<代码> TiMETF值很可能是零。产生无限,超越无限。在Windows上,时钟没有那么快,默认为每秒64次。也许你应该忽略这个示例,也许你应该调用timeBeginPeriod(),也许你应该完全不同地这样做。在上面的例子中,我解释了timeDif为零的可能性,据我所知,秒表比64/s精确得多。我没有仔细观察,注意到您没有使用MSLLHOOKSTRUCT.time成员。这很麻烦,Stopwatch只告诉您代码何时执行,而不告诉您鼠标事件何时生成。我实际上最初使用的是结构中的时间单位,但它也产生了问题,Stopwatch.ticks似乎是更精确的度量单位,但我可能会切换回。切换回可以消除极端错误,但时间单位本身的不准确会导致错误,值在真实值附近闪烁太多。看起来我可能会被迫对多个报告进行采样,并将增量分配为平均值。