Пропустить навигацию.
Главная

Просмотр системных шрифтов

Набор системных шрифтов состоит из совокупности ttf-файлов, зарегистрированных в операционной системе. На разных компьютерах он, естественно, разный, т.к. к шрифтам, подключаемым при установке операционной системы, добавляются шрифты других пакетов программ. Например, установка CorelDraw обычно сопровождается регистрацией большого количества шрифтов, используемых дизайнерами.

Существует большое количество разных приложений, демонстрирующих полный набор символов выбранного шрифта или какой-либо его фрагмент. На примерах некоторых из них, частично заимствованных из других источников или слегка переработанных, частично — оригинальных, мы продемонстрируем особенности работы с некоторыми компонентами визуальных сред и средства управления шрифтами.

Приложение 4_14 (BCB). Прорисовка списков, выполняемая программой пользователя.

Идея этого примера заимствована из приложения Examples\Apps\OwnerLst, поставляемого в составе Builder C++ Borland. Для списков типа ListBox, используемых в стандартном режиме (Style=Standard), перерисовка списка происходит автоматически при внесении в список каких-либо изменений (добавка, удаление, перестановка или прокрутка строк). При этом для текстов всех строк действует общая установка параметров шрифта, сделанная либо во время проектирования, либо модифицированная во время работы приложения. Параметры шрифта, раскрывающиеся при щелчке по кнопочке со знаком плюс слева от свойства Font, включают следующие характеристики:

  • Charset — набор символов, характерных для используемого стандарта, производителя компьютерной техники или страны (ANSI_CHARSET, OEM_CHARSET, RUSSIAN_CHARSET, ARABIC_CHARSET и др.). По умолчанию действует набор DEFAULT_CHARSET, совпадающий с кодовой страницей операционной системы.
  • Color — числовой код, обычно задаваемый в шестнадцатеричной системе и определяющий интенсивности RGB-компонент цвета контуров символов.
  • Height — высота шрифта в пикселах, представленная положительным или отрицательным числом.
  • Name — строка с наименованием шрифта, зарегистрированным в операционной системе. Имя шрифта может включать пробелы.
  • Pitch — свойство, управляющее шириной букв и принимающее одно из трех значений fpDefault, fpVariable, или fpFixed. В файле каждого ttf-шрифта присутствует таблица, задающая ширину любого символа. Большинство ttf-шрифтов относятся к пропорциональным шрифтам, для которых каждый символ имеет индивидуальную ширину (например — узкая буква I, широкая W). При pitch=fpDefault действуют указания о ширине букв, заложенные в ttf-файл. Значения fpVariable заставляет системную программу отображения текстов использовать переменную ширину букв даже в том случае, когда используемый шрифт относится к моноширинным. Значение fpFixed, наоборот, располагает все символы в прямоугольниках равной ширины. Без особой нужды не стоит противопоставлять значение этого свойства параметрам, зашитым в ttf-файле.
  • Size — высота шрифта в пунктах (1 пункт = 1/72 дюйма = 0.3528 мм).

Свойства Height и Size связаны между собой отношением:

Height = - Size * PixelPerInch / 72

Большинству пользователей по аналогии с работой в редакторах типа MS Word привычнее задавать высоту надписи в пунктах. Знак высоты влияет на размер букв таким образом, что в одном случае междустрочный интервал добавляется к высоте буквы, а в другом случае — не добавляется. На форме, приведенной на рис. 4.16, расположены 2 списка типа ListBox. В каждом из них набрано по одной строке из нескольких букв «I».

Работа со списками

Рис. 4.16. Слева Size=-54, справа Size=54

Для того чтобы сформировать в списке перечень всех шрифтов, зарегистрированных в системе, надо воспользоваться свойством Fonts системного объекта Screen:

ListBox1->Items = Screen->Fonts;

Если такое присвоение выполнить во время работы приложения, то в списке ListBox1 немедленно появятся имена всех системных шрифтов в алфавитном порядке, поскольку системный список упорядочен. Однако индивидуальность каждого шрифта при этом пропадет, т.к. все имена отображаются одним и тем же шрифтом, приписанным к свойству Font->Name объекта ListBox1 (рис. 4.17).

Работа со списками

Рис. 4.17. Список шрифтов в режиме lbStandard

Приложение 4_15 (BCB).

Для того чтобы каждая строка списка ListBox1 отображалась своим шрифтом, придется написать процедуру воспроизведения элемента списка — DrawItem, и предупредить об этом систему. Последнее заключается в изменении свойства Style, которому можно назначить один из двух дополнительных режимов — lbOwnerDrawFixed или lbOwnerDrawVariable. Первый из этих режимов означает, что высота каждой строки будет фиксированной, а второй — разрешает каждой строке иметь индивидуальную высоту.

Начнем с простейшего — Style= lbOwnerDrawFixed. Высоту строк в списке регулирует свойство ItemHeight, и мы установим его значение, равным 20 пикселам. Для перерисовки очередной наблюдаемой на экране строки списка система обращается к процедуре обработки события OnDrawItem:

void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control,

int Index,Rect &Rect,TOwnerDrawState State)

{

AnsiString s=ListBox1->Items->Strings[Index];

ListBox1->Canvas->FillRect(Rect);

ListBox1->Canvas->Font->Name = s;

ListBox1->Canvas->TextOut(Rect.Left,Rect.Top,s.c_str());

}

Процедура ListBox1DrawItem получает указатель на объект-инициатор события OnDrawItem (Control), ссылку на прямоугольник (Rect), в котором должно быть построено содержимое очередной строки с номером Index и информацию о состоянии строки (State). Последняя может быть выделена, находиться в фокусе, иметь серый вид (Grayed) и т.п.

Работа со списками

Рис. 4.18. Список шрифтов в режиме lbOwnerDrawFixed

Первый оператор обработчика запоминает значение строки, совпадающее с именем шрифта, в переменной типа AnsiString. Это сделано для сокращения текста программы, т.к. текст воспроизводимой строки в дальнейшем потребуется дважды. Второй оператор обращается к методу FillRect для очистки прямоугольника, расположенного на канве нашего списка. Подробнее о свойстве Canvas речь пойдет в разделе о графических возможностях визуальных сред. В третьем операторе имя шрифта присваивается свойству Font канвы списка (его не надо путать со свойством Font самого списка). Последний оператор вызывает метод TextOut для отображения текста s, начиная с точки (x=Rect.Left, y=Rect.Top). Этот метод очень напоминает функцию outtextxy, знакомую нам по библиотеке графических процедур BGI в системах программирования TP и BC. Обратите внимание на третий аргумент метода. Т.к. переменная s имеет тип AnsiString, то ее надо преобразовать к типу (char *), что выполняется с помощью метода c_str().

Результат работы приложения, содержащего два обработчика событий — Button1Click для загрузки списка системных шрифтов в ListBox1 и только что описанную процедуру отрисовки элемента списка, показан на рис. 4.18.

Приложение 4_16 (BCB).

А теперь немного усложним задачу тем, что заставим список воспроизводить каждую строку тем размером букв, который заложен в ttf-файл. Очевидно, что каждый разработчик шрифта по-своему определяет высоту символов по умолчанию. Поэтому нам придется иметь дело с разновысокими строками. Установим значение свойства Style равным lbOwnerDrawVariable и напишем следующий обработчик события OnMeasureItem:

void __fastcall TForm1::ListBox1MeasureItem(TWinControl *Control,

int Index, int &Height)

{

ListBox1->Canvas->Font->Name = ListBox1->Items->Strings[Index];

ListBox1->Canvas->Font->Size = 0;

Height = ListBox1->Canvas->TextHeight("H")+2;

}

Первый оператор копирует имя шрифта из строки списка в свойство Font канвы. Второй оператор делает, казалось бы, нелепую вещь, устанавливая высоту шрифта канвы равной 0. Однако, это — небольшая хитрость, почти нигде не описанная. В случае такого задания высоты фактический размер шрифта извлекается из ttf-файла. Последний оператор с помощью предшествовавшего таинства определяет высоту текста, обращаясь к методу TextHeight со строкой, содержащей единственную букву. А добавка (+2) позволяет разумно сформировать интервалы между содержимым смежных строк.

Немного изменяется и текст обработчика события OnDraweItem. С учетом приведенного выше секрета строки с нулевой высотой остальные действия обработчика в дополнительных комментариях не нуждаются:

void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control,

int Index, TRect &Rect, TOwnerDrawState State)

{ AnsiString s=ListBox1->Items->Strings[Index];

ListBox1->Canvas->FillRect(Rect);

ListBox1->Canvas->Font->Name = s;

ListBox1->Canvas->Font->Size=0;

ListBox1->Canvas->TextOut(Rect.Left+1,Rect.Top+1,s.c_str());

}

Результат работы этого приложения приведен на рис 4.19.

Работа со списками

Рис. 4.19. Список шрифтов в режиме lbOwnerDrawVariable

Приложение 4_17 (BCB).

Небольшая модификация приложения, заключающаяся в добавке двух объектов Label1 с заголовком «Выделенный шрифт» и Label2 для содержимого выделенной строки списка, позволит получить более полную информацию о наименованиях просматриваемых шрифтов. Дело в том, что некоторые из них не содержат букв и вместо названий шрифтов в списке фигурируют не очень понятные цепочки геометрических фигур (рис. 4.20). Полный текст соответствующего приложения приведен ниже.

void __fastcall TForm1::Button1Click(TObject *Sender)

{

ListBox1->Items=Screen->Fonts;

}

//-------------------------------------------------------------------

void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control,

int Index, TRect &Rect, TOwnerDrawState State)

{ AnsiString s=ListBox1->Items->Strings[Index];

ListBox1->Canvas->FillRect(Rect);

ListBox1->Canvas->Font->Name = s;

ListBox1->Canvas->Font->Size=0;

ListBox1->Canvas->TextOut(Rect.Left+1,Rect.Top+1,s.c_str());

}

//-------------------------------------------------------------------

void __fastcall TForm1::ListBox1MeasureItem(TWinControl *Control,

int Index, int &Height)

{ ListBox1->Canvas->Font->Name = ListBox1->Items->Strings[Index];

ListBox1->Canvas->Font->Size = 0;

Height = ListBox1->Canvas->TextHeight("H")+2;

}

//-------------------------------------------------------------------

void __fastcall TForm1::ListBox1Click(TObject *Sender)

{ Label2->Caption=ListBox1->Items->Strings[ListBox1->ItemIndex];

}

Работа со списками

Рис. 4.20. Список шрифтов с расшифровкой их имен

Приложение 4_18 (BCB). Просмотр всех символов выделенного шрифта.

Иногда у программиста возникает желание поподробнее рассмотреть все символы того или иного шрифта с заданной высотой букв. Ниже приводится пример одного из возможных вариантов такого приложения.

Для его работы понадобится текстовый файл ascii.txt, содержащий несколько строк с числовыми кодами символов от 32 до 255. Этот файл загружается в объект Memo1 для того, чтобы каждый числовой код был заменен соответствующим символом выбранного шрифта. Такой файл может быть изготовлен программным путем, например, с помощью приведенной ниже программы ascii.cpp:

#include <stdio.h>

main()

{

FILE *f1;

int j;

f1=fopen("ascii.txt","wb");

for(j=32;j<256;j++)

{

if((j+1)%32 != 0)

fprintf(f1,"%c",j);

else

fprintf(f1,"%c",0x0A);

}

fclose(f1);

}

В конструкторе приложения (чтобы не заводить лишний обработчик события, например, OnCreate) производятся начальные установки — перечень зарегистрированных в системе шрифтов загружается в список ListBox1, индекс выделяемой строки устанавливается в начало списка, производится загрузка текстового файла ascii.txt в объект Memo1 и назначается начальная высота шрифта.

Для удобства просмотра в списке ListBox1 использован многоколонный режим отображения (Columns=4) и этот список снабжен горизонтальной линейкой прокрутки. Из таких же соображений записная книжка помещена на объект ScrollBox, снабженный линейками прокрутки.

Кнопка UpDown, ассоциированная с окном Edit1, предназначена для задания высоты отображаемых символов в диапазоне от 8 до 72 пунктов с шагом 1.

В момент щелчка по выделяемому шрифту производится замена свойства Font->Name в Memo1 и установка начальной высоты символов, после чего содержимое Memo1 автоматически перерисовывается.

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)

{

ListBox1->Items=Screen->Fonts;

ListBox1->ItemIndex=0;

Memo1->Lines->LoadFromFile("ascii.txt");

}

//----------------------------------------------------------------

void __fastcall TForm1::ListBox1Click(TObject *Sender)

{

Memo1->Font->Name=ListBox1->Items->Strings[ListBox1->ItemIndex];

}

//------------------------------------------------------------------

void __fastcall TForm1::UpDown1Click(TObject *Sender,

TUDBtnType Button)

{

Memo1->Font->Size=UpDown1->Position;

}

Пример работы приложения показан на рис. 4.21.

Работа со списками

Рис. 4.21. Просмотр символов шрифта Times New Roman

Более увлекательное зрелище открывается при просмотре специальных шрифтов (рис. 4.22)

Работа со списками

Рис. 4.22. Просмотр символов шрифта Wingdings