Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОСНОВЫ ОФИСНОГО ПРОГРАММИРОВАНИЯ И ЯЗЫК VBA - 1....doc
Скачиваний:
59
Добавлен:
17.12.2018
Размер:
1.88 Mб
Скачать

События собственных классов

Возможность создавать события собственных классов - это новинка Office 2000. Ранее было возможным для классов иметь только два стандартных события - Initialize и Terminate, играющих роль конструктора и деструктора по умолчанию. Теперь можно в классе создать набор событий и для каждого из экземпляров класса написать обработчики любого из этих событий. Тем самым расширяются возможности созданных Вами объектов. Это существенное продвижение в сторону классики объектного программирования. Попробуем разобраться:

  • как создать класс с событиями,

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

  • где и как следует создавать обработчики событий для экземпляров класса,

  • какие действия конечного пользователя (системы) при работе с объектом инициируют событие,

  • как в ответ на событие посылается сообщение объекту и вызывается обработчик события.

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

Первый вопрос, который необходимо решить при создании класса с событиями, лежит вне программирования, прежде всего, нужно решить, каким должен быть набор событий у объектов класса. Если с объектом связан некоторый графический образ, то ситуация более или менее стандартна, всегда разумно иметь события Click, Move, Resize и другие, типичные для графических объектов. Эти события будут возникать, когда пользователь будет работать с графическим образом, выполняя над ним те или иные типичные действия. Во многих случаях, наши объекты могут и не иметь графического образа, но и для них не менее полезно определить события. Общие рекомендации давать трудно, поэтому обратимся к примеру и рассмотрим ранее созданный класс Личность. Какие события разумно было бы определить для объектов этого класса? Учитывая, что свойств у объектов класса не так много, число разумных событий также не велико. Давайте определим два события - ИзменениеФамилии и ДеньРождения. Первое из этих событий возникает в ответ на изменение значения свойства Фамилия, второе, - когда текущая дата отличается от даты дня рождения Личности не более чем на сутки.

Поняв, какие события должен иметь наш класс, рассмотрим, как создать набор событий в классе. Все делается очевидным и естественным образом. Достаточно в разделе объявлений модуля класса объявить каждое из событий, используя ключевое слово Event. Вот как выглядит объявление класса Личность, имеющего два предусмотренных нами события:

Option Explicit

'Класс Личность

'События класса

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

Public Event ДеньРождения(Dat As Date)

'Далее следует уже знакомое определение свойств и методов класса

'Смотри раздел "Создание класса Личность" этой лекции

Итак, чтобы создать класс с событиями просто добавьте список этих событий в объявление класса!

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

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