为什么 Delphi 报告的PPI与计算的PPI不同?

plicqrtu  于 2023-10-18  发布在  其他
关注(0)|答案(2)|浏览(122)

我使用 Delphi 10.3里约,并需要知道屏幕像素每英寸的比例,以相应地缩放我的应用程序。
用公式计算,我的屏幕有142个像素。(真实的值为:15.5”对角线和1920 x 1080分辨率)。但是当我在 Delphi 中读取Screen.PixelsPerInch属性时,我得到134!这个值也会在我创建的每个TFormPixelsPerInch属性中显示。那么,为什么会有这种差异,哪一种才是真实的差异呢?
AIDA64报告了142公斤的真实的价值。所以我认为是 Delphi 中每英寸像素的比例有问题...

编辑:

我设法用这个代码得到了真实的PPI...但我不能在每个 Delphi 组件中都改变这一点。所以,如果我在组件中使用这个值,我不会把一切都搞砸吗?

procedure TForm1.FormCreate(Sender: TObject);
var PhiW, PhiH, PixW, PixH: Integer;
    DC: HDC;
    PhiD, PixD, PPI: Real;
begin
 DC:= Form1.Canvas.Handle;
 PhiW:= GetDeviceCaps(DC, HORZSIZE);
 PhiH:= GetDeviceCaps(DC, VERTSIZE);
 PixW:= GetDeviceCaps(DC, HORZRES);
 PixH:= GetDeviceCaps(DC, VERTRES);
 PhiD:= (Sqrt((PhiW*PhiW)+(PhiH*PhiH)))/25.4;
 PixD:= Sqrt((PixW*PixW)+(PixH*PixH));
 PPI:= PixD / PhiD;
 Label1.Caption:= IntToStr(Round(PPI))+' ppi';
end;
ejk8hzay

ejk8hzay1#

操作系统PPI

没有bug, Delphi 在PixelsPerInch中返回正确的值。
PPI OS将返回用于缩放应用程序的目的不是实际显示设备的实际PPI值,而是虚拟像素密度。
对于开发应用程序,您需要的PPI值是操作系统提供的值,而不是显示设备的实际PPI值。
您需要知道的一切是OS的基线PPI和当前PPI或比例因子。使用这些数字,然后您可以从一些基线像素值计算缩放像素的数量。
例如,如果控件基线宽度为100像素,屏幕比例为基线PPI的150%,则运行时控件大小将为150像素。
不同的操作系统具有不同的基准PPI。
| OS|基线PPI|
| --|--|
| Windows| 96 PPI|
| macOS| 72 PPI|
| Android| 160 PPI|
| iOS| 163 PPI|
计算:

ScaledPx := MulDiv(Px, PixelsPerInch, BaselinePixelsPerInch);

ScaledPx := Px * ScaleFactor;

在Windows上:

ScaledPx := MulDiv(Px, PixelsPerInch, 96);

为什么需要使用虚拟操作系统PPI而不是硬件PPI?

首先,不同的显示设备具有不同的硬件像素密度。例如,分辨率为1920 x1080像素的全高清显示器将根据设备尺寸是22”还是24”而具有不同的硬件PPI。第一个将有100.13 PPI和第二个91.79 PPI。
但是,当您运行Windows时,如果使用默认的Windows比例设置(100%),则为两台显示器返回的值将为96像素。显然,该值与这些硬件PPI值中的任何一个都不匹配,并且只是近似接近。
因此,在两个显示器上显示100像素的正方形将导致该正方形的不同物理尺寸。
接下来,用户可以选择不同的比例设置。有些人可能想使用125%的比例,即120 PPI。如果您在应用程序中使用实际的硬件PPI,对于这样的用户来说,一切都太小了。
由于虚拟PPI可以调整,因此在编写通用应用程序时,了解实际硬件PPI的用处不大。对于DTP和类似的应用,有时能够看到1:1比例的设计是有价值的,但在这种情况下,人们通常使用硬件密度与操作系统匹配的显示器,或者用户必须能够输入他的硬件配置,该值用于计算需要精确匹配物理尺寸的像素尺寸。
虽然有操作系统API可以给予显示设备的实际硬件PPI,但由于各种原因,在跨平台的许多设备上,您将很难获得正确的PPI值。

字体PPI

除了一般的虚拟PPI,还有一种PPI值可以由用户独立定制--字体PPI。字体比例的基线与不同平台上虚拟PPI的基线相同。完全荣誉用户设置的应用程序将根据字体PPI而不是一般的虚拟PPI显示文本数据和其他相关尺寸。
Delphi 目前没有内置的自定义字体PPI值的支持。换句话说,如果您将字体大小设置为10 pt,则字体的实际像素高度将基于PixelsPerInch-通用PPI计算。
如果用户字体比例设置为100%(这是最常用的值),那么 Delphi 将正确缩放字体的基础上PixelsPerInch值。

w8f9ii69

w8f9ii692#

要缩放应用程序,您可以在设计时(对象检查器)将Form1.Scaled设置为False,然后在运行时使用手动设置的常数按自定义因子缩放窗体:

const DefaultDesignTimePPI = 96; // virtual PPI in Windows for standard font scale (100%)

procedure TForm1.FormCreate(Sender: TObject);
begin
  AutoScroll := false; // to resize the form window when scaling
  ChangeScale(Screen.PixelsPerInch, DefaultDesignTimePPI);
  Scaled := true;

相关问题