Как получить все установленные шрифты с фиксированной шириной?

Мне интересно, есть ли какие-либо простые способы получить список всех шрифтов с фиксированной шириной (моноширинность), установленных в пользовательской системе на С#?

Я использую .net 3.5, поэтому имею доступ к пространству имен WPF System.Windows.Media и LINQ, чтобы получить информацию о шрифтах, но я не уверен, что я ищу.

Я хочу иметь возможность предоставлять отфильтрованный список моноширинных шрифтов и/или выбирать моноширинные шрифты из большего списка шрифтов (как показано в диалоговом окне опций VS).

Ответы

Ответ 1

Посмотрите:

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

Ответ 2

К сожалению, функция 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

Ответ 3

AFAIK вы не можете сделать это, используя только библиотеки BCL. Вы должны использовать WinAPI-интерфейс.

Вам нужно проанализировать 2 младших бита LOGFONT.lfPitchAndFamily. Существует константа FIXED_PITCH (означает, что шрифт является фиксированной шириной), который может использоваться как бит-маска для lfPitchAndFamily.

Вот полезная статья:

Перечисление шрифтов

Перечисление шрифтов может быть немного путают, и если вы не хотите перечислить все шрифты в вашей системе, может быть немного сложнее, чем MSDN предлагает. Эта статья будет объясните, какие шаги вам нужно используйте, чтобы найти шрифт с фиксированной шириной на вашей системы, а также перечислять каждый возможный размер для каждого человека шрифт.