[Lazarus] Zooming a form

Martin Grajcar maaartinus at gmail.com
Thu Jun 23 09:35:15 CEST 2016

On Tue, Jun 21, 2016 at 1:45 PM, Mattias Gaertner <nc-gaertnma at netcologne.de
> wrote:

> On Tue, 21 Jun 2016 04:05:04 +0200
> Martin Grajcar <maaartinus at gmail.com> wrote:
> >[...]Despite that, it works fine for all controls with Anchors
> > = [akLeft, akTop]. For controls with other anchors, nothing works[...]
> > The problem seems to lie in TControl.UpdateBaseBounds when
> > the FBaseParentClientSize gets stored, which happens to be (0, 0) at this
> > point. If I hack it to keep the previously stored value, it somehow
> works.
> BoundsRect (Left,Top,Width,Height) is the current position/size.
> When a form's width is changed the LCL has to adapt the right anchored
> controls - aka changing the Left so that the distance of the right
> side is restored. The right distance is computed from BaseBounds
> and BaseParentClientSize.

Thank you a lot for all the explanations.

That's what I'm doing now manually:

bb := AControl.BaseBounds;
bpcs := AControl.BaseParentClientSize;

OldLeft := bb.Left;
OldWidth := bb.Right - bb.Left;
// right = distance of the right edge from the *right* parent's edge
OldRight := bpcs.cx - OldLeft - OldWidth;

NewRight := OldRight; // keep it
NewWidth := OldWidth * Zoom; // scale it
NewLeft := bpcs.cx - OldRight - OldWidth;

I'm rather sure that the computation is right (the above code mayn't be,
but the real one is). The problem is that not only BaseBounds gets stored,
but also BaseParentClientSize, which gets taken from the actual parent,
which has zero size at the moment.

What I'm doing would be right if the BaseParentClientSize were preserved. I
hacked lcl/include/control.inc and got what I wanted:

 procedure TControl.UpdateAnchorRules;
-  UpdateBaseBounds(true,true,false);
+  UpdateBaseBounds(true,false,true);

This doesn't sound right... not at all. So I guess, Lazarus counts on me
computing the bounds relatively to the zero-size parent??? Maybe replacing
the second occurrence of bpcs.cx by 0 (more exactly: the actual
Parent.ClientWidth) would do? This would imply negative Left, but what...

BaseBounds/BaseParentClientSize is set when you call SetBounds (e.g.
> when setting Left, Top, Width, Height).

My debugger agrees with you. I don't ask why so complicated. ;)

> When the LCL computes the
> autosized values it calls SetBoundsKeepBase, so it changes
> BoundsRect and keeps BaseBounds/BaseParentClientSize.

Makes sense.

> > The zero-client-size parent is a TPage, but I can't claim it guilty as I
> > couldn't reproduce my problem in a small example.
> Do you mean it does work in a small example, but it does not in your
> complex application?

Exactly. I thought that there might be a bug in TNotebook/TPage leading to
zero client area, but this isn't the case.

> So I wonder:
> >
> >    - Is it forbidden to change position and/or size of a component when
> >    it's not shown?
> It is allowed and a pretty normal thing.
> >    - If not, how can I deal with right-aligned controls? Simply setting
> >    c.Left := c.Left * Factor doesn't seem to work (though it should as
> in this
> >    step all positions and all sizes simply get scaled up; anchoring is
> used
> >    when the parent resizes and not the component itself, right?).
> Maybe you forget to disable the autosize updates during the changes?
> Simple example:
> MainControl.DisableAlign;
> try
>   MainControl.SetBounds(Width*f,Height*f);
>   for aControl in List do
> aControl.SetBounds(aControl.Left*f,aControl.Top*f,aControl.Width*f,aControl.Height*f);
> finally
>   MainControl.EnableAlign;
> end;

I sort of intentionally did not use it: I use no align and no autosize
(just anchors), so I though I won't need it. Now, I included it, but I
still need to hack TControl.UpdateAnchorRules as above.

Note: This algorithm has rounding errors, so multiple zooms will
> destroy your layout.

I know. Currently, I don't  care about a pixel or two... my layout has
orders of magnitude bigger problems.

However, for the future, I'm curious if there's a simple way of storing
additional information for a control without subclassing it. Let's say, I
need to store the *original* font size of *every* control. And I don't want
to run to any problems when the control gets freed.

Regards, Martin.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20160623/36a97234/attachment-0002.html>

More information about the Lazarus mailing list