本文和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