EnumDisplayDevices vs WMI Win32_DesktopMonitor, how to detect active monitors?
This is my current work-in-progress code for detecting the monitor device id, reliably.
CString DeviceID;
DISPLAY_DEVICE dd;
dd.cb = sizeof(dd);
DWORD dev = 0;
// device index
int id = 1;
// monitor number, as used by Display Properties > Settings
while (EnumDisplayDevices(0, dev, &dd, 0))
{
DISPLAY_DEVICE ddMon;
ZeroMemory(&ddMon, sizeof(ddMon));
ddMon.cb = sizeof(ddMon);
DWORD devMon = 0;
while (EnumDisplayDevices(dd.DeviceName, devMon, &ddMon, 0))
{
if (ddMon.StateFlags & DISPLAY_DEVICE_ACTIVE &&
!(ddMon.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
{
DeviceID.Format (L"%s", ddMon.DeviceID);
DeviceID = DeviceID.Mid (8, DeviceID.Find (L"\\", 9) - 8);
}
devMon++;
ZeroMemory(&ddMon, sizeof(ddMon));
ddMon.cb = sizeof(ddMon);
}
ZeroMemory(&dd, sizeof(dd));
dd.cb = sizeof(dd);
dev++;
}
Enumerating monitors on a computer
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.
Connected to CIMv2
select * from Win32_DesktopMonitor;
returns two instances.
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)
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!
(WMI) How do I know which monitor is connected to which graphics card? (c++ or c#)
How could I know that Dell is connected to Display1 and VE is
connected to Display2?
EnumDisplayMonitors seems to be what you need.
A simple C + + code sample,
#include <Windows.h>
#include <iostream>
#include <vector>
#include <cstdio>
std::wstring getMonitorName(HMONITOR monitor) {
DISPLAYCONFIG_TOPOLOGY_ID currentTopologyId;
MONITORINFOEXW info;
info.cbSize = sizeof(info);
GetMonitorInfoW(monitor, &info);
UINT32 requiredPaths, requiredModes;
GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &requiredPaths, &requiredModes);
std::vector<DISPLAYCONFIG_PATH_INFO> paths(requiredPaths);
std::vector<DISPLAYCONFIG_MODE_INFO> modes(requiredModes);
QueryDisplayConfig(QDC_DATABASE_CURRENT, &requiredPaths, paths.data(), &requiredModes, modes.data(), ¤tTopologyId);
for (auto& p : paths) {
DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName;
sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
sourceName.header.size = sizeof(sourceName);
sourceName.header.adapterId = p.sourceInfo.adapterId;
sourceName.header.id = p.sourceInfo.id;
DisplayConfigGetDeviceInfo(&sourceName.header);
if (wcscmp(info.szDevice, sourceName.viewGdiDeviceName) == 0) {
DISPLAYCONFIG_TARGET_DEVICE_NAME name;
name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
name.header.size = sizeof(name);
name.header.adapterId = p.sourceInfo.adapterId;
name.header.id = p.targetInfo.id;
DisplayConfigGetDeviceInfo(&name.header);
return std::wstring(name.monitorFriendlyDeviceName);
}
}
return L"";
}
BOOL CALLBACK MyInfoEnumProc(
HMONITOR hMonitor,
HDC hdcMonitor,
LPRECT lprcMonitor,
LPARAM dwData
)
{
MONITORINFOEX mi;
ZeroMemory(&mi, sizeof(mi));
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
wprintf(L"DisplayDevice: %s\n", mi.szDevice);
std::wcout << L"Name: " << getMonitorName(hMonitor) << L"\n";
return TRUE;
}
int main()
{
EnumDisplayMonitors(NULL, NULL, MyInfoEnumProc, 0);
return 0;
}
Debug:
Detect all connected monitors using Windows API
Not an API solution, but you can use MS's DevCon utility on the command line to scan for new hardware.
https://support.microsoft.com/en-us/kb/311272
Download it from that page, then just execute this from a cmd window:
devcon.exe rescan
You can easily create a .bat or .cmd file to run this from a link.
Related Topics
Does Std::Cout Have a Return Value
How to Handle a Transitive Dependency Conflict Using Git Submodules and Cmake
Why Does Pointer to Int Convert to Void* But Pointer to Function Convert to Bool
Why Do We Need to Tie Std::Cin and Std::Cout
Algorithm to Add or Subtract Days from a Date
Why Can't C++11 Move a Noncopyable Functor to a Std::Function
Using Char16_T and Char32_T in I/O
Can a Variable Be Declared Both Static and Extern
How Disastrous Is Integer Overflow in C++
How to Count Cameras in Opencv 2.3
How to Compare Two Character Strings Statically at Compile Time
Error: Cannot Convert 'Const Wchar_T [13]' to 'Lpcstr {Aka Const Char*}' in Assignment
How to Use Unordered_Set with Custom Types
Both Asterisk and Ampersand in a Parameter