412 000 произведений, 108 200 авторов.

Электронная библиотека книг » Иво Салмре » Программирование мобильных устройств на платформе .NET Compact Framework » Текст книги (страница 65)
Программирование мобильных устройств на платформе .NET Compact Framework
  • Текст добавлен: 18 июля 2025, 02:31

Текст книги "Программирование мобильных устройств на платформе .NET Compact Framework"


Автор книги: Иво Салмре



сообщить о нарушении

Текущая страница: 65 (всего у книги 69 страниц)

  Case System.Xml.XmlNodeType.Element

   Dim nodeName As String = xmlReader.Name

   LoadHelper_NewElementEncountered(nodeName, _

    currentReadLocation)

   '–

   'Здесь мы можем извлечь некоторый фактический текст

   'и получить данные, которые пытаемся загрузить

   '–

  Case System.Xml.XmlNodeType.Text

   Select Case currentReadLocation

   Case ReadLocation.inFirstName

    firstName = xmlReader.Value

   Case ReadLocation.inLastName

    lastName = xmlReader.Value

   Case ReadLocation.inUserID

    userId = CInt(xmlReader.Value)

   End Select

   'Конец оператора Case "System.Xml.XmlNodeType.Text"

   '–

   'Вызывается, когда встречается конец

   'элемента

   '

   'Мы можем захотеть переключить состояние в зависимости

   'от вида покидаемого узла, чтобы указать на то, что

   'собираемся вернуться назад к его предку

   '–

  Case System.Xml.XmlNodeType.EndElement

   Dim continueParsing As Boolean

   continueParsing = LoadHelper_EndElementEncountered( _

    currentReadLocation)

   If (continueParsing = False) Then

    GoTo finished_reading_wanted_data

   End If

  Case Else

   'He страшно, если имеются XML-узлы других типов, но

   'в нашем примере работы с XML-документом мы должны

   'оповестить об этом факте

   MsgBox( _

    "Встретился непредвиденный XML-тип " + xmlReader.Name)

  End Select 'Конец оператора Case, используемого для определения текущего

  'типа XML-элeмeнтa, oбpaбaтывaeмoгo анализатором

  'Перейти к следующему узлу

  readSuccess = xmlReader.Read()

 End While

 'Если мы оказались в этом месте программы, не покинув

 'XML-дескриптора UserInfo, то с XML-данными, которые мы считываем,

 'что-то не так

 Throw New Exception("He найден элемент UserInfo в XML-документе!")

finished reading_wanted_data:

 'Закрыть файл, поскольку работа с ним закончена!

 xmlReader.Close()

End Sub

'–

'Вспомогательный код, ответственный за принятие решения

'относительно того, в какое состояние необходимо перейти,

'когда встречается закрывающий дескриптор

'–

Private Shared Function LoadHelper_EndElementEncountered( _

 ByRef currentReadLocation As ReadLocation) As Boolean

 Select Case (currentReadLocation)

 'Если мы покидаем узел Name, то должны вернуться

 'обратно в узел UserInfo

 Case ReadLocation.inName

  currentReadLocation = ReadLocation.inUserInfo

 'Если мы покидаем узел FirstName, то должны вернуться

 'обратно в узел Name

 Case ReadLocation.inFirstName

  currentReadLocation = ReadLocation.inName

 'Если мы покидаем узел LastName, то должны вернуться

 'обратно в узел Name

  Case ReadLocation.inLastName

   currentReadLocation = ReadLocation.inName

 'Если мы покидаем узел UserID, то должны вернуться

 'обратно в узел UserInfo

 Case ReadLocation.inUserID

  currentReadLocation = ReadLocation.inUserInfo

 'Если мы покидаем узел UserInfo, то мы только что

 'закончили чтение данных в узлах UserID, FirstName

 'и LastName

 '

 'Можно выйти из цикла, поскольку у нас уже есть вся

 'информация, которую мы хотели получить!

 Case ReadLocation.inUserInfo

  Return False 'Анализ должен быть прекращен

 End Select

 Return True

 'Продолжить анализ

End Function

Private Shared Sub LoadHelper_NewElementEncountered( _

 ByVal nodeName As String, _

 ByRef currentReadLocation As ReadLocation)

 '–

 'Мы вошли в новый элемент!

 'В какое состояние переход возможен, зависит от того,

 'в каком состоянии мы находимся в данный момент

 '–

 Select Case (currentReadLocation)

 'Если мы находимся в узле AllMyData, то переход возможен

 'в узлы, которые указаны ниже

 Case (ReadLocation.inAllMyData)

  If (nodeName = XML_USERINFO_TAG) Then

   currentReadLocation = ReadLocation.inUserInfo

  End If

 'Если мы находимся в узле UserInfo, то переход возможен

 'в узлы, которые указаны ниже

 Case (ReadLocation.inUserInfo)

  If (nodeName = XML_USERID_TAG) Then

   currentReadLocation = ReadLocation.inUserID

  ElseIf (nodeName = XML_NAMEINFO_TAG) Then

   currentReadLocation = ReadLocation.inName

  End If

 'Если мы находимся в узле Name, то переход возможен

 'в узлы, которые указаны ниже

 Case (ReadLocation.inName)

  If (nodeName = XML_FIRSTNAME_TAG) Then

   currentReadLocation = ReadLocation.inFirstName

  ElseIf (nodeName = XML LASTNAME_TAG) Then

   currentReadLocation = ReadLocation.inLastName

  End If

 End Select

End Sub

End Class

Примеры к главе 11 (производительность и графика)
Листинг 11.1. Заполнение данными и очистка от них элементов управления TreeView с использованием альтернативных стратегий

'–

'Примечание #1: В этом примере используется класс PerformanceSampling,

' определённый ранее в данной книге. Убедитесь в том, что

' вы включили этот класс в свой проект.

'Примечание #2: Этот код необходимо включить в класс Form, содержащий элемент

 ' управления TreeView и кнопки Button, к которым подключены

' приведенные ниже функции xxx_Click.

'–

'Количество элементов, которые необходимо поместить в элемент

'управления TreeView

Const NUMBER_ITEMS As Integer = 800

'–

'Код для кнопки "Fill: Baseline"

'Использование неоптимизированного подхода для заполнения данными элемента

'управления TreeView

'–

Private Sub UnOptimizedFill_Click(ByVal sender As _

 System.Object, ByVal e As System.EventArgs) _

 Handles UnOptimizedFill.Click

 'Очистить массив для создания одинаковых условий тестирования

 If (TreeView1.Nodes.Count > 0) Then

  TreeView1.BeginUpdate()

  TreeView1.Nodes.Clear()

  TreeView1.EndUpdate()

  TreeView1.Update()

 End If

 'Для повышения корректности тестирования предварительно выполнить

 'операцию сборки мусора. В реальных кодах этого делать не следует!

 System.GC.Collect()

 'Запустить таймер

 PerformanceSampling.StartSample(0, "TreeViewPopulate")

 'Заполнить данными элемент управления TreeView

 Dim i As Integer

 For i = 1 To NUMBER_ITEMS

  TreeView1.Nodes.Add("TreeItem" + CStr(i))

 Next

 'Остановить таймер и отобразить результат

 PerformanceSampling.StopSample(0)

 MsgBox(PerformanceSampling.GetSampleDurationText(0))

End Sub

'–

'Код для кнопки "Clear: Baseline"

'Использование неоптимизированного подхода для заполнения данными элемента

'управления TreeView

'–

Private Sub UnOptimizedClear_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles UnOptimizedClear.Click

 'Для повышения корректности тестирования предварительно выполнить

 'операцию сборки мусора

 System.GC.Collect()

 'Запустить таймер

 PerformanceSampling.StartSample(1, "TreeViewClear")

 TreeView1.Nodes.Clear()

 PerformanceSampling.StopSample(1)

 MsgBox(PerformanceSampling.GetSampleDurationText(1))

End Sub

'–

'Код для кнопки "Fill: BeginUpdate"

'Подход, в котором используется метод BeginUpdate()

'–

Private Sub UseBeginEndUpdateForFill_Click(ByVal sender As _

 System.Object, ByVal e As System.EventArgs) _

 Handles UseBeginEndUpdateForFill.Click

 'Очистить массив для создания одинаковых условий тестирования

 If (TreeView1.Nodes.Count > 0) Then

  TreeView1.BeginUpdate()

  TreeView1.Nodes.Clear()

  TreeView1.EndUpdate()

  TreeView1.Update()

 End If

 'Для повышения корректности тестирования предварительно выполнить

 'операцию сборки мусора. В РЕАЛЬНЫХ КОДАХ ЭТОГО ДЕЛАТЬ НЕ СЛЕДУЕТ!

 System.GC.Collect()

 'Запустить таймер

 PerformanceSampling.StartSample(2, _

  "Populate – Use BeginUpdate")

 'Заполнить данными элемент управления TreeView

 TreeView1.BeginUpdate()

 Dim i As Integer

 For i = 1 To NUMBER_ITEMS

  TreeView1.Nodes.Add("TreeItem" + i.ToString())

 Next

 TreeView1.EndUpdate()

 'Остановить таймер и отобразить результат

 PerformanceSampling.StopSample(2)

 MsgBox(PerformanceSampling.GetSampleDurationText(2))

End Sub

'–

'Код для кнопки "Clear: BeginUpdate"

'Подход, в котором используется метод BeginUpdate()

'–

Private Sub UseBeginEndUpdateForClear_Click(ByVal sender As _

 System.Object, ByVal e As System.EventArgs) _

 Handles UseBeginEndUpdateForClear.Click

 'Для повышения корректности тестирования предварительно выполнить

 'операцию сборки мусора. В РЕАЛЬНЫХ КОДАХ ЭТОГО ДЕЛАТЬ НЕ СЛЕДУЕТ!

 System.GC.Collect()

 'Запустить таймер

 PerformanceSampling.StartSample(3, "Clear – Use BeginUpdate")

 TreeView1.BeginUpdate()

 TreeView1.Nodes.Clear()

 TreeView1.EndUpdate()

 'Остановить таймер и отобразить результат

 PerformanceSampling.StopSample(3)

 MsgBox(PerformanceSampling.GetSampleDurationText(3))

End Sub

'–

'Код для кнопки "Fill: Use Array"

'Подход, в котором используется массив

'–

Private Sub FillArrayBeforeAttachingToTree_Click(ByVal _

 sender As System.Object, ByVal e As System.EventArgs) _

 Handles FillArrayBeforeAttachingToTree.Click

 'Очистить массив для создания одинаковых условий тестирования

 If (TreeView1.Nodes.Count > 0) Then

  TreeView1.BeginUpdate()

  TreeView1.Nodes.Clear()

  TreeView1.EndUpdate()

  TreeView1.Update()

 End If

 'Для повышения корректности тестирования предварительно выполнить

 'операцию сборки мусора. В РЕАЛЬНЫХ КОДАХ ЭТОГО ДЕЛАТЬ НЕ СЛЕДУЕТ!

 System.GC.Collect()

 'Запустить таймер

 PerformanceSampling.StartSample(4, "Populate – Use Array")

 'Распределить память для нашего массива узлов дерева

 Dim newTreeNodes() As System.Windows.Forms.TreeNode

 ReDim newTreeNodes(NUMBER_ITEMS – 1)

 'Заполнить массив

 Dim i As Integer

 For i = 0 To NUMBER_ITEMS – 1

  newTreeNodes(i) = _

   New System.Windows.Forms.TreeNode("TreeItem" + _

   i.ToString())

 Next

 'Связать массив с элементом управления TreeView

 TreeView1.BeginUpdate()

 TreeView1.Nodes.AddRange(newTreeNodes)

 TreeView1.EndUpdate()

 'Остановить таймер и отобразить результат

 PerformanceSampling.StopSample(4)

 MsgBox(PerformanceSampling.GetSampleDurationText(4))

End Sub

Листинг 11.2. Динамическое заполнение данными элемента управления TreeView

'Фиктивный текст для размещения в заполнителях дочерних узлов

Const dummy_node As String = "_dummynode"

'Метка, которую мы будем использовать для обозначения узла

Const node_needToBePopulated As String = "_populateMe"

'Текст, который мы будем использовать для наших узлов высшего уровня

Const nodeText_Neighborhoods As String = "Neighborhoods"

Const nodeText_Prices As String = "Prices"

Const nodeText_HouseType As String = "HouseTypes"

'–

'Обработчик события щелчка для кнопки

'Настраивает наш элемент управления TreeView для отображения процесса

'последовательного заполнения дерева

'–

Private Sub Button1_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button1.Click

 Dim tnNewNode As TreeNode

 'Отключить обновление ПИ до тех пор, пока дерево не будет заполнено

 TreeView1.BeginUpdate()

 'Избавиться от устаревших данных

 TreeView1.Nodes.Clear()

 '–

 'Узел "Neighborhoods"

 '–

 'Добавить узел "Neighborhoods" верхнего уровня.

 tnNewNode = TreeView1.Nodes.Add("Neighborhoods")

 'Установить для узла метку, указывающую на то, что узел

 'будет заполняться динамически

 tnNewNode.Tag = node_needToBePopulated

 'Этот фиктивный дочерний узел существует лишь для того, чтобы

 'узел имел, по крайней мере, один дочерний узел и поэтому

 'был расширяемым.

 tnNewNode.Nodes.Add(dummy_node)

 '–

 'Узел "Price"

 '–

 tnNewNode = TreeView1.Nodes.Add("Price")

 'Установить для узла метку, указывающую на то, что узел

 'будет заполняться динамически

 tnNewNode.Tag = node_needToBePopulated

 'Этот фиктивный дочерний узел существует лишь для того, чтобы

 'узел имел, по крайней мере, один дочерний узел и поэтому

 'был расширяемым

 tnNewNode.Nodes.Add(dummy_node)

 '–

 'Узел "HouseType"

 '–

 tnNewNode = TreeView1.Nodes.Add("HouseType")

 'Установить для узла метку, указывающую на то, что узел

 'будет заполняться динамически

 tnNewNode.Tag = node_needToBePopulated

 'Этот фиктивный дочерний узел существует лишь для того, чтобы

 'узел имел, по крайней мере, один дочерний узел и поэтому

 'был расширяемым.

 tnNewNode.Nodes.Add(dummy node)

 'Восстанавливаем обновление ПИ

 TreeView1.EndUpdate()

End Sub

''–

''Обработчик событий BeforeExpand для нашего элемента управления TreeView

''ПРИМЕЧАНИЕ: В отличие от C#, данный обработчик

''      НЕ требует от вас связываться дорабатывать код

''      "InitializeComponent()" (не делайте этого!)

''      Вы можете просто выбрать событие обычным путем

''      выпадающего списка событий в редакторах VB

''

''Вызывается при запросе пользователем расширения узла, у которого имеется,

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

''дочерних узлов данного узла и дает нам возможность динамически заполнить

''данными элемент управления TreeView.

''–

Private Sub TreeView1_BeforeExpand(ByVal sender As Object, _

 ByVal e As System.Windows.Forms.TreeViewCancelEventArgs) _

 Handles TreeView1.BeforeExpand

 'Получить узел, который будет расширяться

 Dim tnExpanding As System.Windows.Forms.TreeNode

 tnExpanding = e.Node

 'Если узел не отмечен как "нуждающийся в заполнении данными",

 'то он устраивает нас в том виде, "как он есть".

 If Not (tnExpanding.Tag Is node needToBePopulated) Then

  Return 'Разрешить беспрепятственное продолжение выполнения

 End If

 'Требуется динамическое заполнение дерева данными.

 'Мы знаем, что узел должен быть заполнен данными; определить,

 'что это за узел

 If (tnExpanding.Text = nodeText_Neighborhoods) Then

  PopulateTreeViewNeighborhoods(tnExpanding)

  Return 'done adding items!

 Else

  'Проверить другие возможности для узлов дерева, которые мы должны

  'добавить.

  MsgBox("HE СДЕЛАНО: Добавьте код для динамического заполнения этого узла")

  'Снять отметку с этого узла, чтобы мы не могли вновь выполнить

  'этот код

  tnExpanding.Tag = ""

 End If

End Sub

'–

'Эта функция вызывается для динамического добавления дочерних узлов

'в узел "Neighborhood"

'–

Sub PopulateTreeViewNeighborhoods(ByVal tnAddTo As TreeNode)

 Dim tvControl As TreeView

 tvControl = tnAddTo.TreeView

 tvControl.BeginUpdate()

 'Очистить имеющийся фиктивный узел

 tnAddTo.Nodes.Clear()

 'Объявить четыре узла, которые мы хотим сделать дочерними узлами

 'того узла, который был передан.

 Dim newNeighborhoodNodes() As TreeNode

 ReDim newNeighborhoodNodes(3)

 newNeighborhoodNodes(0) = New TreeNode("Capitol Hill")

 newNeighborhoodNodes(1) = New TreeNode("Chelsea")

 newNeighborhoodNodes(2) = New TreeNode("Downtown")

 newNeighborhoodNodes(3) = New TreeNode("South Bay")

 'Добавить дочерние узлы в элемент управления TreeView

 tnAddTo.Nodes.AddRange(newNeighborhoodNodes)

 tvControl.EndUpdate()

End Sub

Листинг 11.3. Запуск обработчика событий при изменении содержимого элемента TextBox программным путем

Private m_eventTriggerCount As Integer

Private Sub Button1_Click(ByVal sender As System.Object, _

 ByVal e As  System.EventArgs) Handles Buttonl.Click

 'Запускает событие TextChanged так же,

 'как если бы текст был введен пользователем

 TextBox1.Text = "Привет, мир"

End Sub

Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles TextBox1.TextChanged

 m_eventTriggerCount = m_eventTriggerCount + 1

 'Обновить надпись для отображения количества событий

 Label1.Text = "Событий: #" + CStr(m_eventTriggerCount)

 'Внести каждое событие в список

 ListBox1.Items.Add(m_eventTriggerCount.ToString() + TextBox1.Text)

End Sub

Листинг 11.4. Использование модели состояний для обновления интерфейса и контроль запуска событий с целью более глубокого изучения процесса обработки событий и управления им

'–

'Для активизации контроля запуска событий:

' #Const EVENTINSTRUMENTATION = 1

'Для отмены контроля запуска событий:

' #Const EVENTINSTRUMENTATION = 0

'–

#Const EVENTINSTRUMENTATION = 1

'–

'Флаг, указывающий обработчикам событий, должен ли из них осуществляться

'выход без выполнения каких-либо действий

'–

Private m_userInterfaceUpdateOccuring As Boolean

'Счетчики событий

Private m_radioButton1ChangeEventCount As Integer

Private m_textBox1ChangeEventCount As Integer

'–

'Код, который следует включать лишь в том случае, если приложение

'выполняется в режиме контроля запуска событий. Этот код характеризуется

'относительно высокими накладными расходами, и его следует компилировать и

'выполнять только тогда, когда выполняется диагностика.

'–

#If EVENTINSTRUMENTATION <> 0 Then

Private m_instrumentedEventLog As System.Collections.ArrayList

'–

'Заносит записи о возникновении событий в массив, который мы

'можем просмотреть

'Примечание: Не делается никаких попыток ограничить размерность массива

'  регистрационных записей, поэтому, чем дольше выполняется приложение,

'  тем больше становится размер массива

'–

Private Sub instrumented_logEventOccurrence(ByVal eventData _

 As String)

 'Создать журнал событий, если он еще не был создан

 If (m_instrumentedEventLog Is Nothing) Then

  m_instrumentedEventLog = _

   New System.Collections.ArrayList

 End If

 'Зарегистрировать событие

 m_instrumentedEventLog.Add(eventData)

End Sub

'–

'Отобразить список возникших событий

'Примечание: Этот вариант реализации довольно груб.

' Целесообразнее отображать список событий

' в отдельном диалоговом окне, которое специально выводится

' для этого на экран.

'–

Private Sub instrumentation_ShowEventLog() Dim listItems As _

 System.Windows.Forms.ListBox.ObjectCollection

 listItems = listBoxEventLog.Items

 'Очистить список элементов

 listItems.Clear()

 'При отсутствии событий – выход

 If (m instrumentedEventLog Is Nothing) Then

  listItems.Add("0 событий")

  Return

 End If

 'Отобразить поверх списка общее количество

 'подсчитанных нами событий

 listItems.Add(m_instrumentedEventLog.Count.ToString() + _

  " событий")

 'Перечислить элементы списка в обратном порядке, чтобы

 'первыми отображались самые последние из них

 Dim logItem As String

 Dim listIdx As Integer

 For listIdx = _

  m_instrumentedEventLog.Count – 1 To 0 Step -1

  logItem = CStr(m_instrumentedEventLog(listIdx))

  listItems.Add(logItem)

 Next

End Sub

#End If

'–

'Событие изменения состояния переключателя RadioButton1

'–

Private Sub RadioButton1_CheckedChanged(ByVal sender As _

 System.Object, ByVal e As System.EventArgs) _

 Handles RadioButton1.CheckedChanged

 'Если обновление данных в пользовательском интерфейсе осуществляется

 'приложением, то мы не хотим обрабатывать его так же, как если бы

 'это событие было запущено пользователем. Если это именно так,

 'то осуществить выход из функции без выполнения каких-либо действий.

 If (m userInterfaceUpdateOccuring = True) Then

  Return

 End If

 'Подсчитать, сколько раз выполнена обработка данного события

 m_radioButtonlChangeEventCount = _

  m_radioButtonlChangeEventCount + 1

#If (EVENTINSTRUMENTATION <> 0) Then

 'Зарегистрировать наступление события

 instrumented_logEventOccurrence("radioButton1.Change:" + _

  m_radioButton1ChangeEventCount.ToString() + ":" + _

  RadioButton1.Checked.ToString()) 'value

#End If

End Sub

'–

'Событие щелчка на кнопке Button1

'Имитирует обновление пользовательского интерфейса программным

'кодом, что может приводить к запуску обработчика события

'–

Private Sub Button1_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button1.Click

 'Указать на то, что мы не хотим, чтобы обработчики сразу же

 'обрабатывали события, поскольку мы обновляем

 'пользовательский интерфейс.

 'm_userInterfaceUpdateOccuring = true;

 RadioButton1.Checked = True

 TextBox1.Text = "Hello World"

 'Обновление пользовательского интерфейса закончено

 m_userInterfaceUpdateOccuring = False

End Sub

'–

'Обработчик события изменения состояния элемента управления TextBox

'–

Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles TextBox1.TextChanged

 'Если обновление данных в пользовательском интерфейсе осуществляется

 'приложением, то мы не хотим обрабатывать его так же, как если бы

 'это событие было запущено пользователем. Если это именно так,

 'то осуществить выход из функции без выполнения каких-либо действий.

 If (m_userInterfaceUpdateOccuring = True) Then

  Return

 End If

 'Подсчитать, сколько раз выполнена обработка данного события

 m_textBox1ChangeEventCount = m_textBox1ChangeEventCount + 1

#If EVENTINSTRUMENTATION <> 0 Then

 'Занести событие в журнал

 instrumented_logEventOccurrence("textBox1.Change:" + _

  m_textBoxlChangeEventCount.ToString() + ":" + _

  TextBox1.Text.ToString()) 'Value

#End If

End Sub

Private Sub buttonShowEventLog_Click(ByVal sender As _

 System.Object, ByVal e As System.EventArgs) _

 Handles buttonShowEventLog.Click

#If EVENTINSTRUMENTATION <> 0 Then

 instrumentation_ShowEventLog()

#End If

End Sub

Листинг 11.5. Вызов метода Update() элемента управления для отображения пояснительного текста, информирующего о ходе выполнения задачи

'–

'Этот код принадлежит форме, содержащей по одному элементу управления

'Button (button1) и Label (label1)

'–

Private Sub Button1_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button1.Click

 'Отобразить курсор ожидания

 System.Windows.Forms.Cursor.Current = _

  System.Windows.Forms.Cursors.WaitCursor

 Dim testString As String

 Dim loop3 As Integer

 For loop3 = 1 To 100 Step 10

  Label1.Text = loop3.ToString() + "% Done..."

  '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  'Чтобы отобразить информацию о процессе обновления,!

  'удалите символы комментария в строке ниже         !

  '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  'Label1.Update()

  testString = ""

  Dim loop2 As Integer

  For loop2 = 1 To 1000

   testString = testString + "тест"

  Next

 Next

 Label1.Text = "Готово!"

 'Удалить курсор ожидания

 System.Windows.Forms.Cursor.Current = _

  System.Windows Forms.Cursors.Default

End Sub

Листинг 11.6. Создание изображения на внеэкранной растровой поверхности и передача его в элемент управления PictureBox

'–

'Создать рисунок на растровой поверхности. Переслать его в PictureBox

'–

Private Sub Button1_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button1.Click

 'Создать новую битовую карту

 Dim myBitmap As System.Drawing.Bitmap

 myBitmap = New System.Drawing.Bitmap(PictureBox1.Width, _

  PictureBox1.Height)

 '–

 'Создать объект Graphics, чтобы иметь возможность рисовать на битовой карте

 '–

 Dim myGfx As System.Drawing.Graphics

 myGfx = System.Drawing.Graphics.FromImage(myBitmap)

 'Закрасить нашу битовую карту желтым цветом

 myGfx.Clear(System.Drawing.Color.Yellow)

 'Создать перо

 Dim myPen As System.Drawing.Pen

 rayPen = New System.Drawing.Pen(System.Drawing.Color.Blue)

 '–

 'Нарисовать эллипс

 '–

 myGfx.DrawEllipse(myPen, 0, 0, myBitmap.Width – 1, _

  myBitmap.Height – 1)

 'Создать сплошную кисть

 Dim myBrush As System.Drawing.Brush

 '–

 'Нарисовать текст кистью

 '–

 myBrush = New System.Drawing.SolidBrush( _

  System.Drawing.Color.Black)

 'Примечание: мы используем объект Font из формы

 myGfx.DrawString("Привет!", Me.Font, myBrush, 2, 10)

 '–

 'Важно! Очистить все после себя

 '–

 myGfx.Dispose()

 myPen.Dispose()

 myBrush.Dispose()

 '–

 'Указать объекту pictureBox, на необходимость отображения растрового

 'изображения, которое мы только что создали и нарисовали.

 '–

 PictureBox1.Image = myBitmap

End Sub

Листинг 11.7. Создание объекта Graphics для формы

'–

'Создает объект Graphics для формы и осуществляет рисование

'–

Private Sub Button1_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button1.Click

 'Создать объект Graphics для формы

 Dim myGfx As System.Drawing.Graphics

 myGfx = Me.CreateGraphics()

 'Создать кисть

 Dim myBrush As System.Drawing.Brush

 myBrush = New System.Drawing.SolidBrush( _

  System.Drawing.Color.DarkGreen)

 'Заполнить прямоугольник

 myGfx.FillRectangle(myBrush, 4, 2, 60, 20)

 '–

 'Важно: Выполнить очистку!

 '–

 myBrush.Dispose()

 myGfx.Dispose()

End Sub

Листинг 11.8. Подключение к функции Paint формы

'Кисти, которые мы хотим кэшировать, чтобы избавить себя от необходимости

'все время создавать их и уничтожать

Private m_brushBlue As System.Drawing.Brush

Private m_brushYellow As System.Drawing.Brush

'Ради интереса подсчитаем, сколько раз осуществлялся вызов

Private m_paintCount As Integer

'–

'Мы перекрываем обработчики событий Paint наших базовых классов. Это означает,

'что каждый раз, когда форма вызывается для перерисовки самой себя, будет

'вызываться эта функция.

'–

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

 'ВАЖНО: Вызвать базовый класс и дать ему возможность

 'выполнить всю необходимую работу по рисованию

 MyBase.OnPaint(e)

 'Увеличить на 1 значение счетчика вызовов

 m_paintCount = m_paintCount + 1

 '–

 'Важно:

 'Вместо того чтобы создавать объект Graphics, мы получаем его

 'на время данного вызова. Это означает, что освобождать память путем вызова

 'метода .Dispose() объекта – не наша забота

 '–

 Dim myGfx As System.Drawing.Graphics

 myGfx = e.Graphics

 '–

 'Поскольку эту операцию рисования необходимо выполнить быстро,

 'кэшируем кисти, чтобы избавить себя от необходимости создавать их и

 'уничтожать при каждом вызове

 '–

 If (m_brushBlue Is Nothing) Then

  m_brushBlue = New System.Drawing.SolidBrush( _

   System.Drawing.Color.Blue)

 End If

 If (m_brushYellow Is Nothing) Then

  m_brushYellow = New System.Drawing.SolidBrush( _

   System.Drawing.Color.Yellow)

 End If

 '–

 'Выполнить рисование

 '–

 myGfx.FillRectangle(m_brushBlue, 2, 2, 100, 100)

 myGfx.DrawString("PaintCount: " + CStr(m_paintCount), _

  Me.Font, m_brushYellow, 3, 3)

 'Выход: Объекты, для которых мы должны были бы вызывать метод

 '.Dispose(), отсутствуют.

End Sub

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

'Простейший пользовательский элемент управления

Public Class myButton

Inherits System.Windows.Forms.Control

'–

'Объекты, необходимые нам для рисования

'–

Private m_RectangleBrush As System.Drawing.Brush

Private m_TextBrush As System.Drawing.Brush

Private m_RectangleColor As System.Drawing.Color

'–

'Событие, которое мы хотим предоставить на обработку. Это – общедоступный

'делегат.

'–

Public Event EventButtonTurningBlue(ByVal sender As Object, _

 ByVal e As System.EventArgs)

 'Конструктор

 Public Sub New()

  MyBase.New()

  'ПРИМЕЧАНИЕ: Мы должны написать функцию "Dispose()" и

  'деструктор, который освобождает память от этих объектов

  'Создать необходимые кисти

  m_RectangleColor = System.Drawing.Color.Black

  m_RectangleBrush = New System.Drawing.SolidBrush( _

   m_RectangleColor)

  m_TextBrush = New System.Drawing.SolidBrush( _

   System.Drawing.Color.White)

End Sub

'–

'Внутренним откликом на щелчок является

'повторение трех различных цветов кнопки в цикле

'–

Protected Overrides Sub OnClick(ByVal e As System.EventArgs)

 '–

 'Важно: Вызвать базовую реализацию. Это

 'обеспечит возможность вызова любого обработчика событий,

 'подключенного к данному элементу управления

 '–

 MyBase.OnClick (e)

 '–

 'Выбрать цвет новой кисти, исходя из цвета старой кисти

 '–

 If (m_RectangleColor.Equals(System.Drawing.Color.Black)) Then

  m_RectangleColor = System.Drawing.Color.Blue

  '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  'Запустить событие!

  '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  'Возбудить событие без передачи аргумента

  RaiseEvent EventButtonTurningBlue(Me, Nothing)

 ElseIf (m_RectangleColor.Equals(System.Drawing.Color.Blue)) Then

  m_RectangleColor = System.Drawing.Color.Red

 Else

  m_RectangleColor = System.Drawing.Color.Black

 End If

 '–

 'Освободить старую кисть

 '–

 m_RectangleBrush.Dispose()

 '–

 'Создать новую кисть, которую мы собираемся использовать для фона

 '–

 m_RectangleBrush = _

  New System.Drawing.SolidBrush(m_RectangleColor)

 '–

 'Сообщить операционной системе, что наш элемент управления

 'должен быть перерисован, как только представится возможность

 '–

 Me.Invalidate()

End Sub

'–

'Ради интереса подсчитаем, сколько раз осуществлялась перерисовка

'–

Private m_paintCount As Integer

Protected Overrides Sub OnPaint( _

 ByVal e As System.Windows.Forms.PaintEventArgs)

 '–

 'ВАЖНО: Вызвать базовый класс и позволить ему

 'выполнить работу по рисованию

 '–

 MyBase.OnPaint(e)

 'Увеличить на единицу значение счетчика вызовов

 m_paintCount = m_paintCount + 1

 '–

 'Важно:

 'Вместо того чтобы создавать объект Graphics, мы получаем его

 'на время данного вызова. Это означает, что освобождать память путем вызова

 'метода .Dispose() объекта – не наша забота

 '–

 Dim myGfx As System.Drawing.Graphics

 myGfx = e.Graphics

 'Нарисовать прямоугольник

 myGfx.FillRectangle(m_RectangleBrush, 0, 0, _

  Me.Width, Me.Height)

 'Нарисовать текст

 myGfx.DrawString("Button! Paint: " + m_paintCount.ToString(), _

  Me.Parent.Font, m_TextBrush, 0, 0)

End Sub

End Class

Листинг 11.10. Код, который должен быть помещен в форму для создания экземпляра пользовательского элемента управления

'Наша новая кнопка

Private m_newControl As myButton

'–

'Этот код будет подключен в качестве нашего обработчика событий

'–

Private Sub CallWhenButtonTurningBlue(ByVal sender As Object, _

 ByVal e As System.EventArgs)

 MsgBox("Кнопка становится синей!")

End Sub

'–

'Эта функция подключается для обработки событий

'щелчка на кнопке Button1

'–

Private Sub Button1_Click(ByVal sender As System.Object, _

 ByVal e As System.EventArgs) Handles Button1.Click

 '–

 'Для простоты мы допускаем существование только

 'одного экземпляра элемента управления,

 '–

 If Not (m_newControl Is Nothing) Then Return

  'Создать экземпляр нашей кнопки

  m_newControl = New myButton

  'Указать ему его местоположение внутри родительского объекта

  m_newControl.Bounds = New Rectangle(10, 10, 150, 40)

 '–

 'Присоединить обработчик событий

 '–

 AddHandler m_newControl.EventButtonTurningBlue, _

  AddressOf CallWhenButtonTurningBlue

 'Добавить его в список элементов управления данной формы.

 'Это сделает его видимым

 Me.Controls.Add(m_newControl)

End Sub

Листинг 11.11. Три полезных способа кэширования графических ресурсов

Imports System

Imports System.Drawing

Friend Class GraphicsGlobals

'=======================================================================

'Подход 1: Создать ресурс по требованию

'         и кэшировать его для последующего использования.

'

'Внешний код получает доступ к общедоступным свойствам для их просмотра,

'но сами переменные остаются внутренними переменными класса

'=======================================================================

Private Shared s_bluePen As Pen

Public Shared ReadOnly Property globalBluePen() As Pen

 Get

  'Если перо еще не было создано

  If (s_bluePen Is Nothing) Then

   s_bluePen = New System.Drawing.Pen( _

    System.Drawing.Color.Blue)


    Ваша оценка произведения:

Популярные книги за неделю