我找到了7种不同的方法来枚举连接到计算机上的监视器。但是所有的解决方案都给出了不同的结果(监视器的数量和每个监视器的信息)。
这些解决方案包括:
使用著名的
EnumDisplayDevices
使用Windows Management Instrumentation (WMI):
使用以下查询:SELECT * FROM WmiMonitorID
在root\\WMI
命名空间中。再次使用WMI:
使用新查询:SELECT * FROM Win32_DesktopMonitor
在root\\CIMV2
命名空间中。使用Setup API:
首先调用SetupDiGetClassDevs
来检索设备信息集,然后使用SetupDiEnumDeviceInfo
进行迭代。使用DirectX图形基础设施(DXGI),首先使用
IDXGIFactory::EnumAdapters
,然后使用IDXGIAdapter::EnumOutput
使用连接和配置显示器 (CCD) API:
QueryDisplayConfig
(QDC_ALL_PATHS, &numPathArrayElements, pathInfoArray, &numModeInfoArrayElements, modeInfoArray, nullptr);
我试图通过MSDN文档理解这些方法之间的区别,但徒劳无功。
观察结果
从我的观察中得出以下结论:
- WmiMonitorID和Setup API查询返回已连接的(但不一定是活动的)显示器列表。
- Win32_DesktopMonitor WMI查询返回错误(至少是意外的)结果(即使在另一个显示器上不活动和桌面上,仍只枚举了1个监视器)。
- EnumDisplayDevices返回活动设备列表(除非只有1个监视器处于活动状态并连接了其他监视器)
- EnumDisplayMonitors和DXGI查询返回活动监视器列表。
- CCD 似乎是最可靠的方法(提供目标和源之间所有可能的路径)。
问题
使用这些方法时,我真正应该期望什么结果(连接的显示器列表、安装的显示器列表、活动显示器列表)?如果我使用镜像显示或扩展显示会怎样?如果计算机有多个图形卡但没有多个输出,会怎样?
额外奖励:某些方法(DXGI、EnumDisplayDevices、CCD)使用一种层次结构,其中包含 Adapter-Monitor 的概念,但不会给出相同的适配器和监视器链接。那么,DXGI、CCD、EnumDisplayDevices 中适配器的定义是什么?
GetSystemMetrics(SM_CMONITORS)
仅计算可见的显示器。这与EnumDisplayMonitors
不同,后者枚举了可见的显示器和与镜像驱动程序相关联的不可见伪监视器。不可见的伪监视器与用于远程或其他目的的应用程序绘图镜像的伪设备相关联。 - mikew