如何将DLU转换为像素?

问题描述 投票:9回答:3

微软在其用户界面指南中使用了对话框长度单位(DLU)。如何将其转换为像素?

据我所知,DLU取决于系统字体大小。您能不能提供一些简单的方法,在Delphi for Win32中进行这种转换?

delphi pixels units-of-measurement
3个回答
11
投票

你应该使用 MapDialogRect() 功能。

传入一个 RECT 对话单元中,以及相当于 RECT 以像素单位返回。 需要注意的是,您需要一个对话框的句柄,以便给您的 MapDialogRect() 足够的上下文。该函数需要知道字体才能进行转换。


如果你想使用 GetDialogBaseUnits(),记得陈雷蒙德说过的话。GetDialogBaseUnits是个垃圾。.

正如你从这篇文章的标题中可以猜到的,GetDialogBaseUnits是个垃圾。由于GetDialogBaseUnits没有HWND参数,它不知道你想检索哪个对话框的DLU。所以它就会猜测。

而且它总是猜错。

GetDialogBaseUnits会返回使用默认系统字体的对话框的对话框基本单位。但是现在已经没有人使用默认的系统字体了。它叫嚣着 "古老而呆板"。但由于兼容性的原因,它仍然是默认的。因此GetDialogBaseUnits也是如此)。

如果你必须从DLU计算像素尺寸,而且你没有一个对话框的句柄,那么你必须使用这里概述的方法。如何使用非系统型字体计算对话框基数单位


然而,您在评论中明确表示,对于您的问题,您实际上并不需要从DLU转换为像素。您可以使用Delphi内置的窗体缩放功能来确保您的窗体大小适合当前的字体缩放。


18
投票

首先,我们从以下几个方面入手 什么 一个对话单元是。

为此,我将引用一个 自问自答:

什么是对话框单位?

对话框是基于用户偏好的字体大小的计量单位。 对话框单位的定义是这样的 平均字符 是4个对话单元宽,8个对话单元高。

enter image description here

这意味着对话框单元:

  • 会随着字体的变化而变化
  • 随着所选DPI设置的改变而改变
  • 不方正

我还将引用另一个 自问自答:

你可以检查 Windows用户体验指南 来看看这些测量结果是怎么来的。 简而言之,就是

  • dlu = 对话单元
  • dlu是基于字体大小(项目会随着用户的字体大小而改变)
  • a 横向 Dlu不同于 纵向 dlu (凹凸不平)

这来自于对话单元的定义。平均字符高8dlus,宽4dlus。.

佐治亚州14pt.如果你使用较小的字体(即8pt的Tahoma与14pt的Georgia),dlus会变小::

enter image description here

如果你使用较小的字体(如8pt Tahoma与14pt Georgia),dlus会变小。

Segoe UI 9pt。

enter image description here

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;

注意:: 任何代码都会被发布到公共领域。不需要注明出处。


-4
投票

对于基本值(自然也包括系统字体),请调用 GetDialogBaseUnits. 另见 remarks 段,以替代方法将对话框单元<->像素转换为<->。GetTextMetricsGetTextExtentPoint32 无对话框HWND。

© www.soinside.com 2019 - 2024. All rights reserved.