<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Jun 21, 2016 at 1:45 PM, Mattias Gaertner <span dir="ltr"><<a href="mailto:nc-gaertnma@netcologne.de" target="_blank">nc-gaertnma@netcologne.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">On Tue, 21 Jun 2016 04:05:04 +0200<br>
Martin Grajcar <<a href="mailto:maaartinus@gmail.com">maaartinus@gmail.com</a>> wrote:<br>
<br>
>[...]Despite that, it works fine for all controls with Anchors<br>
> = [akLeft, akTop]. For controls with other anchors, nothing works[...]<br>
<span class="">> The problem seems to lie in TControl.UpdateBaseBounds when<br>
> the FBaseParentClientSize gets stored, which happens to be (0, 0) at this<br>
> point. If I hack it to keep the previously stored value, it somehow works.<br>
<br>
</span>BoundsRect (Left,Top,Width,Height) is the current position/size.<br>
<br>
When a form's width is changed the LCL has to adapt the right anchored<br>
controls - aka changing the Left so that the distance of the right<br>
side is restored. The right distance is computed from BaseBounds<br>
and BaseParentClientSize.<br></blockquote><div><br></div><div>Thank you a lot for all the explanations.</div><div><br></div><div>That's what I'm doing now manually:</div><div><br></div><div><div><font face="monospace, monospace">bb := AControl.BaseBounds;</font></div><div><font face="monospace, monospace">bpcs := AControl.BaseParentClientSize;</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">OldLeft := bb.Left;</font></div><div><font face="monospace, monospace">OldWidth := bb.Right - bb.Left;</font></div><div><span style="font-family:monospace,monospace">// right = distance of the right edge from the <i>right</i> parent's edge</span><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">OldRight := <a href="http://bpcs.cx">bpcs.cx</a> - OldLeft - OldWidth;</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">NewRight := OldRight; // keep it</font></div><div><font face="monospace, monospace">NewWidth := OldWidth * Zoom; // scale it</font></div><div><font face="monospace, monospace">NewLeft := <a href="http://bpcs.cx">bpcs.cx</a> - OldRight - OldWidth;</font></div></div><div><br></div><div>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.</div><div><br></div><div>What I'm doing would be right if the BaseParentClientSize were preserved. I hacked lcl/include/control.inc and got what I wanted:</div><div><br></div><div><div><font face="monospace, monospace"> procedure TControl.UpdateAnchorRules;</font></div><div><font face="monospace, monospace"> begin</font></div><div><font face="monospace, monospace">- UpdateBaseBounds(true,true,false);</font></div><div><font face="monospace, monospace">+ UpdateBaseBounds(true,false,true);</font></div><div><font face="monospace, monospace"> end;</font></div></div><div><br></div>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 <font face="monospace, monospace"><a href="http://bpcs.cx">bpcs.cx</a></font> by 0 (more exactly: the actual Parent.ClientWidth) would do? This would imply negative Left, but what...</div><div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
BaseBounds/BaseParentClientSize is set when you call SetBounds (e.g.<br>
when setting Left, Top, Width, Height).</blockquote><div><br></div><div>My debugger agrees with you. I don't ask why so complicated. ;)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">When the LCL computes the<br>
autosized values it calls SetBoundsKeepBase, so it changes<br>
BoundsRect and keeps BaseBounds/BaseParentClientSize.</blockquote><div><br></div><div>Makes sense.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class=""><br>
> The zero-client-size parent is a TPage, but I can't claim it guilty as I<br>
> couldn't reproduce my problem in a small example.<br>
<br>
</span>Do you mean it does work in a small example, but it does not in your<br>
complex application?<br></blockquote><div><br></div><div>Exactly. I thought that there might be a bug in TNotebook/TPage leading to zero client area, but this isn't the case.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
> So I wonder:<br>
><br>
> - Is it forbidden to change position and/or size of a component when<br>
> it's not shown?<br>
<br>
It is allowed and a pretty normal thing.<br>
<br>
> - If not, how can I deal with right-aligned controls? Simply setting<br>
<span class="">> c.Left := c.Left * Factor doesn't seem to work (though it should as in this<br>
> step all positions and all sizes simply get scaled up; anchoring is used<br>
> when the parent resizes and not the component itself, right?).<br>
<br>
</span>Maybe you forget to disable the autosize updates during the changes?<br>
<br>
Simple example:<br>
<br>
MainControl.DisableAlign;<br>
try<br>
MainControl.SetBounds(Width*f,Height*f);<br>
for aControl in List do<br>
aControl.SetBounds(aControl.Left*f,aControl.Top*f,aControl.Width*f,aControl.Height*f);<br>
finally<br>
MainControl.EnableAlign;<br>
end;<br></blockquote><div><br></div><div>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 <font face="monospace, monospace">TControl.UpdateAnchorRules</font> as above.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Note: This algorithm has rounding errors, so multiple zooms will<br>
destroy your layout.<br></blockquote><div><br></div><div>I know. Currently, I don't care about a pixel or two... my layout has orders of magnitude bigger problems.</div><div><br></div><div>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 <i>original</i> font size of <i>every</i> control. And I don't want to run to any problems when the control gets freed.</div><div><br></div><div>Regards, Martin.</div></div></div></div>