服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C# 使用BitBlt进行窗口抓图的示例

C# 使用BitBlt进行窗口抓图的示例

2022-10-26 13:29xhubobo C#

这篇文章主要介绍了C# 使用BitBlt进行窗口抓图的示例,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下

本文和C++使用BitBlt进行窗口抓图对应,使用C#实现。

这种方式对1920*1080大小的窗口,一次抓图的时间参考(VS2015+i5 9400F):低至2~3ms(平均4.3ms)。

参见:C#抓图服务

1、Win32封装

Win32Consts

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System.ComponentModel;
 
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 wingdi.h)
 }
 
 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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
using System.Runtime.InteropServices;
 
namespace CaptureSharp
{
 public sealed class Win32Types
 {
 [StructLayout(LayoutKind.Sequential)]
 public struct Point
 {
  public int x;
  public int y;
 
  public Point(int x, int y)
  {
  this.x = x;
  this.y = y;
  }
 }
 
 [StructLayout(LayoutKind.Sequential)]
 public struct Rect
 {
  public int Left; //最左坐标
  public int Top; //最上坐标
  public int Right; //最右坐标
  public int Bottom; //最下坐标
 
  public int Width => Right - Left;
  public int Height => Bottom - Top;
 }
 
 [StructLayout(LayoutKind.Sequential, Pack = 2)]
 public struct BitmapFileHeader
 {
  public ushort bfType;
  public uint bfSize;
  public ushort bfReserved1;
  public ushort bfReserved2;
  public uint bfOffBits;
 }
 
 [StructLayout(LayoutKind.Sequential)]
 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)Marshal.SizeOf(this);
  }
 }
 
 [StructLayout(LayoutKind.Sequential, Pack = 1)]
 public struct RgbQuad
 {
  public byte rgbBlue;
  public byte rgbGreen;
  public byte rgbRed;
  public byte rgbReserved;
 }
 
 [StructLayout(LayoutKind.Sequential, Pack = 1)]
 public struct BitmapInfo
 {
  public BitmapInfoHeader bmiHeader;
  public RgbQuad bmiColors;
 }
 }
}

Win32Funcs

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System;
using System.Runtime.InteropServices;
 
namespace CaptureSharp
{
 public sealed class Win32Funcs
 {
 [DllImport("User32.dll", SetLastError = true)]
 public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
 
 [DllImport("user32.dll")]
 [return: MarshalAs(UnmanagedType.Bool)]
 public static extern bool GetWindowRect(IntPtr hWnd, out Win32Types.Rect lpRect);
 
 [DllImport("user32.dll")]
 public static extern bool GetClientRect(IntPtr hWnd, out Win32Types.Rect lpRect);
 
 [DllImport("user32.dll", EntryPoint = "GetWindowDC")]
 public static extern IntPtr GetWindowDC(IntPtr hWnd);
 
 [DllImport("gdi32.dll")]
 public static extern IntPtr CreateCompatibleDC(IntPtr hDc);
 
 [DllImport("gdi32.dll")]
 public static extern IntPtr CreateCompatibleBitmap(IntPtr hDc, int nWidth, int nHeight);
 
 [DllImport("gdi32.dll")]
 public static extern bool DeleteDC(IntPtr hDc);
 
 [DllImport("user32.dll")]
 public static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);
 
 [DllImport("gdi32.dll")]
 public static extern IntPtr CreateDIBSection(IntPtr hdc, ref Win32Types.BitmapInfo bmi,
  uint usage, out IntPtr ppvBits, IntPtr hSection, uint dwOffset);
 
 [DllImport("gdi32.dll")]
 public static extern IntPtr SelectObject(IntPtr hDc, IntPtr hObject);
 
 [DllImport("gdi32.dll")]
 public static extern bool DeleteObject(IntPtr hObject);
 
 [DllImport("gdi32.dll", 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("user32.dll")]
 public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags);
 }
}

2、DibCaptureHelper.cs

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using System;
 
namespace CaptureSharp
{
 internal class DibCaptureHelper
 {
 public IntPtr BitmapPtr => _hBitmap;
 public Win32Types.BitmapInfo BitmapInfo => _bitmapInfo;
 public Win32Types.Rect WindowRect => _windowRect;
 public Win32Types.Rect ClientRect => _clientRect;
 public int BitmapDataSize => _bmpDataSize;
 
 private IntPtr _hWnd = IntPtr.Zero;
 private IntPtr _hScrDc = IntPtr.Zero;
 private IntPtr _hMemDc = IntPtr.Zero;
 private IntPtr _hBitmap = IntPtr.Zero;
 private IntPtr _hOldBitmap = IntPtr.Zero;
 private IntPtr _bitsPtr = IntPtr.Zero;
 
 private Win32Types.BitmapInfo _bitmapInfo;
 private Win32Types.Rect _windowRect;
 private Win32Types.Rect _clientRect;
 private int _bmpDataSize;
 
 public bool Init(string windowName)
 {
  var handle = Win32Funcs.FindWindow(null, windowName);
  if (handle.Equals(IntPtr.Zero))
  {
  return false;
  }
 
  return Init(handle);
 }
 
 public bool Init(IntPtr handle)
 {
  _hWnd = handle;
 
  //获取窗口大小
  if (!Win32Funcs.GetWindowRect(_hWnd, out _windowRect)
  || !Win32Funcs.GetClientRect(_hWnd, out _clientRect))
  {
  return false;
  }
 
  _bmpDataSize = _clientRect.Width * _clientRect.Height * 3;
 
  //位图信息
  _bitmapInfo = new Win32Types.BitmapInfo {bmiHeader = new Win32Types.BitmapInfoHeader()};
  _bitmapInfo.bmiHeader.Init();
  _bitmapInfo.bmiHeader.biWidth = _clientRect.Width;
  _bitmapInfo.bmiHeader.biHeight = _clientRect.Height;
  _bitmapInfo.bmiHeader.biPlanes = 1;
  _bitmapInfo.bmiHeader.biBitCount = 24;
  _bitmapInfo.bmiHeader.biSizeImage = (uint) (_clientRect.Width * _clientRect.Height);
  _bitmapInfo.bmiHeader.biCompression = (uint) Win32Consts.BitmapCompressionMode.BI_RGB;
 
  _hScrDc = Win32Funcs.GetWindowDC(_hWnd);
  _hMemDc = Win32Funcs.CreateCompatibleDC(_hScrDc);
  _hBitmap = Win32Funcs.CreateDIBSection(_hMemDc, ref _bitmapInfo,
  (uint) Win32Consts.DibColorMode.DIB_RGB_COLORS,
  out _bitsPtr, IntPtr.Zero, 0);
  _hOldBitmap = Win32Funcs.SelectObject(_hMemDc, _hBitmap);
 
  return true;
 }
 
 public void Cleanup()
 {
  if (_hBitmap.Equals(IntPtr.Zero))
  {
  return;
  }
 
  //删除用过的对象
  Win32Funcs.SelectObject(_hMemDc, _hOldBitmap);
  Win32Funcs.DeleteObject(_hBitmap);
  Win32Funcs.DeleteDC(_hMemDc);
  Win32Funcs.ReleaseDC(_hWnd, _hScrDc);
 
  _hWnd = IntPtr.Zero;
  _hScrDc = IntPtr.Zero;
  _hMemDc = IntPtr.Zero;
  _hBitmap = IntPtr.Zero;
  _hOldBitmap = IntPtr.Zero;
  _bitsPtr = IntPtr.Zero;
 }
 
 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(IntPtr.Zero) || _hMemDc.Equals(IntPtr.Zero) || _hScrDc.Equals(IntPtr.Zero))
  {
  return IntPtr.Zero;
  }
 
  var ret = Win32Funcs.BitBlt(
  _hMemDc, 0, 0, _clientRect.Width, _clientRect.Height,
  _hScrDc, 0, 0,
  (uint) Win32Consts.RasterOperationMode.SRCCOPY);
 
  return ret ? _bitsPtr : IntPtr.Zero;
 }
 
 public bool Capture(out IntPtr bitsPtr, out int bufferSize, out Win32Types.Rect rect)
 {
  bitsPtr = _bitsPtr;
  bufferSize = _bmpDataSize;
  rect = _clientRect;
 
  if (_hBitmap.Equals(IntPtr.Zero) || _hMemDc.Equals(IntPtr.Zero) || _hScrDc.Equals(IntPtr.Zero))
  {
  return false;
  }
 
  var ret = Win32Funcs.BitBlt(
  _hMemDc, 0, 0, _clientRect.Width, _clientRect.Height,
  _hScrDc, 0, 0,
  (uint) Win32Consts.RasterOperationMode.SRCCOPY);
 
  return ret;
 }
 }
}

以上就是C# 使用BitBlt进行窗口抓图的示例的详细内容,更多关于c# 窗口抓图的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/xhubobo/p/12789466.html

延伸 · 阅读

精彩推荐
  • C#C# Fiddler插件实现网站离线浏览功能

    C# Fiddler插件实现网站离线浏览功能

    本文主要介绍了C# Fiddler插件实现网站离线浏览功能的原理与方法。具有很好的参考价值,下面跟着小编一起来看下吧...

    Frank.Cui5772021-12-24
  • C#C#窗体布局方式详解

    C#窗体布局方式详解

    这篇文章主要介绍了C#窗体布局方式详解的相关资料,需要的朋友可以参考下...

    zl大王派我来巡山8382021-12-07
  • C#C#深浅拷贝的深入解析

    C#深浅拷贝的深入解析

    这篇文章主要给大家介绍了关于C#深浅拷贝的深入解析,文中通过示例代码介绍的非常详细,对大家的学习或者使用C#具有一定的参考学习价值,需要的朋友...

    小世界的野孩子4762022-08-09
  • C#ajaxFileUpload插件,C#返回Json数据报错问题的解决方案

    ajaxFileUpload插件,C#返回Json数据报错问题的解决方案

    这篇文章主要介绍了ajaxFileUpload插件,C#返回Json数据报错的解决方案,需要的朋友可以参考下...

    好记性不如烂键盘5882022-02-17
  • C#使用C#编写自己的区块链挖矿算法

    使用C#编写自己的区块链挖矿算法

    这篇文章主要介绍了使用C#编写自己的区块链挖矿算法,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下...

    MyZony8642022-08-01
  • C#利用C#修改Windows操作系统时间

    利用C#修改Windows操作系统时间

    这篇文章主要介绍了利用C#修改Windows操作系统时间,帮助大家更好的利用c#操作系统,感兴趣的朋友可以了解下...

    rainbow706267262022-10-12
  • C#Qt程序中调用C#编写的dll(推荐)

    Qt程序中调用C#编写的dll(推荐)

    这篇文章主要介绍了Qt程序中调用C#编写的dll,本文图文并茂给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...

    风向晚。3802022-08-31
  • C#C#中用foreach语句遍历数组及将数组作为参数的用法

    C#中用foreach语句遍历数组及将数组作为参数的用法

    这篇文章主要介绍了C#中用foreach语句遍历数组及将数组作为参数的用法,C#的数组可作为实参传递给方法形参,需要的朋友可以参考下...

    C#教程网3862021-11-09