Visual Basic 6. Руководство разработчика

       

Инициирование событий из кода класса


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

Совсем другая ситуация с ActiveX DLL. Классы инициируют события, осно­ванные на внутренних событиях, таких как лимит времени. Модифицируем класс CTimer так, чтобы он вызывал события Minute и Hour каждый раз, когда минута или час прошли. Доработанный проект CTimer вместе с его тестовым проектом находится в папке EVNTimer в папке этой главы на компакт-диске.

Так как класс CTimer не может отслеживать время непрерывно, необходимо ему помочь, воспользовавшись элементом управления Timer. Но модуль класса не имеет формы, и как тогда можно использовать элемент управления Timer? Мы добавим форму к проекту, но отображаться она не будет. Это будет скрытая форма с элементом управления Timer. Модуль класса будет иметь доступ к элементу Timer на форме и перехватывать его событие Timer. Это один из способов исполь­зования элемента управления ActiveX в модуле класса.

1. В окне Project Explorer выберите компонент CTimer и переименуйте его на EventTimer, как показано на рис. 15.3. Затем откройте меню Project, выберите команду Add Form (Добавить форму) и добавьте новую форму в проект модуля класса.

Примечание

Убедитесь, что новая форма появилась под компонентом

EventTimer, а не TestProject. Если форма добавилась к тестовому проекту, удалите ее и повторите процесс.

2. Откроите форму Form1 в режиме конструирования и поместите на нее экземпляр элемента управления Timer. Установите его свойство Enabled в True, а его свой ство Interval в 10000. Это значение соответствует 10 секундам. Не нужно, чтобы TimerClass тратил слишком много компьютерного времени на обработку событий Timer, так что установите большой промежуток времени ожидания.


На рис 15.3 показан проект EventTimer в среде разработки Visual Basic. Обратите внимание на компоненты в окне Project, на Form1 в окне Design и на окно Code класса. Новый класс называется EventTimerClass, а проект называется EventTimer. Открывая этот пример проекта, не забудьте выбрать проект теста и добавить ссылку на EventTimer к нему.

Наша задача - перехватить событие Timer от элемента управления. Timer внутри модуля класса и использовать его для генерирования событий Minute и Hour. Событие Minute первый раз происходит через 60 секунд после запуска таймера и каждые 60 секунд после этого. Аналогично, событие Hour происходит первый раз через 60 минут после начала работы класса и через каждые 60 минут после этого.



Рис. 15.3. Проект EventTimer подобен проекту CTimer, но он использует внутренний таймер для отсчета времени



3. Чтобы обеспечить доступ к элементу управления на другой форме, необходимо создать переменную формы в самом классе. Вставьте следующие объявления в окно программного кода класса.

Dim cFrrn As Formi

Dim WithEvents eTimer As Timer

Ключевое слово WithEvents

сообщает Visual Basic, что элемент управления должен содержать свойства, методы и события (вот почему он назван eTimer). Эти переменные оживут, если им поставить в соответствие объекты. Это должно произойти внутри события инициализации класса.

4. Вставьте следующие строки в событие Class_Initialize:

Private Sub Class_Initialize ()

Set cFrm = New Form1

Load cFrm

Set eTimer = cFrm.Timer1

End Sub

Первый оператор связывает новый экземпляр объекта Formi с переменной cFrm. Затем загружается новая форма. С этого времени реализуется доступ к элементам управления, размещенным на форме. Последняя строка делает переменную eTimer

эквивалентной элементу управления Timer1 на форме Form1. Теперь класс может иметь доступ к элементу управления Timeri на форме Formi с помощью имени eTimer, также как и Form1 имеет доступ к нему с помощью имени Timer1. Два выражения эквивалентны, но нельзя получить доступ к элементу управления Timer как Form1.Timer1 из модуля класса.



Если открыть раскрывающийся список объектов в окне программного кода модуля класса, то можно увидеть объект eTimer. Так как объектная переменная eTimer объявлена с использованием ключевого слова WithEvents,

то есть возмож­ность программировать его события. Вот почему его имя появилось в списке объектов. Выберите объект eTimer

в списке объектов и затем откройте список событий в окне Code. Появится имя события Timer. Выберите его, после чего можете программировать событие eTimer_Timer(), что эквивалентно програм­мированию события Timer1_Timer.

5. Добавьте строки программного кода 15.5 в обработчик события eTimer_Timer.

Программа 15.5. Инициирование событий из кода класса

Private Sub eTimer_Timer()

Static seconds As Long

Static minutes As Long

Static hours As Long

Dim RaiseMinutes As Boolean, RaiseHours As Boolean

If Not Counting Then Exit Sub

RaiseMinutes = False

RaiseHours = False

seconds = seconds + eTimer.Interval / 1000

If seconds = 60 Then

minutes = minutes + 1

seconds = 0

RaiseMinutes = True

If minutes = 60 Then

hours = hours + 1

minutes = 0

RaiseHours = True

End If

End If

If RaiseHours Then

RaiseEvent Hour

Elself RaiseMinutes Then

RaiseEvent Minute

End If

End Sub

Булева переменная Counting

объявлена в секции объявлений формы и служит признаком работы таймера. Если таймер остановлен, то не нужно обрабатывать событие Timer. Эта переменная устанавливается в True внутри метода StartCounting и устанавливается в False внутри метода StopCounting.

Эта подпрограмма вызывается каждые 10 секунд и увеличивает число прошедших секунд,

прибавляя к ним 10. Каждые 60 секунд она увеличивает число минут на 1, и каждые 60 минут она увеличивает число часов на 1. Если переменная minutes равна 0 (это значит, что она достигла значения 60 и сброшена в 0), должно быть инициировано событие Hour. Если это не так, то проверяется значение пере­менной seconds.

Если она равна 0, то должно быть инициировано событие Minute. В результате этого инициируются 59 последовательных событий Minute, затем событие Hour, после чего процесс повторяется. Так как нельзя выдать сразу два события, то событие Minute пропускается, когда инициируется событие Hour. Ясно, что событие Hour означает наличие и события Minute.



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

Event Minute ()

Event Hour ()

Полный программный код EventTimerClass показан ниже. Обратите внимание на сходство и отличия с простым классом CTimer. Процедура Property Get и метод класса не изменились. Добавлен только код для доступа к элементу управления Timer на невидимой форме и запрограммировано событие Timer элемента Timer для инициирования соответствующих событий.

Программа 15.6. Листинг EventTimerClass

Dim cFrm As Formi

Dim WithEvents eTimer As Timer

Dim totallnterval As Double

Dim Tl As Double

Dim Counting As Boolean

Event Minute()

Event Hour()

Public Sub StartCounting ()

Tl = Time

Counting = True

End Sub

Public Sub StopCounting()

totallnterval = totallnterval + Time - Tl

Counting = False

End Sub

Property Get ElapsedTime() As Double

ElapsedTime = totallnterval

End Property

Public Sub ResetTimer()

totallnterval = 0

End Sub

Private Sub Class_Initialize ()

Set cFrm = New Formi

Load cFrm

Set eTimer = cFrm.Timer1

End Sub

Private Sub eTimer_Timer()

Static seconds As Long

Static minutes As Long

Static hours As Long

Dim RaiseMinutes As Boolean, RaiseHours As Boolean

If Not Counting Then Exit Sub

RaiseMinutes = False

RaiseHours = False

seconds = seconds + eTimer.Interval / 1000

If seconds = 60 Then

minutes = minutes + 1

seconds = 0

RaiseMinutes = True

If minutes = 60 Then

hours = hours + 1

minutes = 0

RaiseHours = True

End If

End If

If RaiseHours Then

RaiseEvent Hour

Elself RaiseMinutes Then

RaiseEvent Minute

End If

End Sub


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