Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EnumDisplayMonitors callback

I am trying to use the EnumDisplayMonitors to create a dynamic array of each monitor and store the DISPLAY_DEVICE structure. Why is the below code not correct?

BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {

    MONITORINFOEX iMonitor;
    iMonitor.cbSize = sizeof(MONITORINFOEX);
    GetMonitorInfo(hMonitor, &iMonitor);

    if (iMonitor.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER)
    {
        return true;
    }
    else
    {
        *reinterpret_cast<ScreenArray*>(dwData) = ScreenArray(&iMonitor);
        return true;
    };

}

Called using

ScreenArray monitorArray[15];

int i = 0;
EnumDisplayMonitors(NULL, NULL, MyInfoEnumProc, reinterpret_cast<LPARAM>(&monitorArray[i++]));

The first in the array (monitorArray[0]) returns correct information for the second monitor but monitorArray[1] is max values.

EDIT: Solved The method I used was just implementing a function I created:

MonitorArray *mA = reinterpret_cast<MonitorArray*>(dwData);
        mA->addScreen(&iMonitor);
like image 389
Built on Sin Avatar asked Dec 11 '22 02:12

Built on Sin


2 Answers

EnumDisplayMonitors takes the parameter you pass it and calls your callback once for each monitor, passing it the same parameter every time. Your index into monitorArray is never incremented. Instead you need to manage the indexing within the callback itself.

Here's a little class that automatically builds a vector of all monitors in the system.

struct MonitorRects
{
    std::vector<RECT>   rcMonitors;

    static BOOL CALLBACK MonitorEnum(HMONITOR hMon,HDC hdc,LPRECT lprcMonitor,LPARAM pData)
    {
        MonitorRects* pThis = reinterpret_cast<MonitorRects*>(pData);
        pThis->rcMonitors.push_back(*lprcMonitor);
        return TRUE;
    }

    MonitorRects()
    {
        EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this);
    }
};

Use it like this:

MonitorRects monitors;
cout << "You have " << monitors.rcMonitors.size() << " monitors connected.";
like image 158
Jonathan Potter Avatar answered Dec 26 '22 19:12

Jonathan Potter


The callback is called once for each monitor, but your callback is not incrementing through the array each time it is called. You need to do something more like this instead:

struct ScreenArrayInfo
{
    ScreenArray *Array;
    int Count;
    int MaxCount;
};

BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
    MONITORINFOEX iMonitor;
    iMonitor.cbSize = sizeof(MONITORINFOEX);
    GetMonitorInfo(hMonitor, &iMonitor);

    if (iMonitor.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER)
    {
        return true;
    }
    else
    {
        ScreenArrayInfo *info = reinterpret_cast<ScreenArrayInfo*>(dwData);
        if (info->Count == info->MaxCount) return false;
        info->Array[info->Count] = ScreenArray(&iMonitor);
        Info->Count++;
        return true;
    };
}

ScreenArray monitorArray[15];
ScreenArrayInfo info;
info.Array = monitorArray;
info.Count = 0;
info.MaxCount = 15;

EnumDisplayMonitors(NULL, NULL, &MyInfoEnumProc, reinterpret_cast<LPARAM>(&info));

Alternatively:

#include <vector>

BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
    MONITORINFOEX iMonitor;
    iMonitor.cbSize = sizeof(MONITORINFOEX);
    GetMonitorInfo(hMonitor, &iMonitor);

    if (iMonitor.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER)
    {
        return true;
    }
    else
    {
        reinterpret_cast< std::vector<ScreenArray>* >(dwData)->push_back(ScreenArray(&iMonitor));
        return true;
    };
}

std::vector<ScreenArray> monitorArray;
EnumDisplayMonitors(NULL, NULL, &MyInfoEnumProc, reinterpret_cast<LPARAM>(&monitorArray));
like image 40
Remy Lebeau Avatar answered Dec 26 '22 19:12

Remy Lebeau