如何在高dpi值下工作视觉继承?

时间:2017-06-28 19:36:15

标签: delphi delphi-10-seattle highdpi visual-inheritance

我有以下示例表单TForm1,带有两个按钮(BitBtn):

base form

此外,我还有第二种形式TForm2,它来自第一种形式。 第二个按钮向左移动,另一个按钮被添加:

derived form

在运行时(Windows 7),第二种形式如下所示:

standard font size

如果我将字体缩放更改为125%,我的表单如下所示:

increased font size

不知何故,新按钮位置错误,尺寸错误。 我该怎么办?

我使用了以下.dfm个文件(缩写):

object Form1: TForm1
  Left = 0
  Top = 0
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object BitBtn1: TBitBtn
    Left = 8
    Top = 8
    Width = 105
    Height = 105
    Caption = 'BitBtn1'
  end
  object BitBtn2: TBitBtn
    Left = 359
    Top = 8
    Width = 105
    Height = 105
    Caption = 'BitBtn2'
  end
end

inherited Form2: TForm2
  Caption = 'Form2'
  PixelsPerInch = 96
  TextHeight = 13
  inherited BitBtn2: TBitBtn
    Left = 191
    Top = 7
    ExplicitLeft = 191
    ExplicitTop = 7
  end
  object BitBtn3: TBitBtn
    Left = 359
    Top = 8
    Width = 105
    Height = 104
    Caption = 'BitBtn3'
  end
end

类设计器生成它们时,类文件保持不变。它们不包含相关代码。

1 个答案:

答案 0 :(得分:2)

我自己找到了一个可能的解决方案:必须覆盖ReadState 以下代码:

procedure TForm2.ReadState(Reader: TReader);
begin
  IntPtr(FReserved) := 0;
  inherited;
end;    

这看起来很奇怪。它是如何工作的?

我查看了VCL源代码并找到了 表单加载后的缩放是在TForm.ReadState(...)中完成的。显然,受到保护 FReserved的字段TControl用于存储当前应用的DPI值:

  • 首先,我的基类dfm的所有组件都被读取
  • 然后缩放并正确定位
  • ,当前应用的DPI值存储在FReserved
  • 之后再次调用ReadState,派生类的dfm文件
  • 但由于FReserved中的值,缩放不会应用于派生形式的组件

因此,一个想法是在读取组件之前重置缓存的DPI值。它会将Form1的组件缩放两次,但这不会造成伤害,因为原始大小和位置会被记住为缩放的基本值,结果完全相同。