首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何处理Windows 11中引入的TForm和自定义缩放?

如何处理Windows 11中引入的TForm和自定义缩放?
EN

Stack Overflow用户
提问于 2022-09-06 08:30:40
回答 1查看 320关注 0票数 1

Windows 11引入了一个允许自定义屏幕比例的新选项:

应用自定义缩放时,读取和写入表单的宽度和高度会导致不良行为。

特别是在我的Delphi应用程序中,每次关闭表单时,我都会将表单的宽度和高度存储在INI文件中,以便在下次表单显示时恢复它们。

代码语言:javascript
运行
复制
// 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.HeightTForm.Width存储到文件中时,它们通过自定义缩放百分比(或至少是接近它的数字)而增加,而当设置值时,则正确地应用这些值。因此,每次显示表单时,它都会越来越大。

我必须处理缩放问题并对其进行补偿(通过将值除以比例因子),这是正常的吗?我希望这对我来说是透明的。

此外,有人知道如何从windows中检索自定义缩放设置吗?我在谷歌搜索失败了。

谢谢!

EN

回答 1

Stack Overflow用户

发布于 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。

代码应该是这样的:

代码语言:javascript
运行
复制
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\DesktopLogPixels键中。此注册表项控制Windows 10和11中的DPI缩放级别。

代码语言:javascript
运行
复制
LogPixels = 96,  means 100% scaling
LogPixels = 120, means 125% scaling
LogPixels = 144, means 150% scaling
LogPixels = 192, means 200% scaling etc.

因此,解决方法是读取这个注册表项,并缩小(或向上)要写入ini文件的宽度和高度。

代码应该是这样的:

代码语言:javascript
运行
复制
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解决了这个问题。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73618972

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档