如何获取所有已安装的等宽字体?

18

我想知道在C#中是否有任何简单的方法来获取用户系统中安装的所有等宽字体(单间距字体)的列表?

我正在使用.net 3.5,因此可以访问WPF System.Windows.Media命名空间和LINQ以获取字体信息,但我不确定我要找什么。

我希望能够提供一个经过过滤的等宽字体列表和/或从较大的字体列表中挑选出等宽字体(如在VS选项对话框中看到的那样)。

3个回答

13

请看:

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

使用其中的一个结构,在字体族中循环,实例化字体,并获取 LogFont 值并检查 lfPitchAndFamily。

以下代码是即兴编写且未经测试的,但类似以下内容应该可以工作:

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......
        }
    }
}

4
lfPitchAndFamily 无效(始终为零),而 (lf.lfPitchAndFamily ^ 1) 出现错误(CS0029:无法隐式将类型 'int' 转换为 'bool')。 - Doc

6

很遗憾,ToLogFont函数无法正确填充lfPitchAndFamily字段的值。在我的情况下,它总是为0。

检测哪些字体可能是固定的一种近似方法如下:

    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() );
                }
            }

        }

请记住,有几种假阳性,例如 Wingdings。

1
太过于“hacky”,容易出现误报(正如你所提到的):( - Doc
虽然这种方法有些粗糙,但如果你只是想运行一次以获得调试输出,它还是非常有用的。 - rollsch

6
据我所知,仅使用BCL库无法完成此操作。您需要使用WinAPI互操作性。
您需要分析LOGFONT.lfPitchAndFamily成员的2个最低位。有一个常量FIXED_PITCH(表示字体是等宽的),可以用作lfPitchAndFamily的位掩码。
这是一篇有用的文章: 枚举字体

枚举字体可能有点棘手,除非您想枚举系统上的所有字体,否则可能比MSDN建议的更难。本文将解释您需要使用的确切步骤,以查找系统上的每种固定宽度字体,并枚举每个单独字体的每种可能大小。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接