Как исп польз события
Пользовательские события.
Иногда удобно определить некоторое выделенное состояние объекта или взаимное состояние объектов как событие. Такое событие не зарегистрировано в операционной системе, Вы должны сами сказать, когда оно произошло, и что при этом делать. Такие события называются пользовательскими событиями.
Пользовательские события описываются в общей области класса, причем описание похоже на описание процедуры или функции, перед которым стоит служебное слово Event. В методах класса необходимо инициировать события, используя команду RaiseEvent имя_события.
Объектная переменная такого типа (пользовательский класс с событиями) должна описываться со словом WithEvents. Обработчики событий должен писать пользователь Вашего класса.
Пусть описан класс с именем «calc» следующим образом.
Public Event vrong (i As Integer)
Public Function fact(i as integer) as Integer
Dim r as integer, j as Integer
r=1
For j=2 to i
r= r*j
If r>256 Then
RaiseEvent vrong (j)
fact = r
Exit Sub
Endif
Next
fact=r
End Function
Тогда в обычном модуле: описана объектная переменная, создан экземпляр, вызван метод, описан обработчик события.
Dim WithEvents cl as calc
Sub try()
Set cl = New calc
MsgBox cl.fact(5)
MsgBox cl.fact (555)
End Sub
Sub cl_vrong(c as Integer)
MsgBox “Слишком большое число, посчитано только для ” & c
End Sub
При выполнении процедуры try сначала будет выдан результат 120, затем будет выдано сообщение о слишком большом числе и затем – частично посчитанный результат.
Рассмотрим пример, демонстрирующий использование пользовательских событий (т.е. определенных в классе). Задача формулируется следующим образом: класс Class1 в качестве элемента отображения использует Image на форме. Щелчок (click) по image должен регистрироваться и некоторым образом обрабатываться в программе-игре, использующей произвольное количество экземпляров класса Class1. Аналогично должно обрабатываться событие «выход за пределы формы».
Описываем класс class1. Он имеет одно свойство im – ссылка на элемент формы, метод move и два события: click и outform.
Public WithEvents im As Image
Public Event click(str)
Public Event outform(ob)
Private Sub Class_Initialize()
Set im = UserForm1.Controls.Add("Forms.Image.1")
im.Width = 10: im.Height = 10
im.Top = Rnd * 400: im.Left = Rnd * 400
End Sub
Событие click сначала «ловит» операционная система, т.к. оно возникает при щелчке по элементу формы. Умалчиваемая обработка состоит в изменении ширины элемента формы на 10 и в регистрации пользовательского события click, причем это событие имеет параметр str, при его регистрации передается строка с шириной элемента управления.
Private Sub im_Click()
im.Width = im.Width + 10
RaiseEvent click(str(im.Width))
End Sub
Метод move проверяет, не вышел ли элемент за пределы формы. И если нет, то изменяет Top координату элемента формы на 5. В противном случае метод регистрирует событие outform. Параметром в обработчик события передается весь объект – экземпляр класса class1.
Public Sub move()
If im.Top > UserForm1.Height Then
RaiseEvent outform(Me)
Else
im.Top = im.Top + 5
End If
End Sub
Теперь, если на форме нам необходим только один экземпляр класса class1 (или некоторое небольшое фиксированное количество), то мы можем описать на уровне формы переменную, указав описатель WithEvents, пусть назовем ее ob1. После этого в окошке объектов мы можем выбрать объект ob1, в окне событий появятся события, генерируемые этим объектом. Для каждого события мы можем описать обработчик.
Private WithEvents ob1 As Class1
Private Sub UserForm_Initialize()
Set ob1 = New Class1
End Sub
Private Sub ob1_click(str As Variant)
MsgBox "ob1:" & str
ob1.move
End Sub
Private Sub ob1_outform(ob As Variant)
MsgBox "ушел"
End Sub
А что делать, если экземпляров класса несколько, а реакция на события одинаковая или, по крайней мере, отличается незначительно? Не описывать же одно и то же несколько раз. Еще хуже, если мы заранее не знаем, сколько нам потребуется экземпляров класса. Выход мы уже находили. Он состоит в том, что надо описать класс, дочерний по отношению к class1, а в нем описать обработчики событий.
Описываем класс class2, имеющий единственное свойство типа class1. При инициализации создаем экземпляр class1. Описываем обработчики событий click (щелчок) и outform (выход за границы формы). По щелчку просто выдаем на экран переданную родительским классом строчку. А при выходе из формы выдает Top координату и изменяем ее на ноль (перемещаем объект вверх!).
Public WithEvents cls As Class1
Private Sub Class_Initialize()
Set cls = New Class1
End Sub
Private Sub cls_click(str As Variant)
MsgBox str
End Sub
Private Sub cls_outform(ob As Variant)
MsgBox ob.im.Top
ob.im.Top = 0
End Sub
На форме располагаем кнопку, щелчок по которой вызывает создание пяти экземпляров класса class2, ссылки на которые добавляются в коллекцию. Затем в бесконечном цикле вызывается метод move.
Public cl As New Collection
Private Sub Button1_Click()
For i = 1 To 5
cl.Add New Class2
Next
Do While True
For Each c1 In cl
c1.cls.move
Next
Start = Timer ' Set start time.
Do While Timer < Start + 1
DoEvents ' Yield to other processes.
Loop
Loop
End Sub
Вы могли убедиться, что обработка пользовательских событий может быть разная для разных экземпляров.
Важно! Приведенный программный код имеет один существенный недостаток: закрытие формы не останавливает работу программы, т.к. не уничтожаются экземпляры класса class2. Улучшите код, добавив недостающие операторы.
Создание экземпляра класса.
Еще раз повторим все способы создания экземпляра класса (создания объекта).
Наиболее общий способ - применение конструктора New, за которым следует имя класса. Таким образом создаются экземпляры пользовательских классов.
Если вы работаете со встроенной объектной моделью, то часто для создания экземпляра требуется добавить элемент в коллекцию. Таким образом можно добавить лист Excel в коллекцию Sheets, добавить элементы управления на форму (коллекция Controls) и т.п.
Для ActiveX объектов, зарегистрированных в реестре, требуется вызвать CreateObject (или иногда GetObject).
Интересно, что можно воспользоваться и конструктором New для формирования объекта Word из Excel. Рассмотрите пример ниже. Это - программа в Excel, в ней открывается приложение Word, а затем открывается некоторый документ.
Private Sub ww()
Dim w As Word.Application
Set w = New Word.Application
w.Documents.Open "c:\STUDENT\w2.doc"
End Sub