Chester Wilson 5 Posted July 14, 2022 (edited) I have a problem with image scale being different under android and under windows. I have tried to simplify this for Delphi Praxis. It started with trying to draw a black box around tEdit components on Android, so you can actually see them! On windows, the image.scale is left to the default (1,1). On android (at least on my phone), it has to be set to (0.31, 0.31) or the results are weird / awful. To duplicate it, make a new FMX project in a simple window. On the form place a tImage and 2 x tEdit (with some text in each). Use the code below, and put Resize into the Form.Resize in the object inspector. Run it on android and on windows and you should see the oddity. I do not know whether there may be something about using / not using high DPI on the android: ClientWidth x ClientHeight shows as 338 x 660, whereas the Samsung S22 is supposed to have a screen of 1080 x 2340, but I do not know how to access this. I will be interested in your ideas and findings please. unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.Edit, FMX.Memo.Types, FMX.ScrollBox, FMX.Memo, FMX.Objects; type TForm1 = class(TForm) Edit1: TEdit; Edit2: TEdit; Image1: TImage; procedure FormResize(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: tForm1; implementation {$R *.fmx} procedure tForm1.FormResize(Sender: TObject); var Rect, e1Rect, e2Rect : tRectf; begin Image1.Position.X := 20; Image1.Position.Y := 30; Edit1.Position.X := 40; Edit1.Position.Y := 60; Edit2.Position.X := ClientWidth - Edit2.Width - 60; Edit2.Position.Y := 60; //Create rectangle positions for edit boxes with respect to the image. e1Rect := tRectf.Create( Edit1.Position.X - Image1.Position.X, Edit1.Position.Y - Image1.Position.Y, Edit1.Position.X - Image1.Position.X + Edit1.Width, Edit1.Position.Y - Image1.Position.Y + Edit1.Height); e2Rect := tRectf.Create( Edit2.Position.X - Image1.Position.X, Edit2.Position.Y - Image1.Position.Y, Edit2.Position.X - Image1.Position.X + Edit2.Width, Edit2.Position.Y - Image1.Position.Y + Edit2.Height); // --------------- Problem Area ------------------- //Need this for Android: Image1.Scale.X := 0.31; Image1.Scale.Y := 0.31; Image1.Height := 200 * 3; Image1.Width := 3 * (ClientWidth - 40); Image1.Bitmap.SetSize(round(Image1.Width), round(Image1.Height)); //Need this for Windows { Image1.Height := 200; Image1.Width := (ClientWidth - 40); Image1.Bitmap.SetSize(round(Image1.Width), round(Image1.Height)); } // ------------------------------------------------- Image1.Bitmap.Canvas.Stroke.Kind := tBrushKind.Solid; Image1.Bitmap.Canvas.Stroke.Color := tAlphaColorRec.Black; Image1.Bitmap.Canvas.Stroke.Thickness := 2; Image1.Bitmap.Canvas.BeginScene; //Colour the whole image first Image1.Bitmap.Canvas.Clear(tAlphaColorRec.Lightsalmon); //Now white out the bits where we want to place the edit boxes //Left one: Rect.Left := e1Rect.Left - 1; Rect.Right := e1Rect.Left + Edit1.Width + 1; Rect.Top := e1Rect.Top; Rect.Bottom := e1Rect.Top + Edit1.Height + 1; Image1.Bitmap.Canvas.ClearRect(Rect, tAlphaColorRec.Yellow); //Right one: Rect.Left := e2Rect.Left - 1; Rect.Right := e2Rect.Left + Edit2.Width + 1; Rect.Top := e2Rect.Top; Rect.Bottom := e2Rect.Top + Edit2.Height + 1; Image1.Bitmap.Canvas.ClearRect(Rect, tAlphaColorRec.Yellow); //Now draw the rectangles Rect.Left := e1Rect.Left - 1; Rect.Right := e1Rect.Left + Edit1.Width + 1; Rect.Top := e1Rect.Top - 1; Rect.Bottom := e1Rect.Top + Edit1.Height + 1; Image1.Bitmap.Canvas.DrawRect(Rect, 1); Rect.Left := e2Rect.Left - 1; Rect.Right := e2Rect.Left + Edit2.Width + 1; Rect.Top := e2Rect.Top - 1; Rect.Bottom := e2Rect.Top + Edit2.Height + 1; Image1.Bitmap.Canvas.DrawRect(Rect, 1); Image1.Bitmap.Canvas.EndScene; end; end. Edited July 14, 2022 by Sherlock Please use the code tags for better readability Share this post Link to post
Sherlock 663 Posted July 14, 2022 Have you tried your code on Windows set to 150% or any other scale? You need to find out, what the DisplayMetrics are and react accordingly. I use something like this if TBehaviorServices.Current.SupportsBehaviorService(IDeviceBehavior, DeviceBehavior, Context) then begin DisplayMetrics := DeviceBehavior.GetDisplayMetrics(Context); Scale := DisplayMetrics.ScreenScale; ppi := DisplayMetrics.PixelsPerInch; end else ShowMessage('Help?!'); 1 Share this post Link to post
Chester Wilson 5 Posted July 15, 2022 Thanks, Sherlock. It works fine on windows with the scale set to 1 (the default), and I have no problem with that. It is with bloody android! I have put your code in, thanks - but I need to know what to include in the USES. I have found FMX.BehaviourManager, but cannot find where AService is defined (for DeviceBehavior), or how to define DisplayMetrics. Please would you mind filling in the gaps? Share this post Link to post
Sherlock 663 Posted July 15, 2022 OK you'll need: uses FMX.Types, FMX.BehaviourManager, FMX.Platform; And even if you only develop for yourself, you should consider different DPI and scaling in your application because you might treat yourself to a monitor with higher resolution at some point. Share this post Link to post