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

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


Копируем изображение OpenGL в ClipBoard.


Автор: Pierre Alliez.

Пример показывает, как можно скапчурить OpenGL картинку и отправить её в клипборду. После этого картинку можно вставить в любой графический редактор. Так же не составит труда сохранить это изображение как .bmp файл. Предполагается, что разрешение Вашего экрана установлено в true color.



// Замените CRenderView Вашим собственным CView-наследованным классом
void CRenderView::SnapClient()
{
 BeginWaitCursor();

 // Получаем геометрию клиента
 CRect rect;
 GetClientRect(&rect);
 CSize size(rect.Width(),rect.Height());
 TRACE("  client zone : (%d;%d)\n",size.cx,size.cy);
 // Линии получились с выравниванием в 32 байта, и 24 бита на пиксель
 // Урезаем их
 size.cx -= size.cx % 4;
 TRACE("  final client zone : (%d;%d)\n",size.cx,size.cy);

 // Создаём bitmap и устанавливаем его в контексте устройства
 CBitmap bitmap;
 CDC *pDC = GetDC();
 CDC MemDC;
 ASSERT(MemDC.CreateCompatibleDC(NULL));
 ASSERT(bitmap.CreateCompatibleBitmap(pDC,size.cx,size.cy));
 MemDC.SelectObject(&bitmap);

 // Рассчитываем кол-во необходимых байт для изображения
 int NbBytes = 3 * size.cx * size.cy;
 unsigned char *pPixelData = new unsigned char[NbBytes];

 // Копируем из OpenGL
 ::glReadPixels(0,0,size.cx,size.cy,GL_RGB,GL_UNSIGNED_BYTE,pPixelData);

 // Заполняем заголовок
 BITMAPINFOHEADER header;
 header.biWidth = size.cx;
 header.biHeight = size.cy;
 header.biSizeImage = NbBytes;
 header.biSize = 40;
 header.biPlanes = 1;
 header.biBitCount =  3 * 8; // RGB
 header.biCompression = 0;
 header.biXPelsPerMeter = 0;
 header.biYPelsPerMeter = 0;
 header.biClrUsed = 0;
 header.biClrImportant = 0;

 // Генерируем handle
 HANDLE handle = (HANDLE)::GlobalAlloc (GHND,sizeof(BITMAPINFOHEADER) + NbBytes);
 if(handle != NULL)
 {
  // Блокируем handle
  char *pData = (char *) ::GlobalLock((HGLOBAL)handle);
  // Копируем заголовок и данные
  memcpy(pData,&header,sizeof(BITMAPINFOHEADER));
  memcpy(pData+sizeof(BITMAPINFOHEADER),pPixelData,NbBytes);
  // Разблокируем
  ::GlobalUnlock((HGLOBAL)handle);

// Кладём DIB в clipboard
  OpenClipboard();
  EmptyClipboard();
  SetClipboardData(CF_DIB,handle);
  CloseClipboard();
 }

 // Освобождаем всё
 MemDC.DeleteDC();
 bitmap.DeleteObject();
 delete [] pPixelData;

 EndWaitCursor();
}