I have an simple application with a panel contains 2 labels (eg. A & B) and a button C created by Delphi 2009. Label A will display the cursor position when I move the mouse inside the area of panel. Label B just display the static text (caption will not change during app run)
If I move the mouse inside the panel, the label A will flicker.
When I enable 'Double buffer' of form, the flicker is lost. Button C wil demonstrate to enable/disable 'Double buffer' property
I would like to question 'Why does the label in panel flicker? What is the root cause? How can we solve this problem thoroughly?'
Here is my code:
unit DemoFlicker;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
System.StrUtils,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
type
TForm1 = class(TForm)
pnlCtr: TPanel;
btnDoubleBuffer: TButton;
lblName: TLabel;
lblNumber: TLabel;
procedure btnDoubleBufferClick(Sender: TObject);
procedure pnlCtrMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
FDoubleBuffer: Boolean;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnDoubleBufferClick(Sender: TObject);
begin
FDoubleBuffer := not FDoubleBuffer;
Self.DoubleBuffered := FDoubleBuffer;
if FDoubleBuffer then
begin
btnDoubleBuffer.Caption := 'Not Apply Double Buffer';
end
else
begin
btnDoubleBuffer.Caption := 'Apply Double Buffer';
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FDoubleBuffer := False;
Self.DoubleBuffered := False;
end;
procedure TForm1.pnlCtrMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
mousePos: string;
begin
mousePos := Format('(X=%d, Y=%d)', [Mouse.CursorPos.X, Mouse.CursorPos.Y]);
lblNumber.Caption := mousePos ;
end;
end.
Flicker occurs because of how the drawing is done. Without double buffer, the background is drawn (painted) and then the label is drawn. So at a moment you see only the background only and then you seen the label above the background. If you repeat the update, it flickers.
When using "double buffer", the drawing is done in an invisible buffer and then when drawing is complete, the buffer is rendered on screen. So you only see the complete image at once and no flickering.
To solve the problem, use double buffering as you found it by yourself.
You may also create a new component which does all drawing itself in his Paint procedure.