捕获截图

时间:2011-09-07 01:47:30

标签: winapi visual-c++

我正在尝试让我的程序截取屏幕截图然后格式化数据,以便可以从我的程序中轻松操作。

到目前为止,我已经提出了以下解决方案:

    /**
    * 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 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);
    }

*注意:Rectangle实际上是我用左上角x&amp;的4个size_t字段创建的结构。 y坐标,以及矩形的宽度和高度。它不是WinAPI矩形。

我对此代码有几个疑问:

  1. 我是否正确释放了所有资源?
  2. 有更好的方法吗?我正在寻找具有类似复杂性和灵活性的东西,这是RGB值的二维数组。最终的屏幕捕获数据处理将使用OpenCL完成,所以我宁愿没有任何复杂的结构。

2 个答案:

答案 0 :(得分:1)

  1. 您忘了DeleteObject(hbitmap)

  2. CreateDIBSection创建一个HBITMAP,可以通过内存指针直接访问哪些数据位,因此使用它可以完全避免for循环。

  3. 添加CAPTUREBLT标记和SRCCOPY,否则不会包含分层(透明)窗口。

  4. 在循环后从内存DC中选择一个位图。

  5. 您应该在内存DC上调用DeleteDC而不是ReleaseDC。 (如果你得到它,请释放它。如果你创建它,删除它。)

  6. 如果您想要更有效的方法,可以使用DIBSECTION而不是兼容的位图。这样您就可以跳过慢GetPixel循环,并将像素数据直接写入您想要的格式的数据结构中。

答案 1 :(得分:0)

我刚刚被介绍到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);
    }

然后使用,只需创建一个CImage对象,然后调用GetBits()并将其转换为类似char*的内容。即时访问图像数据。