有没有所有虚拟显示的截图方法?

Is there a method of screenshot for all virtual display?

我发现的所有方法都以某种方式 UI 依赖。那么,如何在没有任何依赖和第三方的情况下捕获所有显示?

您可以对整个桌面使用带有 SM_CXVIRTUALSCREENSM_CYVIRTUALSCREEN 参数的 GetSystemMetrics 函数。它将处理所有虚拟显示器。

using System;
using System.ComponentModel;//You can remove it if you will catch the below exception from another layer
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;

namespace Helpers {
    public static class HelperScreenShot {

        public static void TakeAndSaveByAllScreen(ImageFormat imageFormat, string fullFileName = null) {
            var img = CopyFromScreen();
            if(img == null) return;

            if(string.IsNullOrWhiteSpace(fullFileName)) {
                fullFileName = $"{Guid.NewGuid()}.{imageFormat.ToString().ToLower()}";
            }

            img.Save(fullFileName, imageFormat);
        }

        public static byte[] TakeAsBinary(ImageFormat imageFormat) {
            using var image = CopyFromScreen();
            if(image == null) return default;

            using var ms = new MemoryStream();
            image.Save(ms, imageFormat);
            return ms.ToArray();
        }

        private static Bitmap CopyFromScreen() {
            try {
                var size = HelperDisplay.GetVirtualScreenSize();
                var image = new Bitmap(size.Width, size.Height);
                using var graphics = Graphics.FromImage(image);
                graphics.CopyFromScreen(Point.Empty, Point.Empty, size);
                return image;
            }
            catch(Win32Exception) {//When screen saver is active
                return null;
            }
        }

        private static class HelperDisplay {

            [DllImport("user32.dll")]
            private static extern int GetSystemMetrics(MetricType metricType);

            public static Size GetVirtualScreenSize() {
                var width = GetSystemMetrics(MetricType.VirtualScreenWidth);
                var height = GetSystemMetrics(MetricType.VirtualScreenHeight);
                return new Size(width, height);
            }

            private enum MetricType {
                VirtualScreenWidth = 78,
                VirtualScreenHeight = 79
            }
        }
    }
}

用法

var dir = Path.Combine("images", "screenshot");
var imgFormat = ImageFormat.Png;
var fileName = $"{Guid.NewGuid()}.{imgFormat.ToString().ToLower()}";
fileName = Path.Combine(dir, fileName);

if(!Directory.Exists(dir)) {
    Directory.CreateDirectory(dir);
}

HelperScreenShot.TakeAndSaveByAllScreen(fileName, imgFormat);
//or 
var binaryImg = HelperScreenShot.TakeAsBinary(imgFormat);

进一步阅读:

Multiple Monitor System Metrics
winuser.h header
How do you use System.Drawing in .NET Core?