Страницы

Поиск по вопросам

воскресенье, 7 июля 2019 г.

Захват изображения рабочего стола активного монитора

Если к ПК подключено более одного монитора (например, ноутбук с дополнительным экраном, подключенным по D-SUB или HDMI), как захватить экран именно на том, на котором сейчас курсор? Или может можно как-то сразу все мониторы захватить в индивидуальный буфер для каждого?
Захват изображения основного рабочего стола выполняю так:
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; }


Ответ

EnumDisplayMonitors поможет Вам определить координаты каждого подключенного монитора в системе.
BOOL CALLBACK monEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData){
// lprcMonitor - координаты монитора hMonitor на HDC
return TRUE; } ... EnumDisplayMonitors(NULL, NULL, monEnumProc, 0);
А CreateDC позволяет захватить сразу все мониторы в одном HDC, в котором эти координаты актуальны.
hAllDTopsDC = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
// hAllDTopsDC - HDC, с которого можно делать скриншот любого монитора
::DeleteDC(hAllDTopsDC);
Посмотрите для полноценного примера исходники Monitors Viewer, который как раз следит за мышью и показывает содержимое активного монитора.

Комментариев нет:

Отправить комментарий