1. Tech

Your suggestion is on its way!

An email with a link to:

http://delphi.about.com/library/bluc/text/uc052102g.htm

was emailed to:

Thanks for sharing About.com with others!

RTL referenceGlossary|Tips/Tricks|FREE App/VCL|Best'O'Net|Books|Link To
 
GDI Graphics In Delphi
Page 7: Four Ways To Kill Flicker
 More of this Feature
• Page 1: GDI Jargon
• Page 2: Drawing: Lines
• Page 3: Drawing: Shapes
• Page 4: Draw vs. Paint
• Page 5: Handles and Stuff
• Page 6: Pictures: TBitmap
• Page 8: GDI, The Hard Way
• Page 9: API Drawings
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• Graphics programming in Delphi
• Screen zooming
• Double buffering
• Win API in Delphi

   Four Ways To Kill Flicker
Flickering is very annoying when you first start drawing using Delphi. However, there are four easy ways to squish it good. Each will be discussed below. The four methods are:

1) Use the DoubleBuffered property for TWinControl descendants
2) Set the ControlStyle to use csOpaque if your control is not transparent
3) Handle the WM_ERASEBKGND Windows message
4) Use off-screen bitmaps (like 1, but can work for any drawing)

Now for a really interesting fact: Delphi 4 and above introduce a property in TWinControl called DoubleBuffered, which is a boolean value. This allows you to do double buffering with one simple boolean assignment :-). The only drawback to double buffering is that it uses more memory. However, this is usually not a major issue unless you plan to go insane with your interface.

procedure TForm1.FormCreate(Sender: TObject);
begin
  DoubleBuffered := True;
end;

This ONE line alone in your form will reduce the flicker if you plan to use the form's canvas for drawing.

The next technique involves using the ControlStyle set for any TControl. You can bung this into the constructor of any object you write (e.g. any descending from TGraphicControl, in particular), or you can use it to set stuff at run-time for other controls. Anyway, it looks like this:

  ControlStyle := ControlStyle + [csOpaque];

This means the program realises the control should not have its background erased, as it will be opaque and doing so would cause flicker. A nice, easy technique. However, you should only use this for non-transparent controls (which is usually most of 'em).

Next up, there is a way to massively decrease flicker: handle the WM_ERASEBKGND message. This message gets sent by Windows whenever a window needs to have its background erased. However, if you plan to draw the entire background then this just causes LOTS of unnecessary flicker. To stop that, bung in this message handler prototype:

  procedure StopFlicker(var Msg: TWMEraseBkgnd); message WM_ERASEBKGND; 

Add that somewhere in your form or classes prototype (the bit at the top of your unit, within "{ Private Declarations }"). Next, add in this code in the implementation section:

procedure T<<yourclassorform>>.StopFlicker(var Msg: TWMEraseBkgnd);
begin
  Msg.Result := 1;
end;

I shouldn't need to say this, but replace the T> with the appropriate thing (for example, TForm1 or TMyClass).

The help for WM_ERASEBKGND says that if you handle it, you should set the result to a non-zero value. That's all the above code does. Make sure with this technique to draw the background fully. If you don't, Windows gets all huffy and sometimes explodes. This, by the way, is not an exaggeration - I have actually managed to reduce Windows to a crawl (more so) and/or actually hang the system by not drawing anything in my OnPaint. Not good.

   Off-Screen Bitmaps
I mentioned above "off-screen drawing". What does that mean? Well, instead of drawing directly onto the screen you draw onto a bitmap in memory instead, copying the end result to the screen. This technique is known as double-buffering.

Why is double-buffering good?

  • It reduces flicker as the graphics hardware is used as little as possible
  • It gives a perceived speed boost, as the drawing cannot be seen partially completed.
Normally, when drawing to the screen you will see flicker. Try drawing on a TImage to see what I mean. This is because for every line you draw, the graphics card gets invoked, which is typically slower than using memory and visible to the user. When drawing to memory and copying the final image, the graphics card only needs to draw once, and the user doesn't see the image being created.

Double-buffering is very straightforward. If you, for example, drew some lines onto a form's canvas, like this:

for i := 0 to 20000 do
begin
  Canvas.MoveTo(Random(ClientWidth), Random(ClientHeight));
  Canvas.LineTo(Random(ClientWidth), Random(ClientHeight));
end;

...then to do double-buffering, you would create a bitmap and draw onto its canvas instead, then copy the results to screen - much like this:

Bmp := TBitmap.Create;
try
  Bmp.Width := ClientWidth;
  Bmp.Height := ClientHeight;

  // Draw lines onto the **bitmap's** canvas 
  for i := 0 to 20000 do
  begin
    Bmp.Canvas.MoveTo(Random(ClientWidth), Random(ClientHeight));
    Bmp.Canvas.LineTo(Random(ClientWidth), Random(ClientHeight));
  end;

  Canvas.Draw(0,0, Bmp); // draw the bitmap to screen now
finally  
  Bmp.Free;
end;

That's as easy as it gets. Instead of using the form's canvas, you use the one on the bitmap instead. Then, once you've finished, you use the form's Canvas.Draw method to copy the bitmap to screen. Nice and easy. Note, if you're interested in demos, that some tutorials refer to this as using a 'virtual screen'.

A comment to be made here is that you should consider creating the bitmap at start-up and freeing it when the program closes (in FormCreate and FormDestroy). This would be quicker than creating a bitmap for every Paint procedure, of course.

   Question, Suggestions...
If you have any questions or comments to this (huge) article, please post them on the Delphi Programming Forum. Discuss!

Next page > GDI, The Hard (Win API) Way > Page 1, 2, 3, 4, 5, 6, 7, 8, 9

All graphics (if any) in this feature created by Zarko Gajic.

 More Delphi
· Learn another routine every day - RTL Quick Reference.
· Download free source code applications and components.
· Talk about Delphi Programming, real time.
· Link to the Delphi Programming site from your Web pages.
· Tutorials, articles, tech. tips by date: 2001|2000|1999|1998 or by TOPIC.
· NEXT ARTICLE: Articles.
More Delphi articles
 Stay informed with all new and interesting things about Delphi (for free).
Subscribe to the Newsletter
Name
Email

 Got some code to share? Got a question? Need some help?

©2017 About.com. All rights reserved.