I am developing a tool that displays a status about various hardware components on a system we use at work. Currently, we have 16 touch screen monitors (all by 3M) plugged in to a Windows 10 box. I need to verify that any given monitor has an associated touch screen recognized by windows. This is to assess the system for any hardware malfunctions i.e. bad cable, bad USB port, bad Monitor, etc. We see this more than we would like to admit, usually where a monitor's display will be working fine but the USB controller on either end drops out and needs to be reset by unplugging/plugging back in
Unfortunately my code posting will be limited due to work constraints.
I can enumerate all of the monitors plugged in to the system via winapi's EnumDisplayDevices and EnumerateDisplayMonitors. I am able to build a list of all the HID touch screen devices using HIDApi.
From here I have no direction on where to go to link these two things together, if it is even possible. My first thought was the HID device information should have some sort of identifier shared by the results of calling the EnumDisplayDevices and EnumerateDisplayMonitors, but I have not found this to be the case. Another possibility would be to compare the coordinates/size of a monitor to a region that one of the touch controllers is responsible for. Again, not sure if that is possible.
In short, is there a way to associate a Touch device with it's corresponding monitor via c++?
After the suggestions in the comments and looking deeper into the registry, I've found a way to link Touch controllers to a monitor.
Using HIDApi, you can poll the system and find a list of all the Touch Controllers you need to monitor. I filtered by the VID of the monitors we are using. A sample return value for the path looks something like this:
"\\?\hid#vid_0596&pid_0520&col02#8&33d9e616&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}"
The bold part can be used to link to the entries in HKLM/Software/Microsoft/Wisp/Pen/Digimon. An example entry is this:
"\\?\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}"
The first bold matches the data found through HIDApi and the second set of bolding, the monitor name and a UID, is listed in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\DISPLAY. Under here you can use the combination of monitor name and UID to find the Driver entry. Below is a sample driver entry:
{4d36e96e-e325-11ce-bfc1-08002be10318}\0010
The last bold number can then be used to match up with a DeviceID returned from EnumDisplayDevices(). Below is a sample DeviceID:
"MONITOR\MSY1C2B\{4d36e96e-e325-11ce-bfc1-08002be10318}\0010".
Then you can use this bolded section to match up to names of monitors returned from EnumDisplayMonitors().
I think you were just lucky that this driver suffix matched your monitor configuration. In my Windows 10 multi-monitor setup I get wrong displays when I look them up with this number in the driver entry as you described.
A reliable way for associating a HID device with a display seems to be:
GetRawInputDeviceList()
to obtain the HID devicesGetRawInputDeviceInfo()
withRIDI_DEVICEINFO
to determineUsage
andUsagePage
GetRawInputDeviceInfo()
withRIDI_DEVICENAME
to get a device string in the form\\\\?\\HID#VID_0EEF&PID_7200&Col01#6&152cc7f9&1&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wisp\Pen\Digimon
and look up the display device name. In my case the HID names are all prefixed with20-
there but the remaining part seems to match the name queried byGetRawInputDeviceInfo()
exactly. As a fallback method in case there is no match, I also parse the middle part as Clay Brooks described in his answer.EnumDisplayDevices()
with a null pointer forlpDevice
and 0 fordwFlags
in a loop until the function returns zero.EnumDisplayDevices()
again with the current device aslpDevice
andEDD_GET_DEVICE_INTERFACE_NAME
fordwFlags
and observe that it returns aDeviceID
in the form\\\\?\\DISPLAY#ELO2243#5&607b301&0&UID24833#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
DeviceName
returned by the "outer"EnumDisplayDevices()
call which should be something like\\.\DISPLAY3