X和Y坐标来自带有原始输入的Precision触摸板

X and Y coordinate from Precision touchpad with raw input

本文关键字:输入 原始 Precision 触摸 坐标      更新时间:2023-10-16

背景

我试图在Win10中用C++从精密触摸板中获取触摸坐标,程序在后台运行。


研究

Rawnput可以在后台获取数据。

我可以从微软获得这些使用id和页面的数据:

Member  Description                         Page    ID      Mandatory/Optional
X       X coordinate of contact position    0x01    0x30    Mandatory for T Optional for C
Y       Y coordinate of contact position    0x01    0x31    Mandatory for T Optional for C

根据这个答案,我可以将它们与HIDP_函数放在一起。


代码

case WM_INPUT: {
UINT dwSize;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
LPBYTE lpb = new BYTE[dwSize];
if (lpb == NULL) {
return 0;
}
RAWINPUT* raw = (RAWINPUT*)lpb;
GetRawInputDeviceInfo(raw->header.hDevice, RIDI_PREPARSEDDATA, NULL, &dwSize);
PHIDP_PREPARSED_DATA preparsedData = (PHIDP_PREPARSED_DATA)HeapAlloc(GetProcessHeap(), 0, dwSize);
GetRawInputDeviceInfo(raw->header.hDevice, RIDI_PREPARSEDDATA, preparsedData, &dwSize); 
HIDP_CAPS caps;
HidP_GetCaps(preparsedData, &caps);
USHORT capsLength = caps.NumberInputValueCaps;
PHIDP_VALUE_CAPS valueCaps = (PHIDP_VALUE_CAPS)HeapAlloc(GetProcessHeap(), 0, capsLength*sizeof(HIDP_VALUE_CAPS));
HidP_GetValueCaps(HidP_Input, valueCaps, &capsLength, preparsedData);
for (int i=0; i < capsLength; i++) {
CHAR value;
USHORT valuelength = valueCaps[i].BitSize * valueCaps[i].ReportCount;
HidP_GetUsageValueArray (HidP_Input, valueCaps[i].UsagePage, 0, valueCaps[i].NotRange.Usage, &value, valuelength, preparsedData, (PCHAR)raw->data.hid.bRawData, raw->data.hid.dwSizeHid);
std::cout << valueCaps[i].UsagePage << "  " << valueCaps[i].NotRange.Usage <<std::endl;
std::cout << value << std::endl;
switch(valueCaps[i].NotRange.Usage) {
case 0x30:    // X-axis
std::cout << "X: " << value << std::endl;
break;
case 0x31:    // Y-axis
std::cout << "y: " << value << std::endl;
break;
}
}
}

问题

我编译了代码并触摸了触摸板,但所有的输出都是:

0  0
³

我做错什么了吗?有人知道吗?

最小联系人ID,x,y,Contact,Scan的数据包可能包含多个联系人ID,x,y三元组用于多个点,然后必须使用valueCaps[i].LinkCollection来自valueCaps[]数组,从1增加最多5点。

HidP_GetUsageValue
(
HidP_Input, 
valueCaps[i].UsagePage, 
valueCaps[i].LinkCollection, //** !!!!!
valueCaps[i].NotRange.Usage, 
&value, 
preparsedData, 
(PCHAR)raw->data.hid.bRawData, 
raw->data.hid.dwSizeHid
);

如果valueCaps[i].UsagePage=1且valueCaps[i].NotRange.Usage=0x30(x),valueCaps[i].NotRange.Usage=0x30(y)

valueCaps[i]数组中的xLogicalMin、yLogicalMin、xLogicalMax和yLogicalMax非常重要

xLogicalMin = valueCaps[i].LogicalMin;
xLogicalMax = valueCaps[i].LogicalMax;
xPhysicalMin = valueCaps[i].PhysicalMin;
xPhysicalMax = valueCaps[i].PhysicalMax;

所有分配的空间必须正确释放!!!!!

按下触摸板的周界点以启动多个功能,或者像ASUS NumberPad上一样,触摸板上的网格单元也具有电容和有源笔的有限功能,一个手指轻击,沿着触摸板的四边移动以滚动/缩放,用一个手指移动光标并点击,按下,再移动,双击,单击并按第二个手指。两个手指操作计数在手指空间附近或远处随着坐标而增加。对于坐标;扫描";并在";联系人";触摸板上所有可能的复杂手势都可以访问。

调用您的程序

HidP_GetUsageValueArray(HidP_Input,valueCaps[i].UsagePage,0,valueCaps[i].NotRange.Usage,&value,valuelength,preparedData,(PCHAR)raw->data.hid.bRawData,raw->data.dwSizeHid);

返回HIDP_STATUS_NOT_VALUE_ARRAY=0xc011000b

在带PTP的笔记本上的数组中,valueCaps[]为valueCaps[i].UsagePage=1和valueCaps[i].NotRange.Usage=0x30/0x31。你可以使用简单的

HidP_GetUsageValue(HidP_ Input,valueCaps[i].UsagePage,0,valueCaps[i].NotRange.Usage,&价值准备的数据,(PCHAR)原始->数据.hid.bRawData,原始->数据.hid.dwSizeHid);

具有1/30小时、1/31小时

对应

_Must_inspect_result_NTSTATUS __stdcallHidP_GetUsageValue(HIDP_REPORT_TYPE ReportType中,USAGE UsagePage中,_在USHORT链接集合中,用法中,OutPULONG UsageValue,PHIDP_PREPARSED_DATA PreparsedData中,_在_reads_bytes_(ReportLength)PCHAR报告中,ULONG ReportLength中);

和value(UsageValue)必须为LONG!!!!!。

WM_INPUT的第一个值随UsagePage 0x0D用法0x51 一起出现

联系人ID唯一标识给定帧内的联系人0x0D 0x51强制