Should I store Graphics object ?

S

Sanjay

hi,

We are currently porting our project from VB6 to VB .NET.

Earlier we used to make scale transformations on objects like pictureBox ,
forms etc.Now Such transformations are made on the graphics object of the
form/pictureBox.

Should It be better if make a graphics object from my pictureBox in load
event handler of the form and store it as member variable of the form , make
transformations as and when required(we really require such transformations
from mils to pixels.). And finally I can dispose it when the form is
disposed.

But I have read somewhere that Graphics object should never be stored as
member varibale of a class.And so I am really confused as to what should I
do ?

Plz help me regarding this..

sanjay
 
S

Sean Hederman

You should definately not store the graphics object. All the code using
Graphics should ideally be encapsulated within the Paint/OnPaint procedures.
 
S

Sanjay

Hi Hederman,
thanks for your reply.
But our's is a different requirement.We do all our drawing in units of
mils(0.001 inch).And so we are doing a lot of transformations
to/from supported units to/from mils here and there.If I put all the
transformations in the paint,It will really be messy.Anyway it is not
possible with the current implementations.

Also could u plz make me clear as to why r u against making in a data
member.

I will be thankful to u for the same

thanking u
sanjay

----- Original Message -----
From: "Sean Hederman" <[email protected]>
Newsgroups:
microsoft.public.dotnet.framework,microsoft.public.dotnet.framework.drawing,
microsoft.public.dotnet.framework.windowsforms,microsoft.public.dotnet.gener
al,microsoft.public.dotnet.languages.vb
Sent: Friday, March 11, 2005 6:10 PM
Subject: Re: Should I store Graphics object ?
 
S

Sean Hederman

If you need to store the effects of transformations, what you can do is have
Matrix member variable that you store your transformations in. Apply the
changes to the Matrix in your various procedures, and then apply the Matrix
to the Graphics object in the Paint.

As for why you shouldn't store the Graphics object, there's no guarantee
that the Graphics object has any meaning outside the Paint event. For
example, when double bufferring is enabled, then the Graphics object being
passed to your Paint relates to a GraphicsBuffer object rather than the
actual drawing surface. More importantly, the next time Paint is invoked,
you're given a different GraphicsBuffer object. Thus, painting on your
stored Graphics object will not result in the painting being on the drawing
surface. In addition, since there's no guarantee, future versions of .NET
may break your code even if you don't use double buffering.
 
G

Guest

I'm curious as to where M'soft documents that future versions may use double
buffering as the default? Can you cite a link or reference? It's very
convientent to use a class graphics variable to update only parts of the
display without recalculating and re-displaying the entire control.
 
S

Sean Hederman

Dennis said:
I'm curious as to where M'soft documents that future versions may use
double
buffering as the default? Can you cite a link or reference? It's very
convientent to use a class graphics variable to update only parts of the
display without recalculating and re-displaying the entire control.

They don't. There are two issues here. One is that if you ever decide to
switch on double bufferring, then all your code outside of Paint could be
rendered useless. The other is that there are no guarantees about the
Graphics object outside Paint. Since there are no guarantees, using the
Graphics object elsewhere *could* be invalidated by future versions of .NET.
Using Graphics outside Paint, knowing that it wraps an HDC is breaking
encapsulation.

As to updating only parts of your display, there are two main approaches you
could follow here:
1. Use the Invalidate() overrides to only invalidate the parts of your
control you're interested in, and only paint those items within the
Graphics.ClipRectangle.
2. Roll your own double-bufferring system. Create a Bitmap object with the
same characteristics as your control, generate a Graphics object from that,
and manipulate that where you see fit. In your Paint, just blit the Bitmap
onto your Control.
 
G

Guest

Thanks. I like the double buffering idea and would chose that if I decide to
change my program as this is the least amount of re-programming. I would
assume the bltbit transfer of the bitmap is almost as quick as the double
buffering. In any event, there are only two guarantees in life, i.e., you
will pay taxes and you will die!
 
G

Guest

Let me ask you another question if you don't mind. I have a User Control
Class that inheiits from the Panel Class. When my control is instaniated, I
create a graphics object (myGraphics as Graphics = new Me.CreateGrahics) I
maintain this graphics object and draw on it to repaint parts of the control
or all of the control which ever is required depending on what the user does.
If the control is resized, I recreate myGraphics object in the sizechanged
event.

If I understand you correctly, this will not work under future versions of
..net..is that correct.
 
S

Sean Hederman

*May* not work. No guarantees one way or another. As for using
CreateGraphics, it should only be used to get information about the graphics
surface and not to paint on. Have a look at
http://www.bobpowell.net/creategraphics.htm for more details.

Basically if you replace all your CreateGraphics with a bitmap Graphics
creation, and your Paint to bitblt the Bitmap, you should be fine, and be
able to keep your code pretty much as it is.
 
G

Guest

Thanks. It just so happens that I have a utility bitblt routine that copies
a bitmap to a Graphics object so can easily use this
 
G

Guest

I am trying to implement drawing on the bitmap and using bitblt to transfer
it to the control graphics object in the paint event. It seems to draw on
the bitmap ok but doesn't get transferred to the control graphics object in
the paint event. Any help would be appreciated. Here is my code:

public class as mycontrol

Private Declare Auto Function BitBlt Lib "GDI32.DLL" (ByVal hdcDest As
IntPtr, ByVal nxDest As Integer, ByVal nyDest As Integer, ByVal nWidth As
Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As
Integer, ByVal nYSrc As Integer, ByVal dwRop As Int32) As Boolean

Private v_BackImage As Bitmap = New Bitmap(Me.Width, Me.Height,
Me.CreateGraphics)
Private gph As Graphics = Graphics.FromImage(v_BackImage)

'do some drawing on gph

Private Sub Panel_Paint(ByVal sender As Object, ByVal e As
System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
'Get Device contexts for Source and Memory Graphics Objects
Dim hdcSrc As IntPtr = gph.GetHdc
Dim hdcDest As IntPtr = e.Graphics.GetHdc
BitBlt(hdcDest, 0, 0, Me.Width, Me.Height, hdcSrc, Me.Width, Me.Height,
13369376)
'Clean Up
gph.ReleaseHdc(hdcSrc)
e.Graphics.ReleaseHdc(hdcDest)
end sub

end class
 

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