Problem calling dispose for a graphics object

S

steve bull

When adding a new user control to a panel I get the following call stack. Having put debugs everywhere I can think of I
cannot get the program to break anywhere near where it is having this problem.



System.ArgumentException: Invalid parameter used
at System.Drawing.Graphics.EndContainer(GraphicsContainer container)
at System.Windows.Forms.DibGraphicsBufferManager.ReleaseBuffer(GraphicsBuffer buffer)
at System.Windows.Forms.GraphicsBuffer.Dispose()
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Design.DesignerWindowTarget.DefWndProc(Message& m)
at System.Windows.Forms.Design.ControlDesigner.DefWndProc(Message& m)
at System.Windows.Forms.Design.ControlDesigner.WndProc(Message& m)
at System.Windows.Forms.Design.DesignerWindowTarget.OnMessage(Message& m)



Does anyone have any idea? I have included a stripped down version of the original control.
The problem appears to be with the dispose in the OnPaint method. If I leave it out the control runs fine but I thought
all graphics objects should be disposed of when no longer needed.

Thanks,

Steve







using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using Graphics2D;

namespace NewControls
{
[ToolboxItem(true)]
[ToolboxBitmap(typeof(resfinder),"ColorPictureBox.bmp")]

/// <summary>
/// Summary description for ColorPictureBox.
/// </summary>
public class ColorPictureBox : System.Windows.Forms.PictureBox
{
private Color m_selectedColor = Color.Black;
private System.ComponentModel.Container components = null;

public ColorPictureBox()
{

}

protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}

}
base.Dispose( disposing );

} /* End of Dispose(bool) */



protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint (e);

Graphics g = e.Graphics;

ControlPaint.DrawBorder3D(g, new Rectangle(1, 1, Width - 20, Height - 20));

g.Dispose();

} /* End of OnPaint(PaintEventArgs) */


} /* End of public class ColorPictureBox */

} /* End of namespace NewControls */
 
M

Martin Stenhoff

If I leave it out the control runs fine but I thought all graphics objects
should be
disposed of when no longer needed.
Thanks,

Steve

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint (e);
Graphics g = e.Graphics;
ControlPaint.DrawBorder3D(g, new Rectangle(1, 1, Width - 20, Height -
20));
g.Dispose();

} /* End of OnPaint(PaintEventArgs) */

I believe that one is only supposed to dispose objects that one has
created( with new i.e)
The Graphic object you are disposing above has been provided for you and you
don't own it.
From the stack trace it looks like Windows gets mighty upset when it tries
to dispose the graphics
object (it had created to be used during WMPaint) and now finds out it is
not valid.

Now, I don't know if this is the problem you're having as I'm just getting
started with C#
(I usually come up with explanations that sounds good in my head when I
don't really have a clue)

Martin
 
R

Richard Blewett [DevelopMentor]

You need to Dispose resources that *you acquire* as no-one else will do that. This Graphics object is being passed to you by someone else (the Winforms infrastructure) - in theory they will Dispose it. This the problem with IDisposable - it requires a very strong notion of ownership of the object which everyone agrees on - and the owneer *and only the owner* should call Dispose.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

When adding a new user control to a panel I get the following call stack. Having put debugs everywhere I can think of I
cannot get the program to break anywhere near where it is having this problem.



System.ArgumentException: Invalid parameter used
at System.Drawing.Graphics.EndContainer(GraphicsContainer container)
at System.Windows.Forms.DibGraphicsBufferManager.ReleaseBuffer(GraphicsBuffer buffer)
at System.Windows.Forms.GraphicsBuffer.Dispose()
at System.Windows.Forms.Control.WmPaint(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Design.DesignerWindowTarget.DefWndProc(Message& m)
at System.Windows.Forms.Design.ControlDesigner.DefWndProc(Message& m)
at System.Windows.Forms.Design.ControlDesigner.WndProc(Message& m)
at System.Windows.Forms.Design.DesignerWindowTarget.OnMessage(Message& m)



Does anyone have any idea? I have included a stripped down version of the original control.
The problem appears to be with the dispose in the OnPaint method. If I leave it out the control runs fine but I thought
all graphics objects should be disposed of when no longer needed.

Thanks,

Steve
 
M

Martin Stenhoff

I'm getting a bit confused now. I thought that one should never call dispose
on Graphics objects that one
has not created, but then I stumbled onto this article
http://windowsforms.net/articles/windowsformspainting.aspx
which seems to be coming from the Microsoft folks themselves and they
provide this code sample

protected override void OnPaintBackground(PaintEventArgs e) {
base.OnPaintBackground(e);
Graphics bgGraphics = e.Graphics;

bgGraphics.SetClip(textRegion, CombineMode.Exclude);
bgGraphics.FillRectangle(backgroundBrush, e.ClipRectangle);

bgGraphics.Dispose();
}

Is this a bad example or what?

Martin
 
R

Richard Blewett [DevelopMentor]

I think your just looking at a bad sample.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

I'm getting a bit confused now. I thought that one should never call dispose
on Graphics objects that one
has not created, but then I stumbled onto this article
http://windowsforms.net/articles/windowsformspainting.aspx
which seems to be coming from the Microsoft folks themselves and they
provide this code sample

protected override void OnPaintBackground(PaintEventArgs e) {
base.OnPaintBackground(e);
Graphics bgGraphics = e.Graphics;

bgGraphics.SetClip(textRegion, CombineMode.Exclude);
bgGraphics.FillRectangle(backgroundBrush, e.ClipRectangle);

bgGraphics.Dispose();
}

Is this a bad example or what?

Martin
 

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