如何将WPF ScrollViewer的所有内容保存为图像

3

我有一个包含许多垂直扩展子控件的ScrollViewer控件的WPF窗口。当用户单击位于ScrollViewer底部的按钮时,我希望将所有内容(当前在视图中和不在视图中的内容)保存为图像。

我正在使用以下代码,该代码是我从示例中改编而来,用于显示如何保存窗口的内容:

public static void SaveForm(ScrollViewer container, string filename)
{        
    const int dpi = 96;
    var rtb = new RenderTargetBitmap(
        (int)container.ExtentWidth, //width 
        (int)container.ExtentHeight, //height 
        dpi, //dpi x 
        dpi, //dpi y 
        PixelFormats.Pbgra32 // pixelformat 
        );

    rtb.Render(container);
    SaveRTBAsPNG(rtb, filename);
}

private static void SaveRTBAsPNG(RenderTargetBitmap bmp, string filename)
{
    var enc = new System.Windows.Media.Imaging.PngBitmapEncoder();
    enc.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(bmp));

    using (var stm = System.IO.File.Create(filename))
    {
        enc.Save(stm);
    }
}

目前正在生成PNG文件,但它只包含了ScrollViewer中当前可见的部分。是否有办法让PNG文件包含所有内容,包括那些需要滚动查看的内容?

2个回答

11

使用此方法时,将您的滚动视图的内容作为源,而不是滚动视图本身:(即使内容不可见,它也会拍摄快照)

    public static void SnapShotPNG(this UIElement source, Uri destination, int zoom)
    {
        try
        {
            double actualHeight = source.RenderSize.Height;
            double actualWidth = source.RenderSize.Width;

            double renderHeight = actualHeight * zoom;
            double renderWidth = actualWidth * zoom;

            RenderTargetBitmap renderTarget = new RenderTargetBitmap((int)renderWidth, (int)renderHeight, 96, 96, PixelFormats.Pbgra32);
            VisualBrush sourceBrush = new VisualBrush(source);

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

            using (drawingContext)
            {
                drawingContext.PushTransform(new ScaleTransform(zoom, zoom));
                drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight)));
            }
            renderTarget.Render(drawingVisual);

            PngBitmapEncoder encoder = new PngBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(renderTarget));
            using (FileStream stream = new FileStream(destination.LocalPath, FileMode.Create, FileAccess.Write))
            {
                encoder.Save(stream);
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e);
        }
    }

完美地发挥作用了,当我找到了缩放选项。给这个点赞! - evilfish

3
这里是我导出画布为图像的代码。我认为,如果你将画布更改为滚动视图,它也可以适用于滚动视图。使用这段代码,您还可以保存所有视图。
    public static void ExportToImage(Canvas canvas)
    {
        
        var dlg = new SaveFileDialog();
        dlg.Filter = "JPEG Files (*.jpeg)|*.jpeg|PNG Files (*.png)|*.png|JPG Files (*.jpg)|*.jpg|GIF Files (*.gif)|*.gif";
        dlg.DefaultExt = "png";
        dlg.FilterIndex = 2;
        dlg.FileName = "DesignerImage.png";
        dlg.RestoreDirectory = true;

        // Display OpenFileDialog by calling ShowDialog method 
        Nullable<bool> result = dlg.ShowDialog();
        string path = dlg.FileName;
        int selectedFilterIndex = dlg.FilterIndex;

        if(result==true)
        {

            try
            {
                RenderTargetBitmap renderBitmap = new RenderTargetBitmap(
                         (int)canvas.ActualWidth, (int)canvas.ActualHeight,
                          96d, 96d, PixelFormats.Pbgra32);
                // needed otherwise the image output is black
                canvas.Measure(new Size((int)canvas.ActualWidth, (int)canvas.ActualHeight));
                canvas.Arrange(new Rect(new Size((int)canvas.ActualWidth, (int)canvas.ActualHeight)));

                renderBitmap.Render(canvas);
                BitmapEncoder imageEncoder = new PngBitmapEncoder();


                if (selectedFilterIndex == 1)
                {
                    imageEncoder = new JpegBitmapEncoder();
                }
                else if (selectedFilterIndex == 2)
                {
                    imageEncoder = new PngBitmapEncoder();
                }
                else if (selectedFilterIndex == 3)
                {
                    imageEncoder = new JpegBitmapEncoder();
                }
                else if (selectedFilterIndex == 4)
                {
                    imageEncoder = new GifBitmapEncoder();
                }

              imageEncoder.Frames.Add(BitmapFrame.Create(renderBitmap));

                using (FileStream file = File.Create(path))
                {
                    imageEncoder.Save(file);
                }
            }
            catch (Exception ex)
            {

            }
     }

    }

代码很棒,但有一个小问题。在这里发布了相关内容: https://stackoverflow.com/questions/76692063/wpf-scrollviewer-arrange-make-it-go-up - user1019042
@user1019042 谢谢你的更新。那是非常老的代码 :) - Ugur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接