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

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

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

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


person Nidonocu    schedule 22.10.2008    source источник


Ответы (3)


Посмотри на:

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

Используйте одну из структур, а затем перебирайте семейства, создавая экземпляр Font, получая значение 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......
        }
    }
}
person Tim Ebenezer    schedule 22.10.2008
comment
lfPitchAndFamily не работает (всегда ноль), а (lf.lfPitchAndFamily ^ 1) выдает ошибку (CS0029: Cannot implicitly convert type 'int' to 'bool') - person Doc; 04.09.2014

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

person Panos Theof    schedule 17.12.2011
comment
Слишком хакерский и склонный к ложным срабатываниям (как вы упомянули) :( - person Doc; 04.09.2014
comment
В то время как хаки, если вы просто хотите запустить его один раз для вывода отладки, это весьма полезно. - person rolls; 16.08.2019

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

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

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

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

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

person aku    schedule 22.10.2008