Конструирование элемента управления
FLEXLabel
Перед тем как создать элемент управления, хотелось бы обсудить выгоды от создания элементов ActiveX. Некоторые могут удивиться, зачем возиться с элементами ActiveX, если уже есть код для отображения трехмерной надписи на форме любым способом? Если захотеть, то можно модифицировать код для работы с элементом PictureBox, который можно расположить где угодно на форме.
Действительно, элементы управления, подобные FLEXLabel, не что иное, как обычное приложение, но завернутые в другую упаковку. Есть определенные преимущества компоновки приложения в виде элементов управления ActiveX. Вот некоторые из них.
• Код элемента управления не будет пересекаться с кодом основного приложения. Приложение даже не будет знать о коде элемента управления.
• Можно менять текст, стили выравнивания и специальные эффекты из окна свойств, не меняя исходного кода приложения. Кроме того, можно визуально менять свойства и наблюдать изменения без запуска всего проекта.
• Элемент управления может накрывать только часть формы. Кроме того, можно поместить на одной форме несколько элементов управления с различными надписями.
• Наконец, можно свободно распространять элемент управления, и другие разработчики могут использовать его, не затрагивая его код.
Первый шаг в конструировании элемента управления — это разработка его интерфейса, который определяет, как элемент будет выглядеть при помещении его на форму и как разработчики могут получить доступ к возможностям элемента управления через его компоненты. Уверен, что вы слышали этот совет не один раз, но многие пользователи все равно начинают кодирование элемента, не уделяя достаточно времени конструированию его интерфейса.
Элемент ActiveX должен предоставлять определенные свойства, которые автоматически отображаются в окне свойств. Разработчик должен иметь возможность настраивать каждый параметр, влияющий на отображение, посредством манипуляции его свойствами. В дополнение, разработчики ожидают увидеть стандартные свойства, присущие всем стандартным элементам (такие как цвет фона, шрифт текста и т.д.). Следует тщательно конструировать методы так, чтобы они обеспечивали все функциональные возможности элемента управления и были доступны из кода приложения. Кроме того, методы не должны перекрываться. Наконец, нужно предусмотреть события, необходимые для реакции на внешние воздействия. Можно кодировать обычные приложения без предварительного конструирования, но элементы ActiveX и приложения для работы с базами данных требуют тщательной подготовки. Не начинайте кодировать элемент управления до тех пор, пока не сформулируете абсолютно четко, что будет делать элемент и как он будет использоваться разработчиками во время конструирования их приложений.
Alarm
Первым шагом является конструирование интерфейса элемента управления. В отличие от элемента управления Timer из Visual Basic, элемент управления Alarm имеет видимый интерфейс. Его работа основана на двух конституэнтных элементах управления:
• Timer, который обновляет изображение каждую секунду, и
• Label, который отображает время.
Конструирование интерфейса пользователя
Для конструирования интерфейса элемента управления, выполните такие шаги.
1. Поместите элемент управления Label на форму UserControl и установите в свойстве Font желаемые шрифт и размер.
2. Выровняйте Label по верхнему левому углу элемента управления, и измените размеры элемента управления так, чтобы он полностью вмещал элемент Label. (Запомните значения свойств Width и Height элемента управления. Они понадобятся позже при написании кода для предотвращения изменения размеров этого элемента управления.)
3. Поместите элемент управления Timer на объект UserControl He имеет значения, где поместить элемент управления Timer. Он будет невидим во время выполнения Можно поместить Timer вне видимой области пользовательского элемента управления или даже поверх элемента Label.
4. Чтобы завершить разработку элемента управления и препятствовать изменению его размеров, добавьте следующий код в обработчик события Resize элемента управления:
Private Sub UserControl Resize()
UserControl.Size 1800, 500
End Sub
Метод Size заставляет элемент управления сохранять фиксированный размер Значения 1800 (ширина) и 500 (высота) размеров элемента управления нужно изменить согласно реальным размерам элемента управления Label.
Теперь можно проверить поведение нового элемента управления. Попробуйте изменить его размеры Даже при том, что можно перемещать органы управления этого элемента, его размеры изменить нельзя.
Реализация компонентов элемента управления
Теперь все готово для реализации свойств элемента управления, его методов и событий. Давайте начнем со свойств. Нам уже известно, как добавить свойства к элементу управления с помощью мастера интерфейса элемента управления ActiveX и как это сделать вручную. Теперь давайте рассмотрим еще один инструмент. Мы еще сделаем это с помощью мастера, но сейчас просто добавим одно свойство или метод.
Начнем с объявления переменных. Вставьте следующие строки в окно Code объекта UserControl:
Private startTime As Date
Private Running As Boolean
Private m_CountDown As Boolean
Private m_AlarmTime As Date
Уже можно догадаться, что m_CountDown
и m_Alarm Time — две закрытые переменные, которые содержат значения свойств CountDown и AlarmTime. Пока запущен Alarm, переменная Running равна True, и она объявлена вне всех процедур, чтобы все они могли обращаться к ее значению. Переменная startTime устанавливается равной времени начала отсчета и используется, когда элемент управления не считает в обратном направлении (дальше будет видно, как это используется).
Чтобы сделать заготовки для свойств элемента управления с помощью команды Add Procedure, выполните следующие действия.
1. Переключитесь в окно UserControl и выполните двойной щелчок на форме, чтобы открыть окно Code.
2. Выберите команду Add Procedure меню Tools, чтобы открыть диалоговое окно Add Procedure.
3. Введите имя свойства CountDown и выберите тип Property. В окно кода будут вставлены следующие строки.
Public Property Get CountDown() As Variant
End Property
Public Property Let CountDown(ByVal vNewValue As Variant)
End Property
4. Измените тип свойства, чтобы он соответствовал объявлению, а затем введите строки кода для вставленных ранее процедур.
Public Property Get CountDown() As Boolean
CountDown = m_CountDown
End Property
Public Property Let CountDown(ByVal vNewValue As Boolean)
m_CountDown = vNewValue
End Property
Примечание
Приведенный код совершенно тривиален. Все процедуры Property ставят в соответствие закрытой переменной название свойства и имеют одинаковую структуру. Нужно не забывать только изменять их типы с Variant на требуемый.
5. Сделайте то же самое для переменной AlarmTime. Процедуры для этого свойства имеют следующий вид.
Public Property Get AlarmTime() As Date
AlarmTime = m_AlarmTime
End Property
Public Property Let AlarmTime(ByVal vNewValue As Date)
If IsDate(vNewValue) Then m_AlarmTime = vNewValue
End Property
Последняя процедура проверяет правильность значения свойства, чтобы удостовериться, что введено допустимое время. Если введена дата, то программа предполагает, что время равно 00:00:00 (полночь).
6. Теперь можно добавить два метода. В окне Code выберите команду Add Procedure меню Tools. В открывшемся диалоговом окне Add Procedure введите название метода StartTimer, но на этот раз установите переключатель в Sub. В код будут вставлены следующие строки.
Public Sub StartTimer()
End Sub
7. В подпрограмме StartTimer() введите код для запуска таймера.
Public Sub StartTimer()
If Not Running Then
Timer1.Enabled = True
Running = True
startTime = Time
If Time = m_AlarmTime > 0 Then NextDay = True
Label1.Caption = "00:00:00"
End If
End Sub
Эта подпрограмма ничего не делает, если таймер уже запущен. Если таймер не запущен, то подпрограмма инициализирует элемент управления Timer и устанавливает значение переменной startTimer равным текущему времени, а изображение в "00:00:00". Переменная Running устанавливается в True, чтобы предотвратить повторное выполнение этой подпрограмм, когда таймер уже запущен. Переменная NextDay устанавливается в True, если время срабатывания сигнала меньше текущего времени. Это означает, что элемент управления должен сработать в заданное время на следующий день.
8. Снова выберите команду Add Procedure меню Tools, чтобы создать еще одну общедоступную подпрограмму — метод StopTimer(). Ниже приведен код для этой подпрограммы.
Public Sub StopTimer()
If Running Then
Timer1.Enabled = False
Running = False
End If
End Sub
Так же как и в методе StartTimer, таймер останавливается только в том случае, если он был запушен. В этом случае код отключает элемент управления Timer и устанавливает переменную Running в False.
9. Теперь добавьте событие элемента управления. Выберите команду Add Procedure меню Tools, чтобы открыть диалоговое окно Add Procedure.
10. Введите имя TimeOut и выберите переключатель Event. После этого к коду добавится еще одна строка.
Event TimeOut()
Как заставить произойти это событие? С помощью оператора RaiseEvent из любого места кода. Всякий раз, когда таймер должен сработать, можно вызывать событие TimeOut с помощью следующего ниже оператора.
RaiseEvent TimeOut
Событие TimeOut вызывается из кода элемента управления
Timer (мы познакомимся с ним позже).
Только что был завершен костяк элемента управления
Alarm, нечто похожее было сделано ранее с помощью мастера интерфейса элемента управления ActiveX. На этот раз все элементы интерфейса элемента управления были добавлены вручную с помощью меню Tools. Проще позволить мастеру сформировать элемент управления автоматически, но знание того, как это можно сделать вручную, поможет добавить несколько свойств к существующему элементу управления без выполнения всех шагов мастера интерфейса элемента управления ActiveX.
Совет
Если запустить мастер интерфейса элемента управления
ActiveX для изменения существующего элемента управления, можно обнаружить, что мастер ставит символ комментария перед кодом пользователя. Поэтому всегда следует проверять свой код после обработки его мастером.
Команда Add Procedure не добавляет соответствующие строки в события ReadProperties и WriteProperties — их следует добавить вручную.
Программа 16.15. Сохранение и чтение свойств элемента правления Alarm
Private Sub UserControl ReadProperties(PropBag As PropertyBag)
CountDown = PropBag.ReadProperty ("CountDown", CountDown)
m_AlarmTime = PropBag.ReadProperty ("AlarmTime", AlarmTime)
End Sub
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
PropBag.WriteProperty "CountDown", m_CountDown, False
PropBag.WriteProperty "AlarmTime", m_AlarmTime, 0
End Sub __ ___ ___ ___ __
В заключение, нужно добавить следующий ниже код, также вручную, для инициализации значения свойства.
Private Sub UserControl InitProperties()
m_CountDown = True
Running = False
End Sub