How to loop over monitors and get their coordinates on Windows in C++?


The previous three blogs (Capturing the screen on Windows in C++ using OpenCV & Capturing the screen on Windows in C++ using GDI+ and Comparing screen capturing using GDI+ and OpenCV on Windows in C++) described capturing a screenshot of only one monitor. However, nowadays we often use multiple monitors and capturing the content of all of them or a specific one, two or more. Therefore, we will need to retrieve the coordinates of the targeted monitors. This blog will provide a short explanation and a C++ implementation for how to loop the existing monitors in a multiple monitors setup, get their dimensions and coordinates which can be used later into capturing the monitors content.

*Keywords*: multiple monitors, multi-monitors dimensions, monitor coordinates, C++

Approach and implementation

The trick for looping the screens dimensions is to use the function EnumDisplayMonitors(NULL, NULL, MyInfoEnumProc, 0), which is available as part of the Win32 API. A nice approach to this, is to pack the enumeration code in a structure that can be looped to retrieve the information related to each monitor. This can be done as in the following:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <windows.h>
#include <vector>
#include <iostream>


// Structure that includes all screen hanldes and rectangles
struct cMonitorsVec
{
      std::vector<int>       iMonitors;
      std::vector<HMONITOR>  hMonitors;
      std::vector<HDC>       hdcMonitors;
      std::vector<RECT>      rcMonitors;

      static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
      {
              cMonitorsVec* pThis = reinterpret_cast<cMonitorsVec*>(pData);

              pThis->hMonitors.push_back(hMon);
              pThis->hdcMonitors.push_back(hdc);
              pThis->rcMonitors.push_back(*lprcMonitor);
              pThis->iMonitors.push_back(pThis->hdcMonitors.size());
              return TRUE;
      }

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



int main()
{
      cMonitorsVec Monitors;

      for (int monitorIndex=0;  monitorIndex < Monitors.iMonitors.size(); monitorIndex++)
      {
              std::wcout << "Screen id: " << monitorIndex << std::endl;
              std::wcout << "-----------------------------------------------------" << std::endl;
              std::wcout << " - screen left-top corner coordinates : (" << Monitors.rcMonitors[monitorIndex].left
                                                                 << "," << Monitors.rcMonitors[monitorIndex].top
                                                                 << ")" << std::endl;
              std::wcout << " - screen dimensions (width x height) : (" << std::abs(Monitors.rcMonitors[monitorIndex].right - Monitors.rcMonitors[monitorIndex].left)
                                                                 << "," << std::abs(Monitors.rcMonitors[monitorIndex].top - Monitors.rcMonitors[monitorIndex].bottom)
                                                                 << ")" << std::endl;
              std::wcout << "-----------------------------------------------------" << std::endl;
      }
}

The previous code can be also found under here.

Conclusion

This post introduced a small example of how to retrieve the coordinates and dimensions of the connected monitors using C++ on Windows in the case of a multi-monitors setup. The retrieved coordinates can then be used in capturing the screens content using the snippets from the previous blogs (Capturing the screen on Windows in C++ using OpenCV & Capturing the screen on Windows in C++ using GDI+)

References and Further readings

1

EnumDisplayMonitors function (winuser.h), Microsoft, https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumdisplaymonitors

2

Enumeration and Display Control, Microsoft, https://docs.microsoft.com/en-us/windows/win32/gdi/enumeration-and-display-control

3

Multi-monitor Screenshots only 2 monitors in C++ with WinApi, Stackoverflow, https://stackoverflow.com/questions/37132196/multi-monitor-screenshots-only-2-monitors-in-c-with-winapi