Flicker problem with labels in panel of form Delphi-2009

747 Views Asked by At

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.
2

There are 2 best solutions below

3
fpiette On

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.

0
Uri S On

I've had the same problem, Delphi 10.4

Setting the enclosing TPanel in this way -

DoubleBuffered = True

ParentBackground = False

seems to fix it. The VCL has become way too complicated in its implementation, especially since Themes were introduced, making its behavior very buggy and unpredictable IMHO.