枚举计算机上的监视器
我find了7种不同的方法来枚举连接到电脑的显示器。 但是所有的解决scheme都会给出不同的结果(监视器数量和每个监视器上的信息)。
这些解决scheme是:
-
使用着名的
EnumDisplayDevices
-
使用
EnumDisplayMonitors
-
使用Windows Management Instrumentation(WMI) :
使用以下查询:在root\\WMI
名称空间中SELECT * FROM WmiMonitorID
。 -
再次使用WMI :
使用新的查询:SELECT * FROM Win32_DesktopMonitor
位于root\\CIMV2
命名空间中。 -
使用安装程序API :
通过首先调用SetupDiGetClassDevs
来检索设备信息集,然后使用SetupDiEnumDeviceInfo
-
使用DirectXgraphics基础结构(DXGI)
首先使用IDXGIFactory::EnumAdapters
,然后使用IDXGIAdapter::EnumOutput
-
使用连接和configuration显示(CCD)API :
QueryDisplayConfig
(QDC_ALL_PATHS, &numPathArrayElements, pathInfoArray, &numModeInfoArrayElements, modeInfoArray, nullptr);
我试图正确地理解所有这些方法与MSDN参考之间的区别。
意见
从我观察到的情况来看:
- WmiMonitorID和Setup API查询返回已连接(不一定是活动)显示的列表。
- Win32_DesktopMonitor WMI查询返回错误 (至less意外)结果(即使在非活动状态下,也只能枚举1个监视器,而在另一个监视器上的桌面上)。
- EnumDisplayDevices返回活动设备列表(当连接其他监视器时只有1个监视器处于活动状态时除外)
- EnumDisplayMonitors和DXGI查询返回活动监视器的列表。
- CCD似乎是最可靠的方法(提供目标和来源之间的所有可能path)。
问题
当使用这些方法时(连接显示列表,已安装显示列表,活动显示列表),我应该得到什么结果? 如果我使用镜像显示器或扩展显示器怎么办? 如果电脑有多个显卡没有多个输出?
奖金:一些方法( DXGI , EnumDisplayDevices , CCD )使用适配器 – 监视器的一种层次结构。 但是在适配器和显示器之间并没有提供相同的链接。 那么, 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#屏幕; )枚举所有显示。
或者如果不相关,你可以随时查看他们的源代码,他们如何枚举显示并获取所有相关的属性(也就是镜像,扩展桌面等等)。