如何将delphi表单的宽度和高度像素转换为对话框单元?

时间:2017-09-29 15:50:22

标签: delphi winapi

我试图将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来自创建的表单Font句柄。 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乘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"
{
} 

enter image description here

2 个答案:

答案 0 :(得分:3)

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是对话框字体的平均宽度除以4。垂直DLU是字体的高度除以8。

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

答案 1 :(得分:2)

GetDialogBaseUnits实际上并非如此"无用。"它将告诉您系统字体的平均高度和宽度(以像素为单位):

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