Запись изображения окна в BMP файл
Компилятор: Visual C++
Чтобы сохранить изображение окна в BMP файл, необходимо нарисовать картинку на контексте устройства, преобразовать битмап, связанный с DC в памяти в устройство-независимый битмап, а затем записать DIB в файл. Ниже преведена функция WriteWindowToDIB(), в которой для решения нашей задачи используются функции DDBToDIB() и WriteDIB().
Давайте разберёмся, как создаётся изображение окна на контексте устройства в памяти и как создаётся логическая палитра, которая отвечает за изображение. Для начала создадим DC в памяти, совместимый с оконным DC. Далее создадим совместимый битмап, который имеет такой же размер как и окно. Затем воспользуемся BitBlt(), чтобы передать изображение в DC в памяти, получив тем самым битмап.
Однако, это только половина работы; другая половина заключается в том, чтобы получить логическую палитру, которая будет использоваться с битмапом. Если битмапу требуется логическая палитра, и она не будет доступна, то битмап не захочет правильно отображаться. Воспользуемся функцией GetDeviceCaps(), чтобы определить, поддерживает ли дисплей манипуляции с палитрой. Далее выделяем достаточное количество памяти для структуры LOGPALETTE, а затем используем GetSystemPaletteEntries() чтобы заполнить таблицу цветов. Теперь мы можем спокойно создать логическую палитру.
В заключение используются функции DDBToDIB() и WriteDIB(). Обратите внимание, что если окно частично перекрывается другими окнами, то в сохранённом битмапе будут содержаться части этих окон.
BOOL WriteWindowToDIB( LPTSTR szFile, CWnd *pWnd )
{
CBitmap bitmap;
CWindowDC dc(pWnd);
CDC memDC;
CRect rect;
memDC.CreateCompatibleDC(&dc);
pWnd->GetWindowRect(rect);
bitmap.CreateCompatibleBitmap(&dc, rect.Width(),rect.Height() );
CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);
memDC.BitBlt(0, 0, rect.Width(),rect.Height(), &dc, 0, 0, SRCCOPY);
//Если устройство поддерживает палитру, то создаём логическую палитру
CPalette pal;
if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE )
{
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries =
GetSystemPaletteEntries( dc, 0, 255, pLP->palPalEntry );
// Создаём палитру
pal.CreatePalette( pLP );
delete[] pLP;
}
memDC.SelectObject(pOldBitmap);
// Преобразуем битмап в DIB
HANDLE hDIB = DDBToDIB( bitmap, BI_RGB, &pal );
if( hDIB == NULL )
return FALSE;
// Записываем в файл
WriteDIB( szFile, hDIB );
// Освобождаем память выделенную DDBToDIB для DIB
GlobalFree( hDIB );
return TRUE;
}