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!