Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

FlickerFree - Creating flicker-free graphics with GDI+

0.00/5 (No votes)
14 Nov 2002 1  
Sample code on how to create flicker-free graphics with GDI+.

Sample Image - FlickerFree.jpg

Introduction

First I want to say: "Sorry about my spelling - but I'll try to become better!"

When you create moving objects/graphics using GDI+, you have to refresh the screen every time the timer ticks :-) But then the graphics begin to flicker - to avoid this you can use Double-Buffering. In this sample, I'll show what you need for flicker-free-graphics and also how to use KeyEvents.

Using the code

I've used a timer with an interval of 40 milliseconds because we need about 25 frames per second (1000 milliseconds / 25 frames = 40). To demonstrate how to move the graphics-object I have also built in KeyEvents.

At first you have to set Double-Buffering in the constructor of your class:

SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);

Then we use a timer to refresh the form every 40 milliseconds:

private System.Windows.Forms.Timer t;
t = new Timer();
t.Interval = 40;
t.Tick += new System.EventHandler(TimerOnTick);
t.Enabled = true;

private void TimerOnTick(object sender, System.EventArgs e)
{
  this.Refresh(); // #### 84: Refresh the form

  this.Text = DateTime.Now.ToString();
  this.Text += " " + this.PlayerPosition.ToString();
}

Next we "listen" to our keyboard:

this.KeyDown += new System.Windows.Forms.KeyEventHandler(OnKeyPress);

private void OnKeyPress(object sender, System.Windows.Forms.KeyEventArgs e)
{
  // #### 84: When the Left-Cursor has been pressed

  if(e.KeyValue == 37)
  {
    this.PlayerPosition = new Point(this.PlayerPosition.X
                                - this.playerSize.Width,
                                    this.PlayerPosition.Y);
  }

  // #### 84: When the Up-Cursor has been pressed

  if(e.KeyValue == 38)
  {
    this.PlayerPosition = new Point(this.PlayerPosition.X,
                                    this.PlayerPosition.Y
                                    - this.playerSize.Width);
  }

  // #### 84: When the Right-Cursor has been pressed

  if(e.KeyValue == 39)
  {
    this.PlayerPosition = new Point(this.PlayerPosition.X
                                    + this.playerSize.Height,
                                    this.PlayerPosition.Y);
  }

  // #### 84: When the Down-Cursor has been pressed

  if(e.KeyValue == 40)
  {
    this.PlayerPosition = new Point(this.PlayerPosition.X,
                                    this.PlayerPosition.Y
                                    + this.playerSize.Height);
  }
}

And we have to overwrite the OnPaint event to draw our object:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
  e.Graphics.FillRectangle(new SolidBrush(Color.Red),
               this.PlayerPosition.X,
                   this.PlayerPosition.Y,
               this.playerSize.Width,
               this.playerSize.Height);
}

To calculate if the new position of our graphics-object is in the client area and what to do if not, I've used a property:

private Point PlayerPosition
{
  get
  {
    return this.playerPosition;
  }
  set
  {
    if(value.X < 0)
    {
      this.playerPosition.X = this.ClientSize.Width - this.playerSize.Width;
    }
    else if(value.X + this.playerSize.Width > this.ClientSize.Width)
    {
      this.playerPosition.X = 0;
    }
    else
    {
      this.playerPosition.X = value.X;
    }

    if(value.Y < 0)
    {
      this.playerPosition.Y = this.ClientSize.Height - 
                                    this.playerSize.Height;
    }
    else if(value.Y + this.playerSize.Height > this.ClientSize.Height)
    {
      this.playerPosition.Y = 0;
    }
    else
    {
      this.playerPosition.Y = value.Y;
    }
  }
}

Now we have a flicker-free animation ;-)

Points of interest

In the first version of my sample I used if() - else if() for the KeyEvent. But then one key worked at a time. Using if() for every key makes it possible to combine the keys for a diagonal movement. It's also important to use this.Client.Width and this.Client.Height instead of this.Width and this.Height - because the graphics-object can only be moved in the client-area and so you can calculate areas for the movement.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here