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#include <windows.h>
 2#include <vector>
 3#include <iostream>
 4
 5
 6// Structure that includes all screen hanldes and rectangles
 7struct cMonitorsVec
 8{
 9      std::vector<int>       iMonitors;
10      std::vector<HMONITOR>  hMonitors;
11      std::vector<HDC>       hdcMonitors;
12      std::vector<RECT>      rcMonitors;
13
14      static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
15      {
16              cMonitorsVec* pThis = reinterpret_cast<cMonitorsVec*>(pData);
17
18              pThis->hMonitors.push_back(hMon);
19              pThis->hdcMonitors.push_back(hdc);
20              pThis->rcMonitors.push_back(*lprcMonitor);
21              pThis->iMonitors.push_back(pThis->hdcMonitors.size());
22              return TRUE;
23      }
24
25      cMonitorsVec()
26      {
27              EnumDisplayMonitors(0, 0, MonitorEnum, (LPARAM)this);
28      }
29};
30
31
32
33int main()
34{
35      cMonitorsVec Monitors;
36
37      for (int monitorIndex=0;  monitorIndex < Monitors.iMonitors.size(); monitorIndex++)
38      {
39              std::wcout << "Screen id: " << monitorIndex << std::endl;
40              std::wcout << "-----------------------------------------------------" << std::endl;
41              std::wcout << " - screen left-top corner coordinates : (" << Monitors.rcMonitors[monitorIndex].left
42                                                                 << "," << Monitors.rcMonitors[monitorIndex].top
43                                                                 << ")" << std::endl;
44              std::wcout << " - screen dimensions (width x height) : (" << std::abs(Monitors.rcMonitors[monitorIndex].right - Monitors.rcMonitors[monitorIndex].left)
45                                                                 << "," << std::abs(Monitors.rcMonitors[monitorIndex].top - Monitors.rcMonitors[monitorIndex].bottom)
46                                                                 << ")" << std::endl;
47              std::wcout << "-----------------------------------------------------" << std::endl;
48      }
49}

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+)

Share this blog#

Updated on 08 April 2022

👨‍💻 edited and review were on 08.04.2022

References and Further readings#