Не секрет, что своей популярностью операционная система Windows версии 3.1 во многом обязана использованной в ней технологии масштабируемых шрифтов True Type. Только с помощью этих шрифтов можно готовить документы на профессиональном уровне, выполнять верстку изданий и другую аналогичную работу.
Мы уже классификацировали шрифты Windows, поэтому вы знаете, что для приложений доступны растровые, векторные и масштабируемые шрифты (рис. 1.5 в первой главе). Кроме этого, приложения могут использовать шрифты, встроенные или загружаемые в устройство вывода, например, в принтер.
Растровые шрифты удобны для вывода текста на экран (особенно при малой высоте букв), однако для каждого видеорежима и типа контроллера используется свой набор растровых шрифтов.
Векторные шрифты используются в тех случаях, когда в качестве устройства вывода применяется плоттер. Более того, для вывода на плоттер можно использовать только векторные шрифты.
Однако подавляющее большинство компьютеров предназначено для подготовки текстовой и табличной информации, причем для печати используются матричные, струйные или лазерные принтеры. В этом случае приемлемое качество документа может быть получено только с использованием масштабируемых шрифтов (или, в некоторых случаях, с использованием принтерных шрифтов).
Масштабируемые шрифты True Type, доступные приложениям Windows, не только сохраняют свое начертание при произвольном изменении высоты букв, но и обладают другими достоинствами.
Отметим, например, возможность вывода строк текста, расположенных под любым углом относительно горизонтальной оси. Растровые и векторные шрифты позволяют располагать строки текста только в горизонтальном направлении, что может создать определенные трудности, например, при необходимости надписать название улицы на карте города.
Еще одно преимущество масштабируемых шрифтов True Type связано с тем, что вы можете встроить такой шрифт непосредственно в документ. Зачем это может понадобиться?
Дело в том, что стандартный набор шрифтов True Type, поставляемых в составе Windows, не всегда удовлетворяет пользователей. Поэтому они приобретают дополнительные шрифты у независимых разработчиков. Однако использование нестандартных шрифтов может привести к проблемам при необходимости переноса документа из одного компьютера в другие, так как там нужного шрифта может не оказаться. Вы, конечно, можете просто скопировать нужный шрифт и перенести его вместе с документом, однако такая процедура может быть запрещена по условию лицензионного соглашения с разработчиками шрифта.
Проблему переноса документа на другой компьютер с сохранением прав разработчиков шрифта можно решить, используя шрифты, встроенные в документ. Пользователь может, например, подготовить документ в текстовом процессоре Microsoft Word for Windows версии 6.0 и встроить в него все использованные шрифты. При переносе такого документа на другой компьютер эти шрифты можно будет использовать для просмотра и, возможно, редактирования этого (и только этого) документа. Возможность редактирования с использованием встроенного шрифта определяется разработчиком шрифта.
В этой главе вы узнаете о классификации шрифтов, принятой в операционной системе Windows, научитесь выбирать шрифт для вывода текста и определять параметры выбранного шрифта. Мы приведем пример приложения, которое выводит строку текста под заданным углом.
Перед тем, как двигаться дальше, нам необходимо уточнить некоторые понятия и термины, связанные со шрифтами.
Можно сказать, что шрифт состоит из изображений (рисунков) отдельных символов - глифов (glyph).
Для внутреннего представления глифа в файле шрифта True Type используются описания контуров, причем один глиф может содержать несколько контуров (рис. 5.1).
Рис. 5.1. Рисунки символов
Глифы могут иметь различный внешний вид (typeface). Операционная система Windows классифицирует шрифты на несколько типов, или семейств (font family). Эти типы называются Modern, Roman, Swiss, Script, Decorative.
Шрифты семейства Modern имеют одинаковую ширину букв. Таким шрифтом оформлены все листинги программ в нашей книге. Шрифты семейства Roman содержат буквы различной ширины, имеющие засечки. Семейство Swiss отличается тем, что при переменной ширине букв они не имеют засечек. Буквы в шрифтах семейства Script как бы написаны от руки. Семейство Decorative содержит глифы в виде небольших картинок (пиктограмм).
В следующей таблице мы привели примеры шрифтов различных семейств.
Семейство |
Название шрифта |
Пример текста |
Modern |
Courier |
Шрифт в стиле Modern |
Roman |
Times |
Шрифт в стиле Roman |
Swiss |
Helvetica |
Шрифт в стиле Swiss |
Script |
Script Cyrillic |
Шрифт в стиле Script |
Decorative |
Wingdings |
Dm13m,0=;rative |
Приложения Windows могут заказывать шрифт, ссылаясь на название соответствующего семейства, однако в зависимости от состава имеющихся шрифтов Windows может предоставить в ваше распоряжение не тот шрифт, какой бы вам хотелось.
Другая важная характеристика шрифта - это размер букв. Из 11 тома "Библиотеки системного программиста" вы знаете, что для описания вертикального размера букв шрифта используются несколько параметров. Не останавливаясь на тонкостях, отметим, что шрифты, содержащие буквы разного размера, являются разными шрифтами.
Растровые шрифты, которые относятся к одному семейству, но имеют разные размеры букв, хранятся в отдельных файлах. В то же время благодаря возможности масштабирования шрифтов True Type для них нет необходимости в отдельном хранении глифов различных размеров.
GDI может выполнять масштабирование растровых шрифтов, увеличивая (но не уменьшая) размер букв. Результат такого масштабирования при большом размере букв обычно неудовлетворительный, так как на наклонных линиях контура букв образуются зазубрины (рис. 1.5 в первой главе).
Векторные шрифты легко поддаются масштабированию, поэтому для хранения шрифта одного семейства, но разного размера, можно использовать один файл.
Вы знаете, что шрифты могут иметь нормальное (normal), жирное (bold) или наклонное (italic) начертание:
Начертание |
Образец шрифта |
Normal |
AaBbCcDdEeFfGgHhIiJjKkLl
АаБбВвГгДдЕеЖжЗзИиКкЛлМмНн |
Bold |
AaBbCcDdEeFfGgHhIiJjKkLl
АаБбВвГгДдЕеЖжЗзИиКкЛлМмНн |
Italic |
AaBbCcDdEeFfGgHhIiJjKkLl
АаБбВвГгДдЕеЖжЗзИиКкЛлМмНнОоПпРр |
GDI получает жирное и наклонное начертание растровых шрифтов из нормального при помощи соответствующих алгоритмов утолщения и наклона шрифта. Такие алгоритмы могут быть использованы и для масштабируемых шрифтов True Type, однако лучших результатов можно достигнуть при использовании отдельных файлов шрифтов True Type для нормального, жирного и наклонного начертания.
Еще один часто используемый атрибут оформления строк текста - подчеркивание:
Текст с подчеркиванием
Иногда используется шрифт с перечеркнутыми буквами.
GDI выполняет подчеркивание самостоятельно, файлы шрифтов не содержат глифы с подчеркиванием.
Растровые и векторные шрифты хранятся в системном каталоге Windows в файлах с расширением имени fon.
Глифы масштабируемых шрифтов True Type находятся в файлах с расширением имени ttf, причем сами эти файлы могут располагаться в любом каталоге. В процессе регистрации масштабируемого шрифта Windows создает в своем системном каталоге файлы с расширением имени fot, которые содержат ссылки на соответствующие ttf-файлы.
С помощью приложения Control Panel вы можете добавлять или удалять любые шрифты. Следует, однако, учитывать ограничение: в системе можно одновременно использовать не более 253, к тому же для представления жирного и наклонного начертания используются отдельные масштабируемые шрифты. Чрезмерное количество установленных шрифтов может привести к снижению производительности системы.
Для того чтобы написать строку текста заданным шрифтом, этот шрифт следует, подобно остальным объектам GDI, выбрать в контекст отображения. После этого функции TextOut, DrawText и аналогичные будут использовать для вывода текста нужный вам шрифт.
Приложения Windows могут использовать либо один из встроенных шрифтов, либо создать свой, описав требуемые характеристики шрифта. В любом случае в распоряжение пользователя будет предоставлен один из шрифтов, зарегистрированных при установке Windows или позже (с помощью Control Panel). Для выбора шрифта, соответствующего описанию, используется достаточно сложный алгоритм, учитывающий степень важности обеспечения соответствия параметров предоставленного шрифта запрошенным параметрам.
Обратим ваше внимание на одно важное обстоятельство.
Приложение заказывает шрифт, описывая его параметры. GDI анализирует запрошенные параметры и подбирает наиболее подходящий шрифт. При этом приложение не может "заставить" GDI выделить ему какой-то конкретный шрифт, указав его название или путь к файлу. Однако приложение может определить параметры шрифта, выбранного пользователем из состава установленных шрифтов, и запросить у GDI шрифт с этими параметрами. В последнем случае будет выделен шрифт, выбранный пользователем.
По умолчанию в контекст отображения при его создании выбирается системный шрифт, основным (и почти единственным) преимуществом которого является то, что он всегда доступен. Системный шрифт не является масштабируемым, содержит буквы переменной ширины, не имеющие засечек, для него используется кодировка ANSI.
Однако в некоторых случаях вам может понадобиться шрифт с фиксированной шириной букв, или шрифт в кодировке OEM. Вы можете получить идентификатор одного из встроенных шрифтов при помощи макрокоманды GetStockFont, описанной в файле windowsx.h:
#define GetStockFont(i) ((HFONT)GetStockObject(i))
В качестве единственного параметра этой макрокоманде следует передать идентификатор одного из встроенных шрифтов:
Идентификатор |
Описание |
SYSTEM_FONT |
Системный шрифт в кодировке ANSI с
переменной шириной букв, используется
операционной системой Windows для отображения
текста в меню, заголовках окон и диалоговых
панелях |
SYSTEM_FIXED_FONT |
Шрифт в кодировке ANSI с фиксированной
шириной букв. Использовался в старых версиях
операционной системой Windows (до версии 3.0) как
системный шрифт |
ANSI_VAR_FONT |
Шрифт в кодировке ANSI с переменной
шириной букв |
ANSI_FIXED_FONT |
Шрифт в кодировке ANSI с фиксированной
шириной букв |
OEM_FIXED_FONT |
Шрифт в кодировке OEM с фиксированной
шириной букв |
DEVICE_DEFAULT_FONT |
Шрифт, который используется для данного
устройства по умолчанию. Если устройство не
имеет своих шрифтов, используется системный
шрифт SYSTEM_FONT |
После того как вы получили идентификатор шрифта, этот шрифт можно выбрать в контекст отображения макрокомандой SelectFont :
#define SelectFont(hdc, hfont) \ ((HFONT)SelectObject((hdc), (HGDIOBJ)(HFONT)(hfont)))
Первый параметр этой макрокоманды определяет идентификатор контекста отображения, в который выбирается шрифт с идентификатором hfont. Она возвращает идентификатор шрифта, который был выбран в контекст отображения раньше, до вызова SelectFont.
Вам не нужно удалять встроенные шрифты, так же как не нужно удалять встроенные кисти и перья.
Если приложение ограничивает себя только встроенными шрифтами, оно не сможет воспользоваться всем многообразием созданных масштабируемых шрифтов и даже просто не сможет изменить размер букв или сделать текст жирным или наклонным. Для полного использования шрифтовых возможностей операционной системы Windows вы должны познакомиться с процедурой определения логических шрифтов.
Приложение может получить идентификатор шрифта, указав его параметры (такие как размеры символов, семейство шрифта, наклон относительно горизонтальной оси и т. п.) функции CreateFont. Эта функция имеет 14 параметров, поэтому не слишком удобна в использовании. Вместо нее лучше пользоваться функцией CreateFontIndirect :
HFONT WINAPI CreateFontIndirect(const LOGFONT FAR* lplf);
Функция возвращает идентификатор созданного логического шрифта, который можно выбрать в контекст отображения макрокомандой SelectFont, при этом для вывода будет подобран наиболее подходящий физический шрифт.
В качестве параметра функции CreateFontIndirect передается указатель на структуру типа LOGFONT, определенную в файле windows.h:
typedef struct tagLOGFONT { int lfHeight; int lfWidth; int lfEscapement; int lfOrientation; int lfWeight; BYTE lfItalic; BYTE lfUnderline; BYTE lfStrikeOut; BYTE lfCharSet; BYTE lfOutPrecision; BYTE lfClipPrecision; BYTE lfQuality; BYTE lfPitchAndFamily; char lfFaceName[LF_FACESIZE]; } LOGFONT; typedef LOGFONT* PLOGFONT; typedef LOGFONT NEAR* NPLOGFONT; typedef LOGFONT FAR* LPLOGFONT;
Перед вызовом функции CreateFontIndirect вы должны заполнить структуру LOGFONT нужными значениями, определяющими параметры шрифта. В неиспользованные поля следует записать нулевые значения. Можно записать нулевые значения во все поля, однако это едва ли имеет смысл.
Опишем назначение отдельных полей структуры LOGFONT. При этом мы будем пользоваться метриками шрифта, описанными в 11 томе "Библиотеки системного программиста" (стр. 144).
Высота шрифта в логических единицах (зависят от установленного режима отображения).
Можно указывать положительные и отрицательные значения, а также нуль. Если указано нулевое значение, выбирается шрифт размером в 12 пунктов (значение по умолчанию).
Положительные значения определяют высоту ячеек, в которых располагается буква, что соответствует содержимому поля tmHeight структуры TEXTMETRICS.
Абсолютная величина отрицательного значения определяет высоту символов, т. е. tmHeight - tmInternalLeading.
Ширина символов в логических единицах.
Если указано нулевое значение, используется значение по умолчанию, которое зависит от высоты шрифта и отношения масштабов по осям координат (aspect ratio) для шрифта и устройства вывода.
Угол между базовой линией шрифта и координатной осью X в десятых долях градуса (угол отсчитывается в направлении против часовой стрелки).
Если в процессе отображения логического шрифта на физический будет выбран растровый или векторный шрифт, текст будет выведен в горизонтальном направлении, так как вращать можно только шрифты True Type и векторные шрифты.
Это поле определяет ориентацию символов шрифта. К сожалению, операционная система Windows версии 3.1 игнорирует поле lfOrientation.
Вес шрифта. Определяет жирность символов шрифта и может находиться в пределах от 0 до 1000. Файл windows.h содержит определение символических констант для этого поля:
Константа |
Значение |
FW_DONTCARE |
0 |
FW_THIN |
100 |
FW_EXTRALIGHT |
200 |
FW_ULTRALIGHT |
200 |
FW_LIGHT |
300 |
FW_NORMAL |
400 |
FW_REGULAR |
400 |
FW_MEDIUM |
500 |
FW_SEMIBOLD |
600 |
FW_DEMIBOLD |
600 |
FW_BOLD |
700 |
FW_EXTRABOLD |
800 |
FW_ULTRABOLD |
800 |
FW_BLACK |
900 |
FW_HEAVY |
900 |
Вы можете использовать любое из указанных значений, однако следует иметь в виду, что многие шрифты содержат описания символов только для веса FW_NORMAL, FW_REGULAR и FW_BOLD.
Если содержимое этого поля не равно нулю, запрашивается шрифт с наклонными буквами.
Если содержимое этого поля не равно нулю, запрашивается шрифт с подчеркиванием букв.
Если содержимое этого поля не равно нулю, запрашивается шрифт с перечеркнутыми буквами.
Набор символов.
Можно использовать одну из следующих констант, определенных в файле windows.h:
Константа |
Значение |
Описание |
ANSI_CHARSET |
0 |
Набор символов в кодировке ANSI |
DEFAULT_CHARSET |
1 |
Не используется при отображении
шрифтов. Определяется при необходимости
запросить шрифт с заданным именем и размером
шрифта. Следует использовать с осторожностью,
так как если указанного шрифта нет, GDI может
выделить шрифт с любым набором символов |
SYMBOL_CHARSET |
2 |
Символьный шрифт, такой как, например,
Wingdings |
SHIFTJIS_CHARSET |
128 |
Шрифт, в котором для представления
символов используется двухбайтовая кодировка.
Нужен для работы с японской версией Windows |
OEM_CHARSET |
255 |
Набор символов в кодировке OEM |
Требуемая степень соответствия параметров шрифта.
Это поле используется для того, чтобы указать GDI способ выбора между двумя шрифтами, имеющими одинаковое название, но разный тип. Например, для удовлетворения запроса можно использовать растровый или масштабируемый шрифт с названием OddType. Если в поле lfOutPrecision указать константу OUT_TT_PRECIS, будет выбран масштабируемый шрифт.
Можно указывать одну из следующих констант:
Константа |
Значение |
Описание |
OUT_DEFAULT_PRECIS |
0 |
Используется точность, заданная по
умолчанию |
OUT_STRING_PRECIS |
1 |
Выбирается шрифт, для которого
соблюдается наибольшее соответствие в размерах
символов |
OUT_CHARACTER_PRECIS |
2 |
Аналогично OUT_STRING_PRECIS |
OUT_STROKE_PRECIS |
3 |
Требуется точное соответствие между
запрошенными атрибутами и атрибутами
полученного шрифта |
OUT_TT_PRECIS |
4 |
Выбирается масштабируемый шрифт True Type,
даже если есть подходящий растровый или
векторный шрифт |
OUT_DEVICE_PRECIS |
5 |
Выбирается шрифт устройства вывода |
OUT_RASTER_PRECIS |
6 |
Выбирается растровый шрифт |
OUT_TT_ONLY_PRECIS |
7 |
Используются только шрифты True Type |
Поле используется для определения способа, при помощи которого обрезается изображение символа, частично попавшего за пределы области ограничения вывода (clipping region), выбранную в контекст отображения.
Можно использовать следующие константы: CLIP_DEFAULT_PRECIS, CLIP_CHARACTER_PRECIS, CLIP_STROKE_PRECIS, CLIP_MASK, CLIP_LH_ANGLES, CLIP_TT_ALWAYS, CLIP_EMBEDDED.
Если указана константа CLIP_LH_ANGLES, направление вращения текста зависит от установленного режима отображения.
Качество шрифта, полученного при отображении.
Можно указывать одну из следующих констант:
Константа |
Описание |
DEFAULT_QUALITY |
Качество не имеет значения |
DRAFT_QUALITY |
Низкое качество. Допустимо
масштабирование шрифтов, синтезирование
наклонных, жирных, перечеркнутых и подчеркнутых
символов |
PROOF_QUALITY |
Высокое качество. Масштабирование
шрифтов не допускается. При этом могут быть
получены символы, имеющие размер, немного
меньший запрошенного |
С помощью этого поля можно определить, нужна ли фиксированная или переменна ширина символов. Кроме этого, можно определить семейство, к которому должен принадлежать полученный шрифт.
Фиксированная или переменная ширина символов задается при помощи следующих констант:
Константа |
Описание |
DEFAULT_PITCH |
Не имеет значения, будет ли шрифт иметь
фиксированную или переменную ширину символов |
FIXED_PITCH |
Нужен шрифт с фиксированной шириной
символов |
VARIABLE_PITCH |
Нужен шрифт с переменной шириной
символов |
Вы можете объединить при помощи логической операции ИЛИ эти константы с константами, соответствующими семейству шрифта:
Константа |
Описание |
FF_DECORATIVE |
Шрифт, содержащий маленькие рисунки
(пиктограммы). Примером такого шрифта может
послужить шрифт Wingdings, поставляемый в составе
Windows |
FF_DONTCARE |
Семейство шрифта не имеет значения |
FF_MODERN |
Семейство Modern. Фиксированная ширина
символов, могут быть засечки (но могут и не быть) |
FF_ROMAN |
Семейство Roman. Переменная ширина букв,
есть засечки |
FF_SCRIPT |
Семейство Script. Рукописный шрифт |
FF_SWISS |
Семейство Swiss. Переменная ширина букв,
нет засечек |
Строка, закрытая двоичным нулем, которая служит названием внешнего вида шрифта. Размер строки (включая закрывающий строку нуль) не должен превышать LF_FACESIZE байт.
Вы можете указать, что вам нужен, например, шрифт "Arial", однако это вовсе не гарантирует, что именно этот шрифт будет предоставлен в распоряжение приложения.
Если вы заполнили все нужные поля в структуре LOGFONT и затем передали адрес структуры функции CreateFontIndirect, эта функция вернет идентификатор шрифта. Вы должны выбрать шрифт с этим идентификатором в контекст отображения с помощью макрокоманды SelectFont (точно так же, как для встроенных шрифтов):
hfontOldFont = SelectFont(hdc, hfont);
Как только в созданном шрифте отпадет необходимость, его следует удалить при помощи макрокоманды DeleteFont, предварительно выбрав в контекст отображения тот шрифт, который был выбран в него раньше:
#define DeleteFont(hfont) \ DeleteObject((HGDIOBJ)(HFONT)(hfont))
Процесс отображения логического шрифта достаточно сложен. GDI сравнивает заданные в структуре LOGFONT параметры с параметрами различных шрифтов, которые можно использовать для данного устройства отображения, выбирая наиболее подходящий шрифт. Для сравнения используются пенальти (штрафные очки), которые имеют разные весовые коэффициенты. Выбирается тот шрифт, для которого сумма пенальти наименьшая.
Наиболее важное поле в структуре LOGFONT - поле lfCharSet. Если в этом поле будет установлено нулевое значение, будет выбран шрифт ANSI_CHARACTER, так как значение соответствующей ему константы равно нулю. Понятно, почему это поле самое важное - если приложение запрашивает шрифт OEM_CHARSET, оно предполагает использовать для вывода кодировку OEM. Если бы GDI предоставил приложению шрифт в кодировке ANSI, скорее всего, строку было бы невозможно прочесть. Если же в Windows нет ни одного шрифта с кодировкой OEM, приложение все равно получит какой-нибудь шрифт, однако результат вывода текста может оказаться неудовлетворительным.
Учтите, что растровые шрифты семейств Modern, Roman и Script, которые пришли из Windows версии 3.0, отмечены как имеющие кодировку OEM, хотя в действительности для этих шрифтов используется кодировка ANSI. Это сделано для того, чтобы в процессе выбора GDI вначале использовал масштабируемые шрифты перечисленных семейств, и только в крайнем случае остановил свой выбор на растровых шрифтах.
Следующее по важности поле в структуре LOGFONT - это поле lfPitchAndFamily. Оно имеет большое значение потому, что приложение, запрашивающее шрифт с фиксированной шириной букв, может работать неправильно, если ему будет выделен шрифт с переменной шириной букв.
Далее следует поле lfFaceName, а после него - поле lfFamily.
После сравнения всех описанных полей GDI сравнивает высоту букв шрифта (поле lfHeight), затем в сравнении принимают участие поля lfWidth, lfItalic, lfUnderline, lfStrikeOut.
Только что мы приближенно описали алгоритм, который используется GDI для отображения логического шрифта на физический. Нетрудно заметить, что приложение может получить от GDI совсем не тот шрифт, который ему нужен. Поэтому лучше всего предоставить пользователю возможность выбрать шрифт самостоятельно.
DLL-библиотека commdlg.dll содержит функцию ChooseFont, специально предназначенную для выбора одного из зарегистрированных в системе шрифтов. Эта функция выводит на экран диалоговую панель "Font", с помощью которой пользователь может выбрать шрифт, стиль шрифта, размер шрифта, цвет букв, может выбрать подчеркнутый или перечеркнутый шрифт (рис. 5.2).
Рис. 5.2. Диалоговая панель "Font"
Из списка "Font", который расположен в левой верхней части этой диалоговой панели, пользователь может выбрать название шрифта. Список "Font Style" позволяет выбрать один из доступных стилей, например, наклонный или жирный шрифт. Список "Size" предназначен для выбора размера шрифта. С помощью переключателей "Strikeout" и "Underline", расположенных в поле "Effects", можно создать, соответственно, перечеркнутый и подчеркнутый шрифт. И, наконец, из меню "Color" можно выбрать цвет букв.
Образец выбранного шрифта отображается в поле "Sample".
Обратите внимание на то, что в списке "Font" некоторые шрифты отмечены двойной буквой "T". Это масштабируемые шрифты True Type.
Приведем прототип функции ChooseFont:
BOOL WINAPI ChooseColor(CHOOSEFONT FAR* lpcf);
Единственный параметр функции является указателем на структуру типа CHOOSEFONT. Эта структура, а также сама функция ChooseFont, определены в файле commdlg.h. Структура определена следующим образом:
typedef struct tagCHOOSEFONT { DWORD lStructSize; HWND hwndOwner; HDC hDC; LOGFONT FAR* lpLogFont; int iPointSize; DWORD Flags; COLORREF rgbColors; LPARAM lCustData; UINT (CALLBACK* lpfnHook)(HWND, UINT, WPARAM, LPARAM); LPCSTR lpTemplateName; HINSTANCE hInstance; LPSTR lpszStyle; UINT nFontType; int nSizeMin; int nSizeMax; } CHOOSEFONT; typedef CHOOSEFONT FAR *LPCHOOSEFONT;
Перед вызовом функции ChooseFont вы должны проинициализировать нужные поля структуры CHOOSEFONT, записав в остальные поля нулевые значения.
Опишем назначение отдельных полей структуры CHOOSEFONT:
Поле |
Описание |
lStructSize |
Размер структуры в байтах. Это поле
необходимо заполнить перед вызовом функции
ChooseFont |
hwndOwner |
Идентификатор окна, которому будет
принадлежать диалоговая панель. Если в поле Flags
не указан флаг CF_SHOWHELP, в это поле можно записать
значение NULL. Поле заполняется до вызова функции
ChooseFont |
hDC |
Идентификатор контекста отображения
или информационного контекста для принтера. Если
установлен флаг CF_PRINTERFONTS, в списке появятся
шрифты, доступные в данном контексте |
lpLogFont |
Указатель на структуру LOGFONT. Приложение
может заполнить нужные поля в этой структуре
перед вызовом функции ChooseFont. Если при этом будет
установлен флаг CF_INITTOLOGFONTSTRUCT, выбранные значения
будут использоваться в качестве начальных. |
iPointSize |
Размер букв выбранного шрифта в десятых
долях пункта. Содержимое этого поля
устанавливается после возврата из функции ChooseFont |
Flags |
Флаги инициализации диалоговой панели.
Можно использовать следующие значения:CF_APPLY -
разрешается использование кнопки
"Apply";CF_ANSIONLY - в списке выбора появляются
только шрифты в кодировке ANSI;CF_BOTH - в списке
шрифтов появляются экранные и принтерные
шрифты;CF_TTONLY - можно выбирать только
масштабируемые шрифты True Type;CF_EFFECTS - если указан
этот флаг, с помощью диалоговой панели можно
определять цвет букв создавать подчеркнутые и
перечеркнутые шрифты. В этом случае необходимо
перед вызовом функции проинициализировать
содержимое полей lfStrikeOut, lfUnderline, rgbColors;CF_ENABLEHOOK -
разрешается использовать функцию фильтра адрес
которой указан в поле lpfnHook;CF_ENABLETEMPLATE -
разрешается использование шаблона диалоговой
панели, определяемого содержимым полей hInstance и
lpTemplateName;CF_ENABLETEMPLATEHANDLE - флаг указывает, что поле
hInstance содержит идентификатор загруженного
шаблона диалоговой панели. Содержимое поля
lpTemplateName игнорируется;CF_FIXEDPITCHONLY - можно выбрать
только шрифты с фиксированной шириной
символов:CF_FORCEFONTEXIST - выдается сообщение об
ошибке, если пользователь пытается выбрать
несуществующий шрифт;CF_INITTOLOGFONTSTRUCT - для
инициализации диалоговой панели используется
содержимое структуры LOGFONT, адрес которой
передается через поле lpLogFont;CF_LIMITSIZE - при выборе
шрифта учитывается содержимое полей nSizeMin и
nSizeMax;CF_NOFACESEL - отменяется выбор в списке
"Font";CF_NOOEMFONTS - нельзя выбирать векторные
шрифты, этот флаг аналогичен флагу
CF_NOVECTORFONTS;CF_NOSIMULATIONS - запрещается эмуляция
шрифтов;CF_NOSIZESEL - отменяется выбор размера
шрифта;CF_NOSTYLESEL - отменяется выбор стиля
шрифта;CF_NOVECTORFONTS - нельзя выбирать векторные
шрифты, этот флаг аналогичен флагу
CF_NOOEMFONTS;CF_PRINTERFONTS - в списке появляются только
такие шрифты, которые поддерживаются принтером,
контекст отображения для которого задан в поле
hDC;CF_SCALABLEONLY - можно выбирать только
масштабируемые и векторные шрифты;CF_SCREENFONTS -
можно выбирать только экранные шрифты;CF_SHOWHELP - в
диалоговой панели отображается кнопка
"Help";CF_USESTYLE - строка lpszStyle содержит указатель
на буфер, который содержит строку описания стиля.
Эта строка используется для инициализации
списка "Font Style" диалоговой панели
"Font";CF_WYSIWYG - можно выбирать только такие
шрифты, которые доступны и для отображения на
экране, и для печати на принтере. Если установлен
этот флаг, следует также установить флаги CF_BOTH и
CF_SCALABLEONLY |
rgbColors |
Цвет символов шрифта, который будет
выбран в меню "Colors" диалоговой панели
"Fonts" сразу после отображения диалоговой
панели. Должен использоваться флаг CF_EFFECTS. Поле
заполняется до вызова функции ChooseFont, после
возврата из функции поле содержит значение
выбранного цвета |
lCustData |
Произвольные данные, передаваемые
функции фильтра, определенной содержимым поля
lpfnHook |
lpfnHook |
Указатель на функцию фильтра,
обрабатывающую сообщения, поступающие в
диалоговую панель. Для работы с фильтром
необходимо в поле Flags указать флаг CF_ENABLEHOOK |
lpTemplateName |
Строка, закрытая двоичным нулем, которая
содержит идентификатор шаблона диалоговой
панели. Для использования этого поля необходимо
указать флаг CF_ENABLETEMPLATE |
hInstance |
Идентификатор модуля, который содержит
шаблон диалоговой панели в качестве ресурса.
Поле используется только в тех случаях, когда в
поле Flags указаны значения CF_ENABLETEMPLATE или
CF_ENABLETEMPLATEHANDLE. Поле заполняется до вызова функции
ChooseFont |
lpszStyle |
Указатель на буфер, содержащий строку,
описывающую шрифт. Если указан флаг CF_USESTYLE, эта
строка используется для инициализации списка
"Font Style". Размер буфера должен быть не меньше
LF_FACESIZE байт |
nFontType |
Тип выбираемого шрифта. Можно
использовать одно из следующих
значений:SIMULATED_FONTTYPE - GDI может эмулировать этот
шрифт;PRINTER_FONTTYPE - принтерный шрифт;SCREEN_FONTTYPE -
экранный шрифт;BOLD_FONTTYPE - жирный шрифт,
используется только для шрифтов True Type;ITALIC_FONTTYPE -
наклонный шрифт, используется только для шрифтов
True Type;REGULAR_FONTTYPE - не жирный и не наклонный шрифт,
используется только для шрифтов True Type |
nSizeMin |
Минимальный размер шрифта, который
можно выбрать. Для использования этого поля
необходимо установить флаг CF_LIMITSIZE |
nSizeMax |
Максимальный размер шрифта, который
можно выбрать. Для использования этого поля
необходимо установить флаг CF_LIMITSIZE |
Если пользователь выбрал шрифт, функция ChooseFont возвращает значение TRUE. Если пользователь отказался от выбора, нажав кнопку "Cancel" или клавишу <Esc>, возвращается значение FALSE.
Для того чтобы вы могли быстро попробовать основные функции, предназначенные для выбора шрифта, мы подготовили приложение FONTVIEW.
Меню "Font" приложения FONTVIEW позволяет вам выбрать шрифт двумя способами - вы можете указать семейство шрифта или выбрать конкретный шрифт при помощи диалоговой панели "Font".
Меню "Orientation" позволяет задать угол поворота текстовой строки, выводя ее с наклоном (рис. 5.3) или даже перевернутой "вверх ногами" (рис. 5.4).
Рис. 5.3. Вывод текста с наклоном
С помощью этого приложения вы можете убедиться в том, что повернуть можно только масштабируемые шрифты True Type.
Рис. 5.4. Вывод перевернутого текста
Исходный текст приложения приведен в листинге 5.1.
Листинг 5.1. Файл fontview/fontview.cpp
// ---------------------------------------- // Приложение FONTVIEW // Просмотр шрифтов // ---------------------------------------- #define STRICT #include <windows.h> #include <windowsx.h> #include <commdlg.h> #include <mem.h> #pragma hdrstop #include "fontview.hpp" // Прототипы функций BOOL InitApp(HINSTANCE); LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM); BOOL GetFont(HWND hWnd, LOGFONT *lf, CHOOSEFONT *cf); // Имя класса окна char const szClassName[] = "FontViewClass"; // Заголовок окна char const szWindowTitle[] = "Font Viewer"; // Размеры внутренней области окна short cxClient, cyClient; // Идентификатор копии приложения HINSTANCE hInst; // Строка для вывода char szChars[] = ": AaBbCcDdEeFfGg АаБбВвГгДдЕе"; char szBuf[256]; // Угол наклона строки при выводе int nOrientation = 0; // ===================================== // Функция WinMain // ===================================== #pragma argsused int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; // структура для работы с сообщениями HWND hwnd; // идентификатор главного окна приложения // Инициализируем приложение if(!InitApp(hInstance)) return FALSE; hInst = hInstance; // После успешной инициализации приложения создаем // главное окно приложения hwnd = CreateWindow( szClassName, // имя класса окна szWindowTitle, // заголовок окна WS_OVERLAPPEDWINDOW, // стиль окна CW_USEDEFAULT, // задаем размеры и расположение CW_USEDEFAULT, // окна, принятые по умолчанию CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, NULL); // Если создать окно не удалось, завершаем приложение if(!hwnd) return FALSE; // Рисуем главное окно ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // Запускаем цикл обработки сообщений while(GetMessage(&msg, 0, 0, 0)) { DispatchMessage(&msg); } return msg.wParam; } // ===================================== // Функция InitApp // Выполняет регистрацию класса окна // ===================================== BOOL InitApp(HINSTANCE hInstance) { ATOM aWndClass; // атом для кода возврата WNDCLASS wc; // структура для регистрации // класса окна // Записываем во все поля структуры нулевые значения memset(&wc, 0, sizeof(wc)); // Подключаем меню wc.lpszMenuName = "APP_MENU"; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszClassName = (LPSTR)szClassName; // Регистрация класса aWndClass = RegisterClass(&wc); return (aWndClass != 0); } // ===================================== // Функция WndProc // ===================================== LRESULT CALLBACK _export WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; static CHOOSEFONT cf; static LOGFONT lf; static HFONT hfont, hfOldFont;; switch (msg) { // При изменении размеров окна сохраняем // новые значения для ширины и высоты case WM_SIZE: { cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; } // Рисование в окне case WM_PAINT: { // Получаем контекст отображения для // рисования во внутренней области окна hdc = BeginPaint(hwnd, &ps); // Устанавливаем угол наклона строки lf.lfOrientation = lf.lfEscapement = nOrientation; // Создаем шрифт на базе заполненной // структуры LOGFONT hfont = CreateFontIndirect(&lf); if(hfont) { // Выбираем шрифт в контекст отображения hfOldFont = SelectFont(hdc, hfont); // Определяем название шрифта GetTextFace(hdc, 80, szBuf); // Добавляем к нему текстовую строку lstrcat(szBuf, szChars); // Устанавливаем цвет текста SetTextColor(hdc, cf.rgbColors); // Выводим текст, пользуясь выбранным шрифтом TextOut(hdc, cxClient/2, cyClient/2, szBuf, lstrlen(szBuf)); // Выбираем старый шрифт SelectFont(hdc, hfOldFont); // Удаляем созданный нами шрифт DeleteFont(hfont); } // Освобождаем контекст отображения EndPaint(hwnd, &ps); return 0; } // Обработка сообщений от меню case WM_COMMAND: { switch (wParam) { // Выбор шрифта при помощи диалоговой панели case CM_FONTSEL: { // Записываем во все поля структуры типа // LOGFONT нулевые значения memset(&lf, 0, sizeof(LOGFONT)); // Выбираем шрифт if(GetFont(hwnd, &lf, &cf)) { // Перерисовываем окно InvalidateRect(hwnd, NULL, TRUE); } return 0; } // Выбираем шрифт, указывая семейство case CM_FDECOR: { memset(&lf, 0, sizeof(LOGFONT)); lf.lfPitchAndFamily = FF_DECORATIVE; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_FMODERN: { memset(&lf, 0, sizeof(LOGFONT)); lf.lfPitchAndFamily = FF_MODERN; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_FROMAN: { memset(&lf, 0, sizeof(LOGFONT)); lf.lfPitchAndFamily = FF_ROMAN; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_FSCRIPT: { memset(&lf, 0, sizeof(LOGFONT)); lf.lfPitchAndFamily = FF_SCRIPT; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_FSWISS: { memset(&lf, 0, sizeof(LOGFONT)); lf.lfPitchAndFamily = FF_SWISS; InvalidateRect(hwnd, NULL, TRUE); return 0; } // Выбираем угол поворота строки case CM_FONT00: { nOrientation = 0; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_FONT30: { nOrientation = 300; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_FONT45: { nOrientation = 450; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_FONT90: { nOrientation = 900; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_FONT180: { nOrientation = 1800; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_FONT270: { nOrientation = 2700; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_FONT360: { nOrientation = 3600; InvalidateRect(hwnd, NULL, TRUE); return 0; } case CM_HELPABOUT: { MessageBox(hwnd, "Font Viewer, v.1.0\n" "(C) Frolov A.V., 1994", "About FONTVIEW", MB_OK | MB_ICONINFORMATION); return 0; } // Завершаем работу приложения case CM_FILEEXIT: { DestroyWindow(hwnd); return 0; } default: return 0; } } case WM_DESTROY: { PostQuitMessage(0); return 0; } default: break; } return DefWindowProc(hwnd, msg, wParam, lParam); } // ===================================== // Функция GetFont // ===================================== BOOL GetFont(HWND hWnd, LOGFONT *lf, CHOOSEFONT *cf) { LPSTR szFontStyle[LF_FACESIZE]; // Записываем нулевые значения во все поля // структуры, которая будет использована для // выбора шрифта memset(cf, 0, sizeof(CHOOSEFONT)); // Размер структуры cf->lStructSize = sizeof(CHOOSEFONT); // Идентификатор окна cf->hwndOwner = hWnd; // Указатель на структуру LOGFONT cf->lpLogFont = lf; // Флаги, определяющие внешний вид диалоговой панели cf->Flags = CF_SCREENFONTS | CF_USESTYLE | CF_EFFECTS; // Дополнительные данные cf->lCustData = 0L; // Цвет текста cf->rgbColors = RGB(0,0,0); // Адрес функции фильтра cf->lpfnHook = (FARPROC)NULL; // Адрес шаблона диалоговой панели cf->lpTemplateName = (LPSTR)NULL; // Идентификатор копии приложения cf->hInstance = hInst; // Стиль шрифта cf->lpszStyle = (LPSTR)szFontStyle; // Тип шрифта cf->nFontType = SCREEN_FONTTYPE; // Ограничения на минимальный и максимальный // размер шрифта cf->nSizeMin = 0; cf->nSizeMax = 0; // Вызываем функцию выбора шрифта return ChooseFont(cf); }
Текстовая строка, которая выводится на экран, находится в глобальном массиве szChars. В переменной nOrientation находится текущее значение угла поворота, которое задается при помощи меню "Orientation".
Обработчик сообщения WM_PAINT пользуется структурой lf типа LOGFONT, подготовленной при выборе шрифта.
Перед созданием шрифта обработчик устанавливает нужный угол наклона строки:
lf.lfOrientation = lf.lfEscapement = nOrientation;
Затем создается шрифт:
hfont = CreateFontIndirect(&lf);
Далее шрифт выбирается в контекст отображения, для чего используется макрокоманда SelectFont:
hfOldFont = SelectFont(hdc, hfont);
Идентификатор шрифта, который был выбран в контекст отображения раньше, сохраняется в переменной hfOldFont.
Затем обработчик вызывает функцию GetTextFace, которая копирует в буфер szBuf текстовую строку с названием шрифта, выбранного в контекст отображения. Эта строка затем дописывается ко строке szChars и выводится на экран.
Перед выводом устанавливается цвет текста, который берется из заполненной на этапе выбора шрифта структуры CHOOSEFONT:
SetTextColor(hdc, cf.rgbColors);
Для вывода текста мы используем функцию TextOut, которая была подробно описана в 11 томе "Библиотеки системного программиста".
Перед возвратом управления обработчик сообщения WM_PAINT выбирает в контекст отображения старый шрифт и удаляет созданный шрифт:
SelectFont(hdc, hfOldFont); DeleteFont(hfont);
Когда вы выберите строку "Fonts..." из меню "Font", получит управление обработчик сообщения WM_COMMAND. Он запишет во все поля структуры lf типа LOGFONT нулевые значения и вызовет функцию GetFont, определенную в нашем приложении. После этого он вызовет функцию InvalidateRect для перерисовки окна приложения.
Функция GetFont инициализирует нулевыми значениями структуру cf типа CHOOSEFONT, а затем заполняет в этой структуре нужные поля и вызывает функцию ChooseFont:
memset(cf, 0, sizeof(CHOOSEFONT)); cf->lStructSize = sizeof(CHOOSEFONT); cf->hwndOwner = hWnd; cf->lpLogFont = lf; cf->Flags = CF_SCREENFONTS | CF_USESTYLE | CF_EFFECTS; cf->lCustData = 0L; cf->rgbColors = RGB(0,0,0); cf->lpfnHook = (FARPROC)NULL; cf->lpTemplateName = (LPSTR)NULL; cf->hInstance = hInst; cf->lpszStyle = (LPSTR)szFontStyle; cf->nFontType = SCREEN_FONTTYPE; cf->nSizeMin = 0; cf->nSizeMax = 0; return ChooseFont(cf);
Если вы выбираете из меню "Font" одно из семейств шрифтов, структура lf инициализируется нулевыми значениями, а затем в ней устанавливается поле lfPitchAndFamily:
memset(&lf, 0, sizeof(LOGFONT)); lf.lfPitchAndFamily = FF_DECORATIVE;
Затем вызывается функция InvalidateRect, что приводит к перерисовке окна приложения.
Установка угла наклона выполняется достаточно просто и заключается в изменении значения переменной nOrientation с последующей перерисовкой окна:
case CM_FONT30: { nOrientation = 300; InvalidateRect(hwnd, NULL, TRUE); return 0; }
Все константы, которые используются для работы с меню, описаны в файле fontview.hpp (листинг 5.2).
Листинг 5.2. Файл fontview/fontview.hpp
#define CM_HELPABOUT 301 #define CM_FONTSEL 302 #define CM_FILEEXIT 303 #define CM_FONT30 304 #define CM_FONT45 305 #define CM_FONT90 306 #define CM_FONT180 307 #define CM_FONT270 308 #define CM_FONT360 309 #define CM_FONT00 310 #define CM_FDECOR 311 #define CM_FMODERN 312 #define CM_FROMAN 313 #define CM_FSCRIPT 314 #define CM_FSWISS 315
Меню определено в файле ресурсов приложения (листинг 5.3).
Листинг 5.3. Файл fontview/fontview.rc
#include "fontview.hpp" APP_MENU MENU BEGIN POPUP "&File" BEGIN MENUITEM "E&xit", CM_FILEEXIT END POPUP "F&ont" BEGIN MENUITEM "FF_DECORATIVE", CM_FDECOR MENUITEM "FF_MODERN", CM_FMODERN MENUITEM "FF_ROMAN", CM_FROMAN MENUITEM "FF_SCRIPT", CM_FSCRIPT MENUITEM "FF_SWISS", CM_FSWISS MENUITEM SEPARATOR MENUITEM "&Select Font...",CM_FONTSEL END POPUP "&Orientation" BEGIN MENUITEM "0", CM_FONT00 MENUITEM "30",CM_FONT30 MENUITEM "45",CM_FONT45 MENUITEM "90",CM_FONT90 MENUITEM "180",CM_FONT180 MENUITEM "270",CM_FONT270 MENUITEM "360",CM_FONT360 END POPUP "&Help" BEGIN MENUITEM "&About...", CM_HELPABOUT END END
Файл определения модуля приложения FONTVIEW приведен в листинге 5.4.
Листинг 5.4. Файл fontview/fontview.def
; ============================= ; Файл определения модуля ; ============================= NAME FONTVIEW DESCRIPTION 'Приложение FONTVIEW, (C) 1994, Frolov A.V.' EXETYPE windows STUB 'winstub.exe' STACKSIZE 8120 HEAPSIZE 1024 CODE preload moveable discardable DATA preload moveable multiple
В программном интерфейсе GDI имеется несколько функций, с помощью которых приложение может получить различную информацию о шрифте, выбранном в контекст отображения. Наибольший интерес представляют метрики шрифта, о которых мы рассказывали в 11 томе "Библиотеки системного программиста", однако для масштабируемых шрифтов True Type можно получить и другую информацию.
Для удобства мы напомним вам методику определения метрик шрифта.
Метрику шрифта, выбранного в контекст отображения, можно определить с помощью функции GetTextMetrics :
BOOL WINAPI GetTextMetrics(HDC hdc, TEXTMETRIC FAR* lptm);
Параметр hdc указывает контекст отображения или устройства, для которого требуется получить информацию о метрике шрифта. В качестве этого параметра можно использовать значение, возвращаемое функцией BeginPaint или GetDC.
Параметр lptm является дальним указателем на структуру типа TEXTMETRIC, в которую будет записана информация о метриках шрифта, выбранного в указанный контекст устройства.
В случае успешного завершения функция возвращает значение TRUE, в противном случае - FALSE.
Структура TEXTMETRIC описана в файле windows.h следующим образом:
typedef struct tagTEXTMETRIC { int tmHeight; int tmAscent; int tmDescent; int tmInternalLeading; int tmExternalLeading; int tmAveCharWidth; int tmMaxCharWidth; int tmWeight; BYTE tmItalic; BYTE tmUnderlined; BYTE tmStruckOut; BYTE tmFirstChar; BYTE tmLastChar; BYTE tmDefaultChar; BYTE tmBreakChar; BYTE tmPitchAndFamily; BYTE tmCharSet; int tmOverhang; int tmDigitizedAspectX; int tmDigitizedAspectY; } TEXTMETRIC;
Параметры, имеющие отношение к вертикальным размерам букв, представлены на рис. 5.5.
Рис. 5.5. Метрики шрифта
Отсчет всех размеров выполняется от так называемой базовой линии шрифта. Для размеров используются логические единицы, которые зависят от режима отображения, установленного в контексте устройства.
Общая высота букв находится в поле tmHeight структуры TEXTMETRIC. Эта высота складывается из двух компонент - tmAscent и tmDescent. Компонента tmAscent представляет собой высоту букв от базовой линии с учетом таких элементов, как тильда в букве "Й". Компонента tmDescent определяет пространство, занимаемое буквами ниже базовой линии. Сумма tmAscent и tmDescent в точности равна tmHeight.
Величина tmInternalLeading определяет размер выступающих элементов букв и может быть равна нулю.
Величина tmExternalLeading определяет минимальный межстрочный интервал, рекомендуемый разработчиком шрифта. Ваше приложение может игнорировать межстрочный интервал, однако в этом случае строки будут соприкасаться друг с другом, что не улучшит внешнего вида окна.
Для ширины букв в структуре TEXTMETRIC есть два поля с именами tmAveCharWidth и tmMaxCharWidth. Поле tmAveCharWidth содержит среднее значение ширины строчных букв шрифта. Это значение приблизительно соответствует ширине латинской буквы "x". Поле tmMaxCharWidth определяет ширину самой широкой буквы в шрифте. Для шрифта с фиксированной шириной букв поля tmAveCharWidth и tmMaxCharWidth содержат одинаковые значения, которые зависят от самого шрифта.
Поле tmWeight определяет жирность шрифта. Может находиться в пределах от 0 до 1000. Файл windows.h содержит определение символических констант для этого поля:
Константа |
Значение |
FW_DONTCARE |
0 |
FW_THIN |
100 |
FW_EXTRALIGHT |
200 |
FW_ULTRALIGHT |
200 |
FW_LIGHT |
300 |
FW_NORMAL |
400 |
FW_REGULAR |
400 |
FW_MEDIUM |
500 |
FW_SEMIBOLD |
600 |
FW_DEMIBOLD |
600 |
FW_BOLD |
700 |
FW_EXTRABOLD |
800 |
FW_ULTRABOLD |
800 |
FW_BLACK |
900 |
FW_HEAVY |
900 |
Поля tmItalic, tmUnderlined, tmStruckOut определяют, соответственно, является ли шрифт наклонным, подчеркнутым или перечеркнутым.
Поля tmFirstChar и tmLastChar определяют, соответственно, коды первого и последнего символа, определенных в шрифте.
Если приложение пытается вывести символ, код которого отсутствует в шрифте, вместо него будет выведен символ с кодом, расположенным в поле tmDefaultChar.
Поле tmBreakChar содержит код символа, который используется для переноса слов с одной строки на другую при выравнивании текста.
Поле tmPitchAndFamily содержит код семейства шрифта. В нем могут находится следующие флаги, соответствующие четырем младшим битам:
Значение |
Описание |
TMPF_FIXED_PITCH |
Шрифт с фиксированной шириной букв |
TMPF_VECTOR |
Векторный шрифт или масштабируемый
шрифт True Type |
TMPF_TRUETYPE |
Шрифт True Type |
TMPF_DEVICE |
Шрифт устройства вывода, например,
принтерный шрифт |
Одновременно может быть установлено несколько флагов с префиксом имени TMPF.
Старшие четыре бита описывают семейство шрифта:
Константа |
Описание |
FF_DECORATIVE |
Шрифт, содержащий маленькие рисунки
(пиктограммы). Примером такого шрифта может
послужить шрифт Wingdings, поставляемый в составе
Windows |
FF_DONTCARE |
Семейство шрифта не имеет значения или
неизвестно |
FF_MODERN |
Семейство Modern. Фиксированная ширина
символов, могут быть засечки (но могут и не быть) |
FF_ROMAN |
Семейство Roman. Переменная ширина букв,
есть засечки |
FF_SCRIPT |
Семейство Script. Рукописный шрифт |
FF_SWISS |
Семейство Swiss. Переменная ширина букв,
нет засечек |
В поле tmCharSet находится код используемого набора символов:
Константа |
Значение |
Описание |
ANSI_CHARSET |
0 |
Набор символов в кодировке ANSI |
DEFAULT_CHARSET |
1 |
Не используется при отображении
шрифтов. Определяется при необходимости
запросить шрифт с заданным именем и размером
шрифта. Следует использовать с осторожностью,
так как если указанного шрифта нет, GDI может
выделить шрифт с любым набором символов |
SYMBOL_CHARSET |
2 |
Символьный шрифт, такой как Wingdings |
SHIFTJIS_CHARSET |
128 |
Шрифт, в котором для представления
символов используется двухбайтовая кодировка.
Нужен для работы с японской версией Windows |
OEM_CHARSET |
255 |
Набор символов в кодировке OEM |
В поле tmOverhang содержится величина, на которую увеличивается ширина символов для синтезированных (эмулированных) шрифтов, например, наклонных или жирных шрифтов, полученных изменением нормального шрифта. Шрифты True Type обычно не используют это поле для наклонных и жирных шрифтов (в нем находится нулевое значение), так как такие шрифты считаются отдельными шрифтами, и не получаются изменением нормального шрифта True Type.
Поля tmDigitizedAspectX и tmDigitizedAspectY содержат значения, которые можно использовать для определения отношения масштабов устройства отображения по горизонтали и вертикали.
В тех случаях, когда вас не устраивают возможности диалоговой панели "Font", создаваемой функцией ChooseFont, придется использовать для выбора шрифтов список, создаваемый с помощью функции EnumFontFamilies. Эту функцию можно также использовать для получения информации о шрифте.
Приведем прототип функции EnumFontFamilies:
int EnumFontFamilies( HDC hdc, // идентификатор контекста отображения LPCSTR lpszFamily, // адрес имени семейства шрифта FONTENUMPROC fntenmprc, // адрес функции обратного вызова LPARAM lParam); // произвольные данные
Параметр hdc определяет контекст отображения устройства, для которого требуется получить список доступных шрифтов.
Через параметр lpszFamily передается адрес строки, закрытой двоичным нулем, содержащей название шрифта, для которого требуется получить информацию. Если этот параметр указан как NULL, выбирается один произвольный шрифт для каждого семейства шрифтов.
Параметр fntenmprc задает адрес функции обратного вызова, полученный с помощью функции MakeProcInstance.
Приложение может передать функции обратного вызова произвольные 32-разрядные данные через параметр lParam.
Функция обратного вызова должна быть определена следующим образом (для функции можно использовать любое имя):
int CALLBACK _export EnumFontFamProc( NEWLOGFONT FAR* lpnlf, // адрес структуры NEWLOGFONT NEWTEXTMETRIC FAR* lpntm, // адрес структуры метрики // физического шрифта int FontType, // тип шрифта LPARAM lParam); // адрес произвольных данных, переданных // функции EnumFontFamilies через // параметр lParam
Когда функция EnumFontFamProc получает управление, через параметр lpnlf передается адрес структуры NEWLOGFONT, которая по непонятной причине не описана в файле windows.h. Эта структура аналогична структуре LOGFONT, но имеет в конце два дополнительных поля, определенных только для шрифтов True Type:
typedef struct tagNEWLOGFONT { int lfHeight; int lfWidth; int lfEscapement; int lfOrientation; int lfWeight; BYTE lfItalic; BYTE lfUnderline; BYTE lfStrikeOut; BYTE lfCharSet; BYTE lfOutPrecision; BYTE lfClipPrecision; BYTE lfQuality; BYTE lfPitchAndFamily; char lfFaceName[LF_FACESIZE];
BYTE lfFullName[2 * LF_FACESIZE];// только для True Type
BYTE lfStyle[LF_FACESIZE]; // только для True Type } NEWLOGFONT;
Поле lfFullName представляет собой массив, содержащий полное имя шрифта, которое состоит из названия шрифта и названия стиля.
В поле lfStyle находится название стиля шрифта.
Параметр lpntm функции EnumFontFamProc содержит адрес структуры NEWTEXTMETRIC, описывающей метрику шрифта:
typedef struct tagNEWTEXTMETRIC { int tmHeight; int tmAscent; int tmDescent; int tmInternalLeading; int tmExternalLeading; int tmAveCharWidth; int tmMaxCharWidth; int tmWeight; BYTE tmItalic; BYTE tmUnderlined; BYTE tmStruckOut; BYTE tmFirstChar; BYTE tmLastChar; BYTE tmDefaultChar; BYTE tmBreakChar; BYTE tmPitchAndFamily; BYTE tmCharSet; int tmOverhang; int tmDigitizedAspectX; int tmDigitizedAspectY; // Дополнительные поля DWORD ntmFlags; UINT ntmSizeEM; UINT ntmCellHeight; UINT ntmAvgWidth; } NEWTEXTMETRIC; typedef NEWTEXTMETRIC* PNEWTEXTMETRIC; typedef NEWTEXTMETRIC NEAR* NPNEWTEXTMETRIC; typedef NEWTEXTMETRIC FAR* LPNEWTEXTMETRIC;
Структура NEWTEXTMETRIC аналогична структуре TEXTMETRIC, за исключением четырех дополнительных полей, добавленных в конце. Эти поля описывают физические атрибуты шрифта True Type.
Поле ntmFlags может содержать значения NTM_REGULAR, NTM_BOLD или NTM_ITALIC, соответственно, для нормального, жирного или наклонного шрифта True Type.
Поле ntmSizeEM содержит ширину буквы "М", в единицах, использованных при разработке шрифта.
В поле ntmCellHeight находится высота шрифта в единицах, использованных при разработке шрифта.
Поле ntmAvgWidth содержит ширину шрифта в единицах, использованных при разработке шрифта.
Параметр FontType функции EnumFontFamProc определяет тип шрифта и может содержать одно из следующих значений:
Значение |
Описание |
DEVICE_FONTTYPE |
Шрифт устройства вывода |
RASTER_FONTTYPE |
Растровый шрифт |
TRUETYPE_FONTTYPE |
Шрифт True Type |
Через последний параметр функции EnumFontFamProc передаются 32-разрядные данные, указанные в параметре lParam функции EnumFontFamilies.
Если приложение собирается продолжить
просмотр доступных шрифтов, функция EnumFontFamProc
должна возвратить ненулевое значение. Если
просмотр должен быть завершен, следует
возвратить нуль.