Если к ПК подключено более одного монитора (например, ноутбук с дополнительным экраном, подключенным по 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, который как раз следит за мышью и показывает содержимое активного монитора.
Комментариев нет:
Отправить комментарий