Sign in Join
Wiki copytemporary

LCL Internals - Resizing, Moving: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Overview
22
33The LCL has a lot of resizing properties (Left, Width, Anchors, Align, AnchorSide, AutoSize, Constraints, ChildSizing, ...) and hooks where applications can alter the behavior (OnResize, OnChangeBounds, ...). All these things can not be calculated in one step, so controls can move quite a lot before the final coordinates come out. To reduce flickering the LCL does not send every move/resize to the LCL interface. For example during Begin/EndAlign and csLoading no move/resize is sent to the interface. The widgetset will try to follow the advices of the LCL, but there are some cases, where it does not follow. For example forms (top level windows) are limited by the window manager policies. And TPage completely depends on the size and theme of the TNotebook.
44
55## How the LCL tells the interface to resize/move a handle
66
77In TWinControl.DoSendBoundsToInterface the widget function SetBounds is called
88
99``` pascal
1010TWSWinControlClass(WidgetSetClass).SetBounds(Self, Left, Top, Width, Height);
1111```
1212
1313## How the Interface tells the LCL to resize/move a handle
1414
1515### When the client area of a Handle was resized
1616
1717*Note*: If the theme changes the frame of a TGroupBox can change. This leaves the Size and Position of the TGroupBox unchanged, but the client area can change. The interface calls
1818
19-` LCLControl.InvalidateClientRectCache(false);`
19+```text
20+ LCLControl.InvalidateClientRectCache(false);
21+```
2022
2123and sends a LM_SIZE message as below.
2224
2325### When a Handle of a TWinControl was resized/moved
2426
2527#### First the LCL interface send a LM_WINDOWPOSCHANGED message
2628
2729- x := Left (relative to 0,0 of client area of parent)
2830- y := Top
2931- cx := Width
3032- cy := Height
3133
3234#### Then a LM_SIZE message is sent
3335
3436- Width
3537- Height
3638- SizeType is a bit flag containing Size_SourceIsInterface plus one of the values SIZENORMAL, SIZEICONIC, SIZEFULLSCREEN.
3739
3840#### Then a LM_MOVE message is sent
3941
4042- MoveType := Move_SourceIsInterface;
4143- XPos := Left (relative to 0,0 of client area of parent)
4244- YPos := Top
4345
4446### When a form is maximized, minimized or restored the interface sends a LM_SIZE message
4547
4648- Width
4749- Height
4850- SizeType is a bit flag containing Size_SourceIsInterface plus one of the values SIZENORMAL, SIZEICONIC, SIZEFULLSCREEN.
4951
5052## How the LCL gets the current size / position of a LCL interface handle
5153
5254### LCLIntf.GetWindowSize(Handle, InterfaceWidth, InterfaceHeight)
5355
5456Returns the current width and height of a Handle.
5557
5658### LCLIntf.GetClientRect(Handle, Result)
5759
5860Returns the current width and height (left and top are always 0) of the client area of a Handle (= inner area inside the border/frame of a control).
5961
6062### TWSWinControlClass(WidgetSetClass).GetDefaultClientRect(Self, Left, Top, Width, Height, Result)
6163
6264This function is called first by the LCL to get the ClientRect. If it returns false, the LCL will use GetClientRect if it has already created a handle, otherwise the values loaded from the .lfm. If all this fails, the default is Rect(0,0,Width,Height). GetDefaultClientRect can be used by the LCL interface to reduce flickering by providing good values before the handle is created.
6365
6466### GetWindowRelativePosition(Handle,NewLeft,NewTop)
6567
6668Returns the current Left, Top of a Handle relative to the client area (0,0) of its parent.
6769
6870## Constraints
6971
7072The LCL asks the interface for constraints (min, max for width and height) with the function
7173
7274``` pascal
7375GetControlConstraints
7476```
7577
7678For example: Under gtk a horizontal scrollbar has a fixed height.
7779
7880## Preferred Size
7981
8082To autosize a control (e.g. a TButton or a TLabel) the LCL asks the interface about the minimum size to render a control nicely:
8183
8284``` pascal
8385TWSWinControlClass(WidgetSetClass).GetPreferredSize(Self, PreferredWidth, PreferredHeight, WithThemeSpace);
8486```
8587
8688## Scrolling
8789
8890The LCL scrolls child controls only virtually. That means, their Left,Top properties do not change. To scroll it uses the LCL interface function
8991
9092``` pascal
9193TWSScrollingWinControlClass(WidgetSetClass).ScrollBy(Self, DeltaX, DeltaY);
9294```
9395
9496## Rectangles
9597
9698- BoundsRect - the rectangle containing coordinates of the control within parents coordinates
9799
98100
99101for TForm (not embedded into another control) coordinates are given in Screen position. The form non-client area (aka header, aka title) section is also NOT PART of the BoundsRect.
100102
101103- ClientsRect - the rectangle containing coordinates of the client area.
102104
103105## Miscellaneous
104106
105107### LCLIntf.GetClientBounds(Handle,Result);
106108
107109Returns the unscrolled client rectangle relative to the top, left of the Handle. In other words it is equivalent to:
108110
109111``` pascal
110112CurClientBounds := GetClientRect(Handle)
111113OffsetRect(CurClientBounds,FrameBorderLeft,FrameBorderTop);
112114```
113115
114116---
115117*From the Free Pascal wiki, page "LCL Internals - Resizing, Moving", as it stood on 2020-02-19 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history