Валерий Борисок - Delphi. Трюки и эффекты
Теперь мы должны изменить атрибуты контекста устройства по умолчанию на те, которые нам необходимы. Изменим цвет карандаша и его толщину, а также цвет кисти. Для этого создадим новый графический объект при помощи функции CreatePen.
...hCurPen := CreatePen(PS_SOLID, 2, RGB(255, 64, 0));
Формат данной функции следующий:
...Function CreatePen(fnPenStyle: Integer; nWidth: Integer; crColor: COLORREF): HPEN;
Параметр f nPenStyle задает стиль карандаша. Возможные значения этого параметра приведены в табл. 6.1.
Таблица 6.1
. Стили карандаша
Параметр nWidth задает ширину карандаша в логических единицах. EonnnWidth равен 0, то карандаш будет шириной в один пиксел независимо от текущей трансформации.
CreatePen возвращает карандаш с заданной шириной со стилем PSSOLID, если вы указали ширину больше, чем 1, для одного из стилей: PS_DASH, PS_DOT, PSJDASHDOT, PS_DASHDOTDOT.
Параметр crColor задает цвет карандаша.
Если функция завершилась удачно, то она возвращает дескриптор логического карандаша. В противном случае она возвращает nil.
После того как карандаш создан, следует его выбрать для полученного контекста при помощи функции SelectObject:
...hOldPen:= SelectObject(hCurDC, hCurPen);
Данная функция имеет следующий формат:
...Function SelectObject(hdc: HDC; hgdiobj: HGDIOBJ): HGDIOBJ;
• hdc – дескриптор контекста устройства;
• hgdiobj – дескриптор на выбираемый объект.
Если выбранный объект не регион и функция выполнилась успешно, то она возвращает дескриптор на объект, который был заменен. Если выбранный объект регион и функция выполнилась успешно, то возвращаемое значение может быть одним из приведенных в табл. 6.2.
Таблица 6.2.
Результат SelectObject для выбранного объекта регион
Если происходит ошибка и выбранный объект не регион, то возвращаемое значение – nil. Иначе – HGDI_ERROR.
Функция возвращает предыдущий выбранный объект указанного типа. Приложение должно всегда восстанавливать объект по умолчанию после того, как закончилось рисование с использованием нового объекта.
Приложение не может выбрать битовый массив более чем для одного контекста устройства одновременно.
После успешного выбора созданного нами карандаша и запоминания предыдущего выбранного необходимо создать и выбрать кисть. Для этого используем функцию CreateSolidBrush:
...hCurBrush:= CreateSolidBrush(RGB(0, 128, 255));
Данная функция имеет следующий формат:
...Function CreateSolidBrush(crColor: COLORREF): HBRUSH;
Параметр crColor задает цвет кисти.
Если функция завершилась успешно, то она возвращает дескриптор логической кисти. В противном случае – nil.
После создания кисти выбираем ее с использованием той же самой функции SelectObj ect и запоминаем ранее выбранную.
...hOldBrush:= SelectObject(hCurDC, hCurBrush);
Далее рисуем примитивы с использованием полученного контекста устройства с новыми графическими объектами.
Чтобы нарисовать эллипс, используем функцию Ellipse:
...Ellipse(hCurDC, 10, 10, 100, 70);
Функция имеет следующий формат:
...Function Ellipse(hdc: HDC; nLeftRect, nTopLeft, nRightRect, nBottomRect: Integer): BOOL;
• hdc – дескриптор контекста устройства;
• nLeftRect – задает координату х (в логических единицах) верхнего левого угла описываемого прямоугольника;
• nTopRect – задает координату у (в логических единицах) верхнего левого угла;
• nRightRect – задает координату х (в логических единицах) правого нижнего угла;
• nBottomRect – задает координату у (в логических единицах) правого нижнего угла.
Если функция завершается успешно, то ее результат – ненулевое значение. В противном случае возвращается 0.
Для рисования прямоугольника используется функция Rectangle.
...Rectangle(hCurDC, 110, 10, 210, 70);
У данной функции такой же формат, как и у Ellipse, но интерпретация последних четырех параметров немного иная. Они задают сам прямоугольник, а не прямоугольник, описываемый вокруг эллипса.
Далее мы рисуем прямоугольник с округленными углами при помощи функции RoundRect.
...RoundRect(hCurDC, 10, 80, 100, 140, 10, 10);
У данной функции первые пять параметров идентичны параметрам предыдущей функции, а последние два задают ширину и высоту эллипса, при помощи которого происходит округление углов прямоугольника.
Следующим примитивом, который мы рисуем, является отрезок. Процесс рисования осуществляется в два этапа. Сначала при помощи функции MoveToEx устанавливается начальная точка отрезка. Затем используем функцию Move То с указанием конечной точки.
...MoveToEx(hCurDC, 10, 150, nil);
LineTo(hCurDC, 100, 220);
Четвертый параметр в функции MoveToEx – это переменная типа TPoint, в которую помещается предыдущее положение карандаша.
И последней рисуется дуга при помощи функции Arc.
...Arc(hCurDC, 110, 150, 210, 220, 110, 150, 210, 220);
В ней первые пять параметров соответствуют параметрам функции Rectangle, а последние четыре параметра задают начальную и конечную радиальные точки дуги.
После того как все операции вывода выполнены, требуется освободить все занятые ресурсы системы. Это осуществляется следующим образом:
...SelectObject(hCurDC, hOldPen);
DeleteObject(hCurPen);
SelectObject(hCurDC, hOldPen);
DeleteObject(hCurPen);
ReleaseDC(Handle, hCurDC);
Сначала восстанавливаются карандаш и кисть для контекста устройства и удаляются созданные нами, а после освобождается и сам контекст устройства. Результат выполнения приложения приведен на рис. 6.1.
Рис. 6.1. Результат работы приложения «Рисование примитивов»
Здесь вы можете увидеть, что рисуется в итоге и как параметры функции влияют на это.
6.7. Работа с текстом
Теперь мы разработаем простое приложение, которое будет способно выводить текст под различным углом через определенный интервал времени. Для этого опять сделаем обработку события OnPaint нашей формы, в которой будем осуществлять вывод некоторого текста на поверхность формы. Исходный код данного обработчика приведен в листинге 6.2.
...Листинг 6.2.
Обработчик события формы OnPaint
procedure TfmText.FormPaint(Sender: TObject);
var
hCurDC: HDC;
hCurFont, hOldFont: HFONT;
nOldMode: Integer;
sText: String;
begin
//получаем общий контекст устройства
hCurDC := GetDC(Handle);
//создаем шрифт из шаблона
hCurFont := CreateFontIndirect(LogFontData);
//выбираем созданный шрифт
hOldFont := SelectObject(hCurDC, hCurFont);
//устанавливаем новый режим вывода
nOldMode := SetBkMode(hCurDC, TRANSPARENT);
//устанавливаем цвет текста
SetTextColor(hCurDC, RGB(0, 0, 255));
//задаем текстовую строку
sText := 'Текст примера
//выводим текст на экран
TextOut(hCurDC, Width div 2, Height div 2, PAnsiChar(sText),
Length(sText));
//восстанавливаем режим вывода
SetBkMode(hCurDC, nOldMode);
//восстанавливаем ранее выбранный шрифт
SelectObject(hCurDC, hOldFont);
//удаляем созданный шрифт
DeleteObject(hCurFont);
//освобождаем общий контекст устройства
ReleaseDC(Handle, hCurDC);
end;
Как можно легко заметить, обработчик co6biTHHOnPaint работает по той же схеме, что и в предыдущем примере. Изначально получаем контекст устройства, потом создаем необходимый графический объект и выбираем его вместо установленного по умолчанию. После чего восстанавливаются все атрибуты контекста устройства, а затем он освобождается. Теперь перейдем от общего к частному. Мы создаем логический шрифт на основании указанных характеристик при помощи функции CreateFontlndirect.
...hCurFont:= CreateFontlndirect(LogFontData);
Данная функция имеет следующий формат заголовка:
...Function CreateFontlndirect(const If: LOGFONT): HFONT;
Параметр If содержит описание характеристик логического шрифта. Если функция завершается успешно, то она возвращает дескриптор логического шрифта. В противном случае ее результатом является nil.
После создания шрифта выбираем его в контексте устройства.
...hOldFont:= SelectObject(hCurDC, hCurFont);
Далее устанавливаем режим прозрачности, то есть такой режим, при котором будет выводиться только текст без предварительной заливки фона определенным цветом.
...nOldMode:= SetBkMode(hCurDC, TRANSPARENT);
Функция SetBkMode служит для установки режима смешивания фона определенного контекста устройства. Этот режим используется для текста, штриховых кистей, а также для карандашей со стилем, отличным от сплошных линий.
Формат заголовка данной функции следующий:
...Function SetBkMode(hdc: HDC; nBkMode: Integer): Integer;
• hdc – задает описатель контекста устройства, для которого устанавливается режим смешивания фона;
• nBkMode – определяет режим смешивания фона, может принимать одно из значений, указанных в табл. 6.3.
Таблица 6.3. Режимы смешивания фона
Если функция завершается успешно, то она возвращает предыдущий установленный режим смешивания фона. В противном случае она возвращает ноль.