netlib.narod.ru | < Назад | Оглавление | Далее > |
FontFamily имеет еще одно статическое свойство и еще один статический метод. Они схожи и очень важны. Оба возвращают набор объектов FontFamily, соответствующий установленным в системе шрифтам TrueType и OpenType:
Статические свойства FontFamily (выборочно)
Тип | Свойство | Доступ |
FontFamily[] | Families | Чтение |
Если выполнить инструкцию
FontFamily[] aff = FontFamily.Families;
каждый элемент массива aff будет объектом FontFamily. Если вам доводилось сталкиваться с перечислением шрифтов в программах Win32 API, вы оцените простоту такого подхода.
Этот массив позволяет легко получить список доступных шрифтов и вывести на внешнее устройство образцы текста с этими шрифтами:
NaiveFamiliesList.cs
//-------------------------------------------------- // NaiveFamiliesList.cs (C) 2001 by Charles Petzold //-------------------------------------------------- using System; using System.Drawing; using System.Windows.Forms; class NaiveFamiliesList: PrintableForm { public new static void Main() { Application.Run(new NaiveFamiliesList()); } public NaiveFamiliesList() { Text = "Naive Font Families List"; } protected override void DoPage(Graphics grfx, Color clr, int cx, int cy) { Brush brush = new SolidBrush(clr); float y = 0; FontFamily[] aff = FontFamily.Families; foreach (FontFamily ff in aff) { Font font = new Font(ff, 12); grfx.DrawString(ff.Name, font, brush, 0, y); y += font.GetHeight(grfx); } } }
Инструкция foreach перебирает все элементы FontFamily. Для каждого элемента конструктор Font создает 12-пунктный шрифт, DrawString использует его для вывода на монитор названия гарнитуры, a GetHeight готовит вертикальные координаты для вывода следующей строки.
Эта программа может не работать на некоторых компьютерах. На моем конструктор Font генерирует исключение для самой первой гарнитуры массива.
К ошибке приводит файл шрифта Ahronbd.ttf, который устанавливается с дистрибутивного диска Windows 2000 для поддержки гарнитуры Hebrew. Он содержит шрифт Aharoni Bold, единственный шрифт гарнитуры Aharoni (по крайней мере в Windows 2000). Это значит, что следующая инструкция будет работать
font = new Font("Aharoni", 12, FontStyle.Bold)
А эта
font = new Font("Aharoni", 12)
не будет, так как она равносильна
font = new Font("Aharoni", 12, FontStyle.Regular)
а шрифт Aharoni с нормальным начертанием не реализован. (Вот лентяи!)
Эту проблему можно решить двумя способами. Первый — использовать конструкции try и catch. Поместите код из предыдущего цикла foreach в блок try. В блоке catch выведите название гарнитуры, из-за которой возникают проблемы, со знаком «звездочка», используя свойство формы Font:
foreach (FontFamily ff in aff) { try { Font font = new Font(ff, 12); grfx.DrawString(ff.Name, font, brush, 0, y); y += font.GetHeight(grfx); } catch { grfx.DrawString("* " + ff.Name, Font, brush, 0, y); у += Font.GetHeight(grfx); } }
Вместе с тем лучше не использовать блоки try и catch, если есть другие способы. В нашем случае альтернативный подход состоит в применении метода IsStyleAvailable класса FontFamily. Вот лучшее решение задачи, которое работает независимо от того, установлен ли шрифт Aharoni Bold.
BetterFamiliesList.cs
//--------------------------------------------------- // BetterFamiliesList.cs (C) 2001 by Charles Petzold //--------------------------------------------------- using System; using System.Drawing; using System.Windows.Forms; class BetterFamiliesList: PrintableForm { public new static void Main() { Application.Run(new BetterFamiliesList()); } public BetterFamiliesList() { Text = "Better Font Families List"; } protected override void DoPage(Graphics grfx, Color clr, int cx, int cy) { Brush brush = new SolidBrush(clr); float y = 0; FontFamily[] aff = FontFamily.Families; foreach (FontFamily ff in aff) { if (ff.IsStyleAvailable(FontStyle.Regular)) { Font font = new Font(ff, 12); grfx.DrawString(ff.Name, font, brush, 0, y); y += font.GetHeight(grfx); } else { grfx.DrawString("* " + ff.Name, Font, brush, 0, y); y += Font.GetHeight(grfx); } } } }
Если у вас установлено большое количество шрифтов, этот подход не позволит вам увидеть все шрифты, даже на большом мониторе или на распечатке.
Если не рассматривать полосы прокрутки, правильнее сформатировать список в колонки. Следующая программа так и работает. А если и этого не хватит для вывода всех шрифтов, попробуйте изменить поле iPointSize на 10, 8 или 6.
FamiliesList.cs
//--------------------------------------------- // FamiliesList.cs (C) 2001 by Charles Petzold //--------------------------------------------- using System; using System.Drawing; using System.Windows.Forms; class FamiliesList: PrintableForm { const int iPointSize = 12; public new static void Main() { Application.Run(new FamiliesList()); } public FamiliesList() { Text = "Font Families List"; } protected override void DoPage(Graphics grfx, Color clr, int cx, int cy) { Brush brush = new SolidBrush(clr); float x = 0, y = 0, fMaxWidth = 0; FontFamily[] aff = GetFontFamilyArray(grfx); foreach (FontFamily ff in aff) { Font font = CreateSampleFont(ff, iPointSize); SizeF sizef = grfx.MeasureString(ff.Name, font); fMaxWidth = Math.Max(fMaxWidth, sizef.Width); } foreach (FontFamily ff in aff) { Font font = CreateSampleFont(ff, iPointSize); float fHeight = font.GetHeight(grfx); if (y > 0 && y + fHeight > cy) { x += fMaxWidth; y = 0; } grfx.DrawString(ff.Name, font, brush, x, y); y += fHeight; } } protected virtual FontFamily[] GetFontFamilyArray(Graphics grfx) { return FontFamily.Families; } Font CreateSampleFont(FontFamily ff, float fPointSize) { if (ff.IsStyleAvailable(FontStyle.Regular)) return new Font(ff, fPointSize); else if (ff.IsStyleAvailable(FontStyle.Bold)) return new Font(ff, fPointSize, FontStyle.Bold); else if (ff.IsStyleAvailable(FontStyle.Italic)) return new Font(ff, fPointSize, FontStyle.Italic); else return Font; } }
В методе DoPage два цикла foreach. В первом определяется ширина названия каждой гарнитуры с соответствующим шрифтом и запоминается максимальная ширина. Второй цикл использует эту величину для построения колонок.
Обратите внимание на метод CreateSampleFont в конце тела класса. Я применяю его в методе DoPage вместо конструктора Font. CreateSampleFont с помощью метода IsStyleAvailable определяет, какое использовать начертание — нормальное, курсивное или полужирное. Это позволяет вывести на экран образец текста со шрифтом Aharoni, тогда как предыдущая программа не могла этого сделать. Вот результат работы программы на моем компьютере:
Если у вас установлены некоторые восточные шрифты, то вы заметите, что межстрочный интервал слишком большой для отображаемого текста. Это вызвано тем, что такие шрифты разработаны для вывода алфавитов, отличных от латинского.
В программе FamiliesList инструкция, получающая массив объектов FontFamily изолирована в небольшом методе, который я назвал GetFontFamilyArray. Это сделано для того, чтобы в следующей программе мне было проще продемонстрировать использование единственного статического метода, реализованного в FontFamily. Этот метод очень похож на свойство Families, за исключением наличия аргумента типа Graphics.
Статический метод FontFamily
FontFamily[] GetFamilies(Graphics grfx) |
Идея здесь в том, что для различных графических устройств вывода могут быть установлены различные шрифты; в частности, у некоторых принтеров есть встроенные шрифты, которые не могут быть отображены на экране. Следующая программа переопределяет метод GetFontFamilyArray, чтобы получать массив гарнитур из GetFamilies, а не из Families.
GetFamiliesList.cs
//------------------------------------------------ // GetFamiliesList.cs (C) 2001 by Charles Petzold //------------------------------------------------ using System; using System.Drawing; using System.Windows.Forms; class GetFamiliesList: FamiliesList { public new static void Main() { Application.Run(new GetFamiliesList()); } public GetFamiliesList() { Text = "Font GetFamilies List"; } protected override FontFamily[] GetFontFamilyArray(Graphics grfx) { return FontFamily.GetFamilies(grfx); } }
Для моего принтера GetFamilies возвращает тот же самый массив, что и Families. Возможно, в будущих версиях Windows Forms мы увидим более развернутую поддержку принтерных шрифтов.
netlib.narod.ru | < Назад | Оглавление | Далее > |