There is an improvement in Delphi 11.0 Alexandria. The IDE now fully supports high DPI scaling on high-resolution screens. This high DPI support includes support in the code editor, and when designing forms, both VCL and FMX. There is a setting to control the scaling in the VCL form designer and so you can set it to unscaled by default.
You have to compile your application to support high DPI (‘DPI aware’). If an application is ‘DPI unaware’, Windows will scale it up, but upscaling adds blurriness. It is much better if an app is ‘DPI aware’ so the scaling applied to its window(s) are crisply.
You can scale the VCL form designer to any DPI (any scale). This is done using the same scaling tech that the VCL uses when scaling itself at runtime. This setting is in Tools > Options > User Interface > Form Designer > High DPI. When you change it, you’ll need to close and reopen the form designer to have an effect.
By default, when you open a form, the form is designed at 96 DPI – that is, at 100%. One key bit of knowledge is that when a form is scaled, the Left, Height etc properties are changed. This is exactly the same as when you run an app and it is scaled; those values are multiplied by the screen scale.
Windows (and so the VCL) uses integer coordinates for its sizes and locations. This means that any scaling may not always be exactly precise. In practice, it’s fine when scaling once (such as when an app is run, and it scales up from the low-res coordinates with which it was designed.) It’s also fine scaling a few times, such as moving from one monitor to another after launching. It matters more when scaling many times. So it is fine to design at high DPI at any scale, and run even at a lower scale – the VCL will scale your app correctly – but it is important to avoid scaling over and over again, which will happen if every time you open a form in the designer it’s opened at a different DPI.
You can read more about the DPI Scaling, in the following embarcadero blog: https://blogs.embarcadero.com/new-in-rad-studio-11-high-dpi-ide-and-form-designing/
First thing to try, is to disable the Scaled property of each Form of your application (you can find this property on object inspector of the Form), and then test if the width and heigth values are written correctly.
If this doesn't fix your problem, then I am suggesting some workarounds.
Here is a workaround, until embarcadero fixes this issue.
You can save the width and height values when closing the form, after you normalize them (using MulDiv function) depending of the dpi the end user has set.
The code would be something like this:
procedure AForm.FormClose(Sender: TObject; var Action: TCloseAction);
var
IniFile: TIniFile;
begin
IniFile := TIniFile.Create( ChangeFileExt( Application.ExeName, '.ini' ) );
try
IniFile.WriteInteger('FORM','Width',MulDiv(AForm.Width, Screen.PixelsPerInch, PixelsPerInch));
IniFile.WriteInteger('FORM','Height',MulDiv(AForm.Height, Screen.PixelsPerInch, PixelsPerInch))
finally
IniFile.Free;
end;
end;
Although, you could try using Monitor.PixelsPerInch
instead of Screen.PixelsPerInch
. That way it will work for cases when different custom scaling is applied in different monitors.
Another workaroung, would be to read the custom scaling property from the registry, and save width and height values after normalizing them.
The custom scaling property, is saved in the following registry entry: HKEY_CURRENT_USER\Control Panel\Desktop
in the LogPixels
key.
This registry key controls the DPI scaling level in Windows 10 and 11.
LogPixels = 96, means 100% scaling
LogPixels = 120, means 125% scaling
LogPixels = 144, means 150% scaling
LogPixels = 192, means 200% scaling etc.
So the workaround is to read this registry key, and scale down (or up) the width and the height you are going to write to the ini file.
The code would be something like this:
procedure AForm.FormClose(Sender: TObject; var Action: TCloseAction);
var
IniFile: TIniFile;
RegKey: TRegistry;
intScalingSize: Integer; //Here I will save the scaling size stored in the registry. (eg. 96, 144 etc)
reaScalingSize: Real; //Here I will save the scaling size percentage (eg. for 96 I will store 1.0, for 144 I will store 1.5 etc)
intFormUnscaledWidth, intFormUnscaledHeight: Integer; //Here I will store the unscaled width and height.
begin
IniFile := TIniFile.Create( ChangeFileExt( Application.ExeName, '.ini' ) );
RegKey := TRegistry.Create;
intScalingSize := 0;
try
RegKey.RootKey := HKEY_CURRENT_USER;
if RegKey.OpenKey('Control Panel\Desktop', False) then
begin
intScalingSize := RegKey.ReadInteger('LogPixels');
RegKey.CloseKey;
end
else
intScalingSize := 96;
// LogPixels = 96, means 100% scaling
// LogPixels = 120, means 125% scaling
// LogPixels = 144, means 150% scaling
// LogPixels = 192, means 200% scaling
//Use linear interpolation to map scaling to percentage
reaScalingSize := 100 + ((100/96)*(intScalingSize - 96));
intFormUnscaledWidth := Round(AForm.Width / reaScalingSize);
intFormUnscaledHeight := Round(AForm.Height / reaScalingSize);
IniFile.WriteInteger('FORM','Width',intFormUnscaledWidth);
IniFile.WriteInteger('FORM','Height',intFormUnscaledHeight);
finally
RegKey.Free;
IniFile.Free;
end;
I hope this workaround will help you, until embarcadero fixes this issue.