I am using the example provided here: http://blogs.msdn.com/b/toub/archive/2006/05/03/589468.aspx
Together with my own code to calculate mouse delta.
Before anybody mentions it, I know there are ways in WPF and WF to directly access a mouse.delta property, but I need this to be a low level hook.
My modifications to the sample code are as follows:
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);
}
It works pretty well for the most part, but the issue is I am getting occasional erratic outputs, when binding the value to a slider for instance, a consistent mouse movement will move the slider as expected except for sudden jolts to extreme min or max values. I thought perhaps it was a division by zero issue due to the callback being called in too rapid of secession for there to be any difference in the time span, but adding logic to ignore 0 does not seem to have made a difference.
I could store a list of values and use an average to help smooth out the errors, but Id rather fix the issue than put a band-aid on it.