c++ 如何将PHYSICAL_MONITOR与监护仪DeviceID关联

uqxowvwt  于 2023-06-25  发布在  其他
关注(0)|答案(3)|浏览(185)

我需要帮助将从GetPhysicalMonitorsFromHMONITOR获得的PHYSICAL_MONITOR与监视器DISPLAY_DEVICE.DeviceID(例如:“\?\DISPLAY#GSM59AB#5&932a802&1&UID261#{e6 f07 b5 f-ee 97 - 4a 90-b 076 - 33 f57 bf 4 eaa 7}”),它来自与标志EDD_GET_DEVICE_INTERFACE_NAME一起使用的EnumDisplayDevices,或者以某种方式从DISPLAY_DEVICE.DeviceID获取PHYSICAL_MONITOR,反之亦然。
我需要这两者的关联,因为:

  1. HANDLE PHYSICAL_MONITOR.hPhysicalMonitor将用于lowlevelmonitorconfigurationapi,因为我需要向监视器发送命令。
  2. DISPLAY_DEVICE.DeviceID用于使用SetupAPI从注册表中获取EDID结构(前128个字节对我来说足够了,只需要制造商代码和型号)
    1和2完成后,问题是将id与物理监视器关联。Also it is possible to get都只使用SetupAPI从注册表监视EDID,但在这种情况下,不可能获得物理监视器HANDLE。
    1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    我还注意到一件事:以下代码枚举所有监视器:
  1. DWORD DispNum = 0;
  2. DISPLAY_DEVICE DisplayDevice;
  3. // Initialize DisplayDevice.
  4. ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
  5. DisplayDevice.cb = sizeof(DisplayDevice);
  6. while ((EnumDisplayDevices(NULL, DispNum, &DisplayDevice, 0)))
  7. {
  8. std::wstring deviceName = DisplayDevice.DeviceName;
  9. DISPLAY_DEVICE DisplayDeviceM;
  10. ZeroMemory(&DisplayDeviceM, sizeof(DisplayDeviceM));
  11. DisplayDeviceM.cb = sizeof(DisplayDeviceM);
  12. int monitorIndex = 0;
  13. while (EnumDisplayDevices(deviceName.c_str(), monitorIndex, &DisplayDeviceM, EDD_GET_DEVICE_INTERFACE_NAME))
  14. {
  15. std::wstring monitorID = DisplayDeviceM.DeviceID;
  16. ++monitorIndex;
  17. }
  18. DispNum++;
  19. }

与此相同的顺序:

  1. BOOL CALLBACK EnumProc2(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
  2. {
  3. LPPHYSICAL_MONITOR pMons = NULL;
  4. DWORD i, mcnt;
  5. MONITORINFOEX mi;
  6. ZeroMemory(&mi, sizeof(mi));
  7. mi.cbSize = sizeof(mi);
  8. GetMonitorInfo(hMonitor, &mi);
  9. DISPLAY_DEVICE dd;
  10. ZeroMemory(&dd, sizeof(dd));
  11. dd.cb = sizeof(dd);
  12. EnumDisplayDevices(mi.szDevice, 0, &dd, EDD_GET_DEVICE_INTERFACE_NAME);
  13. monitorModelMnufac MdlManuf = findMonitorModelManufactFromEDID(dd.DeviceID);
  14. if (!GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &mcnt)) return TRUE;
  15. pMons = (LPPHYSICAL_MONITOR)malloc(mcnt * sizeof(PHYSICAL_MONITOR));
  16. if (GetPhysicalMonitorsFromHMONITOR(hMonitor, mcnt, pMons))
  17. for (i = 0; i < mcnt; i++)
  18. {
  19. AddToMonHandles(pMons[i].hPhysicalMonitor, MdlManuf);
  20. }
  21. free(pMons);
  22. return TRUE;
  23. }

物理监视器的HANDLE是0,1,2等等,所以我可以从“monitorIndex”创建HANDLE,但我不确定这样做是否安全。
我还在注册表中查找物理显示器句柄,但没有任何内容。
还发现了一个有用的函数VideoPortDDCMonitorHelper,但正如我在谷歌上搜索的那样,它需要在驱动程序/过滤器中使用,不能从一个简单的可执行文件中使用。
还试图扭转windows dll,所有的调用似乎是从WIN32U.dll和Ghidra不想反编译它,或者我只是在这方面的菜鸟。
帮帮我吧,伙计们:)

gudnpqoy

gudnpqoy1#

我已经寻找了EnumDisplayDevicesGetPhysicalMonitorsFromHMONITOR之间的联系,目的有点类似;我需要每个显示器的唯一ID,以及设置VCP值的能力。
一些related posts不给予我信心有一个简单的答案。
我不确定它是否有任何帮助,但我发现ControlMyMonitor很有用。
运行:

  1. controlmymonitor.exe /smonitors

为每个显示器生成信息:

  1. Monitor Device Name: "\\.\DISPLAY1\Monitor0"
  2. Monitor Name: "VX4380 SERIES"
  3. Serial Number: ""
  4. Adapter Name: "NVIDIA GeForce GTX 760"
  5. Monitor ID: "MONITOR\VSC5B34\{4d36e96e-e325-11ce-bfc1-08002be10318}\0004"

您可以轻松设置VCP值。例如,告诉显示器更改为HDMI 1:

  1. controlmymonitor.exe /SetValue "\\.\DISPLAY1\Monitor0" 60 17

此外,如果调用EnumDisplayMonitors以获取PHYSICAL_MONITOR.hPhysicalMonitor,然后将该句柄传递给CapabilitiesRequestAndCapabilitiesReply,则会产生以下输出:

  1. prot(monitor)
  2. type(LCD)
  3. model(VX4380)
  4. cmds(01 02 03 07 0C E3 F3)
  5. vcp(02 04 05 08 0B 0C 10 12 14(01 08 06 05 04 0B) 16 18 1A 52 60(0F 10 11 12) 62 87 8D(01 02) A5 AC AE B2 B6 C6 C8 CA CC(01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 12 14 16 17 1A 1E 24) D6(01 04 05) DC(00 01 02 03 05 08 1F) DF E0(00 01 02 03 14) EC(01 02 03) F6 F7(42 FF) FA(00 01 02) FB FC FD FE(00 01 02 04) FF)
  6. mswhql(1)
  7. asset_eep(40)
  8. mccs_ver(2.2)

刚好包含了型号。
希望上面的命令产生的一些信息能帮助你实现目标。
祝你好运!

展开查看全部
x6492ojm

x6492ojm2#

我发现了一些有用的信息,希望对你有帮助。

  1. ...
  2. while ((EnumDisplayDevices(NULL, DispNum, &DisplayDevice, 0)))
  3. {
  4. std::wstring deviceName = DisplayDevice.DeviceName;
  5. DISPLAY_DEVICE DisplayDeviceM;
  6. ZeroMemory(&DisplayDeviceM, sizeof(DisplayDeviceM));
  7. DisplayDeviceM.cb = sizeof(DisplayDeviceM);
  8. int monitorIndex = 0;
  9. while (EnumDisplayDevices(deviceName.c_str(), monitorIndex, &DisplayDeviceM, EDD_GET_DEVICE_INTERFACE_NAME))
  10. {
  11. wcout << "deviceName:" << deviceName << endl;
  12. std::wstring monitorID = DisplayDeviceM.DeviceID;
  13. wcout <<"monitorID :"<< monitorID<< endl;
  14. ++monitorIndex;
  15. }
  16. DispNum++;
  17. }
  18. ...

输出:

  1. deviceName: \\.\DISPLAY1

然后使用EnumDisplayMonitors得到HMONITOR,并将其用作GetMonitorInfo的参数。

  1. static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
  2. {
  3. cout << "hmonitor:" << hMon << endl;
  4. MONITORINFOEX mi;
  5. mi.cbSize = sizeof(mi);
  6. GetMonitorInfo(hMon, (LPMONITORINFO)&mi);
  7. wcout << "deviceName: "<<mi.szDevice << endl;
  8. DWORD cPhysicalMonitors;
  9. BOOL bSuccess = GetNumberOfPhysicalMonitorsFromHMONITOR(hMon, &cPhysicalMonitors);
  10. cout << "GetNumber: " << bSuccess << ", number of physical monitors: " << cPhysicalMonitors << endl;
  11. LPPHYSICAL_MONITOR pPhysicalMonitors = (LPPHYSICAL_MONITOR)malloc(cPhysicalMonitors * sizeof(PHYSICAL_MONITOR));
  12. bSuccess = GetPhysicalMonitorsFromHMONITOR(hMon, cPhysicalMonitors, pPhysicalMonitors);
  13. cout << "GetPhysicalMonitor: " << bSuccess << endl
  14. << "Handle: " << pPhysicalMonitors->hPhysicalMonitor << endl
  15. << "Description: ";
  16. wcout << (WCHAR*)(pPhysicalMonitors->szPhysicalMonitorDescription) << endl;;
  17. D(pPhysicalMonitors->hPhysicalMonitor);
  18. DestroyPhysicalMonitors(cPhysicalMonitors, pPhysicalMonitors);
  19. free(pPhysicalMonitors);
  20. cout << "---------------------------------------" << endl;
  21. return TRUE;
  22. }
  23. ...
  24. EnumDisplayMonitors(0, 0, MonitorEnum, NULL);

输出:

  1. deviceName: \\.\DISPLAY1

如果两个输出相同,则它们对应于同一个监视器。最后,我们可以将得到的HMONITOR作为GetPhysicalMonitorsFromHMONITOR的参数,这样我们就可以得到我们需要的hPhysicalMonitor

展开查看全部
2eafrhcq

2eafrhcq3#

我也有一个困难的时间与这些东西,目前。
我试图找出,哪个是主显示设备的PHYSICAL_MONITOR。
我想更改主显示器的输入源,或者更确切地说是实际的“GetDesktopWindow()”显示器。但是我需要知道它是哪一个,因为同一个HMONITOR用于多个PHYSICAL_MONITOR。
我慢慢地得出结论,这根本不可能。:(

相关问题