Getfriendlyname of a secondary monitor

739 views Asked by At

I need to get device name of a secondary monitor. However when I simply try to retrieve device name, the output is DISPLAY1, DISPLAYV1 and etc.

However I require the name displayed when we check the screen resolution like the Displayname mentioned here:

Firstly I am not sure from where I can obtain this string. On reading a bit I guess it is the friendlyname of the device. However I am not sure since on calling EnumDisplaySetting() has been giving me Unhandled Exception: Could not access memory location when this function is called. So I have not been able to verify what the friendly name is exactly. And I believe that the unhandled exception is caused due to improper allocation of memory to the DISPLAY_DEVICE for driverextra in the DISPLAY_DEVICE. I believe this is because of this:

The function fails if iModeNum is greater than the index of the display device's last graphics mode.

mentioned here

Also I did not understand how much memory needs to be allocated to to
DISPLAY_DEVICE->dmDriverExtra as it has been mention in the same link:

Before calling EnumDisplaySettings, set the dmSize member to sizeof(DEVMODE), and set the dmDriverExtra member to indicate the size, in bytes, of the additional space available to receive private driver data.

So my question is manifold:

1) How much memory needs to be allocated to dmDriverExtra?

2) Is friendlyname the right parameter I need for accessing the name provided in the Display Tab in screen resolution. Or if not what other parameter do I need?

3) Is this unhandled exception caused due to improper memory allocation or is there some other reason for this?

4) Are there any other ways to get access to friendlyname of the secondary monitor?

1

There are 1 answers

3
selbie On

Updated

I switched to using The PhysicalMonitorAPI instead of GetMonitorInfo. I've combined by original solution with the first. This produces more reasonable output that you would expect (e.g. "Dell UH2313" instead of "\.\Display1").

Technically, you should allocate the array of monitors instead of using a hardcoded array - but I've never seen where dwCount will get initialized to anything greater than 1.

This program compiles just fine in Visual Studio, but you'll need to link with dxva2.lib to pick up the definitions for the PhysicalMonitor APIs.

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

BOOL __stdcall MyMonitorEnumProc
(
_In_ HMONITOR hMonitor,
_In_ HDC      hdcMonitor,
_In_ LPRECT   lprcMonitor,
_In_ LPARAM   dwData
)
{
    DWORD dwCount = 0;
    std::wstring strName(L"Unknown monitor name");
    PHYSICAL_MONITOR monitors[100] = {};
    MONITORINFOEX info = {};
    info.cbSize = sizeof(info);

    if (GetMonitorInfo(hMonitor, (LPMONITORINFO)&info))
    {
        strName = info.szDevice;
    }

    if (GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &dwCount) && (dwCount > 0) && (dwCount < ARRAYSIZE(monitors)))
    {
        if (GetPhysicalMonitorsFromHMONITOR(hMonitor, dwCount, monitors))
        {
            strName = monitors[0].szPhysicalMonitorDescription;

            DestroyPhysicalMonitors(dwCount, monitors);
        }
    }

    std::wcout << L"Monitor: " << strName << std::endl;

    return TRUE;
}

void printMonitorNames()
{
    EnumDisplayMonitors(NULL, NULL, MyMonitorEnumProc, NULL);
}

int _tmain(int argc, _TCHAR* argv[])
{
    printMonitorNames();
    return 0;
}

And it's a good bet that the MyMonitorEnumProc will get invoked first for the primary monitor. All other monitors get enumerated next.