If more than one monitor is connected to the PC (for example, a laptop with an additional screen connected via D-SUB or HDMI), how to capture the screen exactly on the one on which the cursor is now? Or can you somehow capture all monitors at once into an individual buffer for each?

Capturing an image of the main desktop is done as follows:

unsigned int Screen::GetMetrics(unsigned int *width, unsigned int *height){ *width = GetSystemMetrics(SM_CXSCREEN); *width-= (*width%4); *height = GetSystemMetrics(SM_CYSCREEN); *height-= (*height%4); return (*width * *height * 3); } unsigned int Screen::Grab(unsigned char **frame, unsigned int *timing){ // Defining screen dimensions unsigned int start = GetTickCount(); unsigned int width, height, size = GetMetrics(&width, &height); unsigned char *framebuf = nullptr; if( size ){ // Creating contexts HDC ScreenDC = GetDC(0); HDC MemoryDC = CreateCompatibleDC(ScreenDC); // Lock object (for multithread use) WaitForSingleObject(M_Screen, INFINITE); // Filling image header struct BitmapInfo.bmiHeader.biWidth = width; BitmapInfo.bmiHeader.biHeight = -height; BitmapInfo.bmiHeader.biSizeImage = width * height * BitmapInfo.bmiHeader.biBitCount / 8; HBITMAP hBitmap = CreateDIBSection(ScreenDC,&BitmapInfo,DIB_RGB_COLORS,(void**)&framebuf,0,0); SelectObject(MemoryDC, hBitmap); BitBlt(MemoryDC, 0, 0, width, height, ScreenDC, 0, 0, SRCCOPY); // Get cursor info CURSORINFO CursorInfo; CursorInfo.cbSize = sizeof(CursorInfo); if( GetCursorInfo(&CursorInfo) ){ ICONINFO IconInfo; GetIconInfo(CursorInfo.hCursor, &IconInfo); DeleteObject(IconInfo.hbmColor); DeleteObject(IconInfo.hbmMask); DrawIcon(MemoryDC, CursorInfo.ptScreenPos.x - IconInfo.xHotspot, CursorInfo.ptScreenPos.y - IconInfo.yHotspot, CursorInfo.hCursor); } ReleaseDC(NULL,ScreenDC); DeleteDC(MemoryDC); // Writing data and clearing buffers memcpy(*frame, framebuf, size); DeleteObject(hBitmap); ReleaseMutex(M_Screen); } // if need to know capture elapsed time if( timing != nullptr){*timing = GetTickCount() - start;} return size; } 

    1 answer 1

    EnumDisplayMonitors will help you determine the coordinates of each connected monitor in the system.

     BOOL CALLBACK monEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData){ // lprcMonitor - ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Π° hMonitor Π½Π° HDC return TRUE; } ... EnumDisplayMonitors(NULL, NULL, monEnumProc, 0); 

    And CreateDC allows you to capture all the monitors at once in one HDC, in which these coordinates are relevant.

     hAllDTopsDC = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); // hAllDTopsDC - HDC, с ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π΅Π»Π°Ρ‚ΡŒ ΡΠΊΡ€ΠΈΠ½ΡˆΠΎΡ‚ любого ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€Π° ::DeleteDC(hAllDTopsDC); 

    Look for a complete example of the sources of the Monitors Viewer , which just watches the mouse and shows the contents of the active monitor.

    • I first saw in your code such a construct - for( auto i : mons ) . Please tell me what standard? - Iceman
    • one
      This is range-based for loop , from Π‘++11 - mega
    • Do not know by chance how to get a monitor on which focus? With the mouse, everything turned out, but you can alt-tab on a window located on another monitor, leaving the mouse on the first. And then you can control the window on the second monitor from the keyboard, but it will not be broadcast. Maybe you can, by analogy with the mouse, get the coordinates in which the keyboard is active? - Iceman
    • one
      Well, yes, by analogy, you can follow the focus: GetFocus returns a window with focus, and GetWindowRect returns its coordinates, and IntersectRect allows you to get the result of intersection of the rectangles: you need to go through all the monitors and call for each IntersectRect , calculate their areas. A focused monitor is one whose intersection area with the focus window is larger. Only not everything is so simple: GetFocus works only in the current thread, i.e. It is necessary to attach a timer ( AttachThreadInput ) to the foreground window stream ( GetForegroundWindow ) and check its focus. - mega
    • Clear. Thanks for the help! - Iceman