1

To clearup what I meant by my question.. I got used when making a game in C# using the .NET framework, to implement my own DrawScene() method and call it whenever I want to redraw the game's graphics (basically after any instance in the game has moved or changed its shape/state), like the following:

private void DrawScene()
{
    Graphics g = this.CreateGraphics();
    g.Clear(Color.Black);

    g.DrawImage(myBitmap, 0, 0);

    g.Dispose();
}

And by doing so, in my Paint event handler, all I do is the following:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    DrawScene();
}

and for example, also when I want to redraw after the player makes some move, I simply call DrawScene() the same way:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Keycode == Keys.Up)
    {
        hero.y -= 5;
    }

    DrawScene();
}

Is there any serious difference between doing that or doing it this way (Which I notice most people follow):

private void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.Clear(Color.Black);

    e.Graphics.DrawImage(myBitmap, 0, 0);
}

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Keycode == Keys.Up)
    {
        hero.y -= 5;
    }

    this.Invalidate();
}

Sorry if this was much talking, but I just wanted to clear things up about my question..

So, if the two cases above does the drawing exactly the same way (From the Graphics viewpoint), and there's no harm keeping on my usual implementation as in the first case.. Then when is it best to use the invalidate() method?

Stefan Madlo
  • 53
  • 1
  • 2
  • 7
  • To add to Andy's answer: You can fix the first way by calling `DrawScene(e.Graphics);` and adding a Graphics paramter to the method which you then use. CreateGraphics is only for special cases.. – TaW May 28 '15 at 10:42
  • A game that updates the window at a high rate is one of the few exceptions to this "is it bad" rule. Still, there are exceedingly few decent reasons to not set the form's DoubleBuffered property to *true* and use the e.Graphics object that is handed to you in the Paint event. Which emulates a game engine's back-buffer pretty well. – Hans Passant May 28 '15 at 11:03

1 Answers1

2

This two approaches differs seriously (second one is preferred).

First of all - in your approach you are creating new Graphics object each time you need to paint something, while in Paint event handler you're using the same graphics object each time.

This increases memory usage (since redraws can occurs very frequently), and also since you're not disposing graphics you're creating (basically you should do it with any object implementing IDisposable you no longer need to use) - system resources used by graphics not being freed.

Also, your form can be redrawed not manually by your call, but in some other cases (overlapping by other window, show/hide and so on). If your paintings will be done in Paint handler - then they will be done automatically, but in your "first" approach whey will not until you manually call your drawing method.

So basically it is always better to paint everything in Paint event handlers (and call Invalidate or even Refresh to force redrawing) and not manually in separate methods.

Sometimes (if your drawing takes much code and can be logically splitted into parts) it can be better to handle it like:

private void DrawScene(Graphics g)
{
    g.Clear(Color.Black);
    g.DrawImage(myBitmap, 0, 0);
}

private void Form1_Paint(object sender, PaintEventArgs e)
{
    DrawScene(e.Graphics);
    DrawSomething(e.Graphics);
}

So you still using grahics object from Paint event handler, but just passing it into drawing methods.

Andrey Korneyev
  • 26,353
  • 15
  • 70
  • 71
  • For the "Dispose()" part, I always write it in my code, just forgot to do so in the code above (Edited), and for cases where my form needs to be drawn automatically, My paint event handler is anyway always written in my code.. but instead of drawing inside it, I simply call my DrawScene() method, so the remaining problem is the cost of creating a new Graphics object and disposing it everytime I need to draw, is there any other differences? – Stefan Madlo May 28 '15 at 10:18
  • So I'm going for the second approach for now, but can you just give me a simple explanation for the Invalidate() method?, I know there are lots of details about it out there, but, 1- Is this method only used to force the redrawing of the control ? or does it have any other uses? .. 2- I really want to know where the name Invalidate() came from? Does it mean like "Invalidate this control to make it able to be redrawn then make it valid again to the user to use it? or what :$? – Stefan Madlo May 28 '15 at 10:23
  • @StefanMadlo in fact, `Invalidate` itself does not forces redrawing of control, it just sets control in something "Need to redraw when it will be possible" state. For the purpose of force redrawing there exists `Refresh` methods, it also invalidates control and forces it to redraw immediately. Also `Refresh` redraws not only control, but also all of its children. As far as I know, invalidate is not used for anythig except redrawing. – Andrey Korneyev May 28 '15 at 10:51
  • Thanks, so I'd better use Refresh() instead of Invalidate() to guarantee an immediate visual response to the user right? I've read this from another post on SO "If you're in a hurry you should call Refresh() but then you run the risk that it will be repainted several times consecutively because of other controls (especially the Parent) Invalidating", by Henk Holterman", But, I guess as long as this is a game and I have only one control which is my main form, It should be safe to always use Refresh() for drawing instead of Invalidate() in my code ? – Stefan Madlo May 28 '15 at 10:59
  • @StefanMadlo well, personally I prefer to use `Refresh`. But frankly I never seen control took a long time to redraw after calling `Invalidate`. It is some milliseconds, I think. – Andrey Korneyev May 28 '15 at 11:06