I have on a form some custom progress bars which are updated/refreshed twice per second and they are flickering.
TMyProgressBar = class(TCustomControl)
I inherited the control from TCustomControl
, because I needed Handle
and some TWinControl
events. The controls (up to 64 items) are created dynamically and put on a ScrollBox. When progress is updated I first call InvalidateRect
.
All painting work (a set of rectangles, DrawText
, etc - inspired from here) are performed in a memory DC and then BitBlt
-ed on the control's DC. It is anyway flickering, it seems like component dis-appears and re-appears. IMHO it is caused by background erasing.
In this flickering-free drawing advice it is written to handle WM_ERASEBKGND
in the following way:
type
TMyProgressBar = class(TCustomControl)
procedure WMEraseBkGnd(var Message:TMessage); message WM_ERASEBKGND;
procedure TMyProgressBar.WMEraseBkGnd(var Message: TMessage);
begin
Message.Result := 1;
end;
But in another component, by TMS (TAdvProgressBar
), Result
is set to 0
for the same message.
Now the Windows documentation states:
An application should return nonzero if it erases the background; otherwise, it should return zero.
I tested both variants (Result = 0, 1), and to my surprise both avoid flickering.
So now, what do I have to put in my Delphi code? What is the correct way?
WM_ERASEBACKGROUND
. For sure if you paint nothing then you'll have no flicker. – HeadwaterTScrollBox
that is tuned to combat flicker : https://mcmap.net/q/1178693/-performance-issues-re-sizing-large-amount-of-components-on-form-resize – Milissamilissent