Microsoft uses dialog length units (DLU) in their guidelines for UI. How can I convert them into pixels?
As I know, DLU depending on system font size. Can you advise some simple method of such conversion in Delphi for Win32?
First we start with what a dialog unit is.
For that i'll quote one of my own un-answered questions:
What's a dialog unit?
A dialog is a unit of measure based on the user's preferred font size. A dialog unit is defined such that the average character is 4 dialog units wide by 8 dialog units high:
This means that dialog units:
- change with selected font
- changed with selected DPI setting
- are not square
i'll also quote another of my own un-answered questions:
You can check the Windows UX Guidelines to see where these measurements come from. The short version is:
- dlu = dialog unit
- dlu is based on the font size (items change with user's font size)
- a horizontal dlu is different from a vertical dlu (dlu's are not square)
This comes from the definition of a dialog unit: the average character is 8dlus high by 4dlus wide.
Georgia 14pt:
If you use a smaller font (i.e. 8pt Tahoma verses 14pt Georgia), the dlus get smaller:
Segoe UI 9pt:
Note: You'll notice that resolution (i.e. dpi) has no impact on the discussion.
So what you need is the average size of a character. Microsoft has an official technique for calculating the average character size.
average height:
GetTextMetrics(dc, {var}textMetrics);
averageHeight := textMetrics.tmHeight;
average width:
Measure the string ABCDEFGHIJLKMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz using GetTextExtentPoint32
, and divide by 52:
GetTextExtentPoint32(dc,
PChar('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'), 52, Size));
averageWidth := size.cx / 52.0;
So now you need the the size of a horizontal and a vertical dialog units. Remember that a horizontal dialog unit is 1/4 the average character width, and a vertical dlu is 1/8 the average character height:
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;
Note: Any code is released into the public domain. No attribution required.