This article includes description of the simple multi-monitor screenshot creation and splicing screenshots from the display monitor into the one virtual screen sized bitmap using Windows GDI functions.
The Virtual Screen
Creating a Screenshot from a Definite Desktop
Enumerating Desktops and Splicing Images
This article describes the process of getting screenshots of all monitors while working in the multi-monitor mode, and locating them in one bitmap programmatically, keeping the arrangement of monitors on a virtual screen. For these purposes, the GDI functions are used in the code. In the final part of the article, the described algorithm is presented as the developed code piece for your attention.
In the picture below, the bounding rectangle with three monitors inside is the virtual screen. The desktop covers the virtual screen instead of a single monitor. The following picture shows a possible arrangement of three monitors (for more information, see MSDN).
The primary monitor (Monitor 1) contains the origin (0,0). The primary monitor does not have to be in the upper left corner of the virtual screen. When it is not there, parts of the virtual screen have negative coordinates.
It is, definitely, a well known task that has a rather simple implementation. But I just want to remind how to get a screenshot of the current display monitor, especially because it will be necessary when we get screenshots from all display monitors.
The following function uses Windows GDI functions:
It implies that we already have a handle to monitor device context (DC) (
CDCGuard &desktopGuard in the parameters list). In case of one monitor handle to DC, we get it using the
Other handles are out parameters, they will serve us for the creation of the bitmap file with the
BITMAPFILEHEADER property. The usage of this function will be described below.
CDCGuard is my class-wrapper that deletes handle to DC in its destructor:
CBitmapGuard is also a class-wrapper and has similar implementation, but deletes the
HBITMAP object in its destructor:
So, here is the function for capturing screen of monitor:
Getting one image from all display monitors is a rather easy and small task. We have to get the DC from each monitor on the virtual screen, and then capture its content. The steps are the following:
- Enumerating display monitors using the
- Creating a screenshot from each enumerated monitor using the
CaptureDesktop ()function , which was described above.
- Splicing screenshots from all monitors into the single virtual screen sized bitmap.
Declaration of the
EnumDisplayMonitors() Windows GDI function is the following:
In this article and in the project code,
LPARAM dwData is a pointer to my class encapsulating the list of pairs of handles to the monitors’ DCs and corresponding monitors’ coordinates (
EnumDisplayMonitors() function is called in its constructor, and the class implementation provides the treatment with the declared above list (
HDCPoolType) for the safety and convenience.
MonitorEnumProc is a callback function:
Now, all we need is to merge the captures of all monitors into the single virtual screen sized bitmap. For the creation of the bitmap, the
SpliceImages() function follows the same algorithm in the beginning as the
CaptureDesktop() function does.Then we have to copy data from the definied DC to the same DC of the vitrual screen using the
The example of the arrangement of the monitors on the virtual screen is presented below. Monitor 2 has a negative top coordinate value. By calculating y coordinate shift, we’ll locate the captures of the monitors keeping the location of windows and desktops on the bitmap.
The result of this sample project work (with the arrangement of the monitors presented on the picture above) is shown on the following picture (we used MaxiVista to emulate the multi-monitor):