前言
Windows 上,屏幕截图一般是调用 win32 api 完成的,如果 C# 想实现截图功能,就需要封装相关 api。在 Windows 上,主要图形接口有 GDI 和 DirectX。GDI 接口比较灵活,可以截取指定窗口,哪怕窗口被遮挡或位于显示区域外,但兼容性较低,无法截取 DX 接口输出的画面。DirectX 是高性能图形接口(当然还有其他功能,与本文无关,忽略不计),主要作为游戏图形接口使用,灵活性较低,无法指定截取特定窗口(或者只是我不会吧),但是兼容性较高,可以截取任何输出到屏幕的内容,根据情况使用。
正文
以下代码使用了 C# 8.0 的新功能,只能使用 VS 2019 编译,如果需要在老版本 VS 使用,需要自行改造。
GDI
用静态类简单封装 GDI 接口并调用接口截图。
1 public static class CaptureWindow
2 {
3 #region 类
4 /// <summary>
5 /// Helper class containing User32 API functions
6 /// </summary>
7 private class User32
8 {
9 [StructLayout(LayoutKind.Sequential)]
10 public struct RECT
11 {
12 public int left;
13 public int top;
14 public int right;
15 public int bottom;
16 }
17 [DllImport("user32.dll")]
18 public static extern IntPtr GetDesktopWindow();
19 [DllImport("user32.dll")]
20 public static extern IntPtr GetWindowDC(IntPtr hWnd);
21 [DllImport("user32.dll")]
22 public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
23 [DllImport("user32.dll")]
24 public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
25
26 [DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Unicode)]
27 public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
28 }
29
30 private class Gdi32
31 {
32
33 public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter
34 [DllImport("gdi32.dll")]
35 public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest,
36 int nWidth, int nHeight, IntPtr hObjectSource,
37 int nXSrc, int nYSrc, int dwRop);
38 [DllImport("gdi32.dll")]
39 public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth,
40 int nHeight);
41 [DllImport("gdi32.dll")]
42 public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
43 [DllImport("gdi32.dll")]
44 public static extern bool DeleteDC(IntPtr hDC);
45 [DllImport("gdi32.dll")]
46 public static extern bool DeleteObject(IntPtr hObject);
47 [DllImport("gdi32.dll")]
48 public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
49 }
50 #endregion
51
52 /// <summary>
53 /// 根据句柄截图
54 /// </summary>
55 /// <param name="hWnd">句柄</param>
56 /// <returns></returns>