2011-09-07 181 views
0

我试图让我的程序拍摄一张截图,然后以这样一种方式格式化数据,以便从我的程序中轻松操作。捕获屏幕截图

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

/** 
    * 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完成,因此我宁愿不要有任何复杂的结构。

回答

1
  1. 你忘了DeleteObject(hbitmap)

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

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

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

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

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

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*瞧。即时访问图像数据。