Quantcast
Channel: Visual C# forum
Viewing all articles
Browse latest Browse all 31927

WH_MOUSE_LL Hook event timing mystery

$
0
0

I have set a WH_MOUSE_LL Low Level Mouse Hook to intercept wheel movements. It's generally working fine, but I am getting odd results when timing the ticks or ms between each HookCallback. This is what I get when moving the wheel progressively from slow to very fast:

// # of ticks elapsed between mouse wheel events:
112180
37428
56167
37436
37454
37428
37501
18550
37547
18722
37432
18720
18861
39636
18755
18324
18753
18707
18863
18582
18695
18713
// etc..

So basically what I am getting here are multiples of ~18700, not an expected linear progression. Translating these values in ms, I get 40, 24, 16 and 8 ms (8 is the shortest time possible as mouse frequency is by default 125 hz). I need very precise timings for my application.

Here's the code in C# (minus UI):

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook,
        LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
        IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);

    [DllImport("kernel32.dll")]
    private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);

    [DllImport("kernel32.dll")]
    private static extern bool QueryPerformanceFrequency(out long lpFrequency);

    private long timerFrequency = 0;
    private long lastWheelTick = 0;
    private LowLevelMouseProc _proc;
    private static IntPtr _hookID = IntPtr.Zero;
    private List<long> log;

    public run()
    {
        log = new List<long>();
        _proc = HookCallback;
        QueryPerformanceFrequency(out timerFrequency);
        _hookID = SetHook(_proc);
    }

    private static IntPtr SetHook(LowLevelMouseProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_MOUSE_LL, proc,
                GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

    private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && MouseMessages.WM_MOUSEWHEEL == (MouseMessages)wParam)
        {
            long wheelTick = 0;
            QueryPerformanceCounter(out wheelTick);
            long diff = wheelTick - lastWheelTick;
            long RPM = (timerFrequency / diff) / 60;
            lastWheelTick = wheelTick;
            log.Add(diff);
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

    private const int WH_MOUSE_LL = 14;

    private enum MouseMessages
    {
        WM_LBUTTONDOWN = 0x0201,
        WM_LBUTTONUP = 0x0202,
        WM_MOUSEMOVE = 0x0200,
        WM_MOUSEWHEEL = 0x020A,
        WM_RBUTTONDOWN = 0x0204,
        WM_RBUTTONUP = 0x0205
    }

There's no other processing between mouse events. Also tried using Stopwatch (ticks and ms) with same results.

Any thoughts as why this may happen? Thanks!


Viewing all articles
Browse latest Browse all 31927

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>