Рисование на visual basic
После прочтения заголовка может возникнуть вопрос: А зачем нужно использовать Windows API. Отвечаю: Visual Basic(VB) сам по себе, при рисовании изображений, используетAPI функции, производя предварительные преобразования переменных. Конечно при вызове API функций напрямую экономия времени невелика, но API, кроме всегопрочего, позволяет пользоваться большим количеством "инструментов".Итак, приступим. Для начала скажу, что весь код, приведённый на этой странице,можно скопировать в файл класса VB.
Начинаться класс будет с задания API функций и типов.
Option Explicit Private Type POINTAPI "Этот тип используется в API для x As Long "задания координат на экране y As LongEnd TypePrivate Declare Function Polygon _ "Функция API для изображения многоугольникаLib "gdi32" (_ ByVal hdc As Long, _ lpPoint As POINTAPI, _ ByVal nCount As Long _) As LongPrivate Declare Function Ellipse _ "Функция API для изображения окружностиLib "gdi32" (_ ByVal hdc As Long, _ ByVal X1 As Long, _ ByVal Y1 As Long, _ ByVal X2 As Long, _ ByVal Y2 As Long, _) As LongPrivate Declare Function FloodFill _ "Функция API для "заливки"Lib "gdi32" ( _ ByVal hdc As Long, _ ByVal x As Long, _ ByVal y As Long, _ ByVal Color As Long _) As Long
Оператор Private , объявляющий эти функции доступными тольковнутри класса, обязателен при задании API функций(во всяком случае, для MS VB 5.0 Enterprise Edition). В дальнейщем доступ к этимфункциям извне будет осуществлятся только через методы класса.
Следующим шагом в создании класса будет задание закрытых переменных,доступных (как и функции) внутри класса.Если возникнут проблемы, удалите символы "_"в фрагменте кода
Private mobjDevice As Object "создание внутренней ссылки "на устройство вывода.Private mfSX1 As Single "Переменные для храненияPrivate mfSY1 As Single "координатPrivate mfXRatio As Single "Переменные для храненияPrivate mfYRatio As Single "масщтабных коэффициентовPrivate mPointArray() As POINTAPI "Массив для хранения координат "верщин многоугольника
После задания внутренних переменных, можно приступить ксозданию свойств класса.
Cоздадим свойство ~~~~~.Device отвечающее за работуAPI функций с устройством вывода.
Property Set Device (objDevice As Object) "Объявление локальных переменных Dim fSX2 As Single Dim fSY2 As Single Dim fPX2 As Single Dim fPY2 As Single Dim nScaleMode As Integer "превращаем присвоенное свойству значение в устройство вывода Set mobjDevice = objDevice With mobjDevice "сохраняем параметры определяющие текущий масштаб nScaleMode = .ScaleMode mfSX1 = .ScaleLeft mfSY1 = .ScaleTop fSX2 = mfSX1 + .ScaleWidth fSY2 = mfSY1 + .ScaleHeight "Временно устанавливаем пиксельный режим .ScaleMode = vbPixels "получаем параметры текущего масштаба "для пиксельного режима fPX2 = .ScaleWidth fPY2 = .ScaleHeight "восстанавливаем исходный масштаб If nScaleMode = 0 Then mobjDevice.Scale (mfSX1, mfSY1)-(fSX2, fSY2) Else mobjDevice.ScaleMode = nScaleMode End If "Вычисляем масштабные коэффициенты mfXRatio = fPX2/(fSX2 - mfSX1) mfYRatio = fPY2/(fSY2 - mfSY1) End If End With End Property
Кстати, ключевое слово Set, следующее за Property,создаёт свойство Device таким образом, что оно должноиспользоваться только с оператором Set.
Следующим шагом будет создание нескольких внутреннихфункций, необходимых для преобразования координат.
Private Function XtoP (fX As Single) As Long XtoP = (fX - mfSX1) * mfXRatioEnd FunctionPrivate Function YtoP (fY As Single) As Long YtoP = (fY - mfSY1) * mfYRatioEnd Function
Нельзя забывать про создание необходимых переменных приинициализации класса.
Private Sub Class_Inintialize () ReDim mPointArray(0)End Sub
Ну и, наконец, приступим к тому ради чего всё это было задумано: к объявлению методов класса, вызывающих ApiФункции.
Начнём с метода ~~~~.Point X, Y , который будет отвечать за запоминание координат вершин многоугольника.
Public Sub Point (fX As Single, fY As Single) " Для тех, кто не знает - Public делает процедуру "Point доступной вне класса. Dim lN As Long lN = UBound(mPointarray) + 1 "Приращение числа точек на 1 Redim Preserve mPointArray(lN) "и создание ещё одного элемента массива. mPointArray(lN).x = XtoP(fX) mPointArray(lN).y = YtoP(fY)End Sub
Следующий метод ~~~~.DrawPolygon должен изображать саммногоугольник, по запомненным вершинам.
Public Sub DrawPolygon () "Вызов API функции для рисования многоугольника Polygon mobjDevice.hdc, mPointArray(1), Ubound(PointArray) "обнуление массива координат верщин ReDim mPointArray(0)End Sub
Теперь разберём метод ~~~~.DrawEllipse X1, Y1, X2, Y2. Отличие егоот метода Circle в том, что аргументы этогометода задают коордианты углов прямоугольника, в который "вписывается" окружность или эллипс. Нелишним будет заметить,что сам VB, как говорилось выше, использует эту APIфункцию передавая ей перерасчитанные аргументы метода Circle.
Public Sub DrawEllipse ( _ fX1 As Single, _ fY1 As Single, _ fX2 As Single, _ fY2 As Single, _) "Вызов API функции Ellipse mobjDevice.hdc, XtoP(fX1), YtoP(fY1), _ XtoP(fX2), YtoP(fY2)End Sub
Ну и последним рассмотрим метод ~~~~.Flood X, Y "заливающий" ограниченный контур.
Public Sub Flood (fX As Single, fY As Single) "Вызов сами знаете чего FloodFill mobjDevice.hdc, XtoP(fX), YtoP(fY), _ mobjDevice.ForeColorEnd Sub
Теперь мы имеем вполне работоспособный класс (надеюсь, что так).Так как нам его использовать?Для этого нужно в проект программы включить файл класса(подразумевается, что класс имеет имя WAGraph, а файлwagraph.cls), а в её текст следующий код.
Dim WAG As New WAGraph
После чего к методам и свойствам класса можно будет обращаться,соблюдая определённую иерархию.
- WAG - имя класса в вашей программе(обязательно для указания)
- Device - свойство (только для записи), определяющееустройство вывода(Например:Set WAG.Device = Form1.Picture1)
- Point(X1, Y1) - метод сохраняющий координату вершинымногоугольника(X1, Y1)
- DrawPolygon - метод рисующий многоугольник.
- DrawEllipse(X1, Y1, X2, Y2) - метод "вписывающий"окружность(эллипс) в воображаемый прямоугольник с координатамилевого верхнего и правого нижнего углов (X1, Y1, X2, Y2 соответственно)
- Flood(X, Y) - метод заполняющий текущим цветом (ForeColor) замкнутый контур. X, Y - координаты точки внутри контура.
Примером обращения к API функциям через этот класс будет:
Set WAG.Device = Form1.Picture1WAG.Ellipse 2, 2, Form1.Picture1.ScaleHeight - 2,Form1.Picture1.ScaleWidth - 2WAG.Flood 1, 1
Результатом должен стать круг, цвет которого задаётся свойствомForeColor Picture1, на фоне, цвет которого - свойство BackColor Picture1.
Напоследок хочу быть честным. Код описанный здесь не совсем моя разработка. Некоторые его части были взяты мною из книг по VBи собраны в один класс.Надеюсь это не уменьшит значение всего этого кода в ваших глазах.
Евгений EugeneO@rambler.ru