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.