Delphi Tokyo启用高DPI后TImage运行时比设计时缩小的问题
问题原因
Delphi Tokyo的VCL框架在高DPI模式下,会自动对窗体和控件按系统DPI比例进行缩放,但TImage的静态图像资源默认基于96DPI(标准DPI)设计,未适配高DPI环境:
- 当
Stretch=True时,图像被强制拉伸到缩放后的控件尺寸,因原始分辨率不足导致像素模糊。 - 当
Stretch=False时,图像仅按原始像素尺寸显示,而控件实际显示区域因高DPI缩放相对设计比例“缩小”,所以图像看起来只有窗体一半大小。
禁用高DPI后,系统停止缩放逻辑,窗体和图像都按原始96DPI渲染,因此显示正常。
解决方法
1. 确保项目启用正确的高DPI支持
- 打开项目选项,进入
Application→Manifest:- 勾选Enable runtime themes,保证主题渲染正常。
- 在
High DPI设置中,优先选择Per Monitor V2(支持动态DPI变化),或至少勾选High DPI aware。
- 确认窗体的
Scaled属性设为True(默认值,确保窗体跟随DPI缩放)。
2. 使用多分辨率图像适配不同DPI
为常用DPI比例(100%/96DPI、125%/120DPI、150%/144DPI、200%/192DPI)准备对应分辨率的图像文件,比如命名为image_96.png、image_120.png等。在代码中根据当前屏幕DPI加载对应图像:
procedure TForm1.LoadImageByDPI; var Dpi: Integer; ImagePath: string; begin Dpi := Screen.PixelsPerInch; case Dpi of 96: ImagePath := 'image_96.png'; 120: ImagePath := 'image_120.png'; 144: ImagePath := 'image_144.png'; 192: ImagePath := 'image_192.png'; else ImagePath := 'image_96.png'; // fallback到标准DPI图像 end; Image1.Picture.LoadFromFile(ImagePath); Image1.Stretch := True; // 保持图像适配控件尺寸 end;
在窗体OnCreate和OnDpiChanged事件中调用该方法,确保DPI变化时自动切换图像。
3. 动态缩放单张图像(无多分辨率资源时)
如果只有单张原始图像,可通过代码按DPI比例缩放,同时用高质量渲染避免模糊:
procedure TForm1.ScaleImageToDPI; var DpiScale: Double; OriginalBmp: TBitmap; ScaledBmp: TBitmap; begin DpiScale := Screen.PixelsPerInch / 96; // 计算DPI缩放比例 OriginalBmp := TBitmap.Create; ScaledBmp := TBitmap.Create; try OriginalBmp.LoadFromFile('original_image.png'); // 创建缩放后的Bitmap ScaledBmp.SetSize(Round(OriginalBmp.Width * DpiScale), Round(OriginalBmp.Height * DpiScale)); // 使用高质量拉伸 ScaledBmp.Canvas.Brush.Color := clWhite; ScaledBmp.Canvas.FillRect(Rect(0, 0, ScaledBmp.Width, ScaledBmp.Height)); ScaledBmp.Canvas.StretchDraw(Rect(0, 0, ScaledBmp.Width, ScaledBmp.Height), OriginalBmp); // 赋值给TImage Image1.Picture.Assign(ScaledBmp); Image1.Stretch := False; // 此时无需再拉伸,图像已适配尺寸 finally OriginalBmp.Free; ScaledBmp.Free; end; end;
同样在OnCreate和OnDpiChanged事件中调用该方法,处理初始加载和DPI变化场景。
内容的提问来源于stack exchange,提问作者robertjains
相关产品推荐
相关产品推荐

