1

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=Intel(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
主要= y
-> bpp=32 w=1920 h=1080 fps=60

1 -> \.\DISPLAY2
str=Intel(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}\0001
主要=n
-> bpp=32 w=1920 h=1080 fps=60

现在,通过这篇文章,我可以获得每台显示器的 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 (Standard)' 找到值 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 首先出现,然后是显示器的 EDID LG。因此我不能在两个枚举中使用出现的顺序,它们没有直接联系(否则没有问题要问)。

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

  3. 我知道这个问题及其答案,但接受的答案对我没有帮助,因为它希望DISPLAY_DEVICE.DeviceID位于注册键\HKLM\System\CurrentControlSet\Enum\DISPLAY中,而我从EnumDisplayDevices得到的位于\HKLM\ System\CurrentControlSet\Enum\PCI(参见输出中的“id”行)。

  4. 我尝试按照此问题中的建议使用标志 EDD_GET_DEVICE_INTERFACE_NAME,但我没有得到已接受答案中所示的 deviceID。

  5. 如何获取关键路径

我检查了SetupAPI 函数列表,但找不到如何连接显示信息和 SetupDiOpenDevRegKey 的结果。

我错过了什么?我设置错了哪个标志?我可以以某种方式使用 SetupDiOpenDevRegKey 返回的密钥路径吗?

非常感谢。

4

1 回答 1

0

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

第一次通话lpDevice=NULL和第二次通话lpDevice=DisplayDevice.DeviceName

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

于 2017-04-06T09:21:14.823 回答