枚举计算机上的监视器

我find了7种不同的方法来枚举连接到电脑的显示器。 但是所有的解决scheme都会给出不同的结果(监视器数量和每个监视器上的信息)。

这些解决scheme是:

  1. 使用着名的EnumDisplayDevices

  2. 使用EnumDisplayMonitors

  3. 使用Windows Management Instrumentation(WMI)
    使用以下查询:在root\\WMI名称空间中SELECT * FROM WmiMonitorID

  4. 再次使用WMI
    使用新的查询: SELECT * FROM Win32_DesktopMonitor位于root\\CIMV2命名空间中。

  5. 使用安装程序API
    通过首先调用SetupDiGetClassDevs来检索设备信息集,然后使用SetupDiEnumDeviceInfo

  6. 使用DirectXgraphics基础结构(DXGI)
    首先使用IDXGIFactory::EnumAdapters ,然后使用IDXGIAdapter::EnumOutput

  7. 使用连接和configuration显示(CCD)API
    QueryDisplayConfig (QDC_ALL_PATHS, &numPathArrayElements, pathInfoArray, &numModeInfoArrayElements, modeInfoArray, nullptr);

我试图正确地理解所有这些方法与MSDN参考之间的区别。

意见

从我观察到的情况来看:

  • WmiMonitorIDSetup API查询返回已连接(不一定是活动)显示的列表。
  • Win32_DesktopMonitor WMI查询返回错误 (至less意外)结果(即使在非活动状态下,也只能枚举1个监视器,而在另一个监视器上的桌面上)。
  • EnumDisplayDevices返回活动设备列表(当连接其他监视器时只有1个监视器处于活动状态时除外)
  • EnumDisplayMonitorsDXGI查询返回活动监视器的列表。
  • CCD似乎是最可靠的方法(提供目标和来源之间的所有可能path)。

问题

当使用这些方法时(连接显示列表,已安装显示列表,活动显示列表),我应该得到什么结果? 如果我使用镜像显示器或扩展显示器怎么办? 如果电脑有多个显卡没有多个输出?

奖金:一些方法( DXGIEnumDisplayDevicesCCD )使用适配器监视器的一种层次结构。 但是在适配器和显示器之间并没有提供相同的链接。 那么, DXGI适配器的定义是什么? 对于CCD ? 为EnumDisplayDevices

我不知道所有的这些API,但是我记得其中的一些(糟糕的回忆),所以我记得在MSDN中玩弄wbemtest,我记得我很记忆。 我承认这个答案可能不是你所希望的。

对于下面的插图(所有这些插图都在我的戴尔Latitude笔记本电脑上,我正在input这个给你,我逻辑上有两个显示器连接到它通过扩展坞)。 但是,笔记本电脑已closures,因此笔记本电脑屏幕不可见。

如果我进入显示属性,我只看到一个屏幕。

在这里输入图像说明

连接到CIMv2

 select * from Win32_DesktopMonitor; 

返回两个实例。

在这里输入图像说明

DesktopMonitor1是外部显示器(GenericPNPDisplay),DesktopMonitor1是默认显示器(屏幕)。

连接到根\ WMI

 select * from WMIMonitorID; 

给我只有一个实例,该实例是外部监视器(我知道这是因为制造商名称是HP)。 (HWP26CE是HP w2408的标识符,请参阅此处 )

在这里输入图像说明

然后,显示适配器和显示器之间是有区别的。 EnumDisplayDevices显示适配器和EnumDisplayMonitors显示您的监视器。 前者主要是枚举适配器,但后者允许您提供一个裁剪矩形,并确定裁剪矩形恰好落在哪个监视器上。 当你有多个活动监视器,并且有人决定做一些会导致跨越多个监视器的绘制时,这会变得很有用。 您可以指定一个callback给EnumDisplayMonitors ,并且callback将被调用一些参数(如果内存正确地服务我,其中一个参数是指定的剪辑矩形的一个子集,落在指定的监视器上)。

我隐约记得SetupDiEnumDeviceInfo ,我认为它给你每个接口的HDEVINFO ,因此它(我相信)只给你我的configuration一个条目,因为我只有一个适配器。 然后,你必须做一些事情去获得SP_DEVINFO_DATA

我从来没有使用DirectX和其他API,所以我会闭嘴这两个。 希望别人可以提出这两个,你可能会得到一个完整的答案!

如果你的情况是相关的,当使用Qt 5.x时,你可以使用QGuiApplication::screens()方法( http://qt-project.org/doc/qt-5.1/qtgui/qguiapplication.html#屏幕; )枚举所有显示。

或者如果不相关,你可以随时查看他们的源代码,他们如何枚举显示并获取所有相关的属性(也就是镜像,扩展桌面等等)。