Основы офисного программирования и язык VBA

         

Как зажигаются события


Чтобы событие, связанное с объектом возникло, его нужно зажечь или возбудить (Raise). Зажигается событие специальной процедурой RaiseEvent, имеющей следующий синтаксис:

Sub RaiseEvent имя_события (параметры)

Эта процедура не только возбуждает событие, но и передает некоторые параметры, которые могут быть использованы в обработчике события. Что стоит за терминами "зажечь" ("возбудить") событие? При выполнении этой процедуры операционной системе посылается уведомление о том, что та должна послать объекту сообщение о возникновении события с указанным именем, в ответ на получение которого будет вызван обработчик этого события. Так что при выполнении этой процедуры плавный ход выполнения программы прерывается, происходит обмен сообщениями, вызов обработчика события и только по его завершении будет продолжено выполнение операторов, стоящих после вызова RaiseEvent.

Процедура RaiseEvent должна выполняться в одном из методов класса с событиями. Правильное определение ее места, это также одна из задач, которую нужно решить при проектировании класса, возможно, придется создавать специальный метод для этой цели. Обратимся к нашему примеру, когда и где нужно зажечь событие ИзменениеФамилии. Здесь ответ очевиден, - всякий раз, когда у объекта изменяется значение свойства Фамилия, должно возникать это событие. Но изменять значение для Private свойства следует единственным образом, - вызовом Property Let ВашаФамилия. Поэтому эта процедура именно то место, где должно возбуждаться событие. А в процедуре разумно поставить вызов RaiseEvent непосредственно перед оператором, изменяющим фамилию. Вот как выглядит эта процедура:

Public Property Let ВашаФамилия(ByVal NewValue As String) 'Зажигает событие ИзменениеФамилии RaiseEvent ИзменениеФамилии(Фамилия, NewValue) Фамилия = NewValue End Property

Заметьте, мы передаем обработчику два параметра, старую и новую фамилию. Важно понимать, что можно не только передавать обработчику данные, но и получать информацию от него.
Добавим еще один параметр Permission нашему событию, так чтобы обработчик события, проверив допустимость изменения фамилии, мог вернуть разрешение на изменение. Новый вариант события теперь выглядит так:

Public Event ИзменениеФамилии(Fam As String, NewFam As String, _ Permission As Boolean)

Соответственно изменится и процедура - свойство Property Let. Вот другой, более разумный вариант этой процедуры:

Public Property Let ВашаФамилия(ByVal NewValue As String) 'Зажигает событие ИзменениеФамилии Dim Permission As Boolean 'Разрешение на изменение фамилии Permission = True RaiseEvent ИзменениеФамилии(Фамилия, NewValue, Permission) 'Обработчик события может запретить изменение фамилии If Permission Then Фамилия = NewValue End Property

Менее ясно, где и когда следует зажигать событие ДеньРождения. Мы решили возбуждать это событие в тот момент, когда пользователь интересуется датой рождения объекта, и вставили соответствующую проверку в Property Get ВашаДатаРождения процедуру:

Public Property Get ВашаДатаРождения() As Date 'Зажигает событие ДеньРождения 'в зависимости от значения текущей даты If (Month(Now) = Month(ДатаРождения)) And _ (Abs(Day(Now) - Day(ДатаРождения)) <= 1) Then RaiseEvent ДеньРождения(ДатаРождения) End If ВашаДатаРождения = ДатаРождения End Property

Здесь событие возбуждается при выполнении некоторого условия, - текущая дата отличается от даты дня рождения не более чем на сутки. Дата рождения передается обработчику события, а тот, в свою очередь, может организовать уведомление и поздравление объекта с днем рождения, как это делает, например, Outlook для контактов из списка контактов.

Заметьте, процедура - свойство Property Get, в которой мы разместили оператор RaiseEvent, возбуждающий событие, - это не единственно возможное место для такого оператора. Вообще, одно и то же событие может возбуждаться в разных местах. В данном случае, может быть, имело смысл написать еще и специальный метод для возбуждения события, который вызывался бы пользователем в нужный момент.


Содержание раздела