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.
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+)
References and Further readings#
EnumDisplayMonitors function (winuser.h), Microsoft, https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumdisplaymonitors
Enumeration and Display Control, Microsoft, https://docs.microsoft.com/en-us/windows/win32/gdi/enumeration-and-display-control
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