I'm trying to calculate a Delphi form's width and height pixels into accurate dialog units to create a .rc (resource script) file that uses a DIALOGEX statement. So far, I have not been able to calculate the correct dialog units using Microsoft's formula described here: https://support.microsoft.com/en-us/help/145994/how-to-calculate-dialog-box-units-based-on-the-current-font-in-visual
The above link uses the GetDialogBaseUnits
Win32 API call but this does not work since that API function uses the system font. So this is useless. Even Microsoft says that we should use MapDialogRect
instead. So, using the formula provided here on how to calculate dialog base units with non-system-based fonts https://support.microsoft.com/en-us/help/125681/how-to-calculate-dialog-base-units-with-non-system-based-font
1 horz dialog base unit == (2 * average char width dialog font / average char width system font) pixels
1 vert dialog base unit == (2 * average char height dialog font / average char height system font) pixels
I have tried something like this:
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);
Note that handle
is from the created forms Font handle. The avgSysWidth
and avgSysHeight
I'm not sure how to get to those values.
I've been looking at this for two days and can't seem to see the simplest way to get to the dialog units. Am I completely off?
Update 2: My updated function:
// 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;
Given a 400z200 pixel form, the above function produces 269 by 123 DLUs. Here is a picture of the form. The left one is the designed form in 400x200 pixels and the right one is produced and created form based on:
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"
{
}
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 );
A DLU is based on the size of the dialog box font. A horizontal DLU is the average width of the dialog box font divided by four. A vertical DLU is the height of the font divided by eight.
Also see remarks section in GetDialogBaseUnits function with recomendation to use MulDiv function.
GetDialogBaseUnits
isn't actually so "useless." It will tell you the average height and width of the system font in pixels:
avgSysWidth := LoWord(GetDialogBaseUnits);
avgSysHeight := HiWord(GetDialogBaseUnits);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With