[win] Take a screenshot to clipboard
Posted: Sun Jul 31, 2011 9:16 pm
With win7, using 'print screen' keyboard key to take a screenshot isn't working well with fullscreen applications. Most of the time only the first ever rendered frame is put into the clipboard. This function will basicly do the same work as print screen but it's working fine all the time:
Code: Select all
#include <windows.h>
#include <iostream> //for std::cout only
//! Create a screenshot of the scene and put it in the clipboard.
//!\param hwnd irrlicht window handle. Can be get thought IVideoDriver::getExposedVideoData.
//!\return true if sucess, false if an errror occured while processing.
bool createScreenShotToClipBoard(HWND hwnd) {
//create the screenshot
IImage *irrImg=driver->createScreenShot();
HDC memHdc=CreateCompatibleDC(NULL);
if(memHdc==NULL) {
std::cout<<"Error : can't create HDC"<<std::endl;
irrImg->drop();
return false;
}
HDC H=GetDC(hwnd);
if(H==NULL) {
std::cout<<"Error : can't get DC"<<std::endl;
DeleteDC(memHdc);
irrImg->drop();
return false;
}
//create the windows bitmap
HBITMAP hBitmap=CreateCompatibleBitmap(H,WINDOW_WIDTH,WINDOW_HEIGHT);
ReleaseDC(hwnd,H);
if(hBitmap==NULL) {
std::cout<<"Error : Can't create bitmap"<<std::endl;
DeleteDC(memHdc);
irrImg->drop();
return false;
}
SelectObject(memHdc,hBitmap);
LPBYTE bmpData=new BYTE[WINDOW_WIDTH*WINDOW_HEIGHT*3]; //1 BYTE per color channel, 3 BYTES per color
//Store pixel data in the bytes array
for(unsigned int j=0; j<WINDOW_HEIGHT; ++j) {
for(unsigned int i=0; i<WINDOW_WIDTH; ++i) {
SColor irrPixelColor=irrImg->getPixel(i,WINDOW_HEIGHT-j);
bmpData[(j*WINDOW_WIDTH+i)*3]=irrPixelColor.getBlue();
bmpData[(j*WINDOW_WIDTH+i)*3+1]=irrPixelColor.getGreen();
bmpData[(j*WINDOW_WIDTH+i)*3+2]=irrPixelColor.getRed();
}
}
//create the bitmapInfo object which hold bitmap information
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
bi.bmiHeader.biWidth = WINDOW_WIDTH;
bi.bmiHeader.biHeight = WINDOW_HEIGHT;
bi.bmiHeader.biBitCount = 24; //8 bit per channel, RGB
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biCompression = BI_RGB;
//put pixel bytes array directly into the bitmap
if(!SetDIBits(memHdc,hBitmap,0,WINDOW_HEIGHT,bmpData,&bi,DIB_RGB_COLORS)) {
std::cout<<"Error : can't set bitmap data"<<std::endl;
return(false);
}
//free some memory
DeleteDC(memHdc);
irrImg->drop();
delete[] bmpData;
//Open the clipboard to put some data into it
if(!OpenClipboard(hwnd)) {
std::cout<<"Error : Can't open win clipboard"<<std::endl;
DeleteObject(hBitmap);
return(false);
}
//empty clipboard from other data which might be there
if(!EmptyClipboard()) {
std::cout<<"Error : Can't empty win clipboard"<<std::endl;
DeleteObject(hBitmap);
return(false);
}
//put bitmap data into clipboard
if(SetClipboardData(CF_BITMAP,hBitmap)==NULL) {
std::cout<<"Error : Can't put the bitmap data into clipboard"<<std::endl;
DeleteObject(hBitmap);
return(false);
}
//delete the bitmap
DeleteObject(hBitmap);
//Close the clipboard so as to allow other apps to get back the screenshot
if(!CloseClipboard()) {
std::cout<<"Error : Can't close clipboard"<<std::endl; //other applications won't be able to use it
return(false);
}
std::cout<<"A screenshot had been copyed to your clipboard."<<std::endl;
return true;
}