Информация о связи из EnumDisplayDevices с информацией из SetupDiOpenDevRegKey (EDID)
Windows 7, конфигурации с несколькими мониторами.
Кросс-компиляция на Linux (opensuse 13.1) с gcc-mingw-5.1.0 (что может быть причиной того, что я не получил ожидаемые значения).
Я получаю список всех устройств отображения с 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 Graphics 4600
ID =PCI\VEN_8086&DEV_0416&SUBSYS_397817AA&REV_06
ключ =\Registry\Machine\System\CurrentControlSet\Control\Video{BBECD187-6CE4-47FD-915A-A4952B2AC000}\0000
первичные = у
-> bpp=32 w=1920 h=1080 fps=60
1 -> \. \ DISPLAY2
str = Intel® R Graphics 4600
ID =PCI\VEN_8086&DEV_0416&SUBSYS_397817AA&REV_06
ключ =\Registry\Machine\System\CurrentControlSet\Control\Video{BBECD187-6CE4-47FD-915A-A4952B2AC000}\0001
первичная = п
-> 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...
}
}
Вывод (часть его):
...
Найденное значение EDID для 'PnP-Monitor (Standard)'
Ключевой путь: "\REGISTRY\MACHINE\SYSTEM\ControlSet001\Enum\DISPLAY\LGD044F\4&1BDB7018&0&UID68092928\ Параметры устройства"
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 - это монитор LG, Дисплей № 2 - это Dell (настройка как таковая, и это можно проверить, когда я изменяю разрешение дисплея № 2), но сначала появляется EDID для монитора Dell, а затем - EDID LG. Поэтому я не могу использовать порядок появления в обоих перечислениях, они не связаны напрямую (иначе не возникает вопросов).
Я также не могу полагаться на информацию о разрешении или частоту синхронизации, поскольку она может быть одинаковой для всех мониторов.
Мне известен этот вопрос и его ответ, но принятый ответ мне не помогает, поскольку он ожидает, что DISPLAY_DEVICE.DeviceID находится в ключе reg \HKLM\System\CurrentControlSet\Enum\DISPLAY, а то, что я получаю от EnumDisplayDevices, находится в \ HKLM \ System \ CurrentControlSet \ Enum \ PCI (см. Строки "id" в выходных данных).
Я пытался использовать флаг EDD_GET_DEVICE_INTERFACE_NAME, как советовалось в этом вопросе, но я не получаю идентификатор устройства, как показано в принятом ответе.
Я проверил список функций SetupAPI, но не смог найти, как подключить отображаемую информацию и результат SetupDiOpenDevRegKey.
Что я упустил? Какой флаг я поставил неправильно? Можно ли как-то использовать путь к ключу, возвращенный SetupDiOpenDevRegKey?
Большое спасибо.
1 ответ
Вам нужно позвонить EnumDisplayDevices
функция дважды для каждого дисплея, например: Получение имени монитора с помощью EnumDisplayDevices
Первый звонок с lpDevice=NULL
и второй звонок с lpDevice=DisplayDevice.DeviceName
После этого вы получили ожидаемое значение в DISPLAY_DEVICE.DeviceID. Для моего случая это имеет следующее значение "MONITOR\DVAF001\{4d36e96e-e325-11ce-bfc1-08002be10"