A Scrollbox containing a series of TImageControls stacked vertically. When I scale the images and readjust the ImageControl positions, the Scrollbox.contents does not size properly. If I scale less than 1, there is extra space at the bottom; when it is more than 1, the last image is cut off. I've tried to call various routines (AdjustSizeValue, InvalidateContentSize, RecalcUpdateRect, RecalcSize etc) but these do nothing.
Here is a complete test project illustrating the problem:
unit Unit3;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.TabControl, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Edit,
FMX.EditBox, FMX.SpinBox, FMX.Layouts;
type
Tform1 = class(TForm)
Button1: TButton;
SpinBox1: TSpinBox;
ScrollBox: TScrollBox;
Layout1: TLayout;
Label1: TLabel;
TrackBar1: TTrackBar;
Label2: TLabel;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
procedure ImageMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Single);
{ Private declarations }
public
{ Public declarations }
end;
var
form1: Tform1;
implementation
{$R *.fmx}
const
PH = 1000;
PW = 750;
procedure Tform1.Button1Click(Sender: TObject);
Function MakeImage(const aOwner:TControl; aNumber:integer): TImageControl;
begin
result := TImageControl.Create(aOwner);
result.EnableOpenDialog := false;
result.SetBounds(0,0,PW,PH);
result.Parent := ScrollBox;
result.bitmap.SetSize( round(PW), round(PH) );
with Result.Bitmap.Canvas do
if BeginScene then
try
fill.Color := TAlphaColorRec.Black;
fill.Kind := TBrushKind.Solid;
Font.Family := 'Arial';
Font.Size := 100;
FillText( RectF(00,00,200,200),aNumber.ToString,false,1, [], TTextAlign.Center,TTextAlign.Leading );
finally
EndScene;
end;
end;
var
i: Integer; Image:TImageControl; vertical:single;
begin
vertical := 0;
for i := 1 to round(SpinBox1.Value) do
begin
Image := MakeImage(ScrollBox,i);
Image.Position.Y := vertical;
vertical := vertical + Image.Height;
Image.OnMouseMove := ImageMouseMove;
end;
end;
procedure Tform1.Button2Click(Sender: TObject);
begin
Scrollbox.AdjustSizeValue;
Scrollbox.InvalidateContentSize;
Scrollbox.RecalcUpdateRect;
Scrollbox.RecalcAbsoluteNow;
Scrollbox.Content.RecalcSize;
Scrollbox.Content.RecalcUpdateRect;
Scrollbox.Content.RecalcAbsoluteNow;
end;
procedure Tform1.ImageMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Single);
begin
Label1.Text := 'X:' + FloatToStrF(X,TFloatFormat.ffFixed,4,2) + ' Y:' + FloatToStrF(Y,TFloatFormat.ffFixed,4,2);
end;
procedure Tform1.TrackBar1Change(Sender: TObject);
var
i: Integer; vertical,ScaleValue:Single;
begin
vertical := 0;
ScaleValue := TrackBar1.Value;
Label2.Text := 'Scale: '+round(ScaleValue*100).ToString +'%';
for i := 0 to ScrollBox.Content.ControlsCount - 1 do
if ScrollBox.Content.Controls[i] is TImageControl then
with ScrollBox.Content.Controls[i] as TImageControl do
begin
Scale.Y := TrackBar1.Value;
Scale.X := TrackBar1.Value;
Position.y := Vertical;
Vertical := vertical + (PH*ScaleValue);
end;
end;
end.
and
object form1: Tform1
Left = 0
Top = 0
Caption = 'Form3'
ClientHeight = 480
ClientWidth = 640
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
DesignerMasterStyle = 0
object Layout1: TLayout
Align = Left
Size.Width = 249.000000000000000000
Size.Height = 480.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
object Button1: TButton
Position.X = 64.000000000000000000
Position.Y = 56.000000000000000000
TabOrder = 1
Text = 'Start'
OnClick = Button1Click
end
object SpinBox1: TSpinBox
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 3
Cursor = crIBeam
Max = 500.000000000000000000
Value = 10.000000000000000000
Position.X = 56.000000000000000000
Position.Y = 104.000000000000000000
end
object Label1: TLabel
Align = Bottom
Position.Y = 192.000000000000000000
Size.Width = 249.000000000000000000
Size.Height = 288.000000000000000000
Size.PlatformDefault = False
TextSettings.HorzAlign = Center
TabOrder = 4
end
object TrackBar1: TTrackBar
CanParentFocus = True
Max = 1.700000047683716000
Min = 0.300000011920929000
Orientation = Horizontal
Position.X = 111.000000000000000000
Position.Y = 152.000000000000000000
TabOrder = 5
Value = 1.000000000000000000
OnChange = TrackBar1Change
end
object Label2: TLabel
Position.X = 39.000000000000000000
Position.Y = 152.000000000000000000
Size.Width = 73.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
TabOrder = 6
end
object Button2: TButton
Position.X = 64.000000000000000000
Position.Y = 208.000000000000000000
TabOrder = 7
Text = 'Adjust'
OnClick = Button2Click
end
end
object ScrollBox: TScrollBox
Align = Client
Size.Width = 391.000000000000000000
Size.Height = 480.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
ShowSizeGrip = True
Viewport.Width = 391.000000000000000000
Viewport.Height = 480.000000000000000000
end
end
Can anyone solve this?
I was able to reproduce the problem, and I did leave some comments on your question before, but deleted as I realized they were wrong.
The solution is rather simple (as they usually are) when the correct code is applied. So here it is:
procedure TForm5.TrackBar1Change(Sender: TObject);
//var
// i: Integer; vertical,ScaleValue:Single;
begin
ScrollBox.Scale.X := TrackBar1.Value;
ScrollBox.Scale.Y := TrackBar1.Value;
ScrollBox.RecalcSize; // This was missing
Label2.Text := TrackBar1.Value.ToString(ffFixed, 3, 3);
end;