Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование на BASIC / Visual Basic / Гед Мид. Удачные диаграммы GDI+ Работа с графикой [doc].doc
Скачиваний:
32
Добавлен:
02.05.2014
Размер:
870.4 Кб
Скачать

Подвижные направляющие линии

    Мы сделали жизнь относительно легче для себя, поместив заранее установленные и легкие для использования значения. Пока это удобно для целей статьи, я уверен, что вы захотите знать, как вы можете преобразовать логику, что позволит вам создать диаграммы для других диапазонов данных и других размеров дисплеев.

    Вот что мы увидим теперь.

Отображаем направляющие линии

    Вместо использования процедуры, которая использует значения, жестко закодированные в нее, мы перейдем к такой, которая принимает параметры. Мы изменим Sub на Function, что позволит нам передать в нее необходимые параметры и получить взамен вновь созданный объект Bitmap.     Вот замещающая функция:

Private Function DisplayGuidelines(ByVal PicBox As PictureBox, ByVal chunks As Integer) As Bitmap

' Шаг 1

' Создаем bitmap для рисования и захвата его объекта Graphics

Dim bm As New Bitmap(PicBox.Width, PicBox.Height)

Dim gr As Graphics = Graphics.FromImage(bm)

' Шаг 2

' Рисуем направляющие линии на главной диаграмме.

' Получаем общую доступную высоту и делим ее на части

Dim total As Integer = PicBox.Height

Dim chunk As Single = total / chunks

' Шаг 3

For i As Single = chunk To total Step chunk

gr.DrawLine(Pens.WhiteSmoke, 0, i, PicBox.Width, i)

Next i

' Шаг 4

' возвращаем результаты.

Return bm

' Шаг 5

gr.Dispose()

End Function

    Давайте посмотрим на ключевые изменения. Шаг 2 вычисляет вертикальное пространство между каждой строкой. Это легко делается делением всей высоты PictureBox’а на требуемое количество линий. Шаг 3 является общей версией оригинального цикла, который рисует линии; значения больше не кодируются жестко.  Хотя я использовал перо Pens.WhuteSmoke в этой процедуре, вы можете, конечно, добавить третий параметр в нее и позволить клиентскому коду установить цвет пера по выбору. Шаг 4 возвращает объект Bitmap. Он немного отличается от оригинального Sub, в котором мы присваиваем Bitmap PictureBox’у, чье имя закодировано. В этой заменяющей функции мы можем присвоить Bitmap любым, удобным для нас способом, любому элементу управления, который будет его использовать.     Мы вызываем эту функцию в Form_Load:

Private Sub _3rd_More_Generic_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load

picGraph.Image = DisplayGuidelines(picGraph, 12)

End Sub

которая в этом примере создает 12 направляющих линий и рисует их на PictureBox’е, называемом picGraph.

Направляющие линии и отображенные значения

    Давайте посмотрим на процедуру, которая отображает значения более удобные.

    Вот замещающая процедура – и снова Function, а не Sub.

Private Function DisplayGuidelinesAndChart(ByVal PicBox As PictureBox, ByVal chunks As Integer,

_ ByVal XMove As Integer, ByVal NewValue As Single, ByVal Min As Single, ByVal Max As Single) As Bitmap

' Шаг 1

' Захватываем текущее изображение (самая последняя версия диаграммы)

Dim bm As New Bitmap(PicBox.Width, PicBox.Height)

Dim gr As Graphics = Graphics.FromImage(bm)

' Шаг 2

' Получаем общую доступную высоту и делим ее на части

Dim total As Integer = PicBox.Height

Dim chunk As Single = total / chunks

' Отмечаем пропущенные линии справа на объекте Graphics.

For i As Single = chunk To total Step chunk

gr.DrawLine(Pens.WhiteSmoke, PicBox.Width - XMove, i, PicBox.Width, i)

Next i

' Шаг 3

' Рисуем это захваченное изображение, помещаем его в XMove пикселей слева

If Not IsNothing(PicBox.Image) Then

gr.DrawImage(PicBox.Image, -XMove, 0)

End If

' Шаг 4

' Отображаем новое значение.

' Вычисляем требуемый масштаб и делаем полное использование высоты

' PictureBox’а

Dim ValueRange As Single = Max - Min

Dim vScale As Single = PicBox.Height / ValueRange

' Применяем масштаб к текущему значению

NewValue *= vScale

' Шаг 5

' Перемещаем начальную точку с верху слева в низ слева.

gr.TranslateTransform(0, picGraph.Height)

' Шаг 6

' Рисуем следующий сегмент объекта Graphics.

' Если Min > 0, то вам нужно переместить изображение вниз еще раз,

' в этот раз помещаем значение Min на горизонтальную ось

If Min > 0 Then gr.TranslateTransform(0, Min * vScale)

' Шаг 7

' Возвращаем Bitmap.

Return bm

' Шаг 8

' Все сделано

gr.Dispose()

End Function

    Мы расширили параметры и теперь получаем значения от клиента для XMove, NewValue, Min и Max. XMove и NewValue играют ту же роль, что и раньше; передача их, как параметров, делает процедуру более общей. Мы использовали в предыдущей функции целое число «кусков» и их роль та же в этой процедуре.     В Шаге 3 я добавил код, чтобы поймать перемежающуюся ошибку, которая вызовет проблемы. Она может быть обработана, как исключение «Значение не может быть нулевым»; проблема может быть сконцентрирована в PicBox.Image в Form_Load. Я не мог устранить эту ошибку из-за ее неустойчивой природы. Альтернативным решением было бы поместить в метод DrawImage блок Try Catch; это обработает исключение без крушения приложения, но я решил, что при появлении новой формы это вызовет нежелательную задержку, поэтому предпочел IsNothing.     В Шаге 4 параметры Min и Max тоже новые. Они введены для того, чтобы дать вам возможность использовать такие диапазоны значений, в которых значение Minimum не закодировано жестко или не должно равняться нулю. Так же значением Maximum может быть любое число, которое может быть продиктовано любым источником данных. Имея эти два значения в виде параметров, функции позволяется вычислять масштаб, необходимый для заполнения всей доступной высоты PictureBox’а.     Также в Шаге 4 мы вычисляем подходящий масштаб, основываясь на доступной высоте PictureBox’а и определенного диапазона Maximum. В предыдущих примерах, как вы можете помнить, что жестко был закодирован масштаб 4:1. Теперь у нас есть бóльшая подвижность.     В Шаге 6, как должно быть ясно из комментариев, нам нужно переместить изображение так, чтобы минимальное значение (если оно есть) было помещено точно на линию горизонтальной оси. Метод TranslateTransform просто перемещает начальную точку рисования на соответствующее значение. Вот и все, ничего нового больше нет.