Enumerating monitors on a computer
Asked Answered
T

2

53

I have found 7 different ways to enumerate the monitors attached to the computer. But all solutions give different results (number of the monitors and information on each monitor).

These solutions are:

  1. Using the famous EnumDisplayDevices

  2. Using EnumDisplayMonitors

  3. Using the Windows Management Instrumentation (WMI):
    With the following query: SELECT * FROM WmiMonitorID in the root\\WMI namespace.

  4. Again using the WMI:
    With the new query: SELECT * FROM Win32_DesktopMonitor in the root\\CIMV2 namespace.

  5. Using the Setup API:
    By first calling SetupDiGetClassDevs to retrieve the device information set then, iterating with SetupDiEnumDeviceInfo

  6. Using the DirectX Graphics Infrastructure (DXGI)
    With first IDXGIFactory::EnumAdapters, then IDXGIAdapter::EnumOutput

  7. Using the Connecting and Configuring Displays (CCD) APIs:
    QueryDisplayConfig(QDC_ALL_PATHS, &numPathArrayElements, pathInfoArray, &numModeInfoArrayElements, modeInfoArray, nullptr);

I've tried to understand precisely the difference between all theses methods with the MSDN reference, in vain.

Observations

From what I've observed:

  • The WmiMonitorID and Setup API queries return the list of connected (not necessarily active) displays.
  • The Win32_DesktopMonitor WMI query returns wrong (at least unexpected) result (only 1 monitor enumerated even when inactive and desktop on another monitor).
  • EnumDisplayDevices returns the list of active devices (except when only 1 monitor is active with other monitor connected)
  • EnumDisplayMonitors and DXGI queries return the list of active monitors.
  • CCD seems to be the most reliable method (gives all possible paths between targets and sources).

Questions

What result should I really expect when using each of these methods (list of connected displays, list of installed displays, list of active displays)? What if I use Mirrored displays or Extended displays? What if the computer has multiple graphics cards without multiple outputs?

Bonus: Some methods (DXGI, EnumDisplayDevices, CCD) use a kind of hierarchy with Adapter-Monitor. But doesn't give the same links between Adapters and Monitors. So, what is the définition of an adapter for DXGI? for CCD? for EnumDisplayDevices?

Tarbox answered 2/8, 2013 at 17:15 Comment(6)
I suppose the trick here will be to know if they all call the same lowest level API and use thatCajun
I guess the right thing to do is to ask a more precise question, such as "How to enumerate X when doing Y ?", where X is monitor, physical device, logical device, etc. and Y is your goal. Having your goal at hand will certainly let you filter out some possibilities. As your (deep and very accurate) research shows, things are not as simple as you thought beforehand, and there is no possible answer using words such as "monitor" and "computer".Candiecandied
@Cedric Bignon I don't use Windows, but why don't you write some test code that uses all of that uses each of those methods, perhaps in separate files and then disassemble the binaries to see if they are making the same system calls?Neapolitan
I second @tibo. Your question is too open. Add to that there are also differences from one version of Windows to another (some DXGI only for Windows 8, etc.). One observation that can be useful: the .NET framework (which can be considered as an abstraction layer over Windows) defines the Screen class (System.Windows.Forms.Screen) that is completely based on EnumDisplayMonitors/GetMonitorInfo (this one tells the device name).Tocci
there is another: GetSystemMetrics(SM_CMONITORS) counts only visible display monitors. This is different from EnumDisplayMonitors, which enumerates both visible display monitors and invisible pseudo-monitors that are associated with mirroring drivers. An invisible pseudo-monitor is associated with a pseudo-device used to mirror application drawing for remoting or other purposes.Chamaeleon
My opinion differs from the posters above. I found that question EXTREMELY helpful, cause i am struggling with the EXACT same stuff at the moment. Especially the mirroring and extended stuff confuses me a lot. I tested most of the same things, the OP did, and the results are very confusing. So i am curious what answers i will find here below. But nonetheless big Kudos from my side, to the OP! Maybe not the most precise question, but a very complete and a very accurate one.Slippery
K
13

I don't know all of these API's but I do remember some of them (bad memories) so here's what I can remember and find from poking around in MSDN and playing with wbemtest which I'm surprised I even remember. I recognize that this answer is probably not ALL that you were hoping for.

For the illustrations below (and all of these illustrations are on my Dell Latitude laptop I'm typing this to you on and I have logically two monitors connected to it through the docking station). But, the laptop is closed and the laptop screen is therefore not visible.

If I go into display properties, I see only one screen.

enter image description here

Connected to CIMv2

select * from Win32_DesktopMonitor;

returns two instances.

enter image description here

DesktopMonitor1 is the external display (GenericPNPDisplay) and DesktopMonitor1 is the default monitor (screen).

Connected to root\WMI

select * from WMIMonitorID;

gives me only one instance and that instance is the external monitor (I know this because the manufacturer name is HP). (HWP26CE is the identifier for HP w2408, see here)

enter image description here

Then, there is a difference between display adapters and monitors. EnumDisplayDevices shows you adapters and EnumDisplayMonitors shows you the monitors. The former is primarily to just enumerate the adapters but the latter allows you to provide a clipping rectangle and determine which monitors that clipping rectangle happens to land on. This becomes useful when you have multiple active monitors and someone decides to do something that causes a draw that will straddle multiple monitors. You get to specify a callback to EnumDisplayMonitors and that callback will be invoked with some parameters (if memory serves me correctly one of the parameters was a subset of the specified clipping rectangle that lands on the specified monitor).

I vaguely remember SetupDiEnumDeviceInfo and I think it gives you the HDEVINFO for each interface and therefore it would (I believe) give you only one entry on my configuration because I have only one adapter. Then you'd have to do something to go get the SP_DEVINFO_DATA.

I have never used DirectX and the other API so I'll shut up about those two. Hopefully someone else can pipe up about those two and you may get a complete answer!

Killoran answered 15/8, 2013 at 23:12 Comment(0)
N
1

In case it is relevant in your case, when using Qt 5.x, you can use the QGuiApplication::screens() method (http://qt-project.org/doc/qt-5.1/qtgui/qguiapplication.html#screens) to enumerate all displays.

Or if it is not relevant, you can always have a look into their source code, how they enumerate the displays and get all relevant properties (also regarding mirroring, extended desktops, and so on).

Nisa answered 14/8, 2013 at 13:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.