Qt 使用RAW INPUT获取HID触摸屏,笔设备,鼠标的原始数据,最低受支持的客户端:Windows XP [仅限桌面应用]
在开发绘图应用程序时,经常会需要读取笔设备的数据,通过对笔数据的解析,来判断笔的坐标,粗细。如果仅仅只是读取鼠标的坐标,就需要人为在应用程序端去修改笔的粗细,并且使用体验不好,如果可以实时获取到触摸屏的笔数据的话,就可以大大提高体验感。
获取USB-HID设备的数据,有多种方式
- 使用Raw Input API
- 使用Windows底层库,如Windows API,Windows HID API
- 使用第三方库,如hidapi,libusb等等
本博文主要分析Raw Input API的操作,官网解析地址:https://learn.microsoft.com/en-us/windows/win32/inputdev/about-raw-input
从官网的概述可以知道Raw Input API为应用程序提供了一种稳定而可靠的方式,可以接受来自任何 HID(包括键盘和鼠标)的原始输入。

并且具有这些优点。

Qt使用Raw Input API具体步骤
- 注册原始输入
- 重写nativeEvent函数
- 执行原始输入的标准读取
(解析截自官网)
1.注册原始输入
为了注册设备,应用程序首先创建 一个 RAWINPUTDEVICE 结构的数组,这些结构为所需的设备指定 顶级集合 (TLC) 。 TLC 由“使用情况页”定义, (设备) 类 (设备) 。 例如,若要获取键盘 TLC,请设置 UsagePage = 0x01 和 UsageID = 0x06。 应用程序调用 RegisterRawInputDevices 来注册设备。
请注意,应用程序可以注册当前未附加到系统的设备。 附加此设备后,Windows 管理器将自动将原始输入发送到应用程序。 若要获取系统上的原始输入设备列表,应用程序会调用 GetRawInputDeviceList。 应用程序使用此调用中的 hDevice 调用 GetRawInputDeviceInfo 以获取设备信息。
TCL:
Usage Page
HID usages are organized into usage pages of related controls. A specific control usage is defined by its usage page, a usage ID, a name, and a description. A usage page value is a 16-bit unsigned value.
Examples of usage pages include:
Expand table
| Page ID | Page Name | hidusage.h constant |
|---|---|---|
| 0x01 | Generic Desktop Controls | HID_USAGE_PAGE_GENERIC |
| 0x05 | Game Controls | HID_USAGE_PAGE_GAME |
| 0x08 | LEDs | HID_USAGE_PAGE_LED |
| 0x09 | Button | HID_USAGE_PAGE_BUTTON |
Usage ID
In the context of a usage page, a valid usage identifier, or usage ID, indicates a usage in a usage page. A usage ID of zero is reserved. A usage ID value is an unsigned 16-bit value.
Examples of controls that are listed on the Generic Desktop Controls usage page:
Expand table
| Usage ID | Usage Name | hidusage.h constant |
|---|---|---|
| 0x01 | Pointer | HID_USAGE_GENERIC_POINTER |
| 0x02 | Mouse | HID_USAGE_GENERIC_MOUSE |
| 0x04 | Joystick | HID_USAGE_GENERIC_JOYSTICK |
| 0x05 | Game Pad | HID_USAGE_GENERIC_GAMEPAD |
| 0x06 | Keyboard | HID_USAGE_GENERIC_KEYBOARD |
| 0x07 | Keypad | HID_USAGE_GENERIC_KEYPAD |
| 0x08 | Multi-axis Controller | HID_USAGE_GENERIC_MULTI_AXIS_CONTROLLER |
bool Dialog::RegisitWindow(HWND hwnd)
{if ( nullptr == hwnd ){return FALSE;}RAWINPUTDEVICE rid[1];rid[0].usUsagePage = 0x0D;rid[0].usUsage = 0x02; // 笔设备rid[0].dwFlags = RIDEV_INPUTSINK;rid[0].hwndTarget = hwnd;if (!RegisterRawInputDevices(rid, 1, sizeof(rid[0]))){return FALSE;}return TRUE;
}
2.重写nativeEvent函数
bool Dialog::nativeEvent(const QByteArray &eventType, void *message, long *result)
{}
3.执行原始输入的标准读取
应用程序从任何 HID 接收原始输入,其 顶级集合 (TLC) 与注册中的 TLC 匹配。 当应用程序收到原始输入时,其消息队列将获取 WM_INPUT 消息, 并且队列 状态标志QS_RAWINPUT设置为 (QS_INPUT 还包括此标志) 。 应用程序在前台和后台时可以接收数据。
有两种方法可以读取原始数据:无缓冲 (或标准) 方法和缓冲方法。 无缓冲区方法一次获取一个 RAWINPUT 结构的原始数据,并且足以用于许多 HID。 在这里,应用程序调用 GetMessage 以获取 WM_INPUT 消息。 然后,应用程序使用包含在 WM_INPUT 中的 RAWINPUT 句柄调用 GetRawInputData。 有关示例,请参阅 执行原始输入的标准读取。
相比之下,缓冲方法一次获取 RAWINPUT 结构的数组。 这是为可以生成大量原始输入的设备提供的。 在此方法中,应用程序调用 GetRawInputBuffer 来获取 RAWINPUT 结构的数组。 请注意, NEXTRAWINPUTBLOCK 宏用于遍历 RAWINPUT 结构的数组。 有关示例,请参阅 执行原始输入的缓冲读取。
若要解释原始输入,需要有关 HID 的详细信息。 应用程序通过使用设备句柄调用 GetRawInputDeviceInfo 来获取设备信息。 此句柄可以来自 WM_INPUT,也可以来自 RAWINPUTHEADER 的 hDevice 成员。
bool Dialog::nativeEvent(const QByteArray &eventType, void *message, long *result)
{MSG* msg = (MSG*)message;LPBYTE lpb;RAWINPUT* raw;UINT dwSize;if(msg->message == WM_INPUT){GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, nullptr, &dwSize, sizeof(RAWINPUTHEADER));lpb = new BYTE[dwSize];if (lpb == nullptr) {qDebug() << "内存分配失败。";return false;}if (GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) {qDebug() << "GetRawInputData 返回的大小不正确!";delete[] lpb;return false;}raw = (RAWINPUT*)lpb;if (raw->header.dwType == RIM_TYPEHID) {qDebug() << "接收到 HID 输入。";//在这里可以使用raw->data.hid.bRawData解析数据。}delete[] lpb;}return false;
}
相关文章:
Qt 使用RAW INPUT获取HID触摸屏,笔设备,鼠标的原始数据,最低受支持的客户端:Windows XP [仅限桌面应用]
在开发绘图应用程序时,经常会需要读取笔设备的数据,通过对笔数据的解析,来判断笔的坐标,粗细。如果仅仅只是读取鼠标的坐标,就需要人为在应用程序端去修改笔的粗细,并且使用体验不好,如果可以实…...
easyexcel导出excel文件到s3服务器
导出excel文件是开发中常见的需求 常见的做法一般是直接通过请求接口响应对象HttpServletResponse把文件输出 我们可以使用原生的poi工具类操作.也可以使用easypoi.easyexcel等基于poi二次封装的工具处理 下面是代码 /*** 导出列表** param request* param response*/Overri…...
xss.haozi.me靶场“0x0B-0x12”通关教程
君衍. 一、0x0B 实体编码绕过二、0x0C script绕过三、0x0D 注释绕过四、0X0E ſ符号绕过五、0x0F 编码解码六、0x10 直接执行七、0x11 闭合绕过八、0x12 闭合绕过 XSS-Labs靶场“1-5”关通关教程 XSS-Labs靶场“6-10”关通关教程 Appcms存储型XSS漏洞复现 XSS-Labs靶场“11-13、…...
linux--redhat系统Yum源配置
1)说明 redhat yum命令使用报错解决-重新配置yum源 解决--更改yum源 2)更改yum源 (1)进入源目录 cd /etc/yum.repos.d/ (2)备份 redhat 默认源 mv redhat.repo redhat.repo-bak (3)…...
el-Switch 开关二次确认
前言 最近在做毕设,有个需求是点击按钮控制用户的状态是否禁用,就看到element有个switch组件可以改造一下,就上网看了一下,结果为了这个效果忙活了很久。。。所以说记录一下,让大家少踩坑。 前置条件 先看完我的需求再…...
(二)丶RabbitMQ的六大核心
一丶什么是MQ Message Queue(消息队列)简称MQ,是一种应用程序对应用程序的消息通信机制。在MQ中,消息以队列形式存储,以便于异步传输,在MQ中,发布者(生产者)将消息放入队列ÿ…...
微信小程序实现上下手势滑动切换
效果图 思路 实现一个微信小程序的复合滚动页面,主要通过Swiper组件实现垂直方向的轮播功能,每个轮播项内部使用Scroll-View组件来展示可垂直滚动的长内容,如图片和文本。 代码 <!-- wxml --> <view class"swiper-container…...
详解命令docker run -d --name container_name -e TZ=Asia/Shanghai your_image
docker run 是Docker的主要命令,用于从镜像启动一个新的容器。下面详细解释并举例说明 -d, --name, -e TZ 参数的用法: -d 或 --detach: 这个标志告诉Docker以守护进程(后台)模式运行容器。这意味着当你执行 docker ru…...
javaEE7
1. <% page pageEncoding"UTF-8"%><% page import"java.io.*"%> <% page import"java.util.*"%> <% page import"java.math.*"%> <html> <head><title>网站计数器</title></head&…...
int与integer的区别
int和integer都是用来表示整数的数据类型,但有一些细微的区别。 int是Java中的基本数据类型,它可以存储整数值。int类型在内存中占4个字节,范围为-2,147,483,648到2,147,483,647。int类型使用最频繁,因为它的存储空间较小&#x…...
Golang实现Redis分布式锁(Lua脚本+可重入+自动续期)
Golang实现Redis分布式锁(Lua脚本可重入自动续期) 1 概念 应用场景 Golang自带的Lock锁单机版OK(存储在程序的内存中),分布式不行 分布式锁: 简单版:redis setnx》加锁设置过期时间需要保证原…...
音乐播放器-C#实现
音乐播放器-C#实现 目录 一、 代码介绍 二、 音乐播放器-C#实现 三、 音乐播放器-C#实现 四、 音乐播放器-C#实现 五、 音乐播放器-C#实现 代码介绍 代码中使用了.NET框架中的System.Media命名空间来处理音频文件的播放和控制。这段代码创建了一个简单的音乐播放器界…...
如何本地搭建hMailServer邮件服务
文章目录 前言1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 前言 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpola…...
裸机编程的几种模式、架构与缺陷。
大多数嵌入式的初学者都是从单片机裸机编程开始的,对于初学者来说,裸机编程更加直观、简单,代码所见及所得,调试也非常方便,区别于使用操作系统需要先了解大量的操作系统基础知识,调度的基本常识࿰…...
TSINGSEE青犀视频AI方案:数据+算力+算法,人工智能的三大基石
背景分析 随着信息技术的迅猛发展,人工智能(AI)已经逐渐渗透到我们生活的各个领域,从智能家居到自动驾驶,从医疗诊断到金融风控,AI的应用正在改变着我们的生活方式。而数据、算法和算力,正是构成…...
Linux认识与学习BASH
Linux认识与学习BASH 认识BASH这个Shellshell是什么系统的合法shell与/etc/shells功能Bash Shell的功能查询命令是否为Bash shell 的内置命令(type)命令的执行与快速编辑按钮 shell的变量功能什么是变量?变量的使用与设置:echo、变量设置规则、unset环境…...
Python JSON 序列化以及反序列化 文件读写
Python JSON 序列化以及反序列化 JSON (JavaScript Object Notation) 是一种轻量级的文本数据存储格式。JSON 数据通常存储在字符串中,即JSON字符串,其实就是一字符串,只是带有一定的格式,可以被解析。本文使用的 Python 版本为3…...
Spring MVC 返回JSON数据
1. 前置准备 1.1 导入jackson依赖 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.0</version> </dependency>1.2 添加json数据转化器 EnableWebMvc …...
前端基础——HTML傻瓜式入门(1)
该文章Github地址:https://github.com/AntonyCheng/html-notes 在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址:https://blog.c…...
【AI】如何创建自己的自定义ChatGPT
如何创建自己的自定义ChatGPT 目录 如何创建自己的自定义ChatGPT大型语言模型(LLM)GPT模型ChatGPTOpenAI APILlamaIndexLangChain参考推荐超级课程: Docker快速入门到精通Kubernetes入门到大师通关课本文将记录如何使用OpenAI GPT-3.5模型、LlamaIndex和LangChain创建自己的…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
