Difference between revisions of "Autosize / Layout"

From Free Pascal wiki
Jump to navigationJump to search
Line 2: Line 2:
  
 
See [[Anchor Sides]].
 
See [[Anchor Sides]].
 +
 +
=AutoSize=
 +
 +
When setting AutoSize = true the LCL auto sizes the control in width and height. This is one of the most complex parts of the LCL, because the result depends on nearly a hundred properties. Let's start simple:
 +
 +
The LCL will only autosize the ''Width'' (Height) if it is free to resize. Or in other words: The width is not autosized if
 +
*if the left and right side is anchored. You can anchor the sides with the '''Anchors''' property or by setting the ''Align'' property to alTop, alBottom or alClient.
 +
*if the ''Width'' is bound by the ''Constraints'' properties. The contraints can also be overriden by the widgetset. For example the winapi does not allow to resize the height of a combobox. And the gtk widgetset does not allow to resize the width of a vertical scollbar.
 +
 +
Same for ''Height''.
 +
 +
The new size is calculated by the protected method '''TControl.CalculatePreferredSize'''.
 +
This method asked the widgetset for some nice Width and Height. For example a TButton has preferred Width and Height. A TComboBox has only a preferred Height. The preferred Width is returned as 0 and so the LCL does not auto size the Width - it will keep the width untouched. Finally a TMemo has no preferred Width nor Height. AutoSize has no effect on a TMemo.
 +
 +
Some controls override this method. For example the TGraphicControl descendants like TLabel have no handle and can therefore not ask the widgetset. They must calculate their preferred Width and Height themselves.
 +
 +
The widgetsets must override the GetPreferredSize method for each widget class that have a preferred size (width or height or both).
 +
 +
==Parent.AutoSize==
 +
 +
The above was the simple version.
  
 
=FAQ=
 
=FAQ=

Revision as of 22:46, 9 February 2008

Anchor Sides

See Anchor Sides.

AutoSize

When setting AutoSize = true the LCL auto sizes the control in width and height. This is one of the most complex parts of the LCL, because the result depends on nearly a hundred properties. Let's start simple:

The LCL will only autosize the Width (Height) if it is free to resize. Or in other words: The width is not autosized if

  • if the left and right side is anchored. You can anchor the sides with the Anchors property or by setting the Align property to alTop, alBottom or alClient.
  • if the Width is bound by the Constraints properties. The contraints can also be overriden by the widgetset. For example the winapi does not allow to resize the height of a combobox. And the gtk widgetset does not allow to resize the width of a vertical scollbar.

Same for Height.

The new size is calculated by the protected method TControl.CalculatePreferredSize. This method asked the widgetset for some nice Width and Height. For example a TButton has preferred Width and Height. A TComboBox has only a preferred Height. The preferred Width is returned as 0 and so the LCL does not auto size the Width - it will keep the width untouched. Finally a TMemo has no preferred Width nor Height. AutoSize has no effect on a TMemo.

Some controls override this method. For example the TGraphicControl descendants like TLabel have no handle and can therefore not ask the widgetset. They must calculate their preferred Width and Height themselves.

The widgetsets must override the GetPreferredSize method for each widget class that have a preferred size (width or height or both).

Parent.AutoSize

The above was the simple version.

FAQ

Why does AutoSize not work in the designer properly?

In the designer controls can be dragged around and properties can be set in almost any order. To allow this and avoid possible conflicts, the AutoSizing is not updated on every change at design time.

Why does TForm.AutoSize not work when something changes?

TForm.AutoSize only works once at creation time. After that the size is up to user and the windowmanager. The application can force a resize with the following:

 AutoSize:=false; // first reset the counter
 AutoSize:=true;  // then do one AutoSize

The reason for this is, that the size of the window is controlled by the window manager. Some window managers do not allow free resizes. This would result in an endless loop between the LCL and the window manager. That's why AutoSize works only once on controls with Parent=nil.

Do I need to call Application.ProcessMessages when creating lots of controls?

Application.ProcessMessages is called by the LCL automatically after every message (e.g. after every event like OnClick). Calling it yourself is only needed if the changes should become visible to the user immediately. For example:

<DELPHI> procedure TFrom.Button1Click(Sender: TObject); begin

 // change width of a control
 Button1.Width := Button1.Width + 10;
 // apply any needed changes and repaint the button
 Application.ProcessMessages;
 // do a lot of things that takes a long time
 ...
 // after leaving the OnClick the LCL automatically processes messages

end; </DELPHI>