微软在其用户界面指南中使用了对话框长度单位(DLU)。如何将其转换为像素?
据我所知,DLU取决于系统字体大小。您能不能提供一些简单的方法,在Delphi for Win32中进行这种转换?
你应该使用 MapDialogRect()
功能。
传入一个 RECT
对话单元中,以及相当于 RECT
以像素单位返回。 需要注意的是,您需要一个对话框的句柄,以便给您的 MapDialogRect()
足够的上下文。该函数需要知道字体才能进行转换。
如果你想使用 GetDialogBaseUnits()
,记得陈雷蒙德说过的话。GetDialogBaseUnits是个垃圾。.
正如你从这篇文章的标题中可以猜到的,GetDialogBaseUnits是个垃圾。由于GetDialogBaseUnits没有HWND参数,它不知道你想检索哪个对话框的DLU。所以它就会猜测。
而且它总是猜错。
GetDialogBaseUnits会返回使用默认系统字体的对话框的对话框基本单位。但是现在已经没有人使用默认的系统字体了。它叫嚣着 "古老而呆板"。但由于兼容性的原因,它仍然是默认的。因此GetDialogBaseUnits也是如此)。
如果你必须从DLU计算像素尺寸,而且你没有一个对话框的句柄,那么你必须使用这里概述的方法。如何使用非系统型字体计算对话框基数单位
然而,您在评论中明确表示,对于您的问题,您实际上并不需要从DLU转换为像素。您可以使用Delphi内置的窗体缩放功能来确保您的窗体大小适合当前的字体缩放。
首先,我们从以下几个方面入手 什么 一个对话单元是。
为此,我将引用一个 自问自答:
什么是对话框单位?
对话框是基于用户偏好的字体大小的计量单位。 对话框单位的定义是这样的 平均字符 是4个对话单元宽,8个对话单元高。
这意味着对话框单元:
- 会随着字体的变化而变化
- 随着所选DPI设置的改变而改变
- 不方正
我还将引用另一个 自问自答:
你可以检查 Windows用户体验指南 来看看这些测量结果是怎么来的。 简而言之,就是
- dlu = 对话单元
- dlu是基于字体大小(项目会随着用户的字体大小而改变)
- a 横向 Dlu不同于 纵向 dlu (凹凸不平)
这来自于对话单元的定义。平均字符高8dlus,宽4dlus。.
佐治亚州14pt.如果你使用较小的字体(即8pt的Tahoma与14pt的Georgia),dlus会变小::
如果你使用较小的字体(如8pt Tahoma与14pt Georgia),dlus会变小。
Segoe UI 9pt。
9pt: 注意: 你会发现 决心 (即dpi)对讨论没有影响。
所以您需要的是 平均大小 的一个字符。微软有一个 绝技 用于计算平均字符大小。
平均高度:平均高度。
GetTextMetrics(dc, {var}textMetrics);
averageHeight := textMetrics.tmHeight;
平均宽度。
测量字符串 ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 使用 GetTextExtentPoint32
然后除以52。
GetTextExtentPoint32(dc,
PChar('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'), 52, Size));
averageWidth := size.cx / 52.0;
所以现在你需要一个水平和一个垂直对话框单元的大小。记住,一个水平对话框单元是14个平均字符宽度,一个垂直对话框单元是18个平均字符高度。
procedure GetDlus(dc: HDC; out HorizontalDluSize, VerticalDluSize: Real);
var
tm: TTextMetric;
size: TSize;
begin
GetTextMetric(dc, tm);
VerticalDluSize := tm.tmHeight / 8.0;
GetTextExtentPoint32(dc,
PChar('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'), 52,
size);
HorizontalDluSize := size.cx / 52.0;
end;
注意:: 任何代码都会被发布到公共领域。不需要注明出处。
对于基本值(自然也包括系统字体),请调用 GetDialogBaseUnits
. 另见 remarks
段,以替代方法将对话框单元<->像素转换为<->。GetTextMetrics
或 GetTextExtentPoint32
无对话框HWND。