WPF 通过 RawInput 获取触摸消息
触摸在 Windows 下属于比较特殊的输入,不同于键盘和鼠标,键盘和鼠标可以通过全局 Hook 的方式获取到鼠标和键盘的输入消息。而触摸则没有直接的 Hook 的方法。如果期望自己的应用,可以在没有作为前台获取焦点的应用时,可以抓取到全局的触摸消息,抓取到其他应用程序的触摸输入,那么可以尝试使用 RawInput 的方式。通过 RawInput 的方式,可以让一个没有任何激活的、触摸直接命中的窗口的应用程序接收到全局的所有触摸消息
在上一篇博客,介绍了 WPF 使用 RawInput 接收裸数据 的方法,但是里面只是和大家演示了如何抓取鼠标和键盘消息
其实通过 RawInput 是可以在注册设备时,声明需要获取 TouchScreen 触摸屏输入,和 Pen 笔输入的。如以下代码
RawInputDevice.RegisterDevice(HidUsageAndPage.TouchScreen,
RawInputDeviceFlags.ExInputSink | RawInputDeviceFlags.DevNotify, hwnd);
RawInputDevice.RegisterDevice(HidUsageAndPage.Pen,
RawInputDeviceFlags.ExInputSink | RawInputDeviceFlags.DevNotify, hwnd);
以上的代码有所省略,没关系,大家可以在本文最后获取到所有的源代码
注册完成之后,即可在消息循环里面,收到 Windows 调度的消息。基于 rawinput-sharp: C# wrapper library for Raw Input 项目的 RawInput.Sharp 库的自动转换,即可通过判断 RawInputHidData 的方式,过滤出触摸的输入,代码如下
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);
// The data will be an instance of either RawInputMouseData, RawInputKeyboardData, or RawInputHidData.
// They contain the raw input data in their properties.
switch (data)
{
case RawInputHidData hid:
Debug.WriteLine($"Hid {hid.Hid}");
TextBlock.Text = @$"DevicePath: {hid.Device.DevicePath}
VID:{hid.Device.VendorId:X2} PID:{hid.Device.ProductId:X2}
RawData:{hid.Hid}
";
if (hid is RawInputDigitizerData rawInputDigitizerData)
{
foreach (var rawInputDigitizerContact in rawInputDigitizerData.Contacts)
{
TextBlock.Text += rawInputDigitizerContact.ToString() + "\r\n";
}
}
break;
}
}
return IntPtr.Zero;
}
如上面代码,可以看到,在获取输入信息时,还可以获取到是哪个触摸框的输入,通过触摸框的 DevicePath 或者是 ProductId 等判断。同时通过 RawInput 的此方法,也可以用来支持双触摸屏同时进行触摸输入
以下是更多代码细节
在使用之前,安装 NuGet 包。如果是 SDK 风格的 csproj 项目格式,可以在项目文件添加以下代码安装
<ItemGroup>
<PackageReference Include="RawInput.Sharp" Version="0.0.2" />
</ItemGroup>
以下是 MainWindow.xaml.cs 的例子代码
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
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;
using Linearstar.Windows.RawInput;
namespace RaicheadoherneanuNalokearwherno;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
SourceInitialized += MainWindow_SourceInitialized;
}
private void MainWindow_SourceInitialized(object? sender, EventArgs e)
{
var windowInteropHelper = new WindowInteropHelper(this);
var hwnd = windowInteropHelper.Handle;
// Get the devices that can be handled with Raw Input.
var devices = RawInputDevice.GetDevices();
// register the keyboard device and you can register device which you need like mouse
RawInputDevice.RegisterDevice(HidUsageAndPage.Keyboard,
RawInputDeviceFlags.ExInputSink | RawInputDeviceFlags.NoLegacy, hwnd);
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 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}");
TextBlock.Text = @$"DevicePath: {hid.Device.DevicePath}
VID:{hid.Device.VendorId:X2} PID:{hid.Device.ProductId:X2}
RawData:{hid.Hid}
";
if (hid is RawInputDigitizerData rawInputDigitizerData)
{
foreach (var rawInputDigitizerContact in rawInputDigitizerData.Contacts)
{
TextBlock.Text += rawInputDigitizerContact.ToString() + "\r\n";
}
}
break;
}
}
return IntPtr.Zero;
}
}
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin bc08596b5f3b261ff621fcdb1426c953e3514b69
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin bc08596b5f3b261ff621fcdb1426c953e3514b69
获取代码之后,进入 RaicheadoherneanuNalokearwherno 文件夹
更多 WPF 相关博客,请参阅我的 博客导航
WPF 通过 RawInput 获取触摸消息的更多相关文章
- 通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息
原文:通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息 WPF 框架自己实现了一套触摸机制,但同一窗口只能支持一套触摸机制,于是这会禁用系统的触摸消 ...
- 通过解读 WPF 触摸源码,分析 WPF 插拔设备触摸失效的问题(问题篇)
在 .NET Framework 4.7 以前,WPF 程序的触摸处理是基于操作系统组件但又自成一套的,这其实也为其各种各样的触摸失效问题埋下了伏笔.再加上它出现得比较早,触摸失效问题也变得更加难以解 ...
- 2019-11-29-WPF-从触摸消息转触摸事件
原文:2019-11-29-WPF-从触摸消息转触摸事件 title author date CreateTime categories WPF 从触摸消息转触摸事件 lindexi 2019-11- ...
- 2019-5-13-WPF-从触摸消息转触摸事件
title author date CreateTime categories WPF 从触摸消息转触摸事件 lindexi 2019-05-13 09:43:48 +0800 2019-05-12 ...
- WPF中的多点触摸事件
UIElement在WPF4下添加了很多支持多点触摸的事件,通过它们可以在硬件支持的情况下处理多点触摸,以下通过代码来说明通过处理这些事件,我们可以做些什么: 一.触摸相关的多种事件,跟鼠标事件是对应 ...
- WPF编程,获取句柄将外部程序嵌入到WPF界面。
原文:WPF编程,获取句柄将外部程序嵌入到WPF界面. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/details ...
- 2dx关于js响应layer触摸消息的bug
cocos2dx关于js响应layer触摸消息的bug cocos2d-x 3.7 问题描述: 目前这个版本中(3.7),c++层的layer触摸消息只能通过消息的方式发送给js,不能像lua一样直接 ...
- XMPP系列(四)---发送和接收文字消息,获取历史消息功能
今天开始做到最主要的功能发送和接收消息.获取本地历史数据. 先上到目前为止的效果图: 首先是要在XMPPFramework.h中引入数据存储模块: //聊天记录模块的导入 # ...
- Xmpp获取离线消息
文章只是选取了其中一段,无XMPP基础的人可能看起来有点复杂; 假设我们注册了一个用户,用户名叫shimiso,那么我们如何让shimiso这个用户一登陆就取到离线消息呢? PPConnection. ...
- VS编程,WPF中,获取鼠标相对于当前屏幕坐标的一种方法
原文:VS编程,WPF中,获取鼠标相对于当前屏幕坐标的一种方法 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/det ...
随机推荐
- windows 10 wsl 环境 docker 无法正常启动 -The system cannot find the file specified
错误信息: error during connect: in the default daemon configuration on Windows, the docker client must b ...
- JavaScript知识总结 终结篇--面向对象,垃圾回收与内存泄漏
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.面向对象 一般使用字面量的形式直接创建对象,但是这种创建方式对于创建大量相似对象的时候,会产生大量的重复代码.但 js和一般的面向对象 ...
- 记录--uni-app实现蓝牙打印小票
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 说明 基于uni-app开发,调用官方蓝牙相关api实现连接蓝牙与向蓝牙热敏打印机发送字节流,可打印文字,二维码,图片,调整字体大小等,本 ...
- Puppet 2024年度报告:平台工程发掘 DevOps 无限潜质
Puppet 于本周发布了一份2024年的 DevOps 现状报告 The State of DevOps Report: The Evolution of Platform Engineering. ...
- 重返ubuntu世界
一直对"重返"两个字充满了情怀感,因为会想起小时候看的一本龙珠同人的标题,它就唤作<重回龙珠世界>.最近这五年基本都是在MacOS下工作和学习的,也习惯用MacOS.就 ...
- Scala Map操作
1 package chapter07 2 3 object Test14_HighLevelFunction_Map { 4 def main(args: Array[String]): Unit ...
- 抗噪液晶屏驱动芯片VK2C22A/B适用于单相电表段码驱动,水瓦斯表段码表、驱动等
产品型号:VK2C22A/B 产品品牌:永嘉微电/VINKA 封装形式:LQFP52/48.DICE(COB邦定片).COG(邦定玻璃用) 产品年份:新年份 (C21-285) VK2C22A/B概述 ...
- 14 CSS列表属性和display属性
14 列表属性和display属性 列表属性 CSS中提供了一些列表属性可以用来: (1).设置不同的列表项标记为有序列表 (2).设置不同的列表项标记为无序列表 (3).设置列表项标记为图像 lis ...
- #结论#洛谷 3199 [HNOI2009]最小圈
题目 求有向图最小平均权值回路. \(n\leq 3*10^3,m\leq 10^4\) 分析 设 \(f_k(x)\) 表示从点 \(x\) 出发恰好走 \(k\) 条边的最短路, 那么答案就是 \ ...
- [AHOI2014/JSOI2014/一本通1722]骑士游戏 题解 (spfa做dp)
题目描述 在游戏中,JYY一共有两种攻击方式,一种是普通攻击,一种是法术攻击.两种攻击方式都会消耗JYY一些体力.采用普通攻击进攻怪兽并不能把怪兽彻底杀死,怪兽的尸体可以变出其他一些新的怪兽,注意一个 ...