TL;DR The direct answer to your question is 8
.
The goodwilled answer is to use NONCLIENTMETRICS.lfMessageFont
, as it is, and don't change anything about it (except DPI-scaling the lfHeight
, if you decide to do that yourself instead of using SystemParametersInfoForDpi
).
TL;DR End.
To answer the question about the point size of "The Default Font", note first that there are multiple possible definitions of what The Default Font could be, and the definition you chose is "the DS_SHELLFONT
definition".
Then question becomes, in the dialog template, what point size goes in the FONT
statement (this is the same concept regardless of whether the dialog was built with an .rc file, or in code):
STYLE DS_SHELLFONT | ...
FONT <WHAT GOES HERE?>, "MS Shell Dlg", 0, 0, 0x1
[...]
Here are some things you need to know:
- There's no good answer because Microsoft screwed up.
DS_SHELLFONT
causes MS Shell Dlg
to be replaced with MS Shell Dlg 2
upon dialog creation (i.e. somewhere in the whole CreateDialog
call chain).
MS Shell Dlg 2
maps to Tahoma
using FontSubstitutes
in the registry, regardless of locale. That has been the case for its entire existence, and that will probably never change, at least not in the foreseeable future.
- Everyone else uses 8 because it's the default in Visual Studio.
- Windows built-in dialogs don't use
DS_SHELLFONT
. For each locale, they use a specific font face and font size that is appropriate for that locale, hard coded in the locale's MUI resource files (they have a handcrafted dialog template for each language). For western systems, the font is MS Shell Dlg
8pt. This may give you the false impression that MS Shell Dlg
is universally applicable (since it's a registry mapped pseudo-font), and that you can distribute a program that uses it at a fixed size of 8pt internationally. But no. On Japanese systems for example, the thing that's hard-coded into the dialog templates is MS UI Gothic
, 9pt (note that it is not MS Shell Dlg
even though on a Japanese system that would have been mapped to MS UI Gothic
). If you had used MS Shell Dlg
8pt here, it would have been substituted to MS UI Gothic
8pt, which is simply too small for Japanese text. The exact details are more complicated and beyond the scope of this answer.
- Some of the replacement fonts for
MS Shell Dlg
are so bad (e.g. MS UI Gothic
) that even latin text looks awful at 8pt - it's only usable at 9pt.
- WinForms applications (.NET Framework <= 4.8) use
GetStockObject(DEFAULT_GUI_FONT)
, which returns a HFONT
with MS Shell Dlg
. .NET >= 5 uses NONCLIENTMETRICSW.lfMessageFont
. So if you want your thing to blend in here, DS_SHELLFONT
is not the way to go either way.
So basically, using MS Shell Dlg
, hardcoded at 8pt, without DS_SHELLFONT
, is an error, regardless of what you're doing. It only works out if you know basically already know exactly that it's going to be replaced with a font which is compatible with the specific script you are using in your text, at a point size of 8pt.
MS Shell Dlg
without DS_SHELLFONT
leaves another issue: If your application is in some Western language, and you are lucky that MS Shell Dlg
does indeed resolve to a font that works at 8pt with Western script, but the user decides to enter Chinese or Japanese text into a text box, then the text in the text box will be too small. Font fallback estimates font sizes according to the font height in pixels, which is not always appropriate. You would have to change the font according to what script is being entered, which is not something anybody wants to do because it would require exhaustive research of all possible languages. (Coincidentally, this is also a huge blunder in CSS, which allows you to define fallback font faces, but not the fallback font sizes.)
If DS_SHELLFONT
is set, both of these problems just happen to be alleviated in practice:
- Because Tahoma at 8pt is good for Western scripts.
- Because the default font fallback for Tahoma tends to behave better (it just happens to be bigger).
In principle, MS Shell Dlg 2
has the same problem as MS Shell Dlg
, in that theoretically it could be mapped to a font which requires a different size to be displayed correctly. But because MS Shell Dlg 2
likely always will be Tahoma
, and because basically every dialog created with the dialog editor in Visual Studio defaulting to size 8, it is most likely safe to assume that Microsoft will never break this. So the font you want to put there is MS Shell Dlg
, 8pt, and DS_SHELLFONT
will translate that to, effectively, Tahoma
8pt. That 8
is hard-coded in practically everyone's dialog template.
What do I mean by "Microsoft screwed up"? Well we shouldn't be in this complicated situation. Basically by using a dynamic pseudo-font like MS Shell Dlg 2
you're saying I'm totally ready for the default font to change any minute now, and if it does, I'll still blend in with all the cool kids who used the correct defaults! But the truth is, you didn't use anything like a default font. You only used some default font face. If some Windows GUI designer ever did decide that it was time to change the default font for all applications, it would be important that they also have control over font size, weight, and style. The current system doesn't allow for that. Fonts are finicky, the individual characters of Segoe UI 9pt look more like those of a typical 8pt font, for example (Segoe UI is barely readable at 8pt). Not to mention that it wouldn't work anyway because Microsoft themselves hard-coded specific fonts for specific locales into their dialogs.
Which is why NONCLIENTMETRICSW.lfMessageFont
is recommended everywhere now. It does allow exactly what a hypothetical Microsoft GUI designer would want. And you don't have to guess what the correct font size, weight, and style is. Only problem is, you can't put that in a dialog template, so it requires manual programming. But beware that it doesn't necessarily solve the problem of having a user enter foreign text in a text box -- Segoe UI, just like Tahoma, just happens to behave more nicely with font fallback so in practice it shouldn't be an issue anymore.
On a final note: If your program is not localized at all, it might be a better idea to hard-code a concrete font that looks good in English. Be it Microsoft Sans Serif
, or Tahoma
, or Segoe UI
. That makes layout easier (you don't have to accomodate for the wildest font metric differences on different systems and user settings, etc.), and you can use the dialog template designer as-is. And it ensures that your beautiful English text doesn't get utterly defaced by the default MS Shell Dlg
font on, say, a Chinese PC (it's really bad, man).