Graphics object

M

mick

I was under the impression that when you obtain your
graphics object via


Graphics g = e.Graphics // e being PaintEventArgs

then you didnt need to Dispose() it, but Ive started reading
a book on GDI+ and in the examples it does does Dispose g.
Why so? Thought you only needed to Dispose objects that had
been new`d up.

mick
 
P

Peter Duniho

mick said:
I was under the impression that when you obtain your
graphics object via

Graphics g = e.Graphics // e being PaintEventArgs

then you didnt need to Dispose() it, but Ive started reading
a book on GDI+ and in the examples it does does Dispose g.
Why so? Thought you only needed to Dispose objects that had been new`d up.

..NET != GDI+ (in spite of the close relationship between the two)

Also, without specifics about those examples, it's not clear that you
are comparing apples to apples even ignoring the API difference. In
particular, the Graphics instance obtained from the PaintEventArgs is
special, having been retrieved earlier on your behalf, and being
disposed later also on your behalf.

It is definitely not true that you only need to call Dispose() on
objects your own code has specifically created using "new". But in this
particular case, you are correct that that particular Graphics instance
is not your responsibility to dispose.

Pete
 
M

mick

Peter Duniho said:
.NET != GDI+ (in spite of the close relationship between the two)

I know. I`m using both.
Also, without specifics about those examples, it's not clear that you are
comparing apples to apples even ignoring the API difference. In
particular, the Graphics instance obtained from the PaintEventArgs is
special, having been retrieved earlier on your behalf, and being disposed
later also on your behalf.

Well this is an example from the book -

Listing 2.2 Using Dispose calls
protected override void OnPaint(PaintEventArgs e)
{
// Obtain the Graphics object
Graphics g = e.Graphics;
// Set the composite quality and smoothing mode
// of the surface
g.SmoothingMode = SmoothingMode.AntiAlias;
// Create a rectangle from point (20, 20) to (100, 100)
Rectangle rect = new Rectangle(20, 20, 100, 100);
// Create two Pen objects, one red and one black
Pen redPen = new Pen(Color.Red, 3);
Pen blackPen = Pens.Black;
// Create a SolidBrush object
SolidBrush greenBrush = new SolidBrush(Color.Green);
// Draw shapes and lines
g.DrawRectangle(redPen, rect);
g.FillEllipse(greenBrush, rect);
g.DrawLine(blackPen, 0, 250, this.Width, 250);
g.FillEllipse(Brushes.Blue, 70, 220, 30, 30);
g.FillEllipse(Brushes.SkyBlue, 100, 210, 40, 40);
g.FillEllipse(Brushes.Green, 140, 200, 50, 50);
g.FillEllipse(Brushes.Yellow, 190, 190, 60, 60);
g.FillEllipse(Brushes.Violet, 250, 180, 70, 70);
g.FillEllipse(Brushes.Red, 320, 170, 80, 80);
// Dispose of objects
greenBrush.Dispose();
// blackPen.Dispose();
redPen.Dispose();
g.Dispose();
}

It is definitely not true that you only need to call Dispose() on objects
your own code has specifically created using "new". But in this
particular case, you are correct that that particular Graphics instance is
not your responsibility to dispose.

The reason I was surprised at the Dispose above is when I was learning a bit
about
classes and subclassing I created a custom label as an excercise. All I did
was
give options for the text in the label to have a shadow or a border.
However, if
i use g.Dispose() at the end of the paint event the app will crash


protected override void OnPaint(PaintEventArgs e)
{
if (this.__prvCustomFontStyle == CustomFontStyle.None)
{
base.OnPaint(e);
return;
}

Graphics g = e.Graphics;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
this.drawSize = e.Graphics.MeasureString(this.Text, this.Font,
new PointF(), StringFormat.GenericTypographic);

< Text Alignment stuff snipped for brevity>

if (__prvCustomFontStyle == CustomFontStyle.Outline)
{
float fontSize = e.Graphics.DpiY * this.Font.SizeInPoints /
72;
this.drawPath.Reset();
this.drawPath.AddString(this.Text, this.Font.FontFamily,
(int)this.Font.Style, fontSize, point, StringFormat.GenericTypographic);
g.FillPath(this.foreColorBrush, this.drawPath);
g.DrawPath(this.textBorderPen, this.drawPath);
}
else //Shadow
{
g.DrawString(this.Text, this.Font, new
SolidBrush(this.ShadowColor), this.Displacement.X + point.X,
this.Displacement.Y + point.Y);
g.DrawString(this.Text, this.Font, new
SolidBrush(this.ForeColor), point);
}
// g.Dispose(); //BOOOM!
}


mick
 
P

Peter Duniho

mick said:
[...]
The reason I was surprised at the Dispose above is when I was learning a
bit about
classes and subclassing I created a custom label as an excercise. All I
did was
give options for the text in the label to have a shadow or a border.
However, if
i use g.Dispose() at the end of the paint event the app will crash

Of course. Because you're not supposed to do that.

Sounds like a crummy book. Not only is it telling you to call Dispose()
when you're not supposed to, it's not showing use of the "using"
statement to handle object diposal.

I recommend you find a better book.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top