Welcome to AspAdvice Sign in | Join | Help

Saving the state of a Graphics object

Today I discovered a new class : GraphicsContainer; it allows you to save the state of aGraphics object (transformation, clipping region, and rendering properties) and to restore it later.

This class is used in conjunction with 2 pairs of methods belonging to the Graphics class:

BeginContainer saves the state of the graphics object (and returns a GraphicsContainer object), EndContainer restores the state (when provided with a GraphicsContainer object). MSDN provides a sample here: http://msdn2.microsoft.com/en-us/library/azdschfw.aspx.

There exists overloads of BeginContainer that accept two rectangles and unit allowing the Graphics object to be applied a new transformation after its state is saved.

In the same maneer, but in a simpler way, the Graphics.Save and Graphics.Restore methods do the same job (Honestly, I don't understand why these two pairs of methods coexist...)

This led me to write a little helper class allowing to save/restore a Graphics with the using syntax.

Here is how to use this class (it is just a rewritten version of the MSDN sample):

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
    Graphics g = e.Graphics;

    // Define transformation for container.
    RectangleF src = new RectangleF(0f, 0f, 200f, 200f);
    RectangleF dest = new RectangleF(100f, 100f, 150f, 150f);

    using (PaintHelper.SaveGraphics(g, dest, src, GraphicsUnit.Pixel))
    {
        // Fill red rectangle in container.
        g.FillRectangle(Brushes.Red, 0.0F, 0.0F, 200.0F, 200.0F);
    }

    // Fill untransformed rectangle with green.
    g.FillRectangle(Brushes.Green, 0.0F, 0.0F, 200.0F, 200.0F);
}

And the source code for the PaintHelper class:   

using System;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace Delta.Internals
{
    public static class PaintHelper
    {
        private class GraphicsBackup : IDisposable
        {
            private Graphics graphics = null;
            private GraphicsContainer container = null;

            public GraphicsBackup(Graphics g)
            {
                Init(g);
                container = g.BeginContainer();
            }

            public GraphicsBackup(Graphics g, Rectangle dest, Rectangle src, GraphicsUnit unit)
            {
                container = g.BeginContainer(dest, src, unit);
            }

            public GraphicsBackup(Graphics g, RectangleF dest, RectangleF src, GraphicsUnit unit)
            {
                container = g.BeginContainer(dest, src, unit);
            }

            private void Init(Graphics g)
            {
                if (g == null) throw new ArgumentNullException("g");
                graphics = g;
            }

            public void Dispose()
            {
                graphics.EndContainer(container);
            }
        }

        public static IDisposable SaveGraphics(Graphics g)
        {
            return new GraphicsBackup(g);
        }

        public static IDisposable SaveGraphics(Graphics g,
            Rectangle dest, Rectangle src, GraphicsUnit unit)
        {
            return new GraphicsBackup(g, dest, src, unit);
        }

        public static IDisposable SaveGraphics(Graphics g,
            RectangleF dest, RectangleF src, GraphicsUnit unit)
        {
            return new GraphicsBackup(g, dest, src, unit);
        }
    }
}

Hope this helps. 

Sponsor
Published Wednesday, August 23, 2006 6:04 PM by odalet

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

No Comments

Leave a Comment

(required) 
required 
(required) 
Enter the code you see below