8

I'm having a bit of trouble retrieving the name of a monitor with winapi. According to other entries on stackoverflow, the correct way to get the name of a monitor is this:

EnumDisplayDevices(nullptr, 0, &oDisplayDevice, 0);

char lpszDeviceName[32];
memcpy(lpszDeviceName, oDisplayDevice.DeviceName, 32);

EnumDisplayDevices(lpszDeviceName, 0, &oDisplayDevice, 0);

char lpszMonitorName[128];
memcpy(lpszMonitorName, oDisplayDevice.DeviceString, 128);

However, EnumDisplayDevices returns FALSE the second time around. The first time around, DeviceName is \\DISPLAY1 and DeviceString is the GPU vendor. Using the MONITORINFOEX struct gives me the same value as DeviceName.

To be clear I'm looking for something like "Samsung blah blah," or what appears in the control panel on the screen resolution page.

NmdMystery
  • 2,778
  • 3
  • 32
  • 60

2 Answers2

7

This seems to return the proper data for me:

#include <Windows.h>
#include <iostream>
#include <string>

int main()
{
    DISPLAY_DEVICE dd;
    dd.cb = sizeof(dd);
    int deviceIndex = 0;
    while(EnumDisplayDevices(0, deviceIndex, &dd, 0))
    {
        std::string deviceName = dd.DeviceName;
        int monitorIndex = 0;
        while(EnumDisplayDevices(deviceName.c_str(), monitorIndex, &dd, 0))
        {
            std::cout << dd.DeviceName << ", " << dd.DeviceString << "\n";
            ++monitorIndex;
        }
        ++deviceIndex;
    }
    return 0;
}

If you're compiling for UNICODE then use this instead:

#include <Windows.h>
#include <iostream>
#include <string>

int main()
{
    DISPLAY_DEVICE dd;
    dd.cb = sizeof(dd);
    int deviceIndex = 0;
    while(EnumDisplayDevices(0, deviceIndex, &dd, 0))
    {
        std::wstring deviceName = dd.DeviceName;
        int monitorIndex = 0;
        while(EnumDisplayDevices(deviceName.c_str(), monitorIndex, &dd, 0))
        {
            std::wcout << dd.DeviceName << L", " << dd.DeviceString << L"\n";
            ++monitorIndex;
        }
        ++deviceIndex;
    }
    return 0;
}

Here's an example of the output:

\.\DISPLAY1\Monitor0, Dell U2410(DP)
\.\DISPLAY2\Monitor0, Dell 2407WFP-HC (Digital)

Retired Ninja
  • 4,785
  • 3
  • 25
  • 35
  • I still get nothing. I'm using LPWSTR (or std::wstring) and the W version of the function instead of a plain LPSTR, could that be why? – NmdMystery Nov 19 '13 at 00:53
  • 1
    Hmm... I tried switching to non-wide strings and I got Generic PnP monitor, is that just because there's no vendor string? – NmdMystery Nov 19 '13 at 00:58
  • I added a Unicode example. For me, this returns the same strings I see in the display control panel and device manager. Presumably if you're using the generic driver for the monitor then it would show the generic string. – Retired Ninja Nov 19 '13 at 01:00
  • Would pretty much every external monitor be something besides Generic PnP? I'm trying to use this as a way to distinguish a monitor preference during the startup of my program. – NmdMystery Nov 19 '13 at 01:03
  • 2
    It's hard to say. The 3 monitors I currently have available all have specific drivers for them, but I have seen the generic driver in use before. I would assume that unless they start switching cables around the combination of the device name and string would be a unique identifier. – Retired Ninja Nov 19 '13 at 01:06
0

This worked for me on Win10. "Retired Ninja" answer returned Generic PnP monitor.

Don't forget to add DEFINES += "WINVER=0x0601" or define that

#include <windows.h>

void QueryDisplay()
{
    std::vector<DISPLAYCONFIG_PATH_INFO> paths;
    std::vector<DISPLAYCONFIG_MODE_INFO> modes;
    UINT32 flags = QDC_ONLY_ACTIVE_PATHS;
    LONG isError = ERROR_INSUFFICIENT_BUFFER;

    UINT32 pathCount, modeCount;
    isError = GetDisplayConfigBufferSizes(flags, &pathCount, &modeCount);

    if( isError )
    {
        return;
    }

    // Allocate the path and mode arrays
    paths.resize(pathCount);
    modes.resize(modeCount);

    // Get all active paths and their modes
    isError = QueryDisplayConfig(flags, &pathCount, paths.data(), &modeCount, modes.data(), nullptr);

    // The function may have returned fewer paths/modes than estimated
    paths.resize(pathCount);
    modes.resize(modeCount);


    if ( isError )
    {
        return;
    }

    // For each active path
    int len = paths.size();
    for( int i=0 ; i<len ; i++ )
    {
        // Find the target (monitor) friendly name
        DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {};
        targetName.header.adapterId = paths[i].targetInfo.adapterId;
        targetName.header.id = paths[i].targetInfo.id;
        targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
        targetName.header.size = sizeof(targetName);
        isError = DisplayConfigGetDeviceInfo(&targetName.header);

        if( isError )
        {
            return;
        }
        QString mon_name = "Unknown";
        if( targetName.flags.friendlyNameFromEdid )
        {
            mon_name = QString::fromStdWString(
                       targetName.monitorFriendlyDeviceName);
        }

        qDebug() << "Monitor " << mon_name;
    }
}
Pazel1374
  • 218
  • 3
  • 14