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?
It doesn't matter. What matters is, as long as you don't call inherited
, default window procedure will not erase the background. Since you're painting the whole surface of the control, you don't need default processing.
What changes when you return '0' or '1' (not '0') is that, when BeginPaint
is called, the system sets the fErase
member of the PAINTSTRUCT
accordingly. When you return '0', it is set 'True', indicating that the background must be erased in the paint process. For '1', it is set 'False', indicating that no erasing is necessary. BeginPaint
is called in TWinControl.PaintHandler
. No one ever checks what fErase
is, VCL only uses the device context BeginPaint
returns, so what you return does not make any difference.
Still, I'd return '1', conceptually hinting that erasing have been taken care of.