【问题标题】:How to convert a delphi form's width and height pixels into dialog units?如何将 delphi 表单的宽度和高度像素转换为对话框单位?
【发布时间】:2018-03-11 13:56:52
【问题描述】:

我正在尝试将 Delphi 表单的宽度和高度像素计算为准确的对话框单元,以创建使用 DIALOGEX 语句的 .rc(资源脚本)文件。到目前为止,我还无法使用此处描述的 Microsoft 公式计算正确的对话单元:https://support.microsoft.com/en-us/help/145994/how-to-calculate-dialog-box-units-based-on-the-current-font-in-visual

以上链接使用GetDialogBaseUnits Win32 API 调用,但这不起作用,因为该API 函数使用系统字体。所以这是没用的。甚至微软也说我们应该改用MapDialogRect。因此,使用此处提供的公式来计算非系统字体的对话框基本单位https://support.microsoft.com/en-us/help/125681/how-to-calculate-dialog-base-units-with-non-system-based-font

1 horz 对话框基本单位 == (2 * 平均字符宽度对话框字体 / 平均字符宽度系统字体)像素

1 vert 对话框基本单位 == (2 * 平均字符高度对话框字体 / 平均字符高度系统字体)像素

我尝试过这样的事情:

  xPixels := 200
  yPixels := 50;

  dc := GetDC(0);

  SelectObject(dc,handle);  // handle := f.Font.Handle  (f := TForm created)
  if not GetTextMetrics(dc, tm) then
    ShowMessage('Error');
  avgHeight := tm.tmHeight / 8.0;

  GetTextExtentPoint32(dc,
       PChar('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'), 52,
       size);
  avgWidth := size.cx / 52.0;

  avgSysWidth := 5;   // Made up value, how to calculate?
  avgSysHeight := 1;  // Made up value, how to calculate?

  horzPixels := Round(2 * 1 * (avgWidth / avgSysWidth));
  vertPixels := Round(2 * 1 * (avgHeight / avgSysHeight));

  HorizontalDialogBaseUnit := Round(xPixels / horzPixels);
  VerticalDialogBaseUnit := Round(yPixels / vertPixels);

请注意,handle 来自创建的表单字体句柄。 avgSysWidthavgSysHeight 我不确定如何获得这些值。

我已经看了两天了,似乎找不到最简单的进入对话单元的方法。我完全没有了?

更新 2: 我的更新功能:

// xPixesl := 400
// yPixels := 200
procedure Tdm.GetDlgBaseUnits(handle: HWND; xPixels, yPixels: integer; out HorizontalDLUs, VerticalDLUs: integer);
var
  dc: HDC;
  tm: TTextMetric;
  size: TSize;
  avgWidth, avgHeight: real;
  VerticalDlu, HorizontalDlu: real;
//  DialogUnits: Cardinal;
begin
//  DialogUnits := GetDialogBaseUnits;
  dc := GetDC(0);

  SelectObject(dc,handle);
  GetTextMetrics(dc, tm);
  avgHeight := tm.tmHeight;

  GetTextExtentPoint32(dc,
       PChar('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'), 52,
       size);
  avgWidth := size.cx / 52.0;

  HorizontalDLUs := Round( (4 * xPixels) / avgWidth );
  VerticalDLUs := Round( (8 * yPixels) / avgHeight );

//  HorizontalDLUs := Round( (xPixels / (avgWidth * LOWORD(DialogUnits))));
//  VerticalDLUs := Round( (yPixels / (avgHeight * HIWORD(DialogUnits))));
end;

给定一个 400z200 像素的形式,上述函数产生 269 x 123 个 DLU。这是表格的图片。左边是设计的 400x200 像素的表格,右边是根据以下内容制作和创建的表格:

DesignForm DIALOGEX 0, 0, 269, 123
STYLE  WS_CAPTION | WS_SIZEBOX | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP
CAPTION "DesignForm"
CLASS "DLGCLASS"
FONT 8, "Tahoma"
{
} 

【问题讨论】:

  • 图片看起来不错,如果您认为对话框资源指定了 client 维度,并且 Delphi 表单为您提供了 window 坐标。跨度>
  • 啊,我完全错过了这个简单的事实。谢谢罗伯。我不敢相信我忽略了这个小细节。惊人的。我使用了表单的 ClientWidth 和 ClientHeight,现在它是一个完美的转换。你们摇滚!

标签: delphi winapi


【解决方案1】:
GetTextMetrics(dc, tm);
avgHeight := tm.tmHeight;

GetTextExtentPoint32(dc,
   PChar('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'), 52,
   size);
avgWidth := Round( size.cx / 52.0 );

HorizontalDLUs := Round( (4 * xPixels) / avgWidth );
VerticalDLUs := Round( (8 * yPixels) / avgHeight );

DLU 基于对话框字体的大小。水平 DLU 是对话框字体的平均宽度除以四。垂直 DLU 是字体高度除以 8。

另请参阅GetDialogBaseUnits function 中的备注部分,并推荐使用 MulDiv 功能。

【讨论】:

  • 我不得不删除水平和垂直数字的回合,因为它产生了不正确的结果。尽管如此,我还是必须将垂直对话框的基本单位乘以 10。我已经更新了我的问题以查看更新后的函数示例。
  • 您计算 avgHeight 的公式有误。不要除以 8,tm.tmHeight 是字体高度。如果您使用整数,则应使用比 DLU 更大的单位,因为舍入误差较高。使用基本对话单元女巫等于 4 x 8 dlu。基本对话单元是字体的平均大小。编辑了我的答案
  • @Dainiel,使用您更新的公式,创建的对话框仍然比原始表单大一点。我的 800 像素 x 400 像素样本形式产生 539 DLU x 246 DLU。显然,我猜这个表格的宽度和高度大约要大 40-50 像素。似乎还是有些不对劲。
  • 对话框模板中的宽度和高度指定客户端大小(无框架)。
  • 啊,我完全错过了这个简单的事实。谢谢丹尼尔和罗布。我不敢相信我忽略了这个小细节。惊人的。我使用了表单的 ClientWidth 和 ClientHeight,现在它是一个完美的转换。
【解决方案2】:

GetDialogBaseUnits 实际上并不是那么“无用”。它会告诉你系统字体的平均高度和宽度(以像素为单位):

avgSysWidth := LoWord(GetDialogBaseUnits);
avgSysHeight := HiWord(GetDialogBaseUnits);

【讨论】:

  • 谢谢罗伯。我之前确实使用过 GetDialogBasedUnits,但它对 DLU 的计算没有影响。
猜你喜欢
  • 2011-12-05
  • 2014-12-06
  • 2011-11-17
  • 1970-01-01
  • 2019-08-06
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
  • 1970-01-01
相关资源
最近更新 更多