将 HID 触摸设备与 Pnp 监视器相关联

Associate HID Touch Device with Pnp Monitor

我正在开发一种工具,可以显示我们在工作中使用的系统上各种硬件组件的状态。目前,我们有 16 个触摸屏显示器(全部由 3M 提供)插入 Windows 10 盒子。我需要验证任何给定的显示器是否具有被 windows 识别的关联触摸屏。这是为了评估系统是否存在任何硬件故障,即电缆损坏、USB 端口损坏、显示器损坏等。我们看到这种情况的次数比我们愿意承认的要多,通常情况下显示器的显示屏可以正常工作,但两端的 USB 控制器退出并需要 unplugging/plugging 重新设置

很遗憾,由于工作限制,我的代码发布将受到限制。

我可以枚举通过 winapi EnumDisplayDevices and EnumerateDisplayMonitors. I am able to build a list of all the HID touch screen devices using HIDApi.

插入系统的所有监视器

从这里我不知道去哪里 link 这两件事在一起,如果可能的话。我的第一个想法是 HID 设备信息应该具有某种由调用 EnumDisplayDevices 和 EnumerateDisplayMonitors 的结果共享的标识符,但我没有发现这种情况。另一种可能性是将监视器的 coordinates/size 与其中一个触摸控制器负责的区域进行比较。同样,不确定是否可行。

简而言之,有没有办法通过 C++ 将 Touch 设备与其对应的显示器相关联?

根据评论中的建议并深入研究注册表,我找到了一种方法 link 将控制器触摸到监视器。

使用 HIDApi,您可以轮询系统并找到您需要监控的所有触摸控制器的列表。我根据我们正在使用的显示器的 VID 进行了过滤。路径的示例 return 值如下所示:

"\\?\hid#vid_0596&pid_0520&col02#8&33d9e616&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}"

粗体部分可用于link到HKLM/Software/Microsoft/Wisp/Pen/Digimon中的条目。一个示例条目是这样的:

"\\?\HID#VID_0596&PID_0520&Col03#8&33d9e616&0&0002#{4d1e55b2-f16f-11cf-88cb-001111000030}" "\\?\DISPLAY#MSY1C2B#7&1083071f&0&UID524#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}"

第一个粗体匹配通过 HIDApi 找到的数据,第二个粗体、监视器名称和 UID 列在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY 中。在这里您可以使用监视器名称和 UID 的组合来查找驱动程序条目。以下是示例驱动程序条目:

{4d36e96e-e325-11ce-bfc1-08002be10318}\0010

然后可以使用最后一个粗体数字与从 EnumDisplayDevices() 编辑的 DeviceID return 匹配。以下是示例 DeviceID:

"MONITOR\MSY1C2B\{4d36e96e-e325-11ce-bfc1-08002be10318}\0010".

然后您可以使用这个粗体部分来匹配从 EnumDisplayMonitors() return编辑的监视器名称。

我认为您很幸运,该驱动程序后缀与您的显示器配置相匹配。在我的 Windows 10 多显示器设置中,当我按照您的描述在驱动程序条目中使用这个数字查找它们时,我得到了错误的显示。

将 HID 设备与显示器相关联的可靠方法似乎是:

  1. 调用GetRawInputDeviceList()获取HID设备
  2. RIDI_DEVICEINFO调用GetRawInputDeviceInfo()来确定UsageUsagePage
  3. 调用 GetRawInputDeviceInfo()RIDI_DEVICENAME 以获得形式为 \\?\HID#VID_0EEF&PID_7200&Col01#6&152cc7f9&1&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
  4. 的设备字符串
  5. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wisp\Pen\Digimon 处查询映射 table 的注册表并查找显示设备名称。在我的例子中,HID 名称都以 20- 为前缀,但其余部分似乎与 GetRawInputDeviceInfo() 查询的名称完全匹配。作为在没有匹配项的情况下的后备方法,我还按照 Clay Brooks 在他的回答中描述的那样解析了中间部分。
  6. 在循环中用 lpDevice 的空指针和 dwFlags 的 0 调用 EnumDisplayDevices(),直到函数 returns 为零。
  7. 在每次循环迭代中,再次调用 EnumDisplayDevices(),当前设备为 lpDeviceEDD_GET_DEVICE_INTERFACE_NAMEdwFlags,并观察到它 returns DeviceID 格式为 \\?\DISPLAY#ELO2243#5&607b301&0&UID24833#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
  8. 循环直到找到 HID <-> 显示匹配项并获取 "outer" EnumDisplayDevices() 调用返回的 DeviceName,它应该类似于 \.\DISPLAY3