使用来自SetupDiOpenDevRegKey(EDID)

时间:2016-12-21 15:30:13

标签: windows display setupapi edid

Windows 7,多显示器配置。

使用gcc-mingw-5.1.0在linux(opensuse 13.1)上编译交叉(实际上可能是我没有得到预期值的原因)。

我获得了 EnumDisplayDevices 所有显示设备的列表: 代码:

int DispNum = 0;
DISPLAY_DEVICE DisplayDevice;
DEVMODE defaultMode;

// initialize DisplayDevice
ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
DisplayDevice.cb = sizeof(DisplayDevice);

while (EnumDisplayDevices(NULL, DispNum, &DisplayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
{
    ZeroMemory(&defaultMode, sizeof(DEVMODE));
    defaultMode.dmSize = sizeof(DEVMODE);

    if ((DisplayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE) && (DisplayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) && !(DisplayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)) {
        printf("%d -> %s\n\tstr=%s\n\tid=%s\n\tkey=%s\n\tprimary=%s\n", DispNum,DisplayDevice.DeviceName, DisplayDevice.DeviceString,
            DisplayDevice.DeviceID, DisplayDevice.DeviceKey,
            (DisplayDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) ? "y":"n");

        if (!EnumDisplaySettings((LPSTR)DisplayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &defaultMode) ) {
            puts("EnumDisplaySettings failed\n");
        } else {
            printf("    -> bpp=%d w=%d h=%d fps=%d\n",
                (int)defaultMode.dmBitsPerPel, (int)defaultMode.dmPelsWidth,
                (int)defaultMode.dmPelsHeight, (int)defaultMode.dmDisplayFrequency);
        }
    }

    // Reinit DisplayDevice just to be extra clean
    ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
    DisplayDevice.cb = sizeof(DisplayDevice);
    DispNum++;
}

输出(强调我的):

  

0 - > \。\ DISPLAY1
  str =英特尔(R)HD Graphics 4600
    id = PCI \ VEN_8086& DEV_0416& SUBSYS_397817AA& REV_06
      key = \ Registry \ Machine \ System \ CurrentControlSet \ Control \ Video {BBECD187-6CE4-47FD-915A-A4952B2AC000} \ 0000
      primary = y
       - > bpp = 32 w = 1920 h = 1080 fps = 60
  
  1 - > \。\ DISPLAY2
      str =英特尔(R)HD Graphics 4600
       ID = PCI \ VEN_8086&安培; DEV_0416&安培; SUBSYS_397817AA&安培; REV_06
      关键= \注册\计算机\系统\ CurrentControlSet \控制\影片{BBECD187-6CE4-47FD-915A-A4952B2AC000} \ 0001
      初级= N
       - > bpp = 32 w = 1920 h = 1080 fps = 60

现在,使用this article我可以获得每个监视器的EDID:

const GUID GUID_CLASS_MONITOR = {0x4d36e96e, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18};

HDEVINFO devInfo = NULL;
SP_DEVINFO_DATA devInfoData;
ULONG i = 0;

devInfo = SetupDiGetClassDevsEx(
    &GUID_CLASS_MONITOR, //class GUID
    NULL,NULL,
    DIGCF_PRESENT,
    NULL,NULL,NULL);

if (NULL == devInfo)
return -1;

for (i=0;ERROR_NO_MORE_ITEMS != GetLastError();i++) {
    memset(&devInfoData,0,sizeof(devInfoData));
    devInfoData.cbSize = sizeof(devInfoData);

    if (SetupDiEnumDeviceInfo(devInfo,i,&devInfoData))
    {
        // look for EDID with SetupDiOpenDevRegKey + RegEnumValue...
    }
}

输出(部分):

  

...
  找到'PnP-Monitor(标准)'的值EDID   键路径为'\ REGISTRY \ MACHINE \ SYSTEM \ ControlSet001 \ Enum \ DISPLAY \ LGD044F \ 4& 1BDB7018& 0& UID68092928 \ Device Parameters'
  
  00 ff ff ff ff ff ff 00 26 07 01 00 e7 03 00 00
  00 1a 01 03 80 00 00 00 02 00 00 00 00 00 00 00
  ....

我现在的问题是,如何链接这两个信息?如何将EDID归属到人机界面?

预期:

\。\ DISPLAY1 - > EDID1

\。\ DISPLAY2 - > EDID2

注释

  1. 显示器#1是LG显示器,显示器#2是戴尔(设置如此,当我更改显示器#2的分辨率时可以验证这一点),但戴尔显示器的EDID首先出现,然后是LG的EDID。 因此我不能在两个枚举中使用外观顺序,它们没有直接联系(否则无疑问)。

  2. 我也不能依赖于分辨率信息或同步速率,因为它可能对所有显示器都相同

  3. 我知道this question and its answer但是接受的答案对我没有帮助,因为它希望 DISPLAY_DEVICE.DeviceID 在reg键 \ HKLM \ System \中CurrentControlSet \ Enum \ DISPLAY 以及我从 EnumDisplayDevices 获得的内容位于 \ HKLM \ System \ CurrentControlSet \ Enum \ PCI 中(请参阅“id”中的“id”行)输出)。

  4. 我尝试将标记EDD_GET_DEVICE_INTERFACE_NAME用作 advised in this question,但我没有获得接受答案中显示的deviceID。

  5. how to get the key path

  6. 我已检查list of SetupAPI functions但无法找到如何连接显示信息和SetupDiOpenDevRegKey的结果。

    我错过了什么?哪个国旗我错了?可以以某种方式我使用SetupDiOpenDevRegKey返回的密钥路径?

    非常感谢。

1 个答案:

答案 0 :(得分:0)

您需要为每个显示调用两次EnumDisplayDevices函数,如下所示: Getting the monitor's name with EnumDisplayDevices

首先使用lpDevice=NULL拨打电话,然后使用lpDevice=DisplayDevice.DeviceName

进行第二次通话

之后,您在DISPLAY_DEVICE.DeviceID中收到了预期值。对于我的情况,它具有下一个值"MONITOR\DVAF001\{4d36e96e-e325-11ce-bfc1-08002be10"