[SRC] Как скопировать экран и получить BitMap
От: aGrey Литва  
Дата: 27.06.04 01:00
Оценка: 45 (6)
В ответ на эту мессагу
Автор: XFREE86
Дата: 26.06.04
, и прочие ЧАВО о том же... — Как, используя Win API (GDI), скопировать экран и подготовить картинку для передачи по сети или ещечертзнаетдлячего.

Эта простейшая функция копирует экран, уменьшает размер картинки (по желанию), преобразует ее в 24-битный формат, и выдает заполненный BITMAPINFOHEADER и массив BitMap (т.е. собственно битмап). Дальше (исключительно для демонстрации) происходит запись *.BMP файла на диск. Вместо этого, разумеется, следует вставить код сжатия данных (JPEG или др.) и передачи в сеть или ещечертзнаеткуда... Но это уже оффтопик.



BOOL ScreenToBmp24Stretch(BYTE bZoomOut) {
// Рассчитываем масштаб
if(bZoomOut < 1) bZoomOut = 1;
if(bZoomOut > 8) bZoomOut = 8;
WORD wWidth  = GetSystemMetrics(SM_CXSCREEN) / bZoomOut;
WORD wHeight = GetSystemMetrics(SM_CYSCREEN) / bZoomOut;
// Получаем DC экрана
HDC hDCScr = GetDC(NULL);
// Создаем в памяти GDI DC и совместимый BMP
HDC hDCMem = CreateCompatibleDC(hDCScr);
HBITMAP hBmMem = CreateCompatibleBitmap(hDCScr, wWidth, wHeight);
HBITMAP hBmOld = SelectObject(hDCMem, hBmMem);
// Копируем картинку (с изменением масштаба)
if(!SetStretchBltMode(hDCMem, HALFTONE))
    SetStretchBltMode(hDCMem, COLORONCOLOR);
StretchBlt(hDCMem, 0, 0, wWidth, wHeight,
    hDCScr, 0, 0, GetSystemMetrics(SM_CXSCREEN),
    GetSystemMetrics(SM_CYSCREEN), SRCCOPY);
ReleaseDC(NULL, hDCScr);
// Заполняем структуру BITMAPINFO
PBITMAPINFO pBmInf = LocalAlloc(LPTR, sizeof(BITMAPINFO));
BOOL fResult = TRUE;
if(hDCMem != NULL && hBmMem != NULL && pBmInf != NULL) {
pBmInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// Ширина и высота
pBmInf->bmiHeader.biWidth = wWidth;
pBmInf->bmiHeader.biHeight = wHeight;
// Компрессия (нет)
pBmInf->bmiHeader.biCompression = BI_RGB;
// Глубина цвета = 24 (идеально во всех отношениях, в т.ч. для JPEG)
pBmInf->bmiHeader.biBitCount = 24;
pBmInf->bmiHeader.biClrUsed = 16777216; // 2 ^ 24
pBmInf->bmiHeader.biPlanes = 1;
// Размер BitMap в байтах
pBmInf->bmiHeader.biSizeImage = (wWidth + 7) / 8 * wHeight * 24;
// Резервируем память для массива BitMap
PBYTE pBmData = LocalAlloc(LPTR, pBmInf->bmiHeader.biSizeImage);
if(pBmData != NULL) {
// Получаем BitMap заявленного формата
if(GetDIBits(hDCMem, hBmMem, 0,
    wHeight, pBmData, pBmInf, DIB_RGB_COLORS)) {

// -----------------------------------------------------------------------

// Заполняем структуру BITMAPFILEHEADER
BITMAPFILEHEADER BmFileHdr;
BmFileHdr.bfType = 0x4D42; // "BM"
BmFileHdr.bfReserved1 = BmFileHdr.bfReserved2 = 0;
BmFileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
BmFileHdr.bfSize = BmFileHdr.bfOffBits + pBmInf->bmiHeader.biSizeImage;
// Создаем (перезаписываем) *.BMP файл в текущей директории
HANDLE hFile = CreateFile(TEXT("TEST.BMP"), GENERIC_WRITE, 0,
    NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE) {
DWORD dwBytes = 0;
// Записываем структуру BITMAPFILEHEADER
WriteFile(hFile, &BmFileHdr, sizeof(BITMAPFILEHEADER), &dwBytes, NULL);
// Записываем структуру BITMAPINFO
WriteFile(hFile, pBmInf, sizeof(BITMAPINFOHEADER), &dwBytes, NULL);
// Записываем BitMap массив
WriteFile(hFile, pBmData, pBmInf->bmiHeader.biSizeImage, &dwBytes, NULL);
CloseHandle(hFile);
} else fResult = FALSE;

// -----------------------------------------------------------------------

// Убираем мусор и фиксируем результат
} else fResult = FALSE;
LocalFree(pBmData);
} else fResult = FALSE;
} else fResult = FALSE;
if(pBmInf != NULL) LocalFree(pBmInf);
SelectObject(hDCMem, hBmOld);
DeleteDC(hDCMem);
DeleteObject(hBmMem);
return fResult; }


Цитируя SEV: А если нужно "эффективно" получать, то советую начать с поиска в этой конфе по ключевым словам "mirror driver"...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.