Graphics object

S

shijin_zu

Is there a difference between the Graphics object that comes with the Paint
event and the Graphics object that is obtained by Graphics g =
CreateGraphics();?



In a custom control that I'm creating, I noticed that the same line drawn
inside OnPaint() is not exactly the same as the one drawn by my own method
Update(). In the Update() method I tried to replace the same line with a
different color, but there are always some leftover pixels by the original
Black pen and they can't be completed "erased" by the new the Red pen. Here
is my simplified code:



public class myControl : System.Windows.Forms.Control

{

.......

private void OnPaint(object sender, System.Windows.Forms.PaintEventArgs
e)

{

// draw this line with Black

e.Graphics.DrawLine(m_pen1, 10, 10, 50, 50);

return;

}



Public void Update()

{

Graphics g = CreateGraphics();



// draw this line with Red pen

g.DrawLine(m_pen2, 10, 10, 50, 50);

g.Dispose();

}

}


Any insights to the situation?



Thanks,

Shijin
 
T

Tim Wilson

I'm not familiar with exactly what you're trying to accomplish overall, but
as a general rule, unless there is a very compelling reason otherwise, you
should always draw, at least the foreground, from within the OnPaint
override. Consider what would happen if you called your "Update" method at
some random point, not associated with the OnPaint method, and then the user
switched to another application and then came back to your application.
Assuming that your control was obscured by the other application, the
drawing that took place from within the "Update" method would be lost since
the only painting that would be performed would be associated with OnPaint
and OnPaintBackground. So if it's "permanent" paint that should be
associated with the control even when the control is invalidated then you
should paint from within the OnPaint override, or another method that you
call from within OnPaint.
 
S

shijin_zu

Thank you for your input. In my case, only one application is running at a
time and the application has the total control of the display. The OnPaint
override is used to paint a diagram that I'm developing. Infrequently I
need to update the entire diagram and to do so I call Invalidate() to invoke
OnPaint override. However, there is a line in the diagram that needs to be
updated frequently. If I call Invalidate() in order to update just this one
line, the whole diagram gets invalidated and it causes the diagram to flash
continuously, a very annoy effect. That is the reason for using Update() to
just update this one line. Are there other ways to invoke OnPaint override
without using Invalidate(). Invalidate() seems to cause the foreground
stuff to disappear first.



Thanks,

Shijin
 
T

Tim Wilson

There are a few tricks that you can use to get better paint performance in a
case like yours.

(1) Draw everything into a Bitmap in the OnPaint method and then paint the
Bitmap using "e.Graphics.DrawImage(...)". This is a technique commonly
referred to as "double buffering". There is an example of double buffering
in the article linked below.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/ImageButton.asp

(2) Override the OnPaintBackground method and do nothing. Ensure that you
paint the background into the buffer in OnPaint.

protected virtual void OnPaintBackground (PaintEventArgs e)
{
// Do nothing. Don't even call the base class.
// base.OnPaintBackground(e);
}

(3) Only invalidate the area that should be redrawn. Use the Invalidate
overload that allows you to specify a Rectangle representing the region that
should be repainted. This will cause the OnPaint method to be called but the
output will be clipped to be within the specified Rectangle, which should
further reduce the flicker.

The safest thing to do is to always paint from within the OnPaint override.
This ensures that if something happens to cause a WM_PAINT message to be
sent in relation to the control that the control will get painted as
expected.
 

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