4

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?

annie1994
  • 143
  • 1
  • 6

1 Answers1

4

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.

selbie
  • 100,020
  • 15
  • 103
  • 173
  • The output is: `Monitor Name is: \\.\DISPLAY1 Monitor Name is \\.\DISPLAY2` whereas I require the device specific name. For example when I connect my secondary display, in the Screen Resolution Tab, the display name is **TopFoison LCD** so I need this string to be read. Which I believe friendlyname does return from what is mentioned [here](https://msdn.microsoft.com/en-us/library/windows/hardware/ff552837(v=vs.85).aspx) **For a printer, specifies the "friendly name"; for example, "PCL/HP LaserJet" in the case of PCL/HP LaserJet.** – annie1994 Oct 01 '15 at 17:04
  • @annie1994 - Updated my answer. The program now uses the physical monitor APIs to get the user friendly name of the monitor. Link with dxva2.lib. – selbie Oct 02 '15 at 02:49
  • I am unable to get the friendly name, it still returns the useless _Generic PnP Monitor_ (using AutoHotkey `DllCall`, on Windows 7 x64) – Leeroy Feb 21 '19 at 00:22