How do I get all installed fixed-width fonts?
Asked Answered
B

3

18

I'm wondering if there are any simple ways to get a list of all fixed-width (monospaced) fonts installed on a user's system in C#?

I'm using .net 3.5 so have access to the WPF System.Windows.Media namespace and LINQ to get font information, but I'm not sure what I'm looking for.

I want to be able to provide a filtered list of monospaced fonts and/or pick out monospaced fonts from a larger list of fonts (as seen in the VS options dialog).

Bullhorn answered 22/10, 2008 at 8:26 Comment(1)
H
13

Have a look at:

http://www.pinvoke.net/default.aspx/Structures/LOGFONT.html

Use one of the structures in there, then loop over families, instantiating a Font, and getting the LogFont value and checking lfPitchAndFamily.

The following code is written on the fly and untested, but something like the following should work:

foreach (FontFamily ff in System.Drawing.FontFamily.Families)
{
    if (ff.IsStyleAvailable(FontStyle.Regular))
    {
        Font font = new Font(ff, 10);
        LOGFONT lf = new LOGFONT();
        font.ToLogFont(lf);
        if (lf.lfPitchAndFamily ^ 1)
        {
            do stuff here......
        }
    }
}
Hoarse answered 22/10, 2008 at 9:31 Comment(1)
lfPitchAndFamily doesn't work (always zero) and (lf.lfPitchAndFamily ^ 1) gives an error (CS0029: Cannot implicitly convert type 'int' to 'bool')Segno
T
7

Unfortunately ToLogFont function does not fill lfPitchAndFamily field to correct values. In my case it's always 0.

One approximation to detect which fonts might be fixed is the following

    foreach ( FontFamily ff in FontFamily.Families ) {
            if ( ff.IsStyleAvailable( FontStyle.Regular ) ) {
                float diff;
                using ( Font font = new Font( ff, 16 ) ) {
                    diff = TextRenderer.MeasureText( "WWW", font ).Width - TextRenderer.MeasureText( "...", font ).Width;
                }
                if ( Math.Abs( diff ) < float.Epsilon * 2 ) {
                    Debug.WriteLine( ff.ToString() );
                }
            }

        }

Keep in mind that they are several false positives, for example Wingdings

Telencephalon answered 17/12, 2011 at 13:18 Comment(2)
Way too hacky and prone to false positives (as you mentioned) :(Segno
Whilst hacky if you just want to run it once for a debug output it is quite useful.Hypocoristic
T
6

AFAIK you can't do it using BCL libraries only. You have to use WinAPI interop.

You need to analyze 2 lowest bits of LOGFONT.lfPitchAndFamily member. There is a constant FIXED_PITCH (means that font is fixed-width) that can be used as a bit mask for lfPitchAndFamily.

Here is a useful article:

Enumerating Fonts

Enumerating fonts can be a little confusing, and unless you want to enumerate all fonts on your system, can be a little more difficult than MSDN suggests. This article will explain exactly the steps you need to use to find every fixed-width font on your system, and also enumerate every possible size for each individual font.

Turnkey answered 22/10, 2008 at 8:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.