Чтение онлайн

ЖАНРЫ

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

Далее программа

GDIDraw
демонстрирует работу функции
InvertRect
, которая инвертирует цвета в заданной прямоугольной области контекста устройства. Для того чтобы это было нагляднее, мы сначала выведем на форму загруженный в
OnCreate
рисунок (только на этот раз без региона отсечения) и инвертируем область, частично пересекающуюся с областью рисунка (листинг 1.37).

Листинг 1.37. Пример использования функции
InvertRect

// Следующая группа команд выводит рисунок и конвертирует

// его часть

Canvas.Draw(300, 220, FBitmap);

// Функция InvertRect делает указанный прямоугольник

// "негативом".

InvertRect(Canvas.Handle, Rect(320, 240, 620, 340));

Ещё

одна забавная функция GDI, которая почему-то не нашла отражения в классе
TCanvas
— это
GrayString
. Она предназначена для вывода "серого" текста, т.е. текста, который по яркости находится посредине между черным и белым. Обычно для этого просто устанавливается цвет
RGB(128, 128, 128)
, но некоторые черно-белые устройства не поддерживают полутона (это касается, прежде всего, старых моделей принтеров) — именно на них и ориентирована функция
GrayString
. Она позволяет рисовать серый текст произвольным образом с помощью функции обратного вызова, но эту функцию можно не указывать, и тогда рисование осуществляется функцией
TextOut
. Но при этом текст выводится через промежуточную растровую картинку в памяти, что обеспечивает полупрозрачность текста, т.к. закрашиваются не все пикселы, а только половина в шахматном порядке. На черно-белых принтерах с большим разрешением это действительно выглядит как серый текст, на экране же можно получать "полупрозрачные" надписи. Пример использования функции
GrayString
приведен в листинге 1.38.

Листинг 1.38. Пример использования функции
GrayString

// Следующая группа команд выводит "полупрозрачную"

// надпись "Windows API"

Canvas.Brush.Color := clBlue;

// Функция GrayString при выводе текста закрашивает

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

// порядке, оставляя остальные нетронутыми. Это создает

// эффект полупрозрачности.

Canvas.Font.Name := 'Times New Roman';

Canvas.Font.Style := [fsBold];

Canvas.Font.Height := 69;

GrayString(Canvas.Handle, Canvas.Brush.Handle, nil, LPARAM(PChar('Windows API')), 0, 20, 350, 0, 0);

Обратите внимание на второй параметр — через него передается дескриптор кисти, с помощью которой будет осуществляться закраска пикселов в выводимой строке. Функция

GrayString
игнорирует ту кисть, которая выбрана в контексте устройства и использует свою. Здесь для простоты мы передаем ей кисть контекста устройства, но, в принципе, это могла бы быть любая другая кисть. Третий параметр — это указатель на функцию обратного вызова. В нашем случае он равен
nil
, что указывает на использование функции
TextOut
. Четвертый параметр имеет тип
LPARAM
и содержит произвольные данные, которые передаются функции обратного вызова. В случае использования
TextOut
это интерпретируется как указатель на строку, которую нужно вывести, поэтому здесь приходится возиться с приведением типов. Пятый параметр содержит длину выводимой строки. Это очень характерно для функций GDI, предназначенных для вывода текста, конец строки в них определяется не обязательно по завершающему символу
#0
, можно вывести только часть строки, явно задав нужное число символов. Но этот же параметр можно сделать равным нулю (как в нашем случае), и тогда длина строки определяется обычным образом — по символу #0. Прочие параметры функции определяют координаты выводимой строки.

Последняя часть примера посвящена вопросу, который долгое время был очень популярен в форумах: как вывести текст, расположенный наклонно (в программе примером такого текста является надпись Sample, выведенная под углом 60 градусов). Это связано с тем, что только в BDS 2006 у класса TFont появилось свойство

Orientation
, позволяющее задавать направление текста (в справке BDS 2006 информация об этом свойстве отсутствует, она появляется только
в справке Delphi 2007, но это свойство, тем не менее, есть и в BDS 2006, а также в Turbo Delphi). В более ранних версиях текст под углом можно было вывести только с помощью функций GDI, вручную создавая шрифт (листинг 1.9).

Листинг 1.39. Вывод текста под углом средствами GDI

// Следующая группа функций выводит надпись "Sample".

// повернутую на угол 60 градусов.

Canvas.Brush.Style := bsClear;

// При создании логического шрифта для контекста

// устройства следует в обязательном порядке указать

// угол поворота. Однако класс TFont игнорирует такую

// возможность, поэтому шрифт нужно создавать вручную.

// Чтобы выбрать шрифт в контексте устройства, легче

// всего присвоить его дескриптор свойству

// Canvas.Font.Handle. Параметры fdwItalic, fdwUnderline

// и fdwStrikeOut, согласно справке, могут принимать

// значения True или False, но имеют тип DWORD. Для

// С/C++ это не имеет значения - целый и логический типы

// в этих языках совместимы. Но в Delphi приходится

// использовать 0 и 1 вместо True и False. Угол поворота

// шрифта задается в десятых долях градуса, т.е.

// значение 600 означает 60 градусов.

Canvas.Font.Handle := CreateFont(60, 0, 600, 600, FW_NORMAL, 0, 0, 0,

 ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,

 DEFAULT_QUALITY, DEFAULT_РIТСН, 'Times New Roman');

Canvas.TextOut(140, 320, 'Sample');

// Эта строка нужна для того, чтобы пример работал

// корректно в BDS2006 и выше. В этой версии у класса

// TFont появилось свойство Orientation, задающее

// направление текста, и этот класс научился определять

// и сохранять это направление даже в том случае, если

// оно было задано функцией GDI, а не через свойство

// Orientation. Чтобы этого не происходило, нужно снова

// придать шрифту горизонтальное направление. В версиях

// Delphi, более ранних, чем BDS 2006, эта строка

// не нужна: при изменении шрифта через класс TFont

// направление текста и так станет горизонтальным.

Canvas.Font.Handle := Create Font(60, 0, 0, 0, FW_NORMAL, 0, 0, 0,

 ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,

 DEFAULT_QUALITY, DEFAULT_PITCH, 'Times New Roman');

Новый шрифт создается функцией

CreateFont
. Если бы мы программировали без VCL, то полученный в результате вызова этой функции дескриптор шрифта необходимо было бы выбрать в контексте устройства (функция
SelectObject
) и вывести надпись. Затем в устройстве следовало бы выбрать другой шрифт, а созданный ранее удалить. Но т.к. VCL мы все же используем, можно поступить проще: присвоить созданный дескриптор свойств
Canvas.Font.Handle
, а все остальное сделают классы
TCanvas
и
TFont
.

Примечание

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

Функция

CreateFont
имеет 14 параметров, определяющих свойства создаваемого шрифта. Мы не будем перечислять их все, отметим только, что мы здесь создаем шрифт на основе гарнитуры Times New Roman, имеющий размер 60 обычный (т.е. не жирный и не наклонный). О точных значениях всех параметров рекомендуем посмотреть в MSDN.

Поделиться с друзьями: