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();
}