开发者

Capturing screenshot

开发者 https://www.devze.com 2023-04-03 16:24 出处:网络
I\'m trying to have my program take a screenshot and then format the data in such a way that it can be easily manipulated from my program.

I'm trying to have my program take a screenshot and then format the data in such a way that it can be easily manipulated from my program.

So far I've come up with the following solution:

    /**
    * Creates a screenshot of the entire screen
    * @param img - 2d array containing RGB values of screen pixels.
    */
    void get_screenshot(COLORREF** img, const Rectangle &bounds)
    {
        // get the screen DC
        HDC hdc_screen = GetDC(NULL);
        // memory DC so we don't开发者_C百科 have to constantly poll the screen DC
        HDC hdc_memory = CreateCompatibleDC(hdc_screen);
        // bitmap handle
        HBITMAP hbitmap = CreateCompatibleBitmap(hdc_screen, bounds.width, bounds.height);
        // select the bitmap handle
        SelectObject(hdc_memory, hbitmap);
        // paint onto the bitmap
        BitBlt(hdc_memory, bounds.x, bounds.y, bounds.width, bounds.height, hdc_screen, bounds.x, bounds.y, SRCPAINT);
        // release the screen DC
        ReleaseDC(NULL, hdc_screen);
        // get the pixel data from the bitmap handle and put it into a nice data structure
        for(size_t i = bounds.x; i < bounds.x + bounds.width; ++i)
        {
            for(size_t j = bounds.y; j < bounds.y + bounds.height; ++j)
            {
                img[j-bounds.y][i-bounds.x] = GetPixel(hdc_memory, i, j);
            }
        }
        // release our memory DC
        ReleaseDC(NULL, hdc_memory);
    }

*Note: Rectangle is actually a struct I created with 4 size_t fields for the top-left x & y coordinate, and the width and height of the rectangle. It is not the WinAPI Rectangle.

I had a few questions about this code:

  1. Am I properly releasing all resources?
  2. Is there a better way to do this? I'm looking for something with a similar level of complexity and flexibility a 2d array of RGB values would have. The final screen capture data processing will be done with OpenCL so I would prefer to not have any complicated structure.


  1. You forgot to DeleteObject(hbitmap).

  2. CreateDIBSection creates a HBITMAP which data bits are accessible directly through memory pointer, so using it you can avoid the for loops completely.

  3. Add CAPTUREBLT flag along with SRCCOPY, otherwise layered (transparent) windows will not be included.

  4. Select the bitmap back out of the memory DC after the loop.

  5. You should call DeleteDC not ReleaseDC on the memory DC. (If you get it, release it. If you create it, delete it.)

If you want a more efficient approach, you can use a DIBSECTION instead of a compatible bitmap. This would let you skip the slow GetPixel loop and get the pixel data written directly into your data structure with the format you want.


I was just introduced to the wonderful world of CImage.

    /**
    * Creates a screenshot of the specified region and copies it to the specified region in img.
    */
    void get_screenshot(CImage &img, const CRect & src_bounds, const CRect &dest_bounds)
    {
        // get the screen DC
        HDC hdc_screen = GetDC(nullptr);
        // copy to a CImage
        CImageDC memory_dc(img);
        //StretchDIBits(
        StretchBlt(memory_dc, dest_bounds.left, dest_bounds.top, dest_bounds.Width(), dest_bounds.Height(), hdc_screen, src_bounds.left, src_bounds.top, src_bounds.Width(), src_bounds.Height(), SRCCOPY);
        ReleaseDC(nullptr, memory_dc);
        ReleaseDC(nullptr, hdc_screen);
    }

Then to use, just create a CImage object, and call GetBits() and cast it to something like char* and voila. Instant access to the image data.

0

精彩评论

暂无评论...
验证码 换一张
取 消