在做大屏或者平板的业务,或多或少会有监听触摸事件的需求。在WPF 上,监听自身应用的触摸事件是很简单的,可以监听 Windows的 Stylus、Touch、甚至是 Mouse的事件来实现业务逻辑处理。但是如果要监听窗口外的触摸事件,可以使用RawInput.Sharp
1、注册触摸屏和笔的设备:
RawInputDevice.RegisterDevice(HidUsageAndPage.TouchScreen,RawInputDeviceFlags.ExInputSink | RawInputDeviceFlags.DevNotify, hwnd);RawInputDevice.RegisterDevice(HidUsageAndPage.Pen,RawInputDeviceFlags.ExInputSink | RawInputDeviceFlags.DevNotify, hwnd);
2、钩子函数获取 带Hid类型的设备
case RawInputHidData hid:Debug.WriteLine($"Hid {hid.Hid}");text = @$"DevicePath: {hid.Device.DevicePath} VID:{hid.Device.VendorId:X2} PID:{hid.Device.ProductId:X2} RawData:{hid.Hid}"; Console.WriteLine(text);if (hid is RawInputDigitizerData rawInputDigitizerData){foreach (var rawInputDigitizerContact in rawInputDigitizerData.Contacts){text += rawInputDigitizerContact.ToString() + "\r\n";}}Console.WriteLine(text);break;
3、完整代码如下:
using Linearstar.Windows.RawInput; using System.Diagnostics; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes;namespace RawInputTest {/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();Loaded += MainWindow_Loaded;}private void MainWindow_Loaded(object sender, RoutedEventArgs e){var windowInteropHelper = new WindowInteropHelper(this);var hwnd = windowInteropHelper.Handle;// Get the devices that can be handled with Raw Input.var devices = RawInputDevice.GetDevices();
RawInputDevice.RegisterDevice(HidUsageAndPage.TouchScreen,RawInputDeviceFlags.ExInputSink | RawInputDeviceFlags.DevNotify, hwnd);RawInputDevice.RegisterDevice(HidUsageAndPage.Pen,RawInputDeviceFlags.ExInputSink | RawInputDeviceFlags.DevNotify, hwnd);HwndSource source = HwndSource.FromHwnd(hwnd);source.AddHook(Hook);}private string text;private IntPtr Hook(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled){const int WM_INPUT = 0x00FF;// You can read inputs by processing the WM_INPUT message.if (msg == WM_INPUT){// Create an RawInputData from the handle stored in lParam.var data = RawInputData.FromHandle(lparam);// You can identify the source device using Header.DeviceHandle or just Device.var sourceDeviceHandle = data.Header.DeviceHandle;var sourceDevice = data.Device;// The data will be an instance of either RawInputMouseData, RawInputKeyboardData, or RawInputHidData.// They contain the raw input data in their properties.switch (data){case RawInputMouseData mouse:Debug.WriteLine($"Mouse {mouse.Mouse}");break;case RawInputKeyboardData keyboard:Debug.WriteLine(keyboard.Keyboard);break;case RawInputHidData hid:Debug.WriteLine($"Hid {hid.Hid}");text = @$"DevicePath: {hid.Device.DevicePath} VID:{hid.Device.VendorId:X2} PID:{hid.Device.ProductId:X2} RawData:{hid.Hid}"; Console.WriteLine(text);if (hid is RawInputDigitizerData rawInputDigitizerData){foreach (var rawInputDigitizerContact in rawInputDigitizerData.Contacts){text += rawInputDigitizerContact.ToString() + "\r\n";}}Console.WriteLine(text);break;}}return IntPtr.Zero;}} }
参考资料:熙哥的WPF 通过 RawInput 获取触摸消息 - lindexi - 博客园
