简体   繁体   中英

How to get "visible" size of canvas?

I need to save visible content of Canvas as PNG.

I have the folowing method that takes actual size of Canvas and save it as image.

        private void SavePng()
        {
            Rect bounds = VisualTreeHelper.GetDescendantBounds(this.CanvasMain);
            
            //I also tried this
            /*Rect bounds = new Rect(
                  new Point(0, 0), 
                  new Point(this.CanvasMain.ActualWidth, this.CanvasMain.ActualHeight)
              );*/        
    
            double dpi = 96d;

            RenderTargetBitmap rtb = new RenderTargetBitmap((int)bounds.Width, (int)bounds.Height, dpi, dpi, System.Windows.Media.PixelFormats.Default);

            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext dc = dv.RenderOpen())
            {
                VisualBrush vb = new VisualBrush(this.CanvasMain);
                dc.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
            }

            rtb.Render(dv);

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

            try
            {
                System.IO.MemoryStream ms = new System.IO.MemoryStream();

                pngEncoder.Save(ms);
                ms.Close();

                SaveFileDialog dlg = new SaveFileDialog();
                dlg.DefaultExt = ".png";
                dlg.Filter = "Image (.png)|*.png";
                string filename = "";
                if (dlg.ShowDialog() == true)
                    filename = dlg.FileName;

                System.IO.File.WriteAllBytes(filename, ms.ToArray());
            }
            catch (ArgumentException err)
            {
                MessageBox.Show("Wrong path!", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

But if I have an object out of bounds of the window, I will get something like this:

画布是灰色的部分。

How do I get only the visible part of the Canvas that is within the bounds of the window?

A VisualBrush automatically determines the bounds of its "rendered content".

In order to avoid that, set its Viewbox property:

var rect = new Rect(CanvasMain.RenderSize);

var rtb = new RenderTargetBitmap(
    (int)rect.Width, (int)rect.Height, 96, 96, PixelFormats.Default);

var dv = new DrawingVisual();

using (var dc = dv.RenderOpen())
{
    var vb = new VisualBrush
    {
        Visual = CanvasMain,
        Viewbox = rect,
        ViewboxUnits = BrushMappingMode.Absolute
    };

    dc.DrawRectangle(vb, null, rect);
}

rtb.Render(dv);

Alternatively, set the Canvas's ClipToBounds property to true:

<Canvas x:Name="CanvasMain" ClipToBounds="True" ...>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM