You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi自定义TPanel派生组件UI DPI缩放异常问题排查

Delphi自定义TPanel派生组件DPI缩放内容截断问题解决方法

问题根源

你遇到的问题本质是:自定义TPanel派生组件在创建内部控件(TLabel、TComboBox、TButton)时,若在Create方法中硬编码了初始尺寸,Delphi的DPI缩放机制会以这些创建时的初始值为基准计算缩放比例,而非设计阶段你调整后的控件尺寸。而Panel本身因为是窗体缩放的直接对象,能正确按25%放大,但内部控件没跟上设计值的缩放,最终导致内容截断。

解决方案

1. 避免在Create中硬编码尺寸,改用Loaded方法处理

不要在组件构造函数里固定内部控件的宽高,而是把尺寸初始化放到Loaded方法中——这个方法会在组件从DFM文件加载完成后触发,此时设计阶段的参数已经生效。同时确保内部控件的Scaled属性设为True,继承父组件的缩放逻辑。

示例代码:

type
  TMyCustomPanel = class(TPanel)
  private
    FLabel: TLabel;
    FComboBox: TComboBox;
    FButton1: TButton;
    FButton2: TButton;
  protected
    procedure Loaded; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

constructor TMyCustomPanel.Create(AOwner: TComponent);
begin
  inherited;
  // 仅创建控件,不设置固定尺寸
  FLabel := TLabel.Create(Self);
  FLabel.Parent := Self;
  FLabel.Name := 'lblMyLabel';
  FLabel.Caption := '选择项:';

  FComboBox := TComboBox.Create(Self);
  FComboBox.Parent := Self;
  FComboBox.Name := 'cboMyCombo';

  FButton1 := TButton.Create(Self);
  FButton1.Parent := Self;
  FButton1.Name := 'btnOK';
  FButton1.Caption := '确定';

  FButton2 := TButton.Create(Self);
  FButton2.Parent := Self;
  FButton2.Name := 'btnCancel';
  FButton2.Caption := '取消';
end;

procedure TMyCustomPanel.Loaded;
begin
  inherited;
  // 这里可以设置默认布局,或依赖DFM中保存的设计时尺寸
  FLabel.SetBounds(10, 5, 70, 20);
  FComboBox.SetBounds(85, 5, Self.Width - 180, 20);
  FButton1.SetBounds(Self.Width - 80, 5, 70, 20);
  FButton2.SetBounds(Self.Width - 160, 5, 70, 20);

  // 开启内部控件的缩放继承
  FLabel.Scaled := True;
  FComboBox.Scaled := True;
  FButton1.Scaled := True;
  FButton2.Scaled := True;
end;

2. 使用Anchor属性实现自适应布局

给内部控件设置合适的Anchor属性,让它们随父Panel的尺寸变化自动调整,从根源上避免截断问题。比如让ComboBox左右锚定,随Panel宽度拉伸:

在Create或Loaded方法中添加:

FComboBox.Anchors := [akLeft, akTop, akRight];
// 调整Left和Right的间距,留出按钮空间
FComboBox.Left := 85;
FComboBox.Right := 165;

3. 重写ScaleControls手动控制缩放

如果需要更精细的缩放控制,可以重写组件的ScaleControls方法,手动指定内部控件的缩放基准,确保用设计时的尺寸计算缩放比例:

procedure TMyCustomPanel.ScaleControls(Magnification: Integer; const Origin: TPoint);
begin
  inherited;
  // 强制按当前设计尺寸缩放内部控件
  FLabel.ScaleBy(Magnification, 100);
  FComboBox.ScaleBy(Magnification, 100);
  FButton1.ScaleBy(Magnification, 100);
  FButton2.ScaleBy(Magnification, 100);
end;

总结

不需要强制关闭窗体的Scaled属性,只要让内部控件的缩放基准从“创建时初始值”切换到“设计时调整值”,再配合自适应布局,就能解决125% DPI缩放时的内容截断问题。

内容的提问来源于stack exchange,提问作者3delite

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 19:24:20