Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
502 views
in Technique[技术] by (71.8m points)

c# - 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:

Canvas is a gray part.

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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" ...>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...