Your assumption that slowness comes from re-paint controls is probably true, but not the whole story. By default, Delphi code that processes motion controls will delay painting until the next WM_PAINT message is received, and this will happen when the message queue is pumped after all controls have been moved. Unfortunately, there are many things in this that the default behavior can be changed in many places, including Delphi and Windows. I used the following code to check what happens when you move the control at runtime:
var i: Integer; begin for i:=1 to 100 do begin Panel1.Left := Panel1.Left + 1; Sleep(10); // Simulate slow code. end; end;
Behavior depends on management! A TControl (example: TLabel ) will behave according to Delphi rules, but TWinControl depends on too many factors. A simple TPanel not redrawn until after the cycle, in the case of TButton on my machine, only the background is repainted and the TCheckBox is completely repainted. On the machine, David TButton also completely repainted, and this depends on many factors. In the case of TButton most likely factor is the version of Windows: I tested on Windows 8, David tested on Windows 7.
AlignControl Avalanche
In any case, there is another important factor to consider. When you move a control at runtime, all alignment and binding rules for all controls must be taken into account. This can cause an avalanche of calls AlignControls / AlignControl / UpdateAnchorRules . Since all these calls ultimately require recursive calls of the same number, the number of calls will be exponential (therefore, your observation that moving a lot of objects to TWinControl is slow).
The simplest solution, as David suggests, is to place everything on a panel and move the panel as one. If this is not possible, and all of your controls are actually TWinControl ( TWinControl .: they have a Window Handle), you can use:
BeginDeferWindowPos , DeferWindowPos , EndDeferWindowPos
source share