Search code examples
c++winapibmpscreen-capture

How to capture part of the screen and save it to a BMP?


Possible Duplicate:
how to make screen screenshot with win32 in c++?

I am currently trying to create an application that saved a portion of the screen to a bmp. I have found BitBlt but I really don't know what to do with it. I have tried searching for some answers but I still haven't found a clarifying one using C++.

So, basically I want this function:

bool capturePartScreen(int x, int y, int w int, h, string dest){
    //Capture part of screen according to coordinates, width and height.
    //Save that captured image as a bmp to dest.
    //Return true if success, false if failure
}

BitBlt:

BOOL BitBlt(
    __in  HDC hdcDest,
    __in  int nXDest,
    __in  int nYDest,
    //The three above are the ones I don't understand!
    __in  int nWidth,
    __in  int nHeight,
    __in  HDC hdcSrc,
    __in  int nXSrc,
    __in  int nYSrc,
    __in  DWORD dwRop
);

What should that hdc be and how do I obtain the bmp?


Solution

  • It took a while, but I have now finally ended up with a functioning script.

    Requirements:

    #include <iostream>
    #include <ole2.h>
    #include <olectl.h>
    

    Also you might(?) have to add ole32, oleaut32 and uuid to your linker.

    screenCapturePart:

    bool screenCapturePart(int x, int y, int w, int h, LPCSTR fname){
        HDC hdcSource = GetDC(NULL);
        HDC hdcMemory = CreateCompatibleDC(hdcSource);
    
        int capX = GetDeviceCaps(hdcSource, HORZRES);
        int capY = GetDeviceCaps(hdcSource, VERTRES);
    
        HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, w, h);
        HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);
    
        BitBlt(hdcMemory, 0, 0, w, h, hdcSource, x, y, SRCCOPY);
        hBitmap = (HBITMAP)SelectObject(hdcMemory, hBitmapOld);
    
        DeleteDC(hdcSource);
        DeleteDC(hdcMemory);
    
        HPALETTE hpal = NULL;
        if(saveBitmap(fname, hBitmap, hpal)) return true;
        return false;
    }
    

    saveBitmap:

    bool saveBitmap(LPCSTR filename, HBITMAP bmp, HPALETTE pal)
    {
        bool result = false;
        PICTDESC pd;
    
        pd.cbSizeofstruct   = sizeof(PICTDESC);
        pd.picType      = PICTYPE_BITMAP;
        pd.bmp.hbitmap  = bmp;
        pd.bmp.hpal     = pal;
    
        LPPICTURE picture;
        HRESULT res = OleCreatePictureIndirect(&pd, IID_IPicture, false,
                           reinterpret_cast<void**>(&picture));
    
        if (!SUCCEEDED(res))
        return false;
    
        LPSTREAM stream;
        res = CreateStreamOnHGlobal(0, true, &stream);
    
        if (!SUCCEEDED(res))
        {
        picture->Release();
        return false;
        }
    
        LONG bytes_streamed;
        res = picture->SaveAsFile(stream, true, &bytes_streamed);
    
        HANDLE file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, 0,
                     CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    
        if (!SUCCEEDED(res) || !file)
        {
        stream->Release();
        picture->Release();
        return false;
        }
    
        HGLOBAL mem = 0;
        GetHGlobalFromStream(stream, &mem);
        LPVOID data = GlobalLock(mem);
    
        DWORD bytes_written;
    
        result   = !!WriteFile(file, data, bytes_streamed, &bytes_written, 0);
        result  &= (bytes_written == static_cast<DWORD>(bytes_streamed));
    
        GlobalUnlock(mem);
        CloseHandle(file);
    
        stream->Release();
        picture->Release();
    
        return result;
    }