[win] Take a screenshot to clipboard

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
stefbuet
Competition winner
Posts: 495
Joined: Sun Dec 09, 2007 4:13 pm
Location: france

[win] Take a screenshot to clipboard

Post by stefbuet »

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;
}
 
Last edited by stefbuet on Thu Aug 04, 2011 4:40 pm, edited 8 times in total.
CuteAlien wrote:coders are well-known creatures of the night
christianclavet
Posts: 1638
Joined: Mon Apr 30, 2007 3:24 am
Location: Montreal, CANADA
Contact:

Re: Take a screenshot to clipboard

Post by christianclavet »

Hi,

Just by curiosity, theses function:

Code: Select all

//clip board part
        OpenClipboard(hwnd);
        EmptyClipboard();
        SetClipboardData(CF_BITMAP,hBitmap);
        CloseClipboard();


Do they need a specific include? (I assume there is, and that is only windows platform code)
For a quick googling around you should include "afxwin.h" to have the CWnd class (part of the windows MFC)

Can you give me more detail? Never used thoses before...
stefbuet
Competition winner
Posts: 495
Joined: Sun Dec 09, 2007 4:13 pm
Location: france

Re: Take a screenshot to clipboard

Post by stefbuet »

Just windows.h, this is the basic win32 API, not MFC.
This snippet is only using windows API but that was to resolve a win7 problem initially. I added a tag on the OP title to specify that.
WINDOW_WIDTH and WINDOW_HEIGHT are the screen size, not necessary const.
I also changed the code:
-now every possible error is handled (with a bool return value)
-take the window handle as a parameter
-I added comments (documentation creation handled)
-headers

:wink:
CuteAlien wrote:coders are well-known creatures of the night
Post Reply