2011-09-07 288 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*瞧。即時訪問圖像數據。