Как исп польз события


Пользовательские события.

Иногда удобно определить некоторое выделенное состояние объекта или взаимное состояние объектов как событие. Такое событие не зарегистрировано в операционной системе, Вы должны сами сказать, когда оно произошло, и что при этом делать. Такие события называются пользовательскими событиями.

Пользовательские события описываются в общей области класса, причем описание похоже на описание процедуры или функции, перед которым стоит служебное слово 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