Reputation: 1654
I'm currently using a global mouse hook to make an app appear if it the mouse cursor reaches the corner of the screen. I just read about the existence of Raw Input and from what I understand, this is a more robust method as a slowdown in my hook will not impact the overall system.
Problem is I can't find any examples anywhere about using Raw Input in WPF.
Closest I got was SlimDX with the following code:
Device.RegisterDevice(UsagePage.Generic, UsageId.Mouse,
DeviceFlags.None);
Device.MouseInput += new EventHandler<MouseInputEventArgs>(mouse_MouseInput);
But that does not seem to work in WPF, only winforms.
Upvotes: 2
Views: 1722
Reputation: 4939
Those DeviceFlags.None
need to be InputSink
to capture input in the background. SharpDX flags there are actually a wrapper for the RAWINPUTDEVICEFLAGS (InputSink = 0x00000100
).
In WPF, you want to 1) override OnSourceInitialized
and 2) hook WndProc
there. While the window pointer is available you need to define the RAWINPUTDEVICE's you want to watch, flag InputSink
.
It will look something like
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
var win = source.Handle;
RAWINPUTDEVICE[] rid = new RAWINPUTDEVICE[2];
rid[0].UsagePage = (HIDUsagePage)0x01;
rid[0].Usage = (HIDUsage)0x05; // adds game pad
rid[0].Flags = RawInputDeviceFlags.InputSink; // accept input in background
rid[0].WindowHandle = win;
rid[1].UsagePage = (HIDUsagePage)0x01;
rid[1].Usage = (HIDUsage)0x04; // adds joystick
rid[1].Flags = RawInputDeviceFlags.InputSink; // accept input in background
rid[1].WindowHandle = win;
if (RegisterRawInputDevices(rid, (uint)rid.Length, (uint)Marshal.SizeOf(rid[0])) == false)
{
var err = Marshal.GetLastWin32Error();
if (err > 0)
{
throw new Win32Exception($"GetLastWin32Error: {err}");
}
else
{
throw new Win32Exception("RegisterRawInputDevices failed with error code 0. Parameter count mis-match?");
}
}
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_INPUT:
{
System.Diagnostics.Debug.WriteLine("Received WndProc.WM_INPUT");
DoTheThing(lParam);
}
break;
}
return hwnd;
}
Upvotes: 0