Author: Tomas Rutkauskas
I have an application in which the user drags TImage descendants around on a
background image. When an image is dropped, I have to run through all the current
images finding out where they are, and then arrange their z-order appropriately.
When I do this, there's significant flickering. I've tried calling
LockWindowUpdate(Handle) before the operation, then LockWindowUpdate(0) at the end,
but several repaint operations still seem to take place at once. I'd like to be
able to repaint the whole form once only, or failing that, limit the repaint to a
specific area of the form (so that all my buttons etc, which aren't involved in any
of this, don't have to flicker too).
Answer:
Below is a fragment of code implementing reference counted form redraw locking. I
use it in my apps where any form is derived from TLwForm (subclass of TForm). It
suggests locking not limited to one window as it's the case with LockWindowUpdate.
The approach can be applied not to the form as the whole but, via iteration, to all
its TWinControl children.
1 var
2 FLockFormUpdatePile: integer;
3
4 procedure TLwForm.LockFormUpdate;
5 begin
6 if FLockFormUpdatePile = 0 then
7 Perform(WM_SetRedraw, 0, 0);
8 inc(FLockFormUpdatePile);
9 end;
10
11 procedure TLwForm.UnlockFormUpdate;
12 begin
13 dec(FLockFormUpdatePile);
14 if FLockFormUpdatePile = 0 then
15 begin
16 Perform(WM_SetRedraw, 1, 0);
17 RedrawWindow(Handle, nil, 0, RDW_FRAME + RDW_INVALIDATE +
18 RDW_ALLCHILDREN + RDW_NOINTERNALPAINT);
19 end;
20 end;
|