EnumDisplayDevices function not working for me

I am trying to get information about my monitors programmatically. The contents of the loops doesn't matter right now, they just contain debugging instructions that will be printed when the loop condition is met. Right now, the outer loop code is executed three times, and the inner loop code never opens, which means that the while condition of the (inner) loop is never true, which means that the call fails.

My problem is that the Windows API is talking about this function:

To get information about the display monitor, first call EnumDisplayDevices with lpDevice> set to NULL. Then call EnumDisplayDevices with lpDevice set to DISPLAY_DEVICE.DeviceName> from the first call to EnumDisplayDevices and with iDevNum set to zero. Then> DISPLAY_DEVICE.DeviceString is the name of the monitor.

... but even after doing exactly what he says, the second call to EnumDisplayDevices always fails? Any insight ???

I also do this as a service level application for both Windows XP and Windows 7 and get the same results. When I try to print dd.DeviceName, it gives me the address (for example: 0x12cfa4), but that should be what the function expects in the second call, since MSDN says that just pass the display device pointer and add .DeviceName to this ...

C ++ (using Qt) uses Windows API / MSDN calls.

DISPLAY_DEVICE dd; dd.cb = sizeof(DISPLAY_DEVICE); DWORD deviceNum = 0; while( EnumDisplayDevices(NULL, deviceNum, &dd, 0) ){ qWarning() << "We've entered the outer loop."; while( EnumDisplayDevices(dd.DeviceName, 0, &dd, 0)){ qWarning() << "We've entered the inner loop."; } deviceNum++; } 
+4
source share
2 answers

The problem is passing 'dd' to the internal call when using the 'dd' member as input string. I know this doesn't make sense, but I suspect that since dd is the out parameter that the API writes, but then looks at the contents of the input parameter after it has scratched it. This can happen if they did something like memset'ing the output parm to 0 before executing for reasonableness.

Just make sure that this is not something to send to a non-empty dd, I made a second dd with the same bits in it, and everything still works fine. This is definitely an alias memory.

 #include <windows.h> #include <stdio.h> #pragma comment(lib, "user32.lib") void DumpDevice(const DISPLAY_DEVICE& dd, size_t nSpaceCount ) { printf("%*sDevice Name: %s\n", nSpaceCount, "", dd.DeviceName ); printf("%*sDevice String: %s\n", nSpaceCount, "", dd.DeviceString ); printf("%*sState Flags: %x\n", nSpaceCount, "", dd.StateFlags ); printf("%*sDeviceID: %s\n", nSpaceCount, "", dd.DeviceID ); printf("%*sDeviceKey: ...%s\n\n", nSpaceCount, "", dd.DeviceKey+42 ); } int main() { DISPLAY_DEVICE dd; dd.cb = sizeof(DISPLAY_DEVICE); DWORD deviceNum = 0; while( EnumDisplayDevices(NULL, deviceNum, &dd, 0) ){ DumpDevice( dd, 0 ); DISPLAY_DEVICE newdd = {0}; newdd.cb = sizeof(DISPLAY_DEVICE); DWORD monitorNum = 0; while ( EnumDisplayDevices(dd.DeviceName, monitorNum, &newdd, 0)) { DumpDevice( newdd, 4 ); monitorNum++; } puts(""); deviceNum++; } return 0; } 

There is only 1 monitor in the box now, so I can’t check the inner loop, but I suspect this is good, since "newdd" never gets aliases in the call. You also say that you are in the context of a service β€” I'm not sure that this winstation will limit what you see on the displays β€” so that could also be a problem; but I suspect that you can still at least see the physical device. On my machine, I get:

 Device Name: \\.\DISPLAY1 Device String: NVIDIA GeForce GTX 580 State Flags: 8000005 DeviceID: PCI\VEN_10DE&DEV_1080&SUBSYS_15803842&REV_A1 DeviceKey: ...\Control\Video\{B0CDD262-FCFB-4FD4-A03C-54621896C9CD}\0000 Device Name: \\.\DISPLAY1\Monitor0 Device String: Generic PnP Monitor State Flags: 3 DeviceID: MONITOR\DEL4016\{4d36e96e-e325-11ce-bfc1-08002be10318}\0002 DeviceKey: ...\Control\Class\{4d36e96e-e325-11ce-bfc1-08002be10318}\0002 Device Name: \\.\DISPLAY2 Device String: NVIDIA GeForce GTX 580 State Flags: 0 DeviceID: PCI\VEN_10DE&DEV_1080&SUBSYS_15803842&REV_A1 DeviceKey: ...\Control\Video\{B0CDD262-FCFB-4FD4-A03C-54621896C9CD}\0001 Device Name: \\.\DISPLAYV1 Device String: RDPDD Chained DD State Flags: 8 DeviceID: DeviceKey: ...\Control\Video\{DEB039CC-B704-4F53-B43E-9DD4432FA2E9}\0000 Device Name: \\.\DISPLAYV2 Device String: RDP Encoder Mirror Driver State Flags: 200008 DeviceID: DeviceKey: ...\Control\Video\{42cf9257-1d96-4c9d-87f3-0d8e74595f78}\0000 Device Name: \\.\DISPLAYV3 Device String: RDP Reflector Display Driver State Flags: 200008 DeviceID: DeviceKey: ...\Control\Video\{b043b95c-5670-4f10-b934-8ed0c8eb59a8}\0000 
+9
source

If you code specifically for Win7 and later, you may need to look at QueryDisplayConfig and its related functions.

0
source

Source: https://habr.com/ru/post/1399265/


All Articles