WPF:获取截图的方法

 手浪用户2602924633 发布于 2023-02-13 12:49

希望修改以下内容以截取所有显示器的屏幕截图.我试过调整它但我的图像是空白的.将它写入test.png是为了测试.在byte[]将被发送到接收应用程序.

public byte[] Take()
{
    int screenWidth = Convert.ToInt32(SystemParameters.VirtualScreenWidth);
    int screenHeight = Convert.ToInt32(SystemParameters.VirtualScreenHeight);
    int screenLeft = Convert.ToInt32(SystemParameters.VirtualScreenLeft);
    int screenTop = Convert.ToInt32(SystemParameters.VirtualScreenTop);

    RenderTargetBitmap renderTarget = new RenderTargetBitmap(screenWidth, screenHeight, 96, 96, PixelFormats.Pbgra32);
    VisualBrush sourceBrush = new VisualBrush();

    DrawingVisual drawingVisual = new DrawingVisual();
    DrawingContext drawingContext = drawingVisual.RenderOpen();

    using (drawingContext)
    {
        drawingContext.PushTransform(new ScaleTransform(1, 1));
        drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(screenWidth, screenHeight)));
    }
    renderTarget.Render(drawingVisual);

    PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
    pngEncoder.Frames.Add(BitmapFrame.Create(renderTarget));

    Byte[] _imageArray;

    using (MemoryStream outputStream = new MemoryStream())
    {
        pngEncoder.Save(outputStream);
        _imageArray = outputStream.ToArray();
    }

    using (FileStream stream = new FileStream(@"c:\test.png", FileMode.Create, FileAccess.ReadWrite))
    {
        using (BinaryWriter writer = new BinaryWriter(stream))
        {
            writer.Write(_imageArray);
        }
    }

    return _imageArray;
}

Mark Feldman.. 14

首先,您需要为以下命名空间添加引用:

using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

然后枚举您的监视器以获取所有显示表面的边界矩形并将其传递给Graphics.CopyFromScreen()方法调用:

private static BitmapSource CopyScreen()
{
    var left = Screen.AllScreens.Min(screen => screen.Bounds.X);
    var top = Screen.AllScreens.Min(screen => screen.Bounds.Y);
    var right = Screen.AllScreens.Max(screen => screen.Bounds.X + screen.Bounds.Width);
    var bottom = Screen.AllScreens.Max(screen => screen.Bounds.Y + screen.Bounds.Height);
    var width = right - left;
    var height = bottom - top;

    using (var screenBmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
    {
        using (var bmpGraphics = Graphics.FromImage(screenBmp))
        {
            bmpGraphics.CopyFromScreen(left, top, 0, 0, new System.Drawing.Size(width, height));
            return Imaging.CreateBitmapSourceFromHBitmap(
                screenBmp.GetHbitmap(),
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());
        }
    }
}

请记住,虽然显示器通常不能整齐地放入单个矩形中,特别是如果它们具有不同的分辨率等,因此您可能更好地快照单个屏幕.无论哪种方式,您的问题的解决方案是更改您传入Graphics.CopyFromScreen()方法调用的坐标.

编辑:请参阅下面的Demetris Leptos的评论,我在这个答案中发布的代码应该是在返回的位图上调用DeleteObject screenBmp.GetHbitmap(),以避免内存泄漏,如MSDN文档中所指定的.

1 个回答
  • 首先,您需要为以下命名空间添加引用:

    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Windows.Forms;
    

    然后枚举您的监视器以获取所有显示表面的边界矩形并将其传递给Graphics.CopyFromScreen()方法调用:

    private static BitmapSource CopyScreen()
    {
        var left = Screen.AllScreens.Min(screen => screen.Bounds.X);
        var top = Screen.AllScreens.Min(screen => screen.Bounds.Y);
        var right = Screen.AllScreens.Max(screen => screen.Bounds.X + screen.Bounds.Width);
        var bottom = Screen.AllScreens.Max(screen => screen.Bounds.Y + screen.Bounds.Height);
        var width = right - left;
        var height = bottom - top;
    
        using (var screenBmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb))
        {
            using (var bmpGraphics = Graphics.FromImage(screenBmp))
            {
                bmpGraphics.CopyFromScreen(left, top, 0, 0, new System.Drawing.Size(width, height));
                return Imaging.CreateBitmapSourceFromHBitmap(
                    screenBmp.GetHbitmap(),
                    IntPtr.Zero,
                    Int32Rect.Empty,
                    BitmapSizeOptions.FromEmptyOptions());
            }
        }
    }
    

    请记住,虽然显示器通常不能整齐地放入单个矩形中,特别是如果它们具有不同的分辨率等,因此您可能更好地快照单个屏幕.无论哪种方式,您的问题的解决方案是更改您传入Graphics.CopyFromScreen()方法调用的坐标.

    编辑:请参阅下面的Demetris Leptos的评论,我在这个答案中发布的代码应该是在返回的位图上调用DeleteObject screenBmp.GetHbitmap(),以避免内存泄漏,如MSDN文档中所指定的.

    2023-02-13 12:51 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有