【问题标题】:Capturing screenshot捕获屏幕截图
【发布时间】:2014-01-11 07:06:04
【问题描述】:

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

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

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

*注意:矩形实际上是我创建的一个结构体,其中包含 4 个size_t 字段,用于左上角 x 和 y 坐标,以及矩形的宽度和高度。它不是 WinAPI 矩形。

我对这段代码有几个问题:

  1. 我是否正确释放所有资源?
  2. 有没有更好的方法来做到这一点?我正在寻找与 RGB 值的二维数组具有相似复杂性和灵活性的东西。最终的屏幕捕获数据处理将使用 OpenCL 完成,因此我希望没有任何复杂的结构。

【问题讨论】:

    标签: winapi visual-c++


    【解决方案1】:
    1. 你忘了DeleteObject(hbitmap)

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

    3. CAPTUREBLT 标志与SRCCOPY 一起添加,否则将不包括分层(透明)窗口。

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

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

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

    【讨论】:

      【解决方案2】:

      我刚刚被介绍到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* 之类的东西,瞧。即时访问图像数据。

      【讨论】:

        猜你喜欢
        • 2011-10-13
        • 1970-01-01
        • 1970-01-01
        • 2012-01-20
        • 2017-12-03
        • 2023-03-29
        • 2014-03-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多