Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows

.pdf
Скачиваний:
0
Добавлен:
11.02.2026
Размер:
13.15 Mб
Скачать

Регионы и отсечение

111

 

 

 

Функция OffsetRgn может применяться для отсечения при многократном ри совании движущихся объектов. Кроме того, при помощи этой функции можно отслеживать положение движущегося объекта в игре, чтобы фиксировать столк новения с другими объектами, описываемыми своими регионами.

Функция CombineRgn позволяет выполнять с объектами регионов некоторые по лезные операции, заимствованные из теории множеств. Она комбинирует два ис ходных региона и строит третий, на который ссылается параметр hrgnDest. Все три дескриптора регионов должны быть действительными еще до вызова функции, од нако регион, представленный дескриптором hrgnDest, заменяется новым, сформи рованным в результате вызова функции. Параметр fnCombineMode определяет опе рацию, выполняемую с исходными регионами, в соответствии с табл. 2.16.

Таблица 2.16. Операции над регионами, выполняемые функцией CombineRgn

Значение fnCombineMode

Новый регион

 

 

RGN_AND

Область пересечения двух исходных регионов

RGN_OR

Объединение двух исходных регионов

RGN_XOR

Объединение двух исходных регионов, за исключением

 

области пересечения

RGN_DIFF

Часть региона hrgnSrc1, не входящая в регион hrgnSrc2

RGN_COPY

Регион hrgnSrc1

 

 

Стоит отметить, что на месте параметров hrgnSrc1 и hrgnDest может быть один и тот же объект, например hrgnSrc1.

Функция CombineRgn возвращает целочисленный код сложности сгенериро ванного региона или код ошибки. Возможные значения кода возврата приведены в табл. 2.17.

Таблица 2.17. Коды, возвращаемые функцией CombineRgn

Значение

Описание

 

 

NULLREGION

Пустой регион

SIMPLEREGION

Регион определяется одним прямоугольником

COMPLEXREGION

Регион определяется несколькими прямоугольниками

ERROR

Регион не создан в результате ошибки (недопустимые значения параметров

 

или нехватка памяти)

 

 

Прорисовка регионов

Для прорисовки регионов, заданных дескриптором hrgn, предусмотрены функ ции, перечисленные в табл. 2.18.

Во всех этих функциях координаты регионов задаются в логической системе координат.

Создание объектов регионов и операции с ними связаны со значительными зат ратами времени и памяти, особенно при усложнении формы региона. Поэтому, если рисуемую фигуру легко воспроизвести другими средствами GDI (функциями ри сования прямоугольников, эллипсов и им подобных), следует отдавать предпочте ние этому способу. Функции прорисовки регионов следует использовать для заме ны более дорогостоящих операций, например функций вывода отдельных пикселов. Также они могут быть полезны, когда приложение рисует на экране два перекрыва

112

Глава 2. GDI — графический интерфейс устройства

 

 

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

Таблица 2.18. Функции рисования регионов

Функция

Описание

 

 

BOOL FillRgn(HDC hdc, HRGN hrgn, HBRUSH hbr);

Закрашивает регион кистью hbr

BOOL PaintRgn(HDC hdc, HRGN hrgn);

Закрашивает регион кистью, выбранной

 

в контекст устройства

BOOL FrameRgn(HDC hdc, HRGN hrgn, HBRUSH hbr, int nWidth, int nHeight);

Обводит контур региона кистью hbr. Ширина вертикальных «мазков» кисти равна nWidth, высота горизонтальных «мазков» кисти равна nHeight

BOOL InvertRgn(HDC hdc, HRGN hrgn);

Инвертирует цвет каждого пиксела внутри

 

региона (работает аналогично функции

 

InvertRect)

 

 

Отсечение

Отсечение — это ограничение вывода рисуемого изображения в пределах некото рой заданной области. Напомним, что Windows использует соответствующие по нятия, связанные с данной проблемой:

Обновляемый регион (недействительный регион) — та часть окна, которая требу ет обновления после тех или иных событий. Обновляемый регион формируется как системой, так и приложением в результате вызова функции InvalidateRect

или InvalidateRgn.

Видимый регион — та часть окна, которую в данный момент видит пользова тель. В результате перекрытия другим окном видимая часть окна может изме ниться.

Регион отсечения — область, внутри которой система разрешает рисование. Ког да приложение получает контекст устройства, система устанавливает регион отсечения как результат пересечения видимого региона и обновляемого реги она. Приложение может усилить ограничения, накладываемые на регион отсе чения, при помощи функции SetWindowRgn или SelectClipRgn.

Обратите внимание на то, что при отсечении координаты всех регионов зада ются в системе координат устройства.

Отсечение для всего окна

Функция SetWindowRgn предназначена для установки региона окна. Регион окна определяет область внутри окна, где Windows разрешает рисование. Функция имеет следующий прототип:

int SetWindowRgn(

 

 

 

HWND hWnd,

//

дескриптор

îêíà

HRGN hRgn,

//

дескриптор

региона

BOOL bRedraw

//

флаг перерисовки окна после установки региона

);

 

 

 

Отображение текста

113

 

 

 

Координаты региона определяются относительно левого верхнего угла окна, а не его клиентской области.

Функция может использоваться для изменения формы главного окна прило жения.

Отсечение для клиентской области окна

Регион с дескриптором hRgn, созданный при помощи рассмотренных выше функ ций, может быть использован для отсечения при выводе в клиентской области окна. Для этого он должен быть выбран в контекст устройства при помощи функ ции SelectClipRgn:

SelectClipRgn(hDC, hRgn);

В этом случае GDI создает копию данных региона и связывает ее с контекстом устройства. Поэтому после выполнения функции SelectClipRgn объект hRgn может быть удален.

Чтобы удалить из контекста устройства выбранный ранее регион отсечения, нужно вызвать функцию SelectClipRgn с параметром NULL:

SelectClipRgn(hDC, NULL);

Чаще всего регионы отсечения применяются для того, чтобы ограничить ри сование только той областью экрана, где это действительно необходимо. Это осо бенно актуально для анимационных или игровых приложений, в которых ско рость рисования может иметь критическое значение, а также для программных имитаторов аппаратуры, требующих рисования в реальном времени (см. главу 12).

Примеры использования регионов отсечения содержатся в листинге 2.2 и лис тингах главы 12.

Отображение текста

В главе 1 уже рассматривалась задача вывода строки текста в центре клиентской области окна (см. листинг 1.1). При этом текст выводился функцией DrawText. Ка жущаяся простота, с которой был достигнут нужный результат, объясняется тем, что в программе использовались значения по умолчанию для тех атрибутов кон текста устройства, которые влияют на рисование текста (табл. 2.19).

Таблица 2.19. Атрибуты контекста устройства, влияющие на вывод текста

Атрибут

Значение по умолчанию

Функции для изменения

 

 

значения атрибута

 

 

 

Шрифт

SYSTEM_FONT

SelectObject

Цвет текста

Черный

SetTextColor

Цвет фона графических элементов

Белый

SetBkColor

Режим смешивания фона

OPAQUE

SetBkMode

Режим отображения

MM_TEXT

SetMapMode

 

 

 

При необходимости можно изменить указанные значения, вызвав соответству ющие функции GDI. Например, можно окрасить выводимый текст любым цве том, вызвав предварительно функцию SetTextColor. Или, если системный шрифт

114

Глава 2. GDI — графический интерфейс устройства

 

 

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

Наборы символов и кодировки

Представление символов в компьютерах базируется на кодовых таблицах, в кото рых каждому отображаемому на экране символу соответствует некоторый цело численный код. Кодовую таблицу называют также набором символов (character set).

Одним из первых стандартов кодовых таблиц был стандарт представления символов ASCII1. В наборе символов ASCII (рис. 2.22) каждому символу со поставлен 7 битный двоичный код, поэтому общее количество символов равно 27 = 128 символов.

Рис. 2.22. Стандарт представления символов ASCII

Для обеспечения компактности кодовая таблица изображена на рис. 2.22 в дву мерном представлении. Номера строк и столбцов даны в шестнадцатеричной нота ции. Шестнадцатеричный код символа образуется в результате сцепления номера строки и номера столбца. Например, код буквы N равен 0x4E, что соответствует двоичному коду 01001110 или десятичному коду 78.

Первые 32 символа в таблице (коды 0x00 — 0x1F) соответствуют неотобража емым управляющим кодам. К ним относятся «возврат каретки» (код 0x0D)2, «пе ревод строки» (код 0x0A) и другие неотображаемые символы3. Затем следуют пробел (код 0x20), синтаксические и служебные знаки, знаки математических опе раций, цифры и буквы английского алфавита в верхнем и нижнем регистрах. Пос ледний символ (код 0x7F) используется также как управляющий код.

Позже появились различные расширения таблицы ASCII с использованием 8 битной кодировки, позволяющей отображать 256 символов. Во всех расшире ниях первые 128 позиций повторяют стандарт ASCII.

Наиболее распространенной реализацией такой кодировки является расши ренный набор символов IBM, предложенный производителями IBM PC в начале 80 х годов. В старшей половине кодовой таблицы эта кодировка содержит псев дографические символы, символы греческого алфавита и некоторые математи ческие символы. Набор символов IBM растиражирован в миллионах микросхем

1 American Standard Code for Information Interchange.

2 Этот код вырабатывается, в частности, при нажатии клавиши Enter.

3 Windows выводит неотображаемые управляющие символы в виде маленьких квадратов.

Отображение текста

115

 

 

 

ПЗУ, которые установлены в видеоадаптерах, принтерах и микросхемах BIOS. Для множества программ, работающих в текстовом режиме и написанных не для Microsoft Windows, используется эта кодировка, поскольку в них для вывода ин формации на экран используются символы псевдографики, имеющие коды от 0xB0 до 0xDF.

Известно несколько вариантов кодирования набора символов IBM, которые называются кодовыми страницами (code pages). Вариант, используемый в США и большинстве европейских стран, называется CP437 (code page 437). В России получила наибольшее распространение так называемая альтернативная кодировка ГОСТа. Она известна также под именем CP866 и отличается от CP437 тем, что некоторые символы во второй половине таблицы заменены на кириллицу, а псев дографические символы остались на своих местах. Кодовая страница CP866 по казана на рис. 2.23.

Рис. 2.23. Кодовая страница CP866

С появлением операционной системы Microsoft Windows возникла необходи мость разработки нового расширения таблицы ASCII, так как текстовый режим MS DOS, а вместе с ним и символы псевдографики стали уже ненужной архаи кой. Так появился набор символов ANSI1, который, фактически, стал международ ным стандартом ISO2.

Набор символов ANSI также имеет разные варианты кодировки, реализован ные в виде кодовых страниц, учитывающих национальные особенности алфави тов разных стран. Некоторые из этих страниц показаны в табл. 2.20.

На рис. 2.24 показано содержимое кодировки Windows Latin1 (кодовая стра ница 1252), а на рис. 2.25 — содержимое кодировки Windows Cyrillic (кодовая стра ница 1251).

Хотя однобайтных кодировок хватает для представления символов большин ства мировых языков, китайский, корейский и японский языки содержат слишком

1 ANSI — American National Standards Institute.

2 ISO — International Organization for Standardization.

116

Глава 2. GDI — графический интерфейс устройства

 

 

много символов, для кодировки которых не хватит одного байта. Поэтому для этих языков используются многобайтные кодировки. Следует отметить, что в ко довых страницах 932 (японский язык), 949 (корейский язык) и 950 (китайский язык) используются также разные принципы кодировки.

Таблица 2.20. Варианты кодирования набора символов ANSI

Кодовая страница

Êîäû 0 .. 127

Êîäû 128 .. 255

 

 

 

1250 (Windows Latin2)

ASCII

Восточная Европа

1251

(Windows Cyrillic)

ASCII

Кириллица

1252 (Windows Latin1)

ASCII

США и Западная Европа

1253

 

ASCII

Греция

1254

 

ASCII

Турция

. . .

 

. . .

. . .

 

 

 

 

Рис. 2.24. Кодировка Windows Latin 1 (1252)

Рис. 2.25. Кодировка Windows Cyrillic (1251)

Отображение текста

117

 

 

 

Если вы хотите узнать на уровне Win API, какие кодовые страницы установ лены или поддерживаются в вашей системе, можно воспользоваться функцией EnumSystemCodePages. На уровне пользователя эту информацию можно получить при помощи приложения Regional Settings (Язык и стандарты) панели управления Windows.

Unicode

Работа с разными кодировками, особенно многобайтными, доставляет програм мисту немало сложностей, например, в случае преобразования символов из од ной кодировки в другую. Для решения подобных проблем был предложен стан дарт Unicode. В Консорциум Unicode, осуществляющий сопровождение данного стандарта, входят Apple, Hewlett Packard, IBM, Microsoft, Sun и другие компа нии. В этом стандарте каждый символ кодируется двумя байтами, что обеспечи вает возможность выражения до 65 536 символов. Стандарт Unicode позволяет представить большую часть символов практически всех языков мира.

Символы в стандарте Unicode группируются в логические зоны. Например,

впервой зоне содержатся символы с кодами от 0x0000 до 0x007F, и младшие бай ты этих кодов повторяют таблицу ASCII. Самая большая зона содержит 29 902 иероглифов, используемых в Китае, Японии и Корее.

Windows поддерживает работу с символами как в традиционной ANSI коди ровке, так и в кодировке Unicode. Почти все функции Win32 API, получающие

вкачестве аргумента адрес строки, имеют ANSI и Unicode версии.

При соблюдении небольшого количества правил вы можете написать програм му так, что она будет компилироваться как в ANSI версии, так и в Unicode версии.

Если в начале файла имеется директива #define UNICODE, то компилятор созда ет Unicode версию, если такой директивы нет — ANSI версию. Разумеется, в мно гофайловом проекте эта директива должна одновременно присутствовать или отсутствовать во всех файлах проекта.

Вот эти правила:

Для определения символов и строк вместо типа char используйте тип TCHAR, вместо типа char* используйте тип LPTSTR, вместо типа const char* — тип LPCTSTR.

Для определения строковых констант используйте макрос TEXT, то есть вместо нотации "abcd" употребляйте нотацию TEXT("abcd").

В случае использования функций из C библиотеки, работающих со строками, предусмотрите вызов нужной версии функции. Для этого нужно добавить в начале файла, но после директивы #define UNICODE, директивы условной ком пиляции, подобные следующим инструкциям:

#ifdef

UNICODE

 

#define

sprintf

swprintf

#define

sscanf

swscanf

#define

strcpy

wcscpy

#define

strcat

wcscat

#define

strlen

wcslen

#endif

 

 

В данной книге все программные примеры даны в ANSI версии, чтобы не ус ложнять программный код.

118

Глава 2. GDI — графический интерфейс устройства

 

 

Шрифты

Любой шрифт, с которым имеет дело Windows, характеризуется несколькими па раметрами:

Гарнитура (typeface) — это совокупность нескольких начертаний шрифта, объе диненных стилевыми и другими признаками. Самыми известными гарнитура ми являются Arial, Times New Roman, Courier New.

Размер шрифта — это высота прямоугольника, в котором помещаются все сим волы шрифта.

Начертание — это специфические характеристики шрифта. В Windows дос тупны нормальное (normal) начертание, курсивное (italic), полужирное (bold), с подчеркиванием символа (underline), с перечеркиванием символа (strike out). Кроме того, эти виды начертаний могут комбинироваться в любом сочетании.

Фиксированная или переменная ширина символов. Шрифты первой группы на зывают моноширинными. В них все символы имеют одинаковую ширину. Шриф ты второй группы называют пропорциональными. В них символ «i» занимает го раздо меньше места, чем символ «m». Пропорциональные шрифты более удобны для чтения и поэтому чаще используются в текстовых документах.

Глиф (glyph) — это графическая форма отдельного символа при его изображе нии на бумаге или экране дисплея. Различные гарнитуры шрифтов различа ются прежде всего глифами символов.

На рис. 2.26 показано, как выглядит текст, нарисованный с использованием разных гарнитур.

Рис. 2.26. Вид текста при выводе с разными гарнитурами

В приведенном примере шрифты Arial и Times New Roman являются пропор циональными, а шрифт Courier New — моноширинным. Можно также отметить, что глифы шрифтов Times New Roman и Courier New имеют так называемые за сечки, а глифы шрифта Arial таких засечек не имеют.

Шрифты, обладающие общими принципами начертания, принадлежат одному из семейств (family). Характеристики семейств шрифтов приведены в табл. 2.21.

Таблица 2.21. Семейства шрифтов

Семейство

Флаг (константа

Êîä

Описание

шрифтов

Windows)

 

 

 

 

 

 

Don't care

FF_DONTCARE

0x00

Шрифт с произвольными атрибутами

 

 

 

(используется шрифт по умолчанию)

Roman

FF_ROMAN

0x10

Пропорциональные шрифты с засечками

 

 

 

(серифами), например Times New Roman

Swiss

FF_SWISS

0x20

Пропорциональные шрифты без засечек,

 

 

 

например Arial

Modern

FF_MODERN

0x30

Моноширинные шрифты с засечками или без

 

 

 

засечек, например Courier New

 

 

 

 

Отображение текста

 

119

 

 

 

 

 

 

 

 

 

 

Семейство

Флаг (константа

Êîä

Описание

шрифтов

Windows)

 

 

 

 

 

 

 

 

Script

FF_SCRIPT

0x40

«Рукописные» шрифты, например Monotype

 

 

 

 

Corsiva

 

Decorative

FF_DECORATIVE

0x50

Декоративные шрифты, например Old English

 

 

 

 

Типы шрифтов

 

 

 

Windows поддерживает две

главные

категории шрифтов: «шрифты GDI»

и «шрифты устройства» (device fonts). Шрифты GDI хранятся в файлах, которые обычно расположены в одном из подкаталогов операционной системы. Шрифты устройства соответствуют конкретному устройству вывода. Например, большин ство принтеров имеет набор встроенных шрифтов устройства.

Шрифты GDI подразделяются на три типа:

растровые шрифты;

векторные шрифты;

шрифты типа TrueType.

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

к«зазубринам» в очертаниях глифов. Чаще всего растровые шрифты применяются для воспроизведения текстовых элементов интерфейса Windows.

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

С появлением шрифтов типа TrueType в версии Windows 3.1 значительно по высились возможности и гибкость работы с текстами. TrueType — это технология контурных шрифтов, которая была разработана Apple Computer Inc. и Microsoft Corporation. Эта технология поддерживается многими производителями шриф тов. Отдельные символы шрифтов TrueType определяются контурами, состоящи ми из прямых линий и кривых. Таким образом, Windows может масштабировать символы, изменяя определяющие контуры координаты. При этом контуры гли фов остаются плавными и при увеличении размеров символов. Шрифты TrueType могут быть использованы как для вывода на экран, так и для вывода на принтер, делая возможным режим отображения текста WYSIWYG (What You See Is What You Get)1.

1 Что видите — то и получаете.

120

Глава 2. GDI — графический интерфейс устройства

 

 

Когда программе необходимо использовать шрифт TrueType определенного размера, Windows формирует растровое представление этого шрифта. Этот про цесс называется растеризацией шрифта. Алгоритмы растеризации учитывают не только координаты точек соединения прямых и кривых каждого символа, но и некоторые дополнительные данные, содержащиеся в описании шрифта, чтобы скомпенсировать ошибки округления, которые могли бы привести к искажению формы символа. В результате достигается хорошее качество изображения глифов символов независимо от коэффициента масштабирования.

Шрифт TrueType обычно хранится в одном файле с расширением .ttf. В опера ционной системе Windows впоследствии появилась поддержка шрифтов OpenType. Эти шрифты аналогичны шрифтам PostScript, но они закодированы в формате шрифтов TrueType. Файлы шрифтов OpenType имеют расширение .otf. Технология OpenType также позволяет объединить несколько шрифтов OpenType в один файл. Для таких шрифтов, называемых коллекциями TrueType, используется расшире ние .ttc.

Установка и удаление шрифтов

Чтобы приложение смогло выводить текст, используя глифы некоего конкретно го шрифта, он должен либо быть установлен в системной таблице шрифтов (system font table), либо присутствовать в используемом графическом устройстве в каче стве встроенного шрифта. Имена шрифтов, установленных на графическом уст ройстве и хранящихся во внутренней системной таблице, можно получить при помощи функции EnumFontFamilies или ChooseFont.

Приложение может загрузить шрифт вызовом одной из функций: AddFontResource или AddFontResourceEx. Эти функции загружают шрифт из соответствующего ресурс ного файла. Однако такая установка является временной, поскольку после рестарта операционной системы шрифт окажется недоступным. Чтобы установленный шрифт присутствовал в системе постоянно, информация о нем должна быть включена в ре естр Windows.

Если установленный шрифт становится ненужным, то он может быть удален из системной таблицы с помощью функции RemoveFontResource.

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

Более подробную информацию об установке шрифтов можно найти в книге [6].

Внедрение шрифтов

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

Технология внедрения шрифтов (font embedding) позволяет включить шриф ты прямо в документ. При открытии документа внедренные шрифты автомати чески устанавливаются на другом компьютере, благодаря чему документ сохра няет прежний вид.