Теперь мы должны изменить атрибуты контекста устройства по умолчанию на те, которые нам необходимы. Изменим цвет карандаша и его толщину, а также цвет кисти. Для этого создадим новый графический объект при помощи функции 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. Результат работы приложения «Рисование примитивов»
Здесь вы можете увидеть, что рисуется в итоге и как параметры функции влияют на это.
Теперь мы разработаем простое приложение, которое будет способно выводить текст под различным углом через определенный интервал времени. Для этого опять сделаем обработку события 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. Режимы смешивания фона
Если функция завершается успешно, то она возвращает предыдущий установленный режим смешивания фона. В противном случае она возвращает ноль.