Reputation: 13454
For years I've use a VCL forms application layout strategy that auto-sizes the form controls on the main form. Users can maximise or resize the application at will with the same general look and feel of button layouts, charts etc. To do this I wrote code to manipulate the BoundsRect of child controls based on the FormResize event of the form, and this simple technique preserves the text font size and aspect ratio (eg of buttons). I have further simple code to raise and lower the font size to track the expanding and reducing button / label sizes of main controls, but many controls e.g a TChart are left with readable albeit small fonts when the application is minimised - I'm very happy with this.
I'd like to migrate my layout to use FireMonkey which has TScaledLayout which, when you align it alClient in form neatly resizes all of its contained controls. Unfortunately the resizing extends to all text fonts too, which is really not desirable. Setting the TScaledLayout to alFit keeps the original aspect ratio of the contents but can result in empty padding at the top or sides to achieve this.
Is there any way in which I could 'turn off' the resizing of all fonts under TScaledLayout action? I've explored the info in FireMonkey Layouts Strategies and also tried each of its vastly increased 'Align' settings without success. Eploying full screen while moving between various display devices would need this ability surely?
Upvotes: 3
Views: 3363
Reputation: 2940
One could try the following strategy:
In my case I wanted to make a zoomable panel (with aspect ratio preservation) inside a TScrollBox layout, so I use Align:=Center at that panel and set its scale programmatically for zooming.
Note that Embarcadero's ScaledLayout sample is misleading in that case since it sets the scale of the ScaledLayout (which is irrelevant to the children scaling capabilities of ScaledLayout upon its resizing - they could have set the Scale at a TPanel or any other container)
Another confusing aspect is that Align := Scale at controls isn't related to Scaling, but to child controls resizing when parent resizes keeping their relative position and relative size (that is they don't scale their display, they actually resize).
Update:
I found that when zooming in/out with the above strategy I'd get scrollbars behave the inverse than expected. I realized it was related to the outer panel not getting resized but only its scale being set (note that since it's in a scrollbox in my case I have it set to Align:=Center, not Align:=Client like you'd do in a form)
So instead of an outer panel I used yet another TScaleLayout since it has extra useful properties OriginalWidth/OriginalHeight that keep the original size of the control. This is needed for calculation of the new size based on the new scale one applies when zooming in/out (not using the Scale property of it as Embarcadero's sample misleadingly suggests, apart from Unit/-Unit axes scale values to support negative scaling [aka axis flipping]):
procedure TForm2.FormCreate(Sender: TObject);
begin
BeginUpdate;
Zoomer.Align := TAlignLayout.Center; //at design mode we have it set to TAlignLayout.Client
UpdateZoomFromTrackbars;
EndUpdate;
end;
procedure TForm2.SetZoom(const Value: Single);
begin
SetZoom(Value, Value);
end;
procedure TForm2.SetZoom(const ValueX, ValueY: Single);
begin
if (ValueX <> 0) and (ValueY <>0) then //FMX has bug where Scale won't work anymore if set to 0
begin
BeginUpdate;
//update track bars
trackZoomX.BeginUpdate; trackZoomX.ValueRange.Value := ValueX; trackZoomX.EndUpdate;
trackZoomY.BeginUpdate; trackZoomY.ValueRange.Value := ValueY; trackZoomY.EndUpdate;
with Zoomer do
begin
Size.Size := TSizeF.Create(OriginalWidth * abs(ValueX), OriginalHeight * abs(ValueY)); //don't use Scale to resize (won't work well here), ScaledLayout scales its contents automatically
Scale.Point := TPointF.Create(sign(ValueX), sign(ValueY));
end;
//ScrollBox.InvalidateContentSize;
EndUpdate;
end;
end;
procedure TForm2.UpdateZoomFromTrackbars;
begin
SetZoom(trackZoomX.Value, trackZoomY.Value);
end;
procedure TForm2.ScrollBoxResize(Sender: TObject);
begin
var scrollBoxSize := ScrollBox.Size.Size;
if not scrollBoxSize.IsZero then
begin
BeginUpdate;
Zoomer.Size.Size := scrollBoxSize;
with Zoomer do
begin
OriginalWidth := Width;
OriginalHeight := Height;
end;
UpdateZoomFromTrackbars;
//ScrollBox.InvalidateContentSize;
EndUpdate;
end;
end;
procedure TForm2.trackZoomXTracking(Sender: TObject);
begin
if trackZoomX.IsUpdating then exit;
BeginUpdate;
if switchSyncAxes.IsChecked then
trackZoomY.Value := trackZoomX.Value;
UpdateZoomFromTrackbars;
EndUpdate;
end;
procedure TForm2.trackZoomYTracking(Sender: TObject);
begin
if trackZoomY.IsUpdating then exit;
BeginUpdate;
if switchSyncAxes.IsChecked then
trackZoomX.Value := trackZoomY.Value;
UpdateZoomFromTrackbars;
EndUpdate;
end;
Upvotes: 1
Reputation: 2287
Think transparent layers like on an overhead projector (remember those?). Put your text labels on a panel that is on the form. Put the scaledlayout on the panel. Put the controls on the scaledlayout. Now when the form resizes, the controls also do, but the labels do not.
Upvotes: 1