Windows 11引入了一个允许自定义屏幕比例的新选项:
应用自定义缩放时,读取和写入表单的宽度和高度会导致不良行为。
特别是在我的Delphi应用程序中,每次关闭表单时,我都会将表单的宽度和高度存储在INI文件中,以便在下次表单显示时恢复它们。
// store to file code
IniFile.WriteInteger('FORM','Width',AForm.Width);
IniFile.WriteInteger('FORM','Top',AForm.Top);
// restore from file code
StoredHeight:= IniFile.readInteger('FORM','Height',AForm.Height);
StoredWidth := IniFile.readInteger('FORM','Width',AForm.Width);
if StoredWidth >= Screen.Width then
AForm.Width := Screen.Width
else
begin
AForm.Width := StoredWidth;
if StoredLeft < 0 then
AForm.left := 0
else
AForm.left := StoredLeft;
end;
if StoredHeight >= Screen.Height then
AForm.Height := Screen.Height
else
begin
AForm.Height := StoredHeight;
if StoredTop < 0 then
AForm.Top := 0
else
AForm.Top := StoredTop;
end;
问题是,当将TForm.Height
和TForm.Width
存储到文件中时,它们通过自定义缩放百分比(或至少是接近它的数字)而增加,而当设置值时,则正确地应用这些值。因此,每次显示表单时,它都会越来越大。
我必须处理缩放问题并对其进行补偿(通过将值除以比例因子),这是正常的吗?我希望这对我来说是透明的。
此外,有人知道如何从windows中检索自定义缩放设置吗?我在谷歌搜索失败了。
谢谢!
发布于 2022-09-10 14:49:22
德尔菲11.0亚历山大有了改进。IDE现在完全支持高分辨率屏幕上的高DPI缩放。这种高度的DPI支持包括代码编辑器中的支持,以及在设计表单时,VCL和FMX的支持。在VCL窗体设计器中有一个控制缩放的设置,因此您可以将其设置为默认情况下的非缩放。。
您必须编译您的应用程序以支持高DPI (‘DPI知道’)。如果一个应用程序是‘DPI不知道’的,Windows会放大它,但是升级会增加模糊。如果一个应用程序是‘DPI感知的’,那么应用到它的窗口的缩放就更清晰了。
您可以将VCL表单设计器缩放到任何DPI (任意缩放)。这是使用VCL在运行时缩放时使用的相同的缩放技术完成的。此设置位于Tools > Options > User Interface > Form Designer > High .中,当您更改它时,需要关闭并重新打开表单设计器才能产生效果。
默认情况下,打开窗体时,表单设计为96 DPI,即100%。知识的一个关键部分是,当表单被缩放时,左、高等属性会发生变化。这与运行应用程序并进行缩放时完全相同;这些值乘以屏幕比例尺。
Windows (所以VCL)对其大小和位置使用整数坐标。这意味着任何缩放可能并不总是精确的。在实践中,当缩放一次(比如运行应用程序时,它会从设计时的低分辨率坐标向上扩展),这是很好的。它还可以进行几次缩放,比如在启动后从一个监视器移动到另一个监视器。当多次缩放时,更重要的是。因此,在任何比例的高DPI上进行设计,甚至在较低的比例上运行-- VCL将正确地缩放您的应用程序--这是很好的,但重要的是要避免一次又一次地缩放,如果每次在设计器中打开表单,都会在不同的DPI中打开。
您可以在以下embarcadero博客中阅读更多关于新闻部缩放的信息:https://blogs.embarcadero.com/new-in-rad-studio-11-high-dpi-ide-and-form-designing/
首先要尝试的是禁用应用程序的每个窗体的缩放属性(您可以在窗体的对象检查器上找到此属性),然后测试是否正确地写入了宽度和高度值。如果这不能解决你的问题,那么我就提出一些解决办法。
这里是一个解决办法,直到embarcadero修复了这个问题。
您可以在关闭表单时保存宽度和高度值(使用MulDiv函数),这取决于最终用户设置的dpi。
代码应该是这样的:
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;
不过,您可以尝试使用Monitor.PixelsPerInch
而不是Screen.PixelsPerInch
。这样,它将在不同的监视器中应用不同的自定义缩放的情况下工作。
另一个工作是从注册表读取自定义缩放属性,并在正常化后保存宽度和高度值。自定义缩放属性保存在以下注册表项中:HKEY_CURRENT_USER\Control Panel\Desktop
在LogPixels
键中。此注册表项控制Windows 10和11中的DPI缩放级别。
LogPixels = 96, means 100% scaling
LogPixels = 120, means 125% scaling
LogPixels = 144, means 150% scaling
LogPixels = 192, means 200% scaling etc.
因此,解决方法是读取这个注册表项,并缩小(或向上)要写入ini文件的宽度和高度。
代码应该是这样的:
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;
我希望这个解决办法能帮助你,直到embarcadero解决了这个问题。
https://stackoverflow.com/questions/73618972
复制相似问题