Visual Basic 6. Руководство разработчика

Функции рисования


Visual Basic предоставляет несколько методов для рисования на формах элементов управления PictureBox (см. гл. 6). Этих методов немного, но разнообразие их параметров делает эти методы достаточно гибкими. Однако они работают не так быстро, как их "двойники" из набора API-функций. Система Windows содержит много графических объектов и достаточное количество API-функций для рисования

и заливки изображений. В этом параграфе рассмотрены некоторые API-функции, которые помогут повысить быстродействие приложений, создаваемых в Visual Basic (рассмотрение всех API-функций для работы с графикой выходит за пределы этой книги). В последнем параграфе главы рассмотрены основные положения графиче­ских API-функций Windows, контекстов устройств и растровых структур. Эти методы помогут написать быстродействующие программы, позволяющие орга­низовать вывод графических изображений и манипулировать отдельными пиксе­лями.

Примечание

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

Вывод линий и окружностей

Двумя основными API-функциями являются функции LineTo() и Ellipse(), позволяющие выводить прямые линии и эллипсы (окружности). Объявление функции LineTo() приведено ниже.

Public Declare Function LineTo Lib "gdi32" Alias ''LineTo" _

(ByVal hdc As Long, ByVal x As Long, ByVal у As Long) As Long

Функция LineTo() позволяет нарисовать отрезок прямой, соединяющий текущую точку и точку с координатами (X, Y) в указанном контексте устройства. Чтобы определить текущую точку, воспользуйтесь функцией MoveToEx():

Private Declare Function MoveToEx Lib "gdi32" Alias "MoveToEx" _

(ByVal hdc As Long, ByVal x As Long, ByVal у As Long,

IpPoint As POINTAPI) As Long




Параметры х и у функции MoveToEx() являются координатами новой текущей точки. Последний параметр - структура POINTAPI - содержит координаты текущей точки перед их изменением данной функцией. Структура POINTAPI рассматрива­лась ранее в параграфе "Объявление 32-х разрядных функций и структур" этой главы.

Координаты точек в обеих функциях (как и во всех графических API-функциях) задаются в пикселях. Если возникает необходимость в совместном использовании графических методов Visual Basic и API-функций, то необходимо установить значение соответствующего свойства элемента управления равным 3 (пиксели). Чтобы в окне формы Form1 нарисовать отрезок прямой линии от точки с координатами (10,10) до точки (85,130), используется следующий набор операторов.

Dim point As POINTAPI

MoveToEx Forml.hDC, 10, 10, point

LineTo Forml.hDC, 85, 130

Функция Ellipse(), объявленная ниже, предназначена для вывода эллипсов и кругов.

Public Declare Function Ellipse Lib "gdi32" Alias "Ellipse" _

(ByVal hdc As Long, ByVal XI As Long, ByVal Yl As Long, _

ByVal X2 As Long, ByVal Y2 As Long) As Long

Эта функция позволяет нарисовать эллипс в контексте устройства, определенном дескриптором hdc.

Эллипс вписан в прямоугольник, определенный координатами противоположных вершин (XI, Y1) и (X2,Y2). Чтобы нарисовать квадрат, нужно задать прямоугольник с одинаковыми сторонами.

Если эти команды используются для создания изображений на формах или элементах управления PictureBox, то цвет линии определяется значением свойства ForeColor формы или PictureBox, а ширина - значением их свойства DrawWidth. Можно изменить значения свойств либо воспользоваться API-функцией CreatePen().

Public Declare Function CreatePen Lib "gdi32" Alias "CreatePen" _

(ByVal nPenStyle As Long, ByVal nWidth As Long, _

ByVal crColor As Long) As Long

Параметр

nPenStyle — целое число, которое может принимать любое из значений, приведенных в табл. 13.8. Указанные значения соответствуют значениям свойства DrawMode.



Таблица 13.8. Значения параметра nPenStyle функции CreatePenQ

Константа

Значение

PS_SOLID

0

PS_DASH

1

PS_DOT

2

PS_DASHDOT

3

PS_NULL

5

PS_DASHDOTDOT

4

PS_JNSIDEFRAME

6

Для создания сплошного пера красного цвета шириной два пикселя необходимо вызвать функцию CreatePen() со следующими параметрами:

myPen = CreatePen (0, 2, RGB (255, 0, 0))

Создание объекта Pen не означает, что данный объект будет автоматически использоваться в последующих операциях вывода графики. Чтобы использовать новое перо в дальнейшем, "свяжите" объект Pen с контекстом устройства, в котором он применяется. Вызовите для этого функцию Select0bject().

Public Declare Function Select0bject Lib "gdi32" Alias _

"SelectObject" (ByVal hdc As Long, ByVal h0bject As _

Long) As Long

Первый параметр — дескриптор контекста устройства, в котором будет выпол­няться процедура рисования, а второй параметр — дескриптор объекта Pen. Чтобы указать, что объект myPen будет использоваться в последующих операциях, вызовите такую функцию:

Select0bject Forml.hDC, myPen

После того как этот оператор выполнится, функции

Line() и Ellipse() смогут использовать перо myPen при выводе изображений в контекст устройства. Анало­гичным объекту Pen является объект Brush, который используется для заливки областей (эта процедура будет рассмотрена позже). Воспользуемся функцией CreateSolidBrush()

для создания объекта Brush.

Public Declare Function CreateSolidBrush Lib "gdi32" Alias _

"CreateSolidBrush" (ByVal crColor As Long) As Long

Цвет кисти задается функцией RGB() или свойством Color в диалоговом окне Color. Чтобы использовать объект Brush в дальнейших операциях, выберите его в контексте устройства с помощью функции SelectObject().

VB6 в действии: проект APIDraw

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





Рис. 13.11. Приложение APIDraw: круг и эллипс, созданные с помощью API-функции Ellipse()

В начале программы объявляются API-функции.

Private Declare Function LineTo Lib "gdi32" (ByVal hdc As Long,

ByVal x As Long, ByVal у As Long) As Long

Private Declare Function Ellipse Lib "gdi32" (ByVal hdc As Long,

ByVal XI As Long, ByVal Yl As Long, ByVal X2 As Long, _

ByVal Y2 As Long) As Long

Private Declare Function MoveToEx Lib "gdi32" (ByVal hdc As Long, _

ByVal x As Long, ByVal у As Long, IpPoint As POINTAPI) _

As Long

Private Declare Function CreateSolidBrush Lib "gdi32" _

(ByVal crColor As Long) As Long

Private Declare Function ExtFloodFill Lib "gdi32" (ByVal hdc _

As Long, ByVal x As Long, ByVal у As Long, ByVal crColor _

As Long, ByVal wFillType As Long) As Long

Private    Declare Function SelectObject Lib "gdi32" _

     (ByVal hdc As Long, ByVal hObject As Long) As Long

Private Declare Function DeleteObject Lib "gdi32" _

(ByVal hObject As Long) As Long

Фрагмент программы, обрабатывающий щелчок на клавише Draw Now (см. рис. 13.11) содержит функции MoveToEx() и LmeTo(), позволяющие нарисо­вать ограничивающие прямоугольники, и функцию Ellipse() для вывода эллипса. Первый эллипс ограничен прямоугольником, противоположные вершины которого расположены в точках с координатами (10, 10) и (500, 300), а второй - ограничен прямоугольником, который простирается из точки (10, 10) в точку (300, 300). Так как второй прямоугольник является квадратом, второй эллипс является окруж­ностью. Фрагмент программы, обрабатывающий нажатие кнопки Draw Now, приведен ниже

Программа 13.12. Вывод эллипсов

Private Sub Commandl Click()

Dim point As POINTAPI

Forml.CIs

Forml.ForeColor = RGB(255, О, О)

MoveToEx Forml.hdc, 10, 10, point

LineTo Forml.hdc, 500, 10

LineTo Forml.hdc, 500, 300

LineTo Forml.hdc, 10, 300

LineTo Forml.hdc, 10, 10

Ellipse Forml.hdc, 10, 10, 500, 300

Forml.ForeColor = RGB(0, 0, 255)



MoveToEx Forml.hdc, 10, 10, point

LineTo Forml.hdc, 300, 10

LineTo Forml.hdc, 300, 300

LineTo Forml.hdc, 10, 300

LineTo Forml.hdc, 10, 10

Ellipse Forml.hdc, 10, 10, 300, 300

End Sub

Заливка замкнутых фигур

Очень полезным режимом (отсутствующим в Visual Basic) является режим заливки замкнутых фигур (областей). Можно легко нарисовать окружность и прямоугольник, залитые определенным цветом, но как быть с фигурами, контуры которых определяются пересечением базовых фигур (см. рис. 13.11)? Для заливки фигур неправильной формы необходимо использовать API-функцию ExtFloodFill().

Public Declare Function ExtFloodFill Lib "gdi32" _

Alias "ExtFloodFill" (ByVal hdc As Long, ByVal x As Long, _

ByVal у As Long, ByVal crColor As Long, ByVal _

wFillType As Long) As Long

Эта функция позволяет залить сплошную область, начинающуюся в точке с координатами (x, у) цветом, определенным параметром crColor.

Последний параметр (wFillType)

определяет тип заливки и может принимать одно из следующих значений.

•   FLOODFILLBORDER (0) - функция выполняет заливку области цветом crColor. Точка (х, у) должна находиться в пределах закрашиваемой области.

•   FLOODFILLSURFACE (1) - параметр cIColor определяет только цвет обрамления.

Поскольку область заливается с помощью кисти, сначала необходимо создать объект Brush, затем выбрать его в контекст устройства и вызвать функцию ExtFloodFill(). Фигуры, появляющиеся на экране после щелчка на кнопке Draw Now (приложения Ellipse), содержат весьма причудливые области, для заливки которых применяется функция ExtFloodFill(). К этой программе добавлен небольшой фрагмент, позволяющий заливать замкнутые области цветом, выбранным пользо­вателем в диалоговом окне Color. Чтобы заполнить область, щелкните на кнопке Fill Color (в общем диалоговом окне Color) и выберите цвет заливки, а затем щелкните на точке, расположенной в пределах области, которую вы хотите залить. Заливка выполняется в обработчике события MouseUp, текст которого приведен ниже.

Программа 13.13. Заливка замкнутой области

Private Sub Form MouseUp(Button As Integer, Shift As Integer, _

x As Single, у As Single)

brush = CreateSolidBrushe(CommonDialogI.Color)

SelectObject Me.hdc, brush

ExtFloodFill Me.hdc,

x,
y, Me.point(x, y), FLOODFILLSURFACE

DeleteObject brush

End Sub

Программа извлекает информацию о выбранном цвете из элемента управления CommonDialogI и использует ее для создания сплошной кисти. Затем кисть выбирается в контекст устройства формы и вызывается функция ExtFloodFill(), с помощью которой выполняется заливка требуемой области.


Содержание раздела