Как сохранить все содержимое WPF ScrollViewer в виде изображения
У меня есть окно WPF с элементом управления ScrollViewer, содержащим много дочерних элементов управления, которые расширяются по вертикали. Когда пользователь нажимает кнопку, расположенную в нижней части 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 ответа
Используйте это с контентом вашего scrollviewer в качестве источника, а не самого scrollviewer: (Он делает снимок, даже если содержимое не видно)
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);
}
}
Здесь у меня есть мой код для экспорта холста как изображения. Я думаю, это будет работать и для ScrollViewer, если вы переключитесь с Canvas на ScrollViewer. С помощью этого кода вы также можете сохранить все View.
public static void ExportToImage(Canvas canvas)
{
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 == 0)
{
}
else 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)
{
}
}
}