SoFunction
Updated on 2025-03-07

C# Example of using BitBlt for window capture

This article andC++ uses BitBlt for window captureCorrespondingly, it is implemented using C#.

This method is used for windows of 1920*1080 size, and the time reference for grabbing pictures at one time (VS2015+i5 9400F): as low as 2~3ms (average 4.3ms).

See:C# picture capture service

1. Win32 package

Win32Consts

using ;

namespace CaptureSharp
{
 public sealed class Win32Consts
 {
 public enum DibColorMode : uint
 {
  DIB_RGB_COLORS = 0x00,
  DIB_PAL_COLORS = 0x01,
  DIB_PAL_INDICES = 0x02
 }

 public enum BitmapCompressionMode : uint
 {
  BI_RGB = 0,
  BI_RLE8 = 1,
  BI_RLE4 = 2,
  BI_BITFIELDS = 3,
  BI_JPEG = 4,
  BI_PNG = 5
 }

 public enum RasterOperationMode : uint
 {
  SRCCOPY = 0x00CC0020,
  SRCPAINT = 0x00EE0086,
  SRCAND = 0x008800C6,
  SRCINVERT = 0x00660046,
  SRCERASE = 0x00440328,
  NOTSRCCOPY = 0x00330008,
  NOTSRCERASE = 0x001100A6,
  MERGECOPY = 0x00C000CA,
  MERGEPAINT = 0x00BB0226,
  PATCOPY = 0x00F00021,
  PATPAINT = 0x00FB0A09,
  PATINVERT = 0x005A0049,
  DSTINVERT = 0x00550009,
  BLACKNESS = 0x00000042,
  WHITENESS = 0x00FF0062,
  CAPTUREBLT = 0x40000000 //only if WinVer >= 5.0.0 (see )
 }

 public enum PrintWindowMode : uint
 {
  [Description(
  "Only the client area of the window is copied to hdcBlt. By default, the entire window is copied.")]
  PW_CLIENTONLY = 0x00000001,

  [Description("works on windows that use DirectX or DirectComposition")]
  PW_RENDERFULLCONTENT = 0x00000002
 }
 }
}

Win32Types

using ;

namespace CaptureSharp
{
 public sealed class Win32Types
 {
 [StructLayout()]
 public struct Point
 {
  public int x;
  public int y;

  public Point(int x, int y)
  {
   = x;
   = y;
  }
 }

 [StructLayout()]
 public struct Rect
 {
  public int Left; //Leftmost coordinate  public int Top; //The top coordinate  public int Right; //The rightmost coordinate  public int Bottom; //The lowest coordinate
  public int Width => Right - Left;
  public int Height => Bottom - Top;
 }

 [StructLayout(, Pack = 2)]
 public struct BitmapFileHeader
 {
  public ushort bfType;
  public uint bfSize;
  public ushort bfReserved1;
  public ushort bfReserved2;
  public uint bfOffBits;
 }

 [StructLayout()]
 public struct BitmapInfoHeader
 {
  public uint biSize;
  public int biWidth;
  public int biHeight;
  public ushort biPlanes;
  public ushort biBitCount;
  public uint biCompression;
  public uint biSizeImage;
  public int biXPelsPerMeter;
  public int biYPelsPerMeter;
  public uint biClrUsed;
  public uint biClrImportant;

  public void Init()
  {
  biSize = (uint)(this);
  }
 }

 [StructLayout(, Pack = 1)]
 public struct RgbQuad
 {
  public byte rgbBlue;
  public byte rgbGreen;
  public byte rgbRed;
  public byte rgbReserved;
 }

 [StructLayout(, Pack = 1)]
 public struct BitmapInfo
 {
  public BitmapInfoHeader bmiHeader;
  public RgbQuad bmiColors;
 }
 }
}

Win32Funcs

using System;
using ;

namespace CaptureSharp
{
 public sealed class Win32Funcs
 {
 [DllImport("", SetLastError = true)]
 public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

 [DllImport("")]
 [return: MarshalAs()]
 public static extern bool GetWindowRect(IntPtr hWnd, out  lpRect);

 [DllImport("")]
 public static extern bool GetClientRect(IntPtr hWnd, out  lpRect);

 [DllImport("", EntryPoint = "GetWindowDC")]
 public static extern IntPtr GetWindowDC(IntPtr hWnd);

 [DllImport("")]
 public static extern IntPtr CreateCompatibleDC(IntPtr hDc);

 [DllImport("")]
 public static extern IntPtr CreateCompatibleBitmap(IntPtr hDc, int nWidth, int nHeight);

 [DllImport("")]
 public static extern bool DeleteDC(IntPtr hDc);

 [DllImport("")]
 public static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);

 [DllImport("")]
 public static extern IntPtr CreateDIBSection(IntPtr hdc, ref  bmi,
  uint usage, out IntPtr ppvBits, IntPtr hSection, uint dwOffset);

 [DllImport("")]
 public static extern IntPtr SelectObject(IntPtr hDc, IntPtr hObject);

 [DllImport("")]
 public static extern bool DeleteObject(IntPtr hObject);

 [DllImport("", SetLastError = true)]
 public static extern bool BitBlt(
  IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight,
  IntPtr hObjectSource, int nXSrc, int nYSrc, uint dwRop);

 [DllImport("")]
 public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);
 }
}

2、

using System;

namespace CaptureSharp
{
 internal class DibCaptureHelper
 {
 public IntPtr BitmapPtr => _hBitmap;
 public  BitmapInfo => _bitmapInfo;
 public  WindowRect => _windowRect;
 public  ClientRect => _clientRect;
 public int BitmapDataSize => _bmpDataSize;

 private IntPtr _hWnd = ;
 private IntPtr _hScrDc = ;
 private IntPtr _hMemDc = ;
 private IntPtr _hBitmap = ;
 private IntPtr _hOldBitmap = ;
 private IntPtr _bitsPtr = ;

 private  _bitmapInfo;
 private  _windowRect;
 private  _clientRect;
 private int _bmpDataSize;

 public bool Init(string windowName)
 {
  var handle = (null, windowName);
  if (())
  {
  return false;
  }

  return Init(handle);
 }

 public bool Init(IntPtr handle)
 {
  _hWnd = handle;

  //Get window size  if (!(_hWnd, out _windowRect)
  || !(_hWnd, out _clientRect))
  {
  return false;
  }

  _bmpDataSize = _clientRect.Width * _clientRect.Height * 3;

  //Bitmap information  _bitmapInfo = new  {bmiHeader = new ()};
  _bitmapInfo.();
  _bitmapInfo. = _clientRect.Width;
  _bitmapInfo. = _clientRect.Height;
  _bitmapInfo. = 1;
  _bitmapInfo. = 24;
  _bitmapInfo. = (uint) (_clientRect.Width * _clientRect.Height);
  _bitmapInfo. = (uint) .BI_RGB;

  _hScrDc = (_hWnd);
  _hMemDc = (_hScrDc);
  _hBitmap = (_hMemDc, ref _bitmapInfo,
  (uint) .DIB_RGB_COLORS,
  out _bitsPtr, , 0);
  _hOldBitmap = (_hMemDc, _hBitmap);

  return true;
 }

 public void Cleanup()
 {
  if (_hBitmap.Equals())
  {
  return;
  }

  //Delete used objects  (_hMemDc, _hOldBitmap);
  (_hBitmap);
  (_hMemDc);
  (_hWnd, _hScrDc);

  _hWnd = ;
  _hScrDc = ;
  _hMemDc = ;
  _hBitmap = ;
  _hOldBitmap = ;
  _bitsPtr = ;
 }

 public bool RefreshWindow()
 {
  var hWnd = _hWnd;
  Cleanup();
  return Init(hWnd);
 }

 public bool ChangeWindowHandle(string windowName)
 {
  Cleanup();
  return Init(windowName);
 }

 public bool ChangeWindowHandle(IntPtr handle)
 {
  Cleanup();
  return Init(handle);
 }

 public IntPtr Capture()
 {
  if (_hBitmap.Equals() || _hMemDc.Equals() || _hScrDc.Equals())
  {
  return ;
  }

  var ret = (
  _hMemDc, 0, 0, _clientRect.Width, _clientRect.Height,
  _hScrDc, 0, 0,
  (uint) );

  return ret ? _bitsPtr : ;
 }

 public bool Capture(out IntPtr bitsPtr, out int bufferSize, out  rect)
 {
  bitsPtr = _bitsPtr;
  bufferSize = _bmpDataSize;
  rect = _clientRect;

  if (_hBitmap.Equals() || _hMemDc.Equals() || _hScrDc.Equals())
  {
  return false;
  }

  var ret = (
  _hMemDc, 0, 0, _clientRect.Width, _clientRect.Height,
  _hScrDc, 0, 0,
  (uint) );

  return ret;
 }
 }
}

The above is the detailed content of C#’s example of using BitBlt for window capture. For more information about c#’s window capture, please pay attention to my other related articles!