How to snap an OpenGL client and send it to the clipboard

This article demonstrates how to snap an OpenGL client and send it to
ClipBoard.

We suppose your screen configuration is set to true color.

We could send the same buffer in a .bmp file in a few lines too….

// Snap OpenGL client and send it to ClipBoard

// so that you can insert it in your favorite

// image editor, Powerpoint, etc...

// Replace CRenderView by your own CView-derived
class


void CRenderView::SnapClient()

{

 BeginWaitCursor();

 // Get client geometry

 CRect rect;

 GetClientRect(&rect);

 CSize size(rect.Width(),rect.Height());

 TRACE("  client zone : (%d;%d)\n",size.cx,size.cy);

 // Lines have to be 32 bytes aligned,
suppose 24 bits per pixel


 // I just cropped it

 size.cx -= size.cx % 4;

 TRACE("  final client zone : (%d;%d)\n",size.cx,size.cy);

 // Create a bitmap and select it in the device context

 // Note that this will never be used 😉 but no matter

 CBitmap bitmap;

 CDC *pDC = GetDC();

 CDC MemDC;

 ASSERT(MemDC.CreateCompatibleDC(NULL));

 ASSERT(bitmap.CreateCompatibleBitmap(pDC,size.cx,size.cy));

 MemDC.SelectObject(&bitmap);

 // Alloc pixel bytes

 int NbBytes = 3 * size.cx *
size.cy;


 unsigned char
*pPixelData = new unsigned char[NbBytes];

 // Copy from OpenGL

 ::glReadPixels(0,0,size.cx,size.cy,GL_RGB,GL_UNSIGNED_BYTE,pPixelData);

 // Fill header

 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;

 // Generate handle

 HANDLE handle = (HANDLE)::GlobalAlloc (GHND,sizeof(BITMAPINFOHEADER)
+ NbBytes);


 if(handle != NULL)

 {

  // Lock handle

  char *pData = (char
*) ::GlobalLock((HGLOBAL)handle);


  // Copy header and data

  memcpy(pData,&header,sizeof(BITMAPINFOHEADER));

  memcpy(pData+sizeof(BITMAPINFOHEADER),pPixelData,NbBytes);

  // Unlock

  ::GlobalUnlock((HGLOBAL)handle);

  // Push DIB in clipboard

  OpenClipboard();

  EmptyClipboard();

  SetClipboardData(CF_DIB,handle);

  CloseClipboard();

 }

 // Cleanup

 MemDC.DeleteDC();

 bitmap.DeleteObject();

 delete [] pPixelData;

 EndWaitCursor();

}

 

 

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read