Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 低级鼠标钩子增量计算不稳定_C#_Mouse Hook - Fatal编程技术网

C# 低级鼠标钩子增量计算不稳定

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

我正在使用此处提供的示例:

加上我自己的代码来计算鼠标的delta

在任何人提到它之前,我知道在WPF和WF中有直接访问mouse.delta属性的方法,但我需要这是一个低级钩子

我对示例代码的修改如下:

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似乎是更精确的度量单位,但我可能会切换回。切换回可以消除极端错误,但时间单位本身的不准确会导致错误,值在真实值附近闪烁太多。看起来我可能会被迫对多个报告进行采样,并将增量分配为平均值。