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

Comments
Gray box, still.
Posted by Legacy on 10/20/2003 12:00amOriginally posted by: Russ Lewis
Here's my copy of this solution, however I still
get the Gray box on the paste operation to mspaint. Any ideas/suggestions?
wglMakeCurrent() returns FALSE but the extended error
message returns "The operation completed successfully."
according to Platform SDK: OpenGL --
When the wglMakeCurrent function succeeds, the return value is TRUE; otherwise the return value is FALSE.
what's up with this?
thanks for any help.
void CSimpleSDIGLView::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;
VERIFY(MemDC.CreateCompatibleDC(NULL));
VERIFY(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];
if( FALSE == wglMakeCurrent(m_OpenGLCtrl.getDC(), m_OpenGLCtrl.getRC()))
{
AfxMessageBox("FALSE from wglMakeCurrent");
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Process any inserts in lpMsgBuf.
// ...
// Display the string.
AfxMessageBox( (LPCTSTR)lpMsgBuf);
// Free the buffer.
LocalFree( lpMsgBuf );
}
// Copy from OpenGL
::glReadPixels(0,0,size.cx,size.cy,GL_BGR_EXT,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();
Reply}
How can I save a graphic as a JPG file?
Posted by Legacy on 10/17/2002 12:00amOriginally posted by: Shujie
I use VC++ and OpenGL. I want to save a graphic as a JPG file. How can I do it?
ReplyThanks!
How can I capture screen into OpenGL?
Posted by Legacy on 02/21/2002 12:00amOriginally posted by: Miguel
Can you help me in the following thing.?
ReplyI need to capture the total screen, without having to use the BitBlt(...) function because this it takes a long time 450 mseg approximately. Does exists some method in OpenGL to make it. Or otherwise, witch library I should to use?.
Thank you.
Miguel
I want download thisfile
Posted by Legacy on 11/12/2001 12:00amOriginally posted by: lee
ReplyPlease send to me thisfile(facedrawing)
10x for the article + a question
Posted by Legacy on 08/01/2001 12:00amOriginally posted by: Eyal Ron
ReplyNot Work On Win'98
Posted by Legacy on 06/07/2001 12:00amOriginally posted by: Sanjay S. Bora
ReplyThanks for fine article and one question !
Posted by Legacy on 04/27/2001 12:00amOriginally posted by: Armen
I am admirer of your great articles both in CodeGuru and
ReplyCodeProject sites.
How can i get this sourse code with workspace ?
How can I Pick/Select control points from mesh on drawing
Posted by Legacy on 12/28/2000 12:00amOriginally posted by: Wu Peng
ReplyShall get I this source code with workspace?
Posted by Legacy on 10/17/2000 12:00amOriginally posted by: Anbumani
Hello, the image file diplayed in this article shoing that it not just as saving into jpg. In left side ofthe splliter window..i am seeing a sphere in 3D..I dont thing so that as an image..what i am feling is, it's a 3D object, may be that window also itself an openGL window..how ot make it? and how to place it?
Thankx in advance.
Replyanbumani@india.com
How can I save to BMP file directly from opengl buffer ?
Posted by Legacy on 10/19/1999 12:00amOriginally posted by: guaguo
How can I save to BMP file directly from opengl buffer ?
Replythank you!
Loading, Please Wait ...