15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Запись изображения окна в 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;
}