Глава 7
Классовое общество
Объектноориентированное
программирование — это методология разработки программ, основанная на
представлении программы в виде совокупности объектов, каждый из которых
является реализацией определенного класса. В объектноориентированном
программировании объект представляет собой элемент приложения, например лист,
ячейку, диаграмму, форму или отчет. Программный код и данные структурируются
так, чтобы имитировалось поведение фактически существующих объектов
В
объектноориентированном программировании важную роль играют четыре понятия. При
абстрагировании реальные процессы ограничиваются их функциями,
существенными для программирования. Внутреннее содержимое объекта защищается от
внешнего мира посредством инкапсуляции. Благодаря наследованию
уже запрограммированные функциональные возможности можно использовать и для
других объектов. Полиморфизм позволяет использовать различные объекты и
поразному реализуемые функции под одним именем.
Вы уже работали с
объектами, возможно, и не замечая этого. Объекты являются программным
представлением физических и/или логических сущностей реального мира. Они
необходимы для моделирования поведения физических или логических объектов,
которые они представляют. Например, элемент управления TextBox служит для
отображения или редактирования текста в форме. Для добавления элемента
управления TextBox в форму не нужно писать ни строчки — можно просто
воспользоваться готовым объектом TextBox из панели элементов. Для изменения
поведения и состояния элементов управления используются их свойства и методы
Классы
На панели элементов
Visual Basic находятся, строго говоря, не объекты, а классы. Различие между
классами и объектами состоит в том, что объекты в Visual Basic существуют
только во время выполнения. Классы же используются для задания структуры
объектов. Во время выполнения создаются копии классов. Благодаря этому для
данного класса можно создавать произвольное количество объектов. С другой
стороны, классы образуют группы одноименных объектов.
Абстрагирование
Человек использует
абстрагирование для того, чтобы проще описывать сложные объекты окружающей
среды. Представьте себе, что в обычном языке не существует объектов (понятий),
абстрагирующих окружающий мир. Тогда для того, чтобы сообщить другому человеку
о какомто предмете, например автомобиле, пришлось бы его подробно описывать.
Трудно вообразить, сколько времени потребовалось бы для описания объекта.
Причем описание должно быть очень точным, чтобы не возникло ошибочное
представление о другом объекте.
То же относится и к
программированию. Например, для использования текстового окна (TextBox) не
нужно разрабатывать специальный драйвер графической карты. Вы просто
используете объект класса TextBox. Этот абстрагированный объект содержит все,
что нужно для редактирования текста в Windows.
Если вы создаете
собственное приложение, то большую помощь при этом окажут собственные объекты.
В исходном коде вы используете программное представление таких объектов, как
фирмы, служащие, товары, счета и многое другое. Такой способ рассмотрения
больше соответствует реальности, чем при чисто процедурной разработке
приложений.
Инкапсуляция
Объекты позволяют
значительно упростить разработку приложения. В очень редких случаях
разработчика интересует внутренняя реализация объектов. Главное, чтобы объект
обеспечивал функции, которые он должен предоставить. Поэтому объекты защищены
от внешнего вмешательства. Например, если вы хотите снять деньги со счета через
банкомат, то без карточки это невозможно, так как его содержимое защищено от
доступа случайного клиента. Денежные автоматы защищены — инкапсулированы. На
процессы, протекающие внутри банкомата, и на его содержимое клиент не имеет
прямого влияния.
Взаимодействие
клиента с объектом происходит через интерфейс. Обычно интерфейс определяет
единственный способ входа в объект и выхода из него; детали реализации остаются
инкапсулированными.
При создании
собственных объектов необходимо организовать такие же интерфейсы. В объектах
Visual Basic интерфейсами являются свойства, методы и события. Только они
предоставляются данным объектом в распоряжение других объектов. Благодаря этому
система программирования предотвращает доступ других объектов (клиентов) к
внутренним переменным состояния объекта, которые могут обрабатываться только
предусмотренными для этого процедурами.
Это имеет большое
значение при сопровождении программы. Если в связи с изменившимися
обстоятельствами потребуется изменить реализацию интерфейса объекта, то
изменение ограничится только процедурой, относящейся к свойству или методу.
Если синтаксис интерфейса не изменился, то можно с уверенностью сказать, что
изменение не отразится на других проектах, использующих этот объект. В
противном случае при попытке использовать переменную, которая не существует в
новом варианте объекта, в других проектах может возникнуть ошибка.
Инкапсуляция
поддерживает абстрагирование тем, что объект можно использовать, не зная, как
он реализован внутри. Если программист поддерживает определенный интерфейс, то
инкапсуляцию можно обеспечить и при процедурном построении программы. В
объектноориентированных языках реализация инкапсуляции обеспечивается системой
программирования.
Наследование
. Наследованием мы
называем повторное использование уже созданной части кода в других проектах.
Посредством наследования формируются связи междуобъектами, а для выражения
процесса используют понятия о родителях и потомках. В программировании
наследование моделирует связь "это — является" или "это —
имеет". Наследование служит для сокращения избыточности кода и суть его
заключается в том, что уже существующий интерфейс вместе с его программной
частью можно использовать для других объектов. При наследовании могут также
проводиться изменения интерфейсов.
Полиморфизм
Полиморфизм означает, что различные объекты
используют одинаковую абстракцию, т.е. могут обладать свойствами и методами с
одинаковыми именами. Однако обращение к ним будет вызывать различную реакцию
для различных объектов. Большое достоинство полиморфизма состоит в том, что при
использовании объекта можно вызывать определенное свойство или метод, не
заботясь о том, как объект выполняет задачу. Это очень важно при модификации
программного обеспечения. Изменения или новшества просто адаптируются к
имеющимся компонентам приложения.
Все вышесказанное
является лишь кратким введением в объектно ориентированное программирование
(ООП). Глубже познакомиться с теорией ООП можно в специальной литературе.
Классы
В данной главе описывается применение классов
внутри проекта (Standard EXE). Для использования классов в элементах
управления ActiveX существуют дополнительные возможности, на которых мы
подробнее остановимся в следующих главах.
В Visual Basic классы
используются в качестве шаблонов объектов. С их помощью во время выполнения
можно создавать любое количество объектов одного класса. Внутренняя структура
класса передается объекту посредством модуля класса. Таким образом, класс
описывает семейство объектов, а каждый экземпляр класса является уникальным
представителем этого семейства.
При написании программ, для имитации
поведения реальных объектов, в объектах объединяются как принципы действия, так
и данные.
Модуль класса
Для создания
собственного объекта нужен шаблон. Эти шаблоны в Visual Basic представляют
модули классов. С помощью команды Add Class Module меню Project или
соответствующей кнопки панели инструментов Visual Basic такой модуль класса
можно добавить в проект.
После добавления
модуля класса появляется пустое окно кода, в котором можно реализовать класс. В
проектах типа Standard.EXE классы имеют только одно свойство—имя класса.
В среде разработки
Visual Basic все модули класса сохраняются как отдельные файлы с расширением
CLS.
Форма
В качестве классов
могут также применяться и формы, в частности если необходимо, чтобы создаваемый
объект функционировал как окно. Все описанные здесь
действия можно выполнять как с модулем
класса, так и с формой. После добавления модуля класса или формы в проект можно
создавать свойства и методы.
Мастер
классов
Visual Basic
предоставляет и другую возможность создания классов. Если на вкладке Environment
диалогового окна Tools\0ptions в группе Show Templates For: активизировать
опцию Class Modules, то при добавлении модуля класса отобразится
диалоговое окно Add Class Module. С его помощью можно либо создать пустой
модуль класса, либо запустить мастер классов Visual Basic (утилита Class
Builder) (рис. 7.4). Для редактирования уже существующих в проекте классов
эту утилиту можно вызвать также посредством команды Class Builder Utility
меню AddIns (рис. 7.5) из окна кода Visual Basic. При помощи команды New\CIass
меню File данного мастера можно добавить новый модуль класса. В
открывающемся диалоговом окне Class Module Builder следует задать имя
класса и, при необходимости, указать ряд других параметров.
В списке Based On можно
указать имя класса, на котором основан создаваемый класс. На вкладке
Attributes можно задать описание модуля класса (комментарий), а также имя
справочного файла для данного класса.
Риc. 7. 7. Дни lo.iinof окно
Class Module Builder
Чтобы все изменения,
выполненные мастером, были перенесены в проект, следует либо выполнить команду Update
Project меню Files мастера, либо при завершении работы с мастером
утвердительно ответить на вопрос о необходимости сохранения изменений. С
помощью мастера, кроме классов, можно создавать собственные семейства,
добавлять к ним свойства, методы и события.
Свойства
Чтобы можно было
использовать объекты класса (class или Form), необходимо создать
соответствующие свойства и методы. Свойства в общем случае предназначены для
изменения значений переменных состояния объектов. Например, свойство Text
текстового окна позволяет задавать либо считывать значение отображаемой строки.
При этом обычно объект не выполняет никаких действий. Свойства, не
соответствующие этому правилу (например, CommonDialogI. Action = 1), следует
заменять методами, реализующими аналогичные функции (CornmonDialogi. showOpen).
Есть две возможности
реализации свойств в классах: использование процедур свойств, позволяющих
контролировать значения свойств, или объявление в классе переменных общего
доступа (Public). Однако переменные, объявленные как Public, не обладают всеми
возможностями процедур свойств.
Процедуры свойств
Кроме известных
процедур Sub и Function, в Visual Basic есть и третья категория — процедуры
Property, с помощью которых можно определять свойства класса. Чтобы процедуры
были видимыми вне собственного контейнера, их следует объявлять как Public.
Поскольку значения
свойств можно как считывать, так и устанавливать, то для одного свойства могут
потребоваться две процедуры с одним и тем же именем: одна для чтения, другая
для присвоения значения свойства. Чтобы различить их, в заголовке процедуры
используется дополнительное ключевое слово (Let или Get).
Оператор Property Let
В Visual Basic
операция присваивания значения переменной имеет следующий синтаксис:
[bet] varname = expression
Явное использование
необязательного ключевого слова Let зависит от стиля программирования, поэтому
при присваивании значения переменной оно обычно не указывается. Однако в
процедуре присваивания значения свойству использование ключевого слова Let
обязательно, так как в этом случае оно указывает, что данная процедура является
процедурой задания значения свойства.
Public Property Let Property_Name (ByVal
vNewValue As Variant)
mVariable
= vNewValue End Property
Переменная vNewValue
содержит значение, присваиваемое свойству. При этом тип данных этой переменной
должен соответствовать типу данных свойства.
Оператор Property Get
Процедура считывания
значения свойства объявляется с использованием ключевого слова Get.
Public Property Get
Property_Name () As Variant Property_Name = mVariable End Property
Здесь, как и в
процедуре Function, возвращаемое значение присваивается имени процедуры. При
создании процедуры Property Get следует обратить внимание на то, что она
использует тот же тип данных, что и одноименная процедура Property Let.
Обычно при
определении свойства необходимо задавать обе процедуры. Воспользовавшись
командой Add Procedure меню Tools, можно сэкономить время,
поскольку эта команда позволяет создать одновременно обе процедуры свойств
(Property Get И Property Let).
Рис. 7. (У. Диалоговое окно
Add Procedure
Оператор Property Set
Существует и третий
тип процедур свойств — процедура Property Set. Проце дура Set используется
аналогично Let, но передает не значение свойства, а ссылку на объект.
Public Property Set Property_Name (ByVal
objNewValue As Object)
Set Property_Name = objNewValue End Property
В этой связи важную
роль играет свойство по умолчанию. Каждый элемент управления имеет такое
свойство, которое всегда используется Visual Basic, если имя свойства в коде
явно не указано.
Textl =
"Hello" '(равнозначно Textl.Text = "Hello") vVariable =
Textl
В приведенном примере
свойству Text текстового окна присваивается определенное значение. Во второй
строке это значение считывается. Но если переменной объекта требуется передать
сам объект Textl, то строка кода должна выглядеть иначе — при присваивании
объектных переменных в Visual Basic вместо неявного ключевого слова Let следует
явно использовать ключевое слово Set.
vVariable
= Textl "Содержимое: "Hello" Set vVariable = Textl 'Содержимое:
копия Textl
Дорога с односторонним движением
Разделение процедур
свойств на процедуры присваивания и процедуры считывания позволяет легко
создавать свойства, доступные только для чтения или только для изменения.
Допустим, вам нужно ограничить доступ к свойству и сделать его доступным только
для чтения. Для этого достаточно создать только одну процедуру —
В этом окне задается
имя, тип данных и доступность свойства. При
необходимости можно
назначить это свойство свойством по умолчанию.
Если при создании
свойства в окне Property Builder установить опцию
Public Property или Friend
Property, мастер добавит в модуль класса три процедуры Property (Let, Get и
Set), а также внутреннюю переменную класса для хранения значения свойства.
Private
mvarProperty_Name As Variant Public Property Let Property_Name (ByVal vData As
Variant)
mvarProperty_Name
=.vData End Property
Public Property Set Property_Name (ByVal
vData As Object)
Set
mvarproperty Name = vData End Property
Public Property Get
Property_Name () As Variant If IsObject(Property_Name) Then Set Property_Name °
mvarProperty_Name Else Property_Mame = mvarProperty_Name End If End Property
Использование
Обычно в процедурах
свойств объем кода не больше, чем в приведенном примере. Дополнительный код
может понадобиться лишь для проверки правильности значения, присваиваемого
свойству. При этом не следует забывать, что свойства не должны вызывать никаких
действий объекта^Ото реализуется только посредством его методов.
Методы
Для использования
объектов класса (Class или Form) нужны соответствующие свойства и методы.
Методы используются для расширения функциональных возможностей объекта.
Существует два типа
процедур: с возвращаемым значением (синтаксис функции) и без возвращаемого
значения (синтаксис оператора). Это также относится и к методам. Например,
метод Clipboard. SetText использует синтаксис оператора, а метод Clipboard.
GetText — синтаксис функции. При создании методов действуют те же правила, за
исключением того, что процедуры Sub и Function следует объявлять как Public.
Синтаксис оператора
Для создания метода
без возвращаемого значения в модуль класса необходимо добавить процедуру public
Sub, имя которой будет именем метода.
Public Sub
Method_Name() vVarName = vVarName * 5 End Sub
Обращение к такому
методу аналогично вызову обычной процедуры. При необходимости процедуре могут
передаваться аргументы.
Public Sub
Method_Name(argi, Optional arg2 As Integer) vVarName = argi * arg2 End Sub
Посредством
аргументов более точно определяется характер выполняемого действия или
передаются обрабатываемые элементы.
Синтаксис
функции
Методы с
возвращаемыми значениями реализуются как Public Function, а имя функции
становится именем метода.
Public Function
Method_Name() Method_Name = vVarName * 5 End Function
Как и в обычной
функции, возвращаемое значение присваивается имени функции. Обращение к такому
методу аналогично обычному вызову функции. В методах такого типа также могут
использоваться аргументы. При этом действуют те же правила, что и в обычных
функциях.
Public Function
Method_Name(argi, Optional arg2 As Integer) Method_Name = argi * arg2 End
Function
Мастер
классов
С'оздать метод очень просто с помощью мастера
классов.
Для
добавления метода следует в левой части окна мастера классов выбрать
соответствующий класс и при помощи команды меню File\New\Method или
соответствующей кнопки панели инструментов окна мастера открыть диало говое
окно Method Builder.
В поле Name следует
указать имя метода, в поле Return Data Type — тип данных возвращаемого
значения (если метод должен возвращать данные). Если поле Return Data Type оставить
пустым, будет создана процедура Sub. Если указать тип данных, будет создана
процедура Function. В список Arguments посредством кнопки со знаком +
можно добавить аргумент метода с указанием его имени и типа данных. Если при
этом установить флажок ByVal, аргумент будет передаваться как значение
(ByVal). В Visual Basic 6.0 аргумент может быть массивом (Array), массивом
параметров (ParamArray, который применяется, если количество передаваемых
процедуре аргументов заранее неизвестно), параметром по умолчанию (Default),
необязательным параметром (Optional), а также передаваться как значение
(ByVal). Кроме того, при использовании аргумента поддерживаются перечисления
(Enums).
PUL'. 7. li. Дилюгивис UKIIO Add ^Irgunwilts
Аргументы, ошибочно
добавленные в список Arguments, можно удалить с помощью кнопки удаления.
Порядок аргументов можно изменить с помощью двух кнопок со стрелками.
Public Function Method_Name(argi As String,
ByVal arg2 As Integer, _
arg3
As Single) As Boolean End Function
Использование
Обычно методы
содержат намного больше кода, чем процедуры свойств, так как в них выполняется
непосредственная обработка данных. Сложные задачи можно разбить на несколько
процедур (Sub или Function), которые объявляются как Private, поскольку могут
использоваться только внутри класса. Инкапсуляция внутренних данных является
большим преимуществом ООП.
События
События — это реакции
объекта на действия системы, пользователя или других приложений. Анализ и
обработка событий позволяет объекту реагировать на внешние воздействия. Каждый
класс имеет набор собственных событий. По умолчанию все классы содержат два
события, которые происходят после загрузки и перед выгрузкой объекта. Эти
события — Initialize и Terminate
— подробно описываются в следующем разделе.
События, определяемые пользователем
Объекты, определяемые
пользователем, могут генерировать собственные события (возможность, впервые
реализованная в Visual Basic 5.0). События создаются в два этапа. Сначала в
секции объявлении класса объявляется событие (при необходимости с аргументами),
а затем в процедуре внутри класса происходит вызов этого события.
'Общие объявления
(Class или Form) Public Event Event_Name()
Public Sub CallEventO RaiseEvent Event_Name
Оператор Event
Событие, определяемое
пользователем, объявляется внутри класса с помощью оператора Event. Аргументы,
передаваемые процедуре обработки события, должны указываться в строке
объявления события.
Оператор RaiseEvent
Для генерации события
внутри класса предназначен оператор RaiseEvent, которому в качестве аргумента
передается имя события.
Ключевое слово WithEvents
Контейнер, в котором
используется объект, должен содержать процедуру обработки события. До создания
процедуры обработки события нужно объявить объект, используя ключевое слово
WithEvents.
'Общие объявления Dim
WithEvents object As classi
Private Sub object
имя события() End Sub
После такого
объявления указанный объект будет добавлен в список (Object) окна кода,
в результате чего из списка (Procedure) можно будет выбирать события
объекта.
Иногда процедуре
обработки события требуется передавать некоторые аргументы (например, процедуре
обработки события MouseMove передаются параметры состояния кнопок мыши и
позиции курсора). Такие аргументы описываются при объявлении события. При
вызове оператора RaiseEvent вместе с именем события указываются и значения
аргументов, которые обрабатываются в соответствующей процедуре:
'Общие объявления
(Classi) Public Event SomeEvent(argi As Variant, arg2 As Integer)
Public
Sub CallEventO
argi = "Picard"
arg2 = 1707
RaiseEvent
SomeEvent(argi, arg2) End Sub
' Общие объявления
Dim WithEvents object As Classi
Private Sub object_SorneEvent (argi As
Variant, arg2 As Integer) End Sub
Заметьте, что события могут генерироваться
только в том классе, в котором объявлены.
События, определяемые
пользователем, применяются только в контейнерах Class Module или
Form.
Мастер
классов
Мастер классов может
помочь и при создании событий. Для создания события в окне мастера выбирается
нужный класс, а затем вызывается команда меню File\New\Event. В появившемся
диалоговом окне следует задать имя события и, при необходимости, его аргументы.
Так же, как и при
создании методов, с помощью соответствующих кнопок в окне мастера можно создать
список аргументов, их типы данных и порядок. В результате работы мастера в
модуль класса вставляется соответствующая строка.
'Для вызова этого
события используйте RaiseEvent с синтаксисом: 'RaiseEvent SomeEvent[(argi,
arg2, ... , argn)] Public Event SomeEvent(argi As Integer, arg2 As Long)
При создании событии
работа с мастером может показаться более хлопотной, чем непосредственный ввод
кода в области объявлений. Все остальные действия при создании событий с
помощью мастера должны выполняться вручную.
Объекты, определяемые пользователем
После обеспечения
класса свойствами, методами и событиями его можно использовать.
Объявление
Использовать классы
непосредственно в программе нельзя. Внутри приложения используются объекты,
созданные на основе класса. На основе одного класса можно создать любое
количество объектов — копий класса.
Ключевое слово New
В Visual Basic
объекты класса создаются с помощью ключевого слова New. Это слово следует
использовать при объявлении переменных, например в строке Dim:
Dim object As New
Classi
В этом примере
создается новый объект класса Classi с именем object. В Visual Basic доступ к
объектам всегда производится посредством переменных. Поэтому неудивительно, что
строка New очень похожа на обычное объявление переменной. Новый объект можно
создать и подругому, с помощью следующего кода:
Dim
object As Classi Set object = New Classi
Оператор Set
Обратите внимание на
то, что при выполнении присваивания объектных переменных всегда нужно
использовать оператор Set. При присваивании значений не обязательно указывать
оператор Let. При объявлении переменных объекта действуют те же правила в
отношении области действия и времени жизни, что и для обычных переменных.
Объекты класса
обладают всеми свойствами, методами и событиями, которые определены в исходном
классе, однако каждый объект класса может иметь различные значения свойств и
функционировать независимо от других.
Использование объектов
После того как
объектной переменной присвоена ссылка на объект класса, к ней можно обращаться
как к обычному элементу управления:
'Общие объявления Dim
object
As New Classi
Private Sub Commandl_Click()
object.Свойство = Значение object.Метод
End Sub
В данном примере вы
не увидите ничего нового. Имя объекта и имя свойства разделены точкой. Свойства
устанавливаются или считываются при помощи оператора присваивания (=). Методы
отделяются от объекта точкой. Используется синтаксис оператора или синтаксис
функции, при необходимости указываются аргументы.
'Общие объявления Dim
WithEvents object As Classi
Private Sub
Cornmandl_Click () Set object New Classi
objectСвойство = Значение object.Метод End
Sub
Private Sub
object_co6brrne () ' Код End Sub
Чтобы использовать
события объекта, при его объявлении следует применять ключевое слово
WithEvents. Однако оно не может применяться вместе с ключевым словом New. Для
удаления объектной переменной из памяти необходимо удалить ссылку на объект.
Если ссылки на объект не существует, переменная удаляется из памяти.
Ключевое
слово Nothing
Для удаления ссылки
из объектной переменной используется ключевое слово Nothing.
'Общие объявления Dim
WithEvents object As Classi
Private Sub
Commandl_Click() Set object = New Classi ' Код Set object = Nothing End
Sub
Если на используемый
объект не ссылаются другие переменные, то Windows удаляет его из памяти.
Обратите внимание на то, что значение Nothing должно присваиваться посредством
оператора Set, как при любом присваивании объектов.
Каталог
объектов
Возможно, вы уже работали с каталогом
объектов Visual Basic (Object Browser). Это средство удобно для просмотра
собственных объектов, особенно если используемый класс разработан не вами. В
таком случае с его помощью можно просмотреть все имеющиеся свойства, методы и
события.
Для открытия окна каталога объектов можно
воспользоваться кнопкой
панели инструментов Visual Basic. Из списка Project/Library
выберите
имя проекта. После этого в списке Classes появляются
имена всех классов
выбранного проекта. Имена всех свойств,
методов и событий данного класса отображаются в
списке
Members of после выбора нужного класса.
Свойства отображаются независимо от того, как
они были реализованы:
как процедуры свойств или как переменные
Public. В окне подсказки
отображается дополнительная информация,
например используемый тип
данных. Голубой кружок над
пиктограммой свойства указывает, что данное свойство является свойством по
умолчанию.
Для методов выводится
список аргументов с указанием их типа данных, а также типа данных возвращаемого
значения. Для событий указываются аргументы и их типы данных.
Если при создании
элемента с помощью мастера в соответствующем диалоговом окне свойств на вкладке
Attributes вы задали описание, введенный текст появится в окне
подсказки. Добавить текст описания можно также в окне каталога объектов,
щелкнув правой кнопкой мыши на соответствующем элементе списка. В появившемся
контекстном меню выберите команду Properties и введите текст описания в
диалоговом окне Procedure Attributes. Это диалоговое окно можно открыть
и в среде разработки с помощью команды Procedure Attributes меню Tools.
Каталог
объектов, как правило, применяется для поиска объектов, методов или свойств.
Если нужный компонент найден, его имя можно скопировать в буфер обмена с
помощью кнопки Copy to Clipboard. Если выбранный класс находится в
текущем проекте, можно отобразить модуль класса с помощью кнопки View
Definition. Если для элемента указан справочный файл и Help Context ID, можно
получить соответствующую тему справки с помощью кнопки Help. С помощью
диалогового окна Procedure Attributes можно выполнить операции над
классом, например скрыть свойство, метод или событие. Обратите внимание на то,
что при использовании каталога объектов внутри проекта также отображаются
элементы, объявленные как Private.
Раннее
и позднее связывание
Скорость выполнения
приложения может зависеть от того, каким образом Visual Basic осуществляет
связывание переменных с их объектами. Связывание может быть ранним (Early
Binding) или поздним (Late Binding).
Раннее
связывание
Раннее связывание
осуществляется, если при объявлении переменной указывается конкретный тип
данных:
Dim objVarl As TextBox Dim objVar2 As Classi
Dim objVar3 As Word.Application
В приведенном примере
при объявлении переменных их типы данных указываются точно. Раннее связывание
выполняется быстрее, чем позднее, поэтому рекомендуется использовать его
всегда.
Позднее
связывание
Позднее связывание
выполняется, если при объявлении переменной определенный тип объекта не
указывается.
Dim objVarl As Object
Dim ob]Var2 As Variant Dim objVar3 As Control
В данном примере типы переменных определяются
только при присваивании им конкретного объекта, а при объявлении переменной
указывается только универсальный тип. При таком объявлении при каждом обращении
к объекту анализируются все допустимые объекты, а это требует значительных
затрат времени.
Позднее связывание
следует использовать в тех случаях, если при разработке невозможно заранее
определить, какие типы объектов будут использоваться.
События
Initialize и Terminate
Кроме событий, определяемых пользователем,
классы всегда содержат события Initialize и.Тегminate, которые являются аналогами
событий формы Load и Unload.
Событие Initialize
Событие Initialize
класса наступает при первом использовании объекта. В процедуре обработки этого
события следует выполнять код, необходимый для инициализации объекта. Это может
быть, например, объявление собственных объектов или подключение к серверу базы
данных.
Private Sub
Commandl_Click() Dim object As New Classi
object.methode
"происходит событие Initialize End Sub
Обратите внимание:
объявление переменной с помощью оператора Dim не вызывает наступление события
Initialize — это событие вызывается только при первом обращении к свойствам или
методам объекта.
Событие Terminate
Как только
уничтожаются все ссылки на объект, Windows удаляет этот объект из памяти. В
этот момент наступает событие Terminate.
Private Sub
Commandl_Click() Set object = Nothing
'наступает Terminate End Sub
Это событие
используется для того, чтобы объект мог корректно освободить память, т.е.
удалить все внутренние объекты или отсоединиться от внешних источников данных.
При создании
собственных классов можно легко контролировать наступление событий Initialize и
Terminate. Для этого в модуль класса следует поместить следующий код:
Private Sub Class_Initialize()
MsgBox
"Инициализация" End Sub Private Sub Class_Terminate()
MsgBox "Удаление" End Sub
Однако следует
учесть, что не каждому пользователю нужна информация о создании или уничтожении
объекта.
Оператор Implements
В предыдущей версии
Visual Basic был введен новый оператор — Implements, с помощью которого можно
передавать интерфейсы одного объекта другим. Для этого в качестве шаблона
используется так называемый абстрактный класс, который не содержит кода, а
только задает структуру интерфейса. Абстрактные классы служат не для создания
объектов, а для определения набора свойств и методов.
Поскольку на основе
класса Visual Basic всегда можно создать объекты, даже если модуль класса не
содержит кода, то, строго говоря, в Visual Basic нет абстрактных классов.
'Class: Vehicle
'Общие объявления Public Speed As Integer Public Sub Movef) End Sub
В этом примере
создается структура интерфейса. При этом были созданы одно свойство (как общая
переменная) и один метод класса.
Implements
Теперь интерфейс
может использовать другой класс. Для этого в модуле класса применяется ключевое
слово Implements.
'Class: Car 'Общие
объявления Implements Vehicle Dim
Speed As Integer
Private Sub
Vehicle_Move() MsgBox "Автомобиль едет" & Speed End Sub
Private Property Let
Vehicle_Speed(ByVal Value As Integer) Speed =• Value End Property
Private Property Get
Vehicle_Speed() As Integer Vehicle_Speed = Speed End Property
Следует учитывать, что при реализации
интерфейса или класса необходимо включить в новый класс или интерфейс все
составные части (процедуры, свойства) исходного объекта, объявленные как
Public.
В производном классе после применения
оператора Implements ИмяКласса вы можете воспользоваться определенными в
абстрактном классе свойствами и методами. При этом переменнаясвойство Speed из
нашего примера реализуется в производном классе двумя процедурами Property.
Заметим, что все
процедуры абстрактного класса объявляются как Private. Это необходимо для того,
чтобы они сами не становились свойствами или методами производного класса.
Private Sub
Commandl_Click Dim Drive As Vehicle Dim Polo As New Car
Set Drive =• Polo Drive.Speed = 50
Drive.Move End Sub
Теперь остается
выбрать класс, в который необходимо поместить нужный код. Весь код может
находиться либо в абстрактном, либо производном классе. Можно разделить код
между двумя классами.
Private Sub Commandl_Click Dim Polo
As New Vehicle Dim
HotAir As New
Vehicle Dim Titanic
As New Vehicle
Dim Park As New
Collection
Vehicle.Add HotAir.
Vehicle.Add Titanic
Vehicle.Add Polo
For Each Vehicle In
Park
I = I + 25
Vehicle.Speed = I
Vehicle.Move Next
ехать End Sub
Оператор Implements
позволяет многократно использовать один и тот же программный код.
Обработка ошибок
Схема обработки
ошибок уже рассматривалась в данной книге. Следует учесть, что классы,
определяемые пользователем, должны иметь собственные обработчики ошибок. Если
внутри класса невозможно устранить ошибку, то эту задачу должна взять на себя
вызывающая процедура. Для этого используется объект Err:
Err.Raise number[,source][,
description]^,help file, helpcontext]
Метод Raise
использует некоторые именованные аргументы. Аргумент number содержит уникальный
код ошибки. Для кодов ошибок, определяемых пользователем, к непосредственному
номеру следует прибавить константу vbObj ectError. При этом нельзя выходить за
пределы области значений переменных типа Long.'
Err.Raise
vbObjectError + 127
Аргумент source
содержит ссылку на источник ошибки, т.е. на класс. При задании аргумента source
следует использовать структуру Pro jectName.ClassName.
Аргумент description
содержит текст, описывающий возникшую ошибку. В процедуре обработки ошибки этот
текст можно получить, воспользовавшись свойством Description объекта Err.
Аргументы helpfile и
helpcontext указывают справочный файл и в нем — тему справки.
С помощью метода
Raise ошибка передается вызывающей процедуре, которая должна иметь
соответствующий обработчик ошибок.
Как реагировать на ошибку?
Реакцию среды
разработки на ошибку можно настроить, воспользовавшись вкладкой General диалогового
окна Options, которое открывается одноименной командой меню Tools. На
вкладке General разработчик может выбрать один из трех вариантов
реакции среды разработки на ошибку:
.
• Break on All Errors — при возникновении ошибки среда
разработки переходит в режим прерывания (отладки) независимо от того, имеется
или нет активная процедура обработки ошибок, и независимо от того, находится ли
ошибочный код в модуле класса.
.
• Break in Class Module — возникновение любой
необрабатываемой ошибки в модуле класса приводит к переключению среды
разработки в режим отладки и выделению строки кода, вызвавшей ошибку. Если при
отладке компонентов ActiveX вы запускаете тестовую клиентскую ActiveXпрограмму
в другом проекте, то при установке этой опции обработка ошибки будет
выполняться в модуле класса компонента ActiveX, а не в тестовой программе.
.
• Break on Unhandled Errors — если процедура обработки ошибок
активна, то возникшая ошибка обрабатывается без переключения среды в режим
отладки. Если же такая процедура отсутствует, то происходит переключение среды
в режим отладки. Если ошибка произошла в модуле класса, то выполнение программы
останавливается в вызывающей процедуре, а не в модуле класса.
Использование
Собственные классы
можно использовать и для централизованной обработки ошибок. При этом код ошибки
передается объекту, определяемому пользователем. Объект анализирует и
обрабатывает ошибку и через возвращаемое значение информирует источник ошибки о
необходимости выполнения определенных действий.
Семейство
Еще одной
особенностью Visual Basic является возможность создания набора элементов,
определяемого пользователем, или семейства (Collection). Объект Collection —
это упорядоченный набор элементов, на который можно ссылаться как на единое
целое. Благодаря этому возможно объединение собственных объектов в легко
управляемые логические единицы. Некоторые задачи, решаемые с помощью семейств,
можно решить также с помощью массивов или переменных, определяемых
пользователем, однако семейства имеют некоторые преимущества:
.
• семействами можно управлять и они более гибко
индексируются;
.
• методы семейства позволяют добавлять и удалять объекты;
.
• семейства требуют меньше памяти;
.
• размер
семейств регулируется автоматически (без явного использования оператора ReDim)
Методы и свойства
Посредством методов
Add и Remove добавляются или удаляются отдельные объекты семейства. Доступ к
конкретному объекту семейства осуществляется с помощью метода Item. Свойство
Count содержит число объектов семейства.
'Общие объявления Dim
collectionname As New Collection
Private Sub
Comniandl_Click() For i " 1 To 5 Dim objectname As New Classi
collectionname.Add objectname, key:""number" & i Next i End
Sub
Метод
Add
Для добавления
объектов в семейство используется метод Add. При этом следует указывать имя
объекта. Дополнительно можно передавать аргумент key, с помощью которого в
дальнейшем можно будет обращаться к данному объекту.
Collection. Add object[,key] [,
before] [, after] Таблица 7.1.
Параметры метода Add
Параметр |
Описание |
object |
Объект, который нужно
добавить |
key |
Символьная строка для
идентификации объекта |
before |
Номер позиции предыдущего
объекта |
after |
Номер позиции последующего
объекта |
Метод Remove
Для удаления объекта
из семейства используется метод Remove. При этом для идентификации объекта
указывается либо номер позиции, либо аргумент key.
Col Section.Remove key\index
collectionname.Remove
3
collectionname.Remove "number2"
Метод Item
С помощью метода item
можно получить доступ к определенному элементу семейства. Для идентификации
этого элемента так же, как и при Remove, используется номер позиции или
аргумент key.
Object.It«m(Aeylindex)
collectionname.Item(2).Property
= vValue Set oVariable
=. collectionname.Item("numberi")
Семейства
представляют собой удобный способ управления большим количеством объектов.
Мастер классов
Собственные семейства
можно создавать также с помощью мастера классов. Для создания семейства в окне
мастера классов нужно выполнить команду File\New\Collectfon или нажать
соответствующую кнопку панели инструментов. На экране появляется диалоговое
окно, в котором следует указать имя семейства.
Рчс. 7. I If.
Дии.югонос UKIIO Collection Builder
Если в проекте уже
существуют классы, то один из них можно использовать для создания коллекции
объектов конкретного класса. Если проект не содержит классов, семейство
создается на основе нового класса. Мастер формирует новый класс, создавая для
него все необходимые методы и свойства.
Private mCol As Collection
Public Function
Add(Key As String, Optional sKey As String) As Classi Dim objNewMember As
Classi Set objNewMember == New Classi
objNewMemberKey = Key
If Len(sKey) = 0 Then
mCoi.Add objNewMember
Else
mCoi.Add
objNewMember, sKey End
If
'return the object
created Set Add =
objNewMember Set
objNewMember
= Nothing
End Function
Public Property Get
Item(vntIndexKey As Variant) As Classi Set Item = mCol(vntIndexKey) End
Property
Public Property Get Count!) As Long
Count mCol.Count End
Property
Public Sub
Remove(vntIndexKey As Variant) mCol.Remove vntIndexKey End Sub
Public Property Get
NewEnumO As lUnknown Set NewEnum = mCol.[_NewEnum] End Property
Private Sub
Class_Initialize() Set mCol = New Collection End Sub
Private Sub Class
Terminate () Set mCol = Nothing End Sub
Данный пример
демонстрирует создание семейства, определяемого пользователем. Семейство
создано с помощью мастера и содержит основные методы и свойства семейства.
Цикл For Each.., Next
Для работы со всеми
элементами семейства можно воспользоваться специальной формой цикла For. .
.Next — For Each. . .Next. В этом цикле также используется объектная переменная
цикла (счетчик).
For Each element In
collectionname Debug.Print element.Property Next element
Этот пример
показывает принцип действия цикла For Each. . .Next. Каждый элемент в указанном
семействе collectionname один раз присваивается объектной переменной. Если
обработаны все элементы, выполняется автоматический выход из цикла. Хотя такую
возможность можно реализовать с помощью свойства Count и цикла For. . .Next,
все же цикл For Each. . .Next более удобен.
Массивы
Наряду с семействами
для объединения объектов используются и массивы. В этом случае действуют те же
правила, что и для статических и динамических массивов.
Dim objVariable(I To
5) As New formi
Массивы объектных
переменных помогают раскрыть принципы создания семейств при объектноориентированном
подходе.
Глава 8
От OLE к ActiveX
Клиенты OLE
Знание объектов
является важной основой для овладения технологией OLE (Object Linking and
Embedding). Однако прежде чем рассмотреть создание компонентов ActiveX,
остановимся ненадолго на другом вопросе — на клиентах.
Основы
К сожалению, и здесь
не обойтись без теории. Но для того, чтобы действительно изучить OLE, ActiveX и
их возможности, необходимо знать их теоретические основы.
Что такое OLE?
Термин OLE это
сокращение от Object Linking and Embedding (связывание и внедрение объектов).
Если попытаться объяснить кратко, то OLE — это метод, позволяющий редактировать
данные из одного приложения в другом или переносить их в другое приложение. Но
это всего лишь верхушка айсберга.
Что такое объекты?
С объектами вы уже
хорошо знакомы. Чтобы получить представление об объектах в OLE, следует
остановиться на таком принципиальном понятии, относящемся к OLE, как контейнер.
Именно контейнер может принимать один или несколько объектов, поэтому, воспользовавшись
OLE, можно формировать документы из нескольких источников данных. Под
документами понимаются не только файлы, созданные с помощью текстового
редактора, — документом может быть и таблица Excel, в которую внедрены
изображения из Paint или объекты из PowerPoint.
Сервер
В этом случае Excel
является контейнером, а изображение из Paint или PowerPoint — объектом, и
приложения Paint или PowerPoint работают подобно так называемым
серверприложениям.
Сегодня многие
приложения уже поддерживают технологию OLE версии 2.0 и тем самым процесс inplace
activation. Это означает, что пользователь не видит двух запущенных по
отдельности приложений. На приведенном выше рисунке запущены и Visual Basic, и
Paint, однако в целом все выглядит так, как если бы был запущен только Visual
Basic.
Рис. А'. /. Контейнер
и объекты
Виды данных объекта
Каждый объект имеет
два различных вида данных: данные представления (Presentation Data, PD) и
естественные данные (Native Data, ND). Данные представления служат для представления
информации так, как она отображается в оригинальном приложении. Например,
таблица Excel как объект должна быть представлена в табличной форме.
Естественные данные — это собственно информация, т.е. содержимое таблицы.
В этом заключается
одно из отличий OLE от DDE. При DDE переносятся только естественные данные. За
представление данных отвечает целевое приложение.
Связывание или внедрение
Когда OLE
расшифровывают как Object Linking and Embedding (связывание и внедрение
объектов), это не совсем правильно. На самом деле следовало бы говорить Object
Linking or Embedding (связывание или внедрение объектов). С OLEобъектами можно
осуществлять одну из двух операций: связывание или внедрение.
Связывание
При связывании
объекты содержат данные представления и ссылку на естественные данные. Это
означает, что естественные данные находятся в файле на диске или гденибудь еще.
В примере, показанном на рис. 8.2, имеется файл Excel с данными и их
отображение в документе Word. Кроме того, к данным связанного объекта могут
иметь доступ другие приложения.
В этом случае
естественные данные хранятся в файле, а данные представления — с
объектомконтейнером.
Внедрение
При внедрении как
естественные данные, так и данные представления хранятся в объектеконтейнере (в
данном случае — документе Word). Поэтому данные недоступны для других
приложений и не существуют в виде отдельных файлов.
OLE Automation
Нельзя не упомянуть и
о другой возможности OLE 2 — OLE Automation. Эта технология позволяет работать
с различными объектами как с элементами управления. Так, вы можете работать в
Visual Basic с редактором Word для Windows почти как с элементом TextBox.
Используя OLE Automation, можно оперировать связанными объектами при помощи
команд. В большинстве случаев имеются в виду макрокоманды связанных объектов,
например команды языка WordBasic или Excel VBA.
Но довольно теории.
Как можно использовать эту новую технологию в Visual Basic?
Элемент управления
OLE Container
Наиболее простои
способ использования OLE в вашем приложении — это применение элемента
управления OLE
Container
или просто OLE.
Вставка объектов OLE
Чтобы вставить объект
OLE в приложение, надо всего лишь поместить в соот ветствующую форму элемент
управления OLE. После добавления
элемента управления OLE в форму отображается диалоговое окно вставки OLEобъекта. С помощью
этого окна можно создать новый объект или создать его из файла, указав, будет
ли это связанный или внедренный объект.
После того как вся
необходимая информация будет указана, запустится приложение данного объекта.
Всем, кто знает
элементы управления еще с 3й версии Visual Basic, следует запомнить, что старое
доброе свойство Action хотя и сохранилось в языке, но лишь по соображениям
совместимости. В версии 6.0 различные действия свойства Action реализованы как
самостоятельные методы.
Таблица 8.]. Методы объекта OLE Container .
Mvniw) |
Змчение Action |
Действие |
CreateEmbed |
0 |
Создает внедренный объект |
CreateLink |
1 |
Создает связанный объект |
Copy |
4 |
Копирует объект в буфер обмена |
Paste |
5 |
Вставляет объект из буфера обмена |
Update |
6 |
Восстанавливает текущие
данные связанного |
|
|
б |
DoVerb |
7 |
Открывает объект для определенной операции (на |
|
|
пример, для редактирования) |
Close |
9 |
Закрывает объект |
Метод |
Значение Action |
Действие |
Delete |
10 |
Удаляет содержащийся в контейнере объект |
SaveToFile |
11 |
Сохраняет объект в файле |
ReadFromFile |
12 |
Загружает объект из файла |
InsertObjDIg |
14 |
Отображает диалоговое окно Insert Object |
PasteSpecialDIg |
15 |
Отображает диалоговое окно Paste Special |
SaveToOlelFile |
18 |
Сохраняет объект в формате OLE 1.0 |
Представляет интерес свойство OLEDropAllowed. Если оно
имеет значение True, объект можно просто взять из другого приложения и
переместить в нужное место с помощью перетаскивания (Drag & Drop). Таким
способом можно, например, перенести изображение из Проводника в элемент
управления OLE Container.
Большинство действии элемента OLE Container
можно превосходно выполнить в диалоговом режиме на этапе разработки. Но все же
следует привести некоторые примеры, чтобы показать, как это происходит в коде
программы.
Создание внедренного объекта осуществляет метод
CreateEmbed.
CreateEmbed sourcedoc, class
При вызове этого метода достаточно
указать имя класса внедряемого объекта:
OLE1.CreateEmbed "",
"Word.Document"
Для связанного
объекта надо указать источник данных, т.е. имя файла.
CreataLink sourcedoc, source!tern
Кроме того, параметр
sourceitem должен содержать ссылку на область в объекте, например на
необходимые ячейки:
OLEi.CreateLink "D:\EXCEL\TERMIN.XLS",
"C1R1"
Сохранение объектов
не только возможно, но даже необходимо, чтобы при следующем запуске приложения
в контейнере находился тот же OLEобъект. Сохранение данных в двоичном формате
применимо к внедренным объектам, так как связанные объекты сохраняются
источником:
fh = FreeFile Open "С:\DATA.OLE"
For Binary As fh OLE1.SaveToFile fh Close #fh
Загрузка объектов
производится аналогичным образом при помощи метода ReadFromFile.
Объекты OLE как элементы управления
Вместо использования
элемента управления OLE Container Visual Basic позво ляет добавить любой объект,
обладающий OLEвозможностями, вывести его на панель инструментов и использовать
как элемент управления. Для добавления таких элементов управления следует
выполнить команду Components меню Project, а затем
во вкладке Insertable Objects диалогового
окна Components выбрать все необходимые объекты (рис. 8.5).
После добавления
объекта его значок появляется на панели инструментов Visual Basic, с помощью
которой объект может быть помещен в форму как обычный элемент управления (рис.
8.6).
Однако не со всеми
объектами можно обращаться так же легко, как с элементами управления. Кроме
того, нельзя точно сказать, какие объекты обладают этой способностью, а какие
нет. Большей частью это можно определить лишь методом проб и ошибок.
Все добавляемые таким
образом объекты не имеют особых свойств и методов и интересны в связи со
следующей темой — OLE Automation.
OLE
Automation
Теперь начинается
самое интересное. OLE Automation — это, несомненно, одна из наиболее заманчивых
возможностей OLE 2. Вы можете работать с другими OLEприложениями так, как если
бы они были "просто" элементами управления. Однако соответствующие
приложения должны поддерживать OLE Automation.
При использовании OLE
Automation подумайте и о проблемах лицензирования. Если ваши приложения Visual
Basic содержат пользовательские элементы управления (Custom Controls), их можно
поставлять не задумываясь. В то же время приложения, которые вы используете в
OLE Automation, должны быть законным образом установлены на компьютере
заказчика.
Это означает, что
если ваше приложение обращается к Microsoft Excel посредством OLE Automation,
то на машине, где будет использоваться приложение, должно быть установлено
приложение Microsoft Excel.
Создание объекта OLE
Объект OLE необходим
и для OLE Automation. Но в этом случае не нужен элемент управления OLE Container. Можно
просто создать объектную переменную и присвоить ей ссылку на объект. Для этого
с помощью команды References меню Project библиотеку объектов
другого приложения следует включить в приложение Visual Basic, после чего
объекты другого приложения станут доступными в вашем коде.
Dim ww As New Word.Application
И в этом случае
проявляются преимущества нового редактора. Уже при введении кода отображается
список доступных для данного объекта методов или свойств. Это полезно, в первую
очередь, при использовании неизвестных вам объектов.
OLEобъект можно
подключить не только из библиотеки, но также из файла (например, *.DOC, *.XLS).
Для этого предназначена функция Get0h;;.ct, которая возвращает ссылку на объект
из файла:
Set
variable = GetObject([filename][,
class])
Dim DB As Object Set
DB = GetObject("C:\TEXT\ACCOUNT.DOC", "Word.Document")
Использование
объекта OLE
После того как объект
создан, с ним можно работать. Для этого обычно используют язык макросов
приложения этого объекта. В приведенном примере открывается документ Word, в
который затем добавляется строка "Hello World":
Private Sub
Commandl_Click() Dim ww As New Word.Application
ww.Visible =
True 'Word становится видимым
ww.Documents.Add 'Открывается документ ww.Selection.TypeText "Hello
World" End Sub
Как вы можете убедиться,
здесь используются команды VBA для Word.
VBA
— Visual Basic для всех?
Visual
Basic for Applications
До сих пор в приложениях Microsoft вы
встречались с разными языками макросов. Существовали WordBasic, ExcelMacro,
AccessBasic и т.д. Все они значительно отличались друг от друга. Начиная с
Office 97, Microsoft стала снабжать свои приложения общим языком макросов —
VBA. Visual Basic for Applications является диалектом Visual Basic. Поэтому
знание Visual Basic пригодится вам, чтобы в будущем программировать приложения
Microsoft.
По сути, все диалекты VBA схожи и разница
заключается только п используемых объектах и функциях, что неудивительно, так
как Excel работает с ячсиками, a Word — с текстом.
VBA для Excel — небольшой пример
На примере VBA для
Excel вы ознакомитесь с VBA и тем самым с будущим Visual Basic:
Sub Testprocedure ()
Dim I As Tntec|pr
Do
I «= I +
1 •' ".^ . ,' ..1 .
Print I
Loop Until I =
10 End Sub
Как видите, на
основании этого кода нельзя определить, что здесь приведен нс код проекта
Visual Basic, а код макросов Microsoft Excel.
VBA и OLE Automation
VBA облегчает работу
именно в области OLE Automation. Здесь можно работать с новыми объектами VBA
так, как вы привыкли это делать в Visual Basic.
Список доступных
элементов, методов и свойств связанного объекта можно получить нс только при
написании кода в виде быстрой подсказки (рис. 8.8), но и из каталога объектов
(рис. 8.9).
После добавления
ссылки на соответствующую библиотеку отдельные объекты можно переносить прямо
из каталога объектов. Это чрезвычайно облегчает работу, поскольку каждый
диалект VBA имеет свои многочисленные объекты.
OLE
Automation и элементы управления
Даже если OLEсервер был включен в
проект Visual Basic в виде элемента управления, с этим элементом можно работать
и с помощью OLE Automation.
Если объект сервера был помещен в форму как
элемент управления OLE Container, то доступ к большинству из его методов сохраняется. Для
этого используется свойство Object. Такой метод работы делает программирование
более гибким, так как можно изменять содержимое элемента OLE Container в любой
момент, в том числе и во время выполнения. В случае если этот элемент находится
в форме, можно использовать следующий код: OLEl.CreateEmbed "",
"Excel.Sheet"
OLE1.Object.Sheets(l).Cells(l, 1).Value =
"99"
Разумеется, можно
применить и другой способ: включить в форму OLE объект, добавленный на панель
инструментов в виде элемента управления. Чаще всего и для этих объектов можно
использовать OLE Automation. В этом случае также применяется свойство Object:
Sheetl.Object.Range("Al").Value
= "99" Sheet 1.Object.Range("A2").Value = "101" Sheetl.Object;.Range("A3")
.Formula » "=A1+A2" result = Sheetl.Object.Range("A3").Value
В будущем OLE
Automation и VBA позаботятся о том, чтобы можно было использовать несколько
различных приложений (Word, Excel,...) в одном единственном приложении, в одномединственном
проекте. Границы между приложениями становятся все более зыбкими. Таким
образом, OLE 2 достигает своей цели: в центре внимания находится не приложение,
а документ.
ActiveX
и СОМ
Название этой главы —
"От OLE к ActiveX". Настало время более серьезно заняться этой
технологией и ее возможностями. В Visual Basic 5.0 стало возможным создание
компонентов ActiveX. К ним относятся исполняемые объекты ActiveX, динамические
библиотеки, документы и, конечно же, элементы управления ActiveX.
Что
такое ActiveX?
Понятие ActiveX в большинстве случаев связано
с понятием Internet. Хотя это в принципе правильно, но значительно ограничивает
область применения технологии ActiveX.
ActiveX базируется на объектной модели
компонентов (Component Object Model, СОМ) Microsoft. Эта технология является
попыткой избежать создания гигантских монолитных программных комплексов и
распределить функциональные возможности программного обеспечения между многими
небольшими компонентами.
Исполняемые
ActiveX
Чтобы в дальнейшем можно
было повторно обращаться к одному и тому же небольшому примеру, мы будем
исходить из того, что во многих приложениях необходима возможность загрузки и
сохранения текстового файла.
Если такая
функциональная возможность необходима более чем в одном приложении, то,
естественно, возникает мысль реализовать ее в виде компонента, например в виде
исполняемого ActiveX.
В Visual Basic 4.0
исполняемые компоненты ActiveX (ActiveX EXE) еще назывались OLEсерверами. В
принципе это и сейчас так. Но теперь иметь доступ к этому серверприложению и
использовать его возможности могут разные клиенты.
Создание компонентов ActiveX
При создании нового
проекта можно указать, что создаваемый проект будет реализован как исполняемый
компонент ActiveX.
По умолчанию
создается проект, состоящий из модуля классов. Обычно этот проект дополняют
стандартным модулем.
ActiveX.EXE является
компонентом. Часто компоненты могут работать без видимого интерфейса, но это не
обязательно.
Настройка проекта
На следующем этапе
следует соответствующим образом настроить свойства проекта (рис. 8.12).
Рис. (У. 12. Диалоговое
окно Project Properties
Sub Main
Сначала следует
задать стартовый объект (список Startup Object). В нашем случае это должна быть
процедура Sub Main. После создания проекта эту процедуру следует
добавить в стандартный модуль. Также следует определить название (поле Project
Name) и описание проекта (поле Project Description), так как эти данные
используются для идентификации в реестре Windows (Project Name) и для описания назначения
и типа проекта (Project Description).
Классы как объекты
Объекты компонента
ActiveX — это экземпляры соответствующего класса. Поэтому следует
соответствующим образом создать и реализовать его свойства File и Text. Кроме
того, нам понадобятся методы сохранения и загрузки файла. Проще всего сделать
это с помощью утилиты Class Builder, с которой вы уже знакомы.
Сам класс получает имя TextFile.
Аналогичным образом в дальнейшем можно без труда реализовать и другие объекты,
например BinaryFile и т.д. Сам по себе код для загрузки и сохранения файла не
составляет проблемы.
Рис. А'. 13.
Создание классов
Свойства
класса
При создании нового класса при помощи утилиты
Class Builder большое значение имеет задание некоторых ключевых свойств класса.
Вопервых, это имя класса (свойство Name), а вовторых — свойство , которое
задает способ создания внешними приложениями экземпляров модуля класса. Другие
классы проекта, содержащего этот модуль, всегда могут создавать экземпляры
данного класса. Вы можете установить для свойства instancing одно из следующих
значений:
.
• Private — другие приложения не могут получить информацию об
этом классе и нс могут создавать экземпляры этого класса. Доступ к этому классу
разрешен только собственным компонентам разработчика.
.
• Public Not Creatable—другие приложения могут использовать
объекты этогокласса, только если проект, в котором этот класс находится, создал
эти объекты. Другие приложения не могут использовать функцию CreateObj ect или
оператор New для создания объектов этого класса.
.
• single Use — другие приложения могут создавать объекты
этого класса, нокаждый объект этого класса, создаваемый клиентом, запускает
новый экземпляр компонента. Недопустимо использовать в проектах ActiveX DLL.
.
• Global Single Use — подобно Single Use, но С одним
дополнением: свойства 11 мсголы этого класса могут вызываться, как если бы они
были глобальными функциями. Вызывающее приложение не обязано сначала явно
создавать экземпляр этого класса, так как он будет создан автоматически.
Недопустимо использовать в проектах ActiveX DLL.
.
• Multi Use — другие приложения могут создавать объекты этого
класса. Вне зависимости от количества создаваемых объектов создается только
один экземпляр компонента.
.
• Global Multi Use — подобно Multi Use, но с одним дополнением:
свойства и методы этого класса могут вызываться, как если бы они были
глобальными функциями.
Тестирование компонента
При создании
компонентов нельзя обойтись без этапа тестирования и устранения ошибок.
Поскольку речь идет о компонентах типа ActiveX EXE, для тестирования следует
запустить другой экземпляр Visual Basic. Созданный нами компонент Files можно
включить в тестовый проект с помощью команды References меню Project.
В Visual Br.sic 6.0 дополнительно появилась возможность задания в настройках
проекта места выполнения компонента при запуске — например, в броузере или в
другом приложении.
Теперь можно просто
объявить компонент Files как объект и использовать его по назначению.
Private Sub
Commandl_Click() Dim dText As New Files.TextFile
dText.filename =
"C:\TEXT.TXT" dText.Load Textl.Text = dText.Text End Sub
Если при выполнении
этого кода встретились ошибки, то приостанавливается и выполнение компонента
Files, и в данном экземпляре Visual Basic отображаются соответствующие ошибки.
Рис. 8.1?. Передача сообщении об
ошибках
Ошибки выполнения
При обработке ошибок
выполнения вы должны осознавать, что пользователь, как правило, не будет
работать непосредственно с вашим компонентом, а будет вызывать его из другого
приложения. Это значит, что при обработке ошибок выполнения сообщения о них не
выдаются непосредственно пользователю, а передаются вызывающей программе или
клиенту.
Именно клиент должен
обеспечить выдачу сообщения и, по возможности, обработку ошибки. Этот механизм
уже известен вам по элементам управления, которые поставляются с Visual Basic.
Например, если задать неправильное значение свойства, то в приложении
генерируется ошибка выполнения.
Передача компонентом
сообщения об ошибке может происходить двумя способами: либо генерируя ошибку
выполнения, как это делает большинство компонентов ActiveX в Visual Basic, либо
через возвращаемое значение метода:
Public Sub Load()
If Dir$(mvarFilename)
= "" Then 'Нет такого файла
Err.Raise vbObjectError + 580,
"", "Bad file name"
Exit Sub
End If
End Sub
В данном примере с
помощью функции Raise объекта Err генерируется ошибка с описанием "Bad
file name". Номер ошибки складывается из значения константы vbObjectError
и вашего собственного номера ошибки (в данном случае — 580).
vbObjectError
Использовать
константу vbObj ectError при задании номера ошибки следует для того, чтобы
значение этого номера не совпадало со значением системных номеров ошибок.
Числовое значение этой константы 2147221504 (&Н80040000). Чтобы ваши номера
ошибок не совпадали с номерами ошибок компонентов ActiveX Visual Basic, они
должны начинаться с 512.
Если процедура не
имеет собственного обработчика ошибок, для клиента генерируется ошибка. Она
может быть обнаружена программистом этой системы и соответствующим образом
обработана.
Второй способ
передачи информации об ошибке — использование возвращаемых значении. Это сходно
с использованием вызовов функций API, но имеет тот недостаток, что при неверном
задании свойства не появляется никакого сообщения.
Независимо от того,
какой способ вы выберете, в пределах одного проекта следует использовать только
один из них.
Формы
Исполняемые ActiveX
могут содержать формы — как модальные, так и немодальные. Однако эти формы не
всегда работают так, как можно от них ожидать.
В нашем примере мы
добавили в класс TextFile новый метод для отображения текста. Этот метод
загружает форму и отображает в находящемся в ней поле ввода содержимое свойства
Text.
Рис. 8. !7. Форма в
исполняемом ActiveX
Модальные
и иемодальпые формы
Одну и ту же форму можно отобразить
как модальную и как немодальную:
Public Sub Display!) Formi.Show
0 'модальная Textl.Text == mVarText End
Sub
' или
Public Sub Display!)
Formi.Show 1 'немодальная Textl.Text =
mVarText End
Sub
Если отображать форму как немодальную, не
происходит ничего необычного, т.е. вы видите форму на экране. Напротив,
модальная форма часто появляется на заднем плане, частично скрытая другими
объектами, а спустя некоторое время выводится сообщение о том, что процесс
компонента завершить нельзя.
Закрытие формы
После закрытия формы
компонент остается загруженным. Хотя это и логично, но при первом знакомстве с
компонентами не очевидно. Итак, формы в принципе можно использовать в различных
компонентах, но при этом необходимо учитывать некоторые особенности их
поведения.
Регистрация
исполняемого ActiveX
Когда создание
исполняемого ActiveX полностью завершено и компонент готов к применению, его
следует зарегистрировать. Это значит, что в реестр Windows должна быть внесена
определенная информация.
Для компонентов
ActiveX это сделать сравнительно просто. В среде разработки Visual Basic сам
выполняет регистрацию при компиляции компонента. В системе, где будет позднее
использоваться компонент, это может выполнить программа установки компонента.
Другой способ регистрации — запустить исполняемый ActiveXкомпонент. В этом
случае он регистрирует себя сам.
Динамические библиотеки ActiveX
Компонент,
реализованный как исполняемый ActiveX, можно реализовать также в виде
динамической библиотеки ActiveX (ActiveX DLL).
Различие между
исполняемыми ActiveX и динамическими библиотеками ActiveX
Исполняемый
ActiveXкомпонент является внешним по отношению к процессу, в котором он
используется, а в случае динамической библиотеки ActiveX компонент является внутренним
по отношению к процессу. Это значит, что исполняемый компонент ActiveX работает
как отдельное приложение в своей собственной области памяти и несколько
клиентов могут обращаться к одному и тому же компоненту ActiveX без его
многократной загрузки. Однако в этом случае обращение осуществляется через
сложный интерфейс, что занимает больше времени.
Напротив,
динамические библиотеки ActiveX загружаются в область памяти вызывающего их
клиента, и каждый клиент должен загрузить собственную копию компонента. В этом
случае обращение осуществляется не через медленный процесс в памяти, а
непосредственно. Это значит, что динамические библиотеки ActiveX обычно
работают значительно быстрее, чем их исполняемые коллеги.
Многое из того, что
мы сделали в проекте исполняемого ActiveX, можно перенести в динамические
библиотеки ActiveX, хотя определенные ограничения и существуют.
Создание динамической библиотеки ActiveX
Для создания проекта
разработки динамической библиотеки ActiveX следует воспользоваться командой New
Project меню File и выбрать в диалоговом окне New Project
опцию ActiveX DLL (рис. 8.19).
Созданный проект ActiveX
DLL также содержит по умолчанию модуль класса. Затем следует создать
стандартный модуль и процедуру Sub Main.
Однако при создании
компонента в виде динамической библиотеки ActiveX существуют определенные
отличия от исполняемого компонента (ActiveX EXE). Так, свойство класса
Instancing может принимать только значения Private, Public Not Creatable, Multi
Use И Global Multi Use. Значения Global Single Use И Single Use использовать
нельзя, так как компоненты разделяют память с клиентом.
Если в проект
добавить форму, то ее функционирование будет зависеть от способа ее отображения
— в модальном или немодальном виде. Для немодальных форм способ отображения
зависит от клиента — не все клиенты могут отображать немодальные формы.
Тестирование
динамической библиотеки ActiveX
На этапе тестирования
динамической библиотеки ActiveX также имеются небольшие отличия. Конечно, можно
запускать ActiveX DLL и из второго экземпляра Visual Basic. Но для чего же
тогда Visual Basic поддерживает группы проектов? Вы можете просто добавить в
окно проектов другой, тестовый проект и назвать его стартовым (Start Up). Таким
способом можно протестировать работу клиента и компонента в среде разработки.
ActiveX правила, ограничения, возможности
Итак, вы получили
основное представление о том, как создаются компоненты ActiveX, и исполняемые,
и в виде динамических библиотек. Создание документов ActiveX будет рассмотрено
позже. Независимо от типа создаваемого компонента существует гораздо больше
возможностей, чем было рассмотрено. В этом разделе будут рассмотрены некоторые
интересные темы, такие как многопоточность, стандарты и совместимость.
Глобальные объекты
Как вы уже
неоднократно видели, при использовании объекта на него должна быть сделана
ссылка в клиенте и обычно должен быть создан экземпляр компонента. Но вы можете
освободить разработчика приложения от этой работы. Если вы хотите предоставить
функции или определяемые пользователем константы целому ряду клиентов, это
можно сделать в глобальном компоненте.
Допустим,
что различным клиентам необходимо предоставить функцию вычисления суммы налога
MwSt. Этой цели можно достичь разными путями. Один из способов (хотя и несколько
консервативный) — это модуль, который загружается в существующий проект. Если
этот результат надо реализовать более чем в одном компоненте, следовало бы
создать компонент с классом и включить в него метод, реализующий эту функцию:
Public Function MwSt
(net, taxrate) MwSt = net * taxrate/100 End Function
Чтобы интегрировать
этот метод в клиенте, необходимо создать экземпляр компонента и получить на
него ссылку:
Private Sub Count!)
Dim FinanceFunction
As New Finances.Functions
Tax = FinanceFunction.MwSt(150, 15) End Sub
В этом примере создан
экземпляр компонента Finances и содержащегося в нем объекта Functions. После
этого метод можно использовать. Однако создавать классы как глобальные объекты
можно, только установив соответствующее значение свойства класса instancing.
Если его значение равно Global single Use (не для динамических библиотек
ActiveX), то класс становится глобальным. В этом случае разработчику клиента
достаточно сделать ссылку на соответствующий компонент.
Рис. У. 21. Ссылка на
компонент
На втором этапе,
однако, не надо создавать новый экземпляр объекта. Функцию можно использовать
просто как встроенную функцию Visual Basic.
Private Sub Count()
Tax = MwSt(150, 15) End Sub
Кроме
того, эта функция будет отображаться в группе <globals> каталога
объектов.
Visual Basic
заботится и о том, чтобы разработчик системыклиента получал соответствующую
справку уже при вводе кода.
Наряду с этим
способом реализации глобальных функций было бы неплохо, если бы можно было
создавать и глобальные определяемые пользователем константы. Для этого в состав
Visual Basic введен оператор Enum, с помощью которого можно создавать
определяемые пользователем перечисления. Однако они могут содержать только
элементы типа Long.
'Общий раздел
объявлений класса Functions Public
Enum Taxrates Normal
= 15 Half = 7 None = 0
End Enum
После приведенного выше объявления глобальные
константы Normal, Half и None становятся доступными для использования. С ними
можно работать так же, как и с константами Visual Basic. Отображаются они и в
каталоге объектов.
Поэтому, код для
вычисления налога может выглядеть следующим образом:
Private Sub Count))
Tax = MwSt(150, Normal) End Sub
Как уже было сказано,
в таких перечислениях могут присутствовать только константы типа Long. Но в
принципе, конечно, можно с помощью процедур Property Get создавать константы со
строковыми или другими значениями.
Public Property Get PayNormalO As String
PayNormal = "15% MwSt" End Property
Создав глобальное
свойство типа String только для чтения, вы получили соответствующую константу.
Несколько окольный путь, но зато цель достигнута.
Производительность прежде всего!
Хотя глобальные
объекты в компонентах очень удобны, они всегда работают медленнее, чем явно
созданные экземпляры объекта. Поэтому использование таких объектов надо хорошо
продумать.
Совместимость
Другой важный фактор
при создании компонентов — их совместимость с предыдущими версиями. Представьте
себе, что вы используете компонент, который создал ваш коллега или который вы купили.
Вы интегрируете этот компонент в ваше приложение и следовательно используете
его методы и свойства. Предположим, вы получили новую версию компонента и
включили ее в приложение. После этого ваше приложение перестает работать,
останавливается с сообщением об ошибке или реагирует не так, как положено.
Что случилось?
Возможно, производитель компонента изменил его код и тем самым изменил,
например, существующие интерфейсы. Допустим, до сих пор интерфейс Date
передавал значение даты в английском формате, а ваше приложение
"переводило" его. В новой версии компонент по умолчанию возвращает
дату в формате, задаваемом системой, которая ошибочно "переводится"
вашим приложением.
Из этого небольшого
примера ясно, что для разработчика компонентов крайне важно, чтобы при
изменениях в коде интерфейсы оставались совместимыми. Так, программист может
изменить код процедуры Date, но возвращаемое значение должно быть совместимо с
предыдущей версией.
Идентификатор CLSID
В такой же степени
для совместимости важны записи в реестре Windows, которые необходимы для
компонента. Записи такого компонента вносятся в реестр по идентификаторам — так
называемым CLSID.
Рт\ К. 25. Запись
реестра
Если, например,
приложение ссылается на компонент, то это происходит с помощью CLSID. Если это
значение изменяется, то соответствующее приложение будет считать компонент
"чужим" или "другим" компонентом. В этом случае компонент
надо устанавливать заново. В Visual Basic доступны два способа, позволяющие
сделать компонент совместимым сверху вниз. Это опции группы Version
Compatibility и функция Implements, с которой вы уже познакомились в главе
"Классы".
На вкладке Components
диалогового окна Project Properties можно установить проверку
совместимости в Visual Basic.
При этом возможны три
установки.
• No Compatibility
Visual Basic не
проверяет совместимость интерфейсов. Поэтому компонент может быть несовместим с
предыдущей версией (а может быть и совместим). При этой установке запись
реестра (CLSID) создастся заново.
• Project Compatibility
В этом случае хотя
значения в реестре и устанавливаются заново, информация в библиотеке классов
остается старой. Поэтому в тестовом проекте не надо устанавливать ссылку
заново.
• Binary Compatibility
Visual Basic
проверяет, насколько изменились интерфейсы, и предупреждает об этом. Новые
значения в реестре устанавливаются, только если это необходимо для
совместимости. Как правило, старые приложения могут работать с этой версией
компонента.
Обычно когда говорят
о совместимости версий, имеется в виду именно двоичная совместимость (Binary
Compatibility). И для этого случая в Visual Basic встроен удобный механизм
проверки на несовместимость. Если в компонент добавлены новые интерфейсы
(методы, свойства или события), компонент остается совместимым и предупреждение
не выдается. Например, в наш компонент File можно добавить новый метод Delete,
и этот компонент останется совместимым со "старыми" приложениями: они
просто не используют новый метод.
Напротив, если
имеющийся интерфейс изменен, Visual Basic при компиляции предупреждает об этом
изменении. Пусть, например, тип свойства FileName изменился CO String на
Variant.
В этом случае
разработчику предоставляется возможность выбора: сохранить совместимость версий
или отказаться от нее.
Если вы создали новые
версии компонентов и хотели бы улучшить их интерфейсы, в большинстве случаев
лучше реализовать эти интерфейсы как новые, чем изменять старые. Таким образом,
приложения, которые работают со старыми версиями компонентов, будут работать и
с новой версией, а новые приложения смогут обращаться к новым свойствам и
методам.
ActiveX и путь в Internet
Возможно, вы уже
неоднократно отметили в этой книге — Visual Basic пригоден для Internet и не
только потому, что в нем имеются специальные элементы управления для Internet.
Вы можете выходить с вашими приложениями прямо в Internet.
Создание документа ActiveX
В число таких
возможных приложении входят, среди прочего, элементы управления ActiveX, с
которыми вы познакомитесь в следующей главе. А сейчас мы займемся документами
ActiveX. Документы ActiveX также можно выполнить либо как исполняемые, либо как
динамические библиотеки (рис. 8.28).
Выбрать один из этих
типов проекта можно при создании нового проекта. В обоих случаях (ActiveX
Document DLL и ActiveX Document EXE) создается проект с новым компонентом
UserDocument. Он сохраняется в файле с расширением DOB (рис. 8.29).
В принципе
UserDocument — то же самое, что форма, однако в нем отсутствуют некоторые
элементы, например заголовок. Этот документ предназначен для выполнения в
приложенияхконтейнерах, к которым относится в том числе и Microsoft Internet
Explorer.
В качестве небольшого
примера создадим документ (Doci) с кнопкой и полем ввода. При щелчке на кнопке
выводится приветствие, содержащее текст (имя) из поля ввода.
Теперь если запустить
или скомпилировать этот проект. Visual Basic, кроме ЕХЕили DLLфайла, создаст
файл с расширением .VBD (Visual Basic Document). Этот файл можно добавить в
виде связи в Internet Explorer (например, C:\VB6\DOC1.VBD). В этом случае
Internet Explorer работает как приложениеконтейнер и вместо страницы в формате
HTML показывает наш UserDocument.
Как вы можете
убедиться, теперь приложение Visual Basic работает в Internet Explorer. Но это
происходит, только если имеются все необходимые файлы приложения и необходимые
компоненты Visual Basic. Простым копированием VBDфайла этого достичь
невозможно.
Особенности документов ActiveX
Как правило,
документу ActiveX доступно почти все, что доступно "нормальному"
проекту Visual Basic. Можно использовать обычные и ActiveX элементы управления,
коды и дополнительные формы. Тем не менее, следует помнить, что документ
ActiveX всегда работает в приложенииконтейнере и поэтому ограничен его
возможностями.
Несколько пользовательских документов
Разумеется, можно
использовать в одном приложении несколько пользовательских документов
(UserDocument). Но в отличие от форм, они не отображаются методом Show, а
должны выводиться на экран средствами навигации приложенияконтейнера: так же,
как в Internet происходит перемещение с одной страницы на другую с помощью
гиперссылки.
Специально для этого
в Visual Basic имеется объект Hyperlink, с помощью которого можно выполнять
такие переходы.
Private Sub
Command2_Click() Hyperlink.NavigateTo "doc2.vbd" End Sub
Метод NavigateTo
производит переход к нужной гиперссылке. Это может быть URL или файл, такой же,
как наш пользовательский документ.
Объект PropertyBag
Если пользователи при
работе будут часто возвращаться к вашему документу, было бы полезно сохранить
его текстовые элементы и т.п. и затем использовать их снова. В течение одного
сеанса это можно выполнить с помощью объекта PropertyBag. Подробнее об этом
объекте можно узнать в главе "Элементы управления ActiveX".
Как уже говорилось
выше, приложения Visual Basic можно без труда запускать в Internet Explorer.
Таким способом можно, например, подключать к HTMLстраницам в виде документов
приложения, которые постоянно нужны сотрудникам вашей
организации.
После этого приложения можно будет легко использовать через
Intranet:
не надо будет искать какието файлы проекта на какомто сервере,
инсталлировать новые версии программы на его диск и т.п.
Напоследок следует
упомянуть, что в Visual Basic имеется мастер, с помощью которого можно
преобразовать уже имеющиеся проекты в документы ActiveX.
Сохранение настроек компонента
Большинство
компонентов обладает определенными свойствами; чаще всего вы обрабатываете
событие класса initialize для'задания начальных значений этих свойств. После
компиляции компонента эти значения "заморожены" в нем, поэтому
возникает проблема — каким образом конкретный разработчик, использующий ваш
компонент, может изменить это начальное значение в соответствии со своими
требованиями? Для реализации этой возможности класс имеет специальное свойство
— Persistable, которое позволяет вам передавать значения свойств компонента
различным экземплярам объекта.
Например, у вас есть
компонент ActiveX DLL, с помощью которого вы вычис ляете прибыль от инвестиций,
основываясь на значении свойства компонента interestRate (процент
прибыльности). Естественно, что значение этого свойства в различных компаниях
будет разным, поэтому задание какоголибо значения для этого свойства по
умолчанию будет, по меньшей мере, некорректным. Используя постоянство класса,
вы можете хранить значение свойства interestRate и изменять его только при
изменении процента прибыльности. Теперь всякий раз при запуске ваш компонент
сможет считывать текущее значение свойства.
Если элементы
управления ActiveX всегда могут иметь постоянные данные, то постоянство для
компонентов ActiveX определяется другим способом. Элемент управления хранит
значения свойств в своем CLSфайле (файл класса), однако компонент не может
сделать это. Вместо этого он использует объект PropertyBag, который может
храниться в самых различных местах — в файле, в базе данных, в ячейке
электронной таблицы или даже в реестре Windows.
Для постоянства
класса он должен отвечать двум условиям: быть общедоступным (public) и
создаваемым (creatable). Если класс отвечает этим условиям, то свойство
Persistable появляется в окне свойств этого класса. Значение этого свойства по
умолчанию равно 0 (NotPersistable). После присвоения этому значению 1
(Persistable) разработчик получает возможность обрабатывать три новых события
класса: ReadProperties, WriteProperties и InitProperties, которые вызываются
соответственно для чтения, записи и инициализации значений свойств класса.
Свойство постоянства
Для обозначения
свойства как постоянного вы должны реализовать вызов метода PropertyChanged из
процедуры Property Let или Property Set:
Private mInterestRate As Single
Public Property Let InterestRate(newRate As
Single)
mInterestRate =
newRate
PropertyChanged
"InterestRate" End Sub
Вызов метода PropertyChanged отмечает
свойство InterestRate как измененное, что приведет к вызову события Writeproperties
при закрытии экземпляра компонента, если какоелибо свойство класса вызовет
метод PropertyChanged.
События ReadProperties, WriteProperties и
InitProperties
Процедура обработки
события Writeproperties используется при завершении работы экземпляра класса
для сохранения текущего значения свойства в объекте PropertyBag:
Private Sub
Class_WriteProperties(PropBag As PropertyBag) PropBag.WriteProperty
"InterestRate", mInterestRate, conDefaultRate End Sub
Метод WriteProperty
объекта PropertyBag принимает три аргумента: имя сохраняемого свойства
("InterestRate"), его текущее значение (mInterestRate) и значение по
умолчанию (conDefaultRate). Если текущее значение и значение по умолчанию
совпадают, то метод WriteProperty не перезаписывает это значение.
Событие
ReadProperties происходит при инициализации класса, но только если объект
PropertyBag содержит в себе какиелибо данные. Если же объект PropertyBag пуст,
то взамен происходит событие InitProperties. Процедуры обработки этих двух
свойств используются для инициализации начальных значений свойств:
Private Sub
Class_ReadProperties(PropBag As PropertyBag) mInterestRate =
PropBag.ReadProperty("InterestRate", conDefaultRate) End Sub
Private
Sub Class_InitProperties()
mInterestRate = conDefaultRate End Sub
Заметьте, что
константа conDefaultRate используется в обеих процедурах для задания значения
по умолчанию — этим вы избегаете риска случайного задания различных значений по
умолчанию в различных процедурах.
Использование объекта PropertyBag для Persist
объектов
Для поддержания
постоянства компонента ActiveX вам следует, вопервых, создать экземпляр объекта
PropertyBag. Такой путь может показаться избыточ ным — в конце концов, каждый
класс уже имеет свой собственный объект Prop ertyBag, почему же нельзя
воспользоваться им? Все очень просто — по завершении работы объекта удаляется и
его PropertyBag, так как он существует только в памяти, поэтому для поддержания
постоянства вы должны сохранить гденибудь копию этого объекта, чтобы потом
воспользоваться им снова.
Представьте себе
объект PropertyBag в виде портфеля, который вы можете заполнить определенным
содержимым и "поставить" гденибудь для безопасного хранения. Где его
"поставить" — зависит полностью от вас. В следующем примере значения
свойств сохраняются в текстовом файле:
Private pb As
PropertyBag ' Объявляем объект PropertyBag. Private LoanObject As Loan '
Объявляем объект Loan.
Private Sub
Form_Unload(Cancel As Integer) Dim varTemp as Variant
' Создаем объект PropertyBag. Set pb =
Mew PropertyBag
' Сохраняем объект LoanObject в PropertyBag.
pb.WriteProperty "MyLoanObject",
LoanObject
' Присваиваем содержимое PropertyBag
переменной типа Variant. varTemp
pb.Contents
' Записываем в
текстовый файл. Open "C:\Loandata.txt" For Binary As #1 Put #1, ,
varTemp Close #1 End Sub
Считывание
настроек объекта
Приведенный пример демонстрирует считывание
значений
сохраненных настроек
при инициализации объекта: Private pb As PropertyBag ' Объявление объекта PropertyBag.
Private LoanObject As Loan ' Объявление объекта Loan.
Private
Sub Form_Load()
Dim varTemp As Variant Dim
byteArrf) As Byte
' Создание объекта PropertyBag. Set pb
= New PropertyBag
' Считывание
содержимого текстового файла в переменную типа Variant. Open
"С:\Loandata.txt" For Binary As #1 Get #1, , varTemp Close #1
' Присваивание переменной типа Variant
массиву байт (Byte). ByteArr =
varTemp
' Заполнение объекта PropertyBag.
pb.Contents = ByteArr
' Инициализация объекта с помощью
PropertyBag Set LoanObject = pb.'ReadProperty ("MyLoanObject") End If
Глава 8
Элементы управления ActiveX
Наряду с компонентами
ActiveX различных типов, с которыми вы познакомились в предыдущей главе, Visual
Basic предоставляет разработчику возможность создавать собственные элементы
управления ActiveX — Custom Controls. Это могут быть как совершенно новые
элементы управления, так и базирующиеся на уже существующих элементах и
расширяющие их функциональные возможности.
Новые элементы можно
использовать как в проектах Visual Basic, так и в других системах
программирования, которые поддерживают технологию ActiveX. К ним относятся,
например, Microsoft Internet Explorer или Netscape Navigator (со специальными
вспомогательными программами PlugIn). По этой причине понятие "элемент
управления ActiveX" часто употребляется в связи с Internet. Элементы
ActiveX должны сделать Internet ярче, лучше и удобнее.
Создание элементов
управления ActiveX
В качестве примера в
этом разделе будет разработан комбинированный список, отображающий имена файлов
из заданного каталога. Вы убедитесь, что несмотря на сложность, эта задача
может быть быстро решена с помощью одного из многочисленных мастеров (рис.
8.1). Мастер обычно можно выбрать при запуске Visual Basic или при создании
нового проекта (рис. 8.2).
Пользовательский интерфейс
Мастер создает
элемент управления ActiveX, который состоит лишь из одного объекта UserControl.
На рис. 9.3 показан внешний вид будущего элемента управления. Он похож на
документ ActiveX, с которым вы уже познакомились в предыдущей главе.
Теперь добавим
элемент управления ComboBox, присвоим ему имя cmbFiles и добавим
соответствующий фон.
Основные свойства
объектов UserControl и ComboBox можно установить в окне свойств. Присвоим
новому элементу управления имя FileCombo. Затем сделаем фон элемента управления
прозрачным (установим значение свойства BackStyle равным 0). Также можно задать
значения и других свойств, например выбрать пиктограмму, которая будет
использоваться при отображении элемента управления на панели инструментов
(свойство ToolBoxBitmap).
Таким образом, мы
подготовили пользовательский интерфейс элемента управления. На следующем этапе
следует создать свойства, методы и события для элемента управления. Это также
можно сделать с помощью мастера.
Интерфейсы
Среди утилит Visual
Basic есть мастер интерфейсов ActiveX (ActiveX Control Interface Wizard). С
его помощью можно легко и просто сконструировать весь набор свойств, методов и
событий разрабатываемого элемента управления.
На первом этапе
мастер предлагает список стандартных интерфейсов (методой, свойств и событий).
Из них следует выбрать те, которые должен иметь элемент управления. Мы
ограничимся пятью свойствами, показанными на рис.
8.4.
На следующем этапе
работы мастера можно создать интерфейсы, определяемые пользователем. Это могут
быть события, свойства и методы. В данном примере создадим два новых свойства:
свойство initDir, которое будет указывать имя соответствующего каталога, и
свойство FileName, которое будет возвращать выбранное имя файла.
Рис. 8. 5. Окно мастера интерфейсов.
Этап 2
Конечно, можно
создать целый ряд других методов, свойств и событий, например свойство для
фильтрации файлов в зависимости от типа.
На следующем этапе
можно распределить методы, свойства и события нового элемента управления между
его компонентами. При этом допускается назначить метод, свойство или событие
как самому элементу управления, так и его составляющему компоненту. Так,
например, свойство ForeColor элемента управления связано со свойством ForeColor
элемента cmbFiles. Это означает, что при изменении значения свойства ForeColor
нового элемента управления, он передаст это изменение и элементу cmbFiles. В
результате изменится цвет элемента cmbFiles.
В данном случае все
свойства, за исключением двух, определяемых пользователем (InitDir, FileName),
связаны непосредственно с элементом управления cmbFiles.
На последнем этапе
работы мастера мастера интерфейсов должны быть установлены атрибуты свойств
FileName и InitDir. Оба свойства должны быть строчными переменными, не имеющими
значений по умолчанию. Кроме того, свойство Filename во время выполнения должно
быть доступно только для чтения.
Текст, который можно
ввести в поле Description окна мастера, потом будет появляться в
качестве подсказки в окне свойств. Однако при этом не забывайте, что, возможно,
использовать данный элемент управления придется не только вам. Поэтому
пояснительный текст должен быть понятен каждому.
После завершения
работы мастер добавляет необходимые строки кода в модуль элемента управления.
Окно свойств
Для многих элементов
управления, которые поставляются с Visual Basic, кроме общего окна свойств
Visual Basic, существует собственное окно свойств. Такое окно свойств можно
создать и самому. Для этого имеется мастер страниц свойств (Property Page
Wizard).
Мастер страниц по
умолчанию создает две страницы свойств: для выбора цвета и шрифта элемента
управления. Добавим к ним еще одну страницу General, с помощью которой
можно будет задавать определяемые пользователем свойства. С помощью мастера
отдельные свойства элемента управления можно разместить на различных страницах
этого диалогового окна.
Мастер создает новый
объект типа PropertyPage с несколькими полями ввода или комбинированными
списками для задания значений свойств. В любой момент этот объект можно
изменить.
Хорошо продумайте
использование таких страниц свойств. Как только элемент управления получает
определенные пользователем страницы свойств, его свойства распределяются между
двумя диалоговыми окнами: окном свойств и страницами свойств.
После создания
страниц просматривать и устанавливать значения свойств элемента управления
можно будет как в стандартном окне свойств Visual Basic, так и в созданном
вами. Большинство свойств элемента управления будут доступны в обоих окнах.
Однако некоторые будут видны лишь в одном из окон, что может привести к тому,
что разработчик потеряет контроль над свойствами и может пропустить какоето из
них.
Код созданного окна
свойств содержит две процедуры: процедуру для передачи изменений значений
свойства элементу управления и процедуру отображения значений свойств элемента.
Private Sub PropertyPage_ApplyChanges()
SelectedControls(0).FileName
= txtFileName.Text SelectedControls(0).InitDir =
txtInitDir.Text
SelectedControls(0).Enabled = (chkEnabled.Value =
vbChecked)
End Sub
Private Sub
PropertyPage_SelectionChanged() txtFileName.Text = SelectedControls(0).FileName
txtInitDir.Text = SelectedControls(0).InitDir chkEnabled.Value =
(SelectedControls(0).Enabled'And vbChecked)
End Sub
Итак, новый элемент
управления уже имеет почти все, что ему необходимо.
Код
Среди множества мастеров легко забыть одну
мелочь: в уже созданном коде еще нет процедур, которые бы обеспечивали
отображение имен файлов из выбранного каталога в элементе управления. Код этих
процедур нужно писать самостоятельно.
Сначала создадим процедуру GetDir, которая
будет считывать имена файлов из каталога, указанного в свойстве InitDir.
Программа будет обращаться к этой процедуре, по меньшей мере, в двух случаях.
Вопервых, при изменении свойства InitDir и вовторых, при запуске приложения,
т.е. при отображении элемента управления. I Private Sub GetDir()
Dim sFile As String
cmbFiles.Clear
sFile = Dir(m_InitDir)
Do Until sFile = ""
cmbFiles.Addltem
sFile sFile = Dir Loop End Sub
Эта процедура
вызывается из процедур Property Get InitDir и UserCon trol_Initialize. Последняя
запускается при инициализации элемента управления (запуске программы).
Public Property Get
InitDir() As String InitDir = m_InitDir Call GetDir
.End Property
Private Sub
UserControl_Initialize() Call GetDir End Sub
Остается еще
инициализировать свойство FileName. Для этого используется свойство Text
элемента cmbFiles.
Public Property Get FileName() As
String m_FileName » cmbFiles.Text FileName = m_FileName
End
Property
После этого созданный
элемент управления UserControl уже может функцио нировать. Однако рекомендуется
сделать еще маленькую корректировку. Так как созданный элемент управления
состоит только из одного комбинированного списка, то размеры элемента
управления не должны быть больше размеров списка cmbFiles. Поэтому следует
добавить еще несколько строк кода для корректировки размеров списка comboBox
при возникновении события Resize элемента управления.
При этом следует
соблюдать осторожность. Высоту элемента управления ComboBox изменить во время
выполнения невозможно. Поэтому необходимо изменять высоту элемента управления
UserControl, а не cmbFiles.
Private Sub UserControl_Resize()
cmbFiles.Width =
UserControl.Width
UserControl.Height = cmbFiles.Height End Sub
Итак, элемент
управления готов. Чтобы проверить его работу, можно создать другой проект и
применить в нем FileCombo.
Код без мастеров
Хотя мастера
предоставляют удобные средства для создания элементов управления, они, к
сожалению, не перекрывают весь диапазон элементов управления ActiveX,
необходимых разработчикам. Более того, часто требуется модифицировать код,
созданный мастером.
Специальные объекты
Следует обратить
внимание еще на два объекта, которые имеют особое значение для элементов
управления ActiveX. Это объекты Extender и AmbientProperties.
Extender
Элементы управления,
созданные разработчиком, помещаются в контейнеры, например п формы. Контейнеры
передают элементу управления значения свойства с помощью своего объекта Extender.
Созданный элемент управления FileCombo имеет гораздо больше свойств, чем их
было определено при разработке.
Эти свойства,
например Тор, передаются элементу управления FileCombo объектом Extender
контейнера. Однако разработчик, использующий элемент управления, не сможет
отличить их от обычных свойств элемента.
Как правило, нет
причины изменять в коде значения свойств, переданные объектом Extender.
Свойства Тор и Left устанавливаются при размещении компонента в форме. Тем не
менее, возможность влиять на эти свойства существует, хотя в большинстве
случаев они доступны только для чтения.
Изменять значения
свойств, переданных объектом Extender, можно, например, в процедуре
UserControl_InitProperties. Однако при изменении значений таких свойств может
случиться так, что элемент управления нельзя будет поместить в контейнер,
который этим свойством не располагает.
AmbientProperties
Объект
AmbientProperties можно использовать для согласования значений свойств элемента
управления и контейнера. Так, с помощью свойства BackColor можно подобрать цвет
элемента управления, соответствующий цвету контейнера.
Свойство UserMode
позволяет определить, в каком режиме (разработки или выполнения) находится
элемент управления. Это важно при работе со свойствами, которые должны
поразному функционировать в этих двух режимах.
Свойство DisplayName
играет важную роль при выдаче сообщений об ошибках выполнения. Оно содержит имя
экземпляра элемента управления. С его помощью разработчик может определить,
какой элемент вызвал ошибку.
С помощью события AmbientChange можно
узнать момент изменения значения свойств объекта AmbientProperties.
Сохранение
значений свойств
Для сохранения
значений свойств и последующего их восстановления используется объект
PropertyBag. Этот объект сохраняет свойства в файле контейнера (например,
свойства формы — в FRMфайле). Это осуществляется при помощи методов
Writeproperty и ReadProperty соответственно. Если элемент управления был создан
мастером интерфейсов, вы не должны беспокоиться о создании процедур сохранении
или чтении свойств — мастер автоматически создает необходимый код:
Private Sub
UserControl_ReadProperties(PropBag As PropertyBag) cmbFiles.BackColor =
PropBag.ReadProperty("BackColor", &H80000005) cmbFiles.ForeColor
= PropBag.ReadProperty("ForeColor", SH80000008) cmbFiles.Enabled =
PropBag.ReadProperty("Enabled", True) Set Font =
PropBag.ReadProperty("Font", Ambient.Font) m InitDir =
PropBag.ReadProperty("InitDir", m_def_InitDir) m_FileName =
PropBag.ReadProperty("FileName", m_def_FileName)
End Sub
В процедуре
UserControl_ReadProperties считываются свойства элемента управления FileCombo с
помощью метода ReadProperty. При этом параметры метода ReadProperty задают имя
свойства и значение по умолчанию, которое присваивается свойству, если значение
этого свойства не было сохранено.
Private Sub
UserControl_WriteProperties(PropBag As PropertyBag) Call
PropBag.WriteProperty("BackColor", _ cmbFiles.BackColor,
&H80000005) Call PropBag.WriteProperty("ForeColor", _
cmbFiles.ForeColor, &H80000008) Call PropBag.WriteProperty("Enabled",
cmbFiles.Enabled, _
True)
Call PropBag.WriteProperty("Font", Font, Ambient.Font) Call
PropBag.WriteProperty("InitDir", m_InitDir, _
m_def_InitDir) Call
PropBag.WriteProperty("FileName",'
m_FileName, _
m_def_FileName) End
Sub
В процедуре
UserControl_WriteProperties сохраняются значения свойств.
Стандарты
При разработке
элемента управления следует обратить внимание на ряд обстоятельств, которые
должны обеспечить простоту и удобство использования элемента.
Категории
свойств
В окне свойств собственные свойства объекта
по умолчанию помещаются в категорию General. По категориям
распределяются только те свойства нового элемента управления, которые переданы
ему объектом Extender.
Чтобы расположить
свойства по категориям, следует соответствующим образом изменить атрибуты
соответствующей процедуры Property (рис. 9.12). Отобразить эти атрибуты можно
при помощи команды Procedure Attributes меню Tools.
I'uc. 8. 12.
Диалоговое окно Procedure Attributes
С помощью диалогового
окна Procedure Attributes можно указать, к какой из категорий должно
относиться выбранное свойство (список Property Category).
Имена
В Visual Basic
большинству событий, свойств, методов, категорий и т.д. можно присваивать любые
допустимые имена. Однако при этом следует придерживаться существующих
стандартов. Например, разработчику легче ориентироваться, если событие имеет
стандартное имя click, а не Mouseclick.
Обработка
ошибок
При создании
элементов управления ActiveX следует предусмотреть возможность обработки ошибок
и выдачу соответствующей информации об ошибках. При этом не следует забывать,
что речь идет об элементах управления и компонентах ActiveX, а не об обычной
программе.
Версии
Насколько важно
организованное управление версиями компонентов ActiveX, вы уже узнали в
предыдущей главе. В не меньшей степени это касается и элементов управления
ActiveX. Представьте себе, что вы каждую неделю получаете новую версию
используемого вами элемента управления и ни одна из них не совместима с
предшествующей.
Элемент
управления выходит в свет
Созданный элемент
управления ActiveX вы можете распространять через сеть Internet или применять в
других проектах Visual Basic.
ActiveX
в проектах Visual Basic
Элемент управления
ActiveX можно использовать в таком виде, в каком он был создан, включив в
проект соответствующий файл компонента (*.CTL).
Однако элемент
управления чаще используется как скомпилированный модуль (ОСХфайл). С
технической стороны проблем возникнуть не должно: компонент должен быть лишь
зарегистрирован в системе. Регистрируя элемент управления, можно ограничить его
использование в среде Visual Basic или другой среде разработки. Это делается
при помощи так называемого лицензионного файла (*.VBL). Элемент управления,
которому необходим такой файл, нельзя запустить в среде разработки без него.
Visual Basic может
создать лицензионный файл автоматически при компиляции элемента управления. Для
этого в диалоговом окне Project Properties следует установить опцию
Require License Key.
REGEDIT
HKEY_CLASSES_ROOT\Licenses = Licensing: Copying the key may _
be a violation of
established copyrights. HKEY_CLASSES_ROOT\Licenses\ _ .
06CF58CF3C55411DOB455OOOOB45416E1
=
qjpjjqnjvjpqlqkqwkmqojojskrknjojpjwk
Это пример созданной Visual Basic
лицензионной записи.
ActiveX в Internet
Как и язык сценариев,
например VBScript, элементы управления ActiveX могут сослужить хорошую службу
при создании HTMLстраниц.
<OBJECT
classid="clsid:2F450484lC9D12DO8908OOB2F20395Fl"
codebase="http://wwwxyz.com/ax/filecombo.ocx#version=_
1,0,0,0"
id="File"
width="250"
height="40"
>
<PARAM
name="InitDir" value="C:\">
</OBJECT> .
В этом примере
элемент управления помещается в HTMLстраницу, однако без возможности
использования его событии. Для обработки событии следует самостоятельно
загрузить не только элемент управления, но и Visual Basic Virtual Machine.
Если при разработке
нового элемента управления вы использовали другие элементы ActiveX, то вместе с
вашим элементом управления вы должны предоставить разработчику и их. При этом подумайте
и о правовой стороне дела и выясните все вопросы с их производителем.
Учтите также и то,
что читатель HTMLстраницы, возможно, не захочет загружать и использовать
элемент управления ActiveX. В этом случае, вероятно, следует предоставить ему
информацию другим способом.
Hoebie возможности
Visual Basic 6.0
предоставляет разработчику новые возможности в области создания компонентов.
Отметим самые интересные из них.
Компоненты —
источники и приемники данных
В профессиональном и
промышленном изданиях появилась возможность создания приемников данных,
базирующихся на пользовательском элементе управления или классе, которые смогут
обеспечить возможность комплексного связывания данных (complex data binding).
Более того, можно создавать и источники данных на базе пользовательского
элемента управления или класса.
Источник данных — это
объект, связывающий другие объекты с данными из внешнего источника. Основу
объекта источника данных составляет модуль класса, обладающий средствами работы
с данными и реализующий набор интерфейсов для обращения к внешним источникам.
Такие классы могут быть также использованы при разработке компонентов ActiveX.
Примером служит элемент управления ADO Data, обеспечивающий визуальное связывание
элементов управления с записями базы данных с использованием интерфейса доступа
ADO (ActiveX Data Objects). Этот элемент управления вы можете использовать для
создания нового компонента ActiveX, имеющего намного больше возможностей, чем
ADO Data. При этом не имеет значения, как будет реализован созданный компонент:
как элемент управления ActiveX, как DLL или как ЕХЕфайл. В любом случае
созданный элемент ActiveX, являясь источником данных, обеспечит простой и
надежный доступ к данным, независимо от места их хранения.
Неоконные элементы
управления
Неоконные элементы
управления отличаются от обычных элементов управления тем, что у них
отсутствует дескриптор (handle) окна (свойство hwnd). Такие элементы управления
требуют меньше системных ресурсов, что делает их незаменимыми для применения в
Internetприложениях, распределенных приложениях или приложениях, в которых
фактор системных ресурсов является одним из основных.
Улучшение функции
CreateObject
Функция CreateObject
позволяет при создании объекта не только указать его тип, но и имя сетевого сервера,
на котором этот объект будет создан. Это позволяет создавать экземпляр объекта
не только на локальном, но и на удаленном компьютере, что особенно важно в тех
случаях, когда локальный компьютер не обладает необходимыми системными
ресурсами.
Мастер создания
объектов данных
Мастер создания
объектов данных (Data Object Wizard) поможет при создании
пользовательского источника данных или пользовательского элемента управления,
предназначенного для отображения и изменения данных при помощи сохраненных процедур
(stored procedures).
Для этого сначала
требуется создать объект Data Environment с соответствующими командами
получения и изменения данных, а затем позволить мастеру Data Object Wizard
воспользоваться командами объекта Data Environment для чтения и изменения
данных.
Новые свойства и события
В
Visual Basic 6.0 введено несколько новых событий и свойств, которые позволяют
улучшить компоненты, создаваемые самим разработчиком.
С
помощью свойства Has DC можно определить, имеет ли элемент управления уникальный
контекст устройства (True) или нет (False).
Событие FontChanged
происходит при изменении параметров шрифта, используемого элементом управления
ActiveX.
Рассмотренные ранее
свойство CauseValidation и событие Validation при создании пользовательских
элементов управления применяются так же, как и для стандартных элементов
управления. Однако все не так просто, если пользовательский элемент управления
включает несколько элементов. В этом случае событие Validation генерируется до
тех пор, пока фокус принадлежит пользовательскому элементу управления. Поэтому
обрабатывать это событие для составных элементов управления не рекомендуется.
Заключение
В этой главе вы
узнали, как с помощью средств Visual Basic можно создавать собственные элементы
управления. При этом мы поясняли материал на довольно простом примере. Однако
это не должно ограничивать вашу фантазию при создании собственных элементов
управления ActiveX.
Глава 9
Особенности Windows
История операционной
системы Windows начинается с 1985 года, когда появилась ее первая версия 1.01.
Уже тогда пользователю предоставлялся графический интерфейс и базовая модель
драйверов устройств. У появившейся в 1987 году версии 2.1 круг пользователей
стал несколько шире, и они были вознаграждены возможностью использовать
перемещаемые окна и динамический обмен данными (DDE). Настоящий прорыв
произошел в 1990 году, когда появилась Windows 3.0. Улучшенная версия 3.1
появилась в 1992 году. В том же году Windows получила встроенные возможности
работы в сети; этот продукт был назван Windows for Workgroups 3.1. Уже в 1993
году была представлена истинно 32разрядная операционная система Windows NT. Ее
интерфейс соответствовал обычной Windows. В версиях Windows for Workgroups,
Windows 95 и Windows 98. еще большее количество компонентов было реализовано в
32разрядном коде и интерфейс стал более эргономичным.
Для чего нужна Windows?
Раньше, приобретая
приложение для DOS, нужно было следить, чтобы видеокарта вашего компьютера или
принтер поддерживались этим приложением. В противном случае приходилось
создавать собственные драйверы для всех используемых видеокарт или принтеров.
С приложениями для
Windows дело обстоит иначе. После установки Windows видеодрайвер и драйвер
принтера уже настроены. Поэтому разработчик приложений для Windows не должен
самостоятельно выполнять эту работу — Windows предоставляет ему функции,
необходимые для использования видеокарты или принтера.
Разработчик
приложений для Windows может получить доступ к функциям операционной системы
различными способами. Вы уже делали это при создании первой программы на Visual
Basic. Тогда не надо было заботиться о том, как отобразить кнопку
CommandButton. Для управления памятью также не требовалось чтото
программировать. Эту часть работы брали на себя Visual Basic и Windows.
Вам также уже
встречался элемент управления CommonDialog. Это превосходный пример обращения к
функциям библиотеки COMDLG32.DLL. В Visual Basic эти функции реализованы как
набор свойств и методов элемента управления CommonDialog. Кроме того, в Visual Basic
встроены и другие компоненты для выполнения различных задач. Если же такие
компоненты в виде элементов управления или ссылок отсутствуют, то приложение
должно непосредственно обращаться к соответствующим функциям операционной
системы. Такой способ также допустим в Visual Basic.
В этой главе
объясняется использование функций Windows в Visual Basic. В дальнейшем будет
рассказано, как из Visual Basic обратиться к произвольной функции Windows.
Соглашения по интерфейсу
При разработке
программы следует обращать внимание на то, чтобы поведение приложения
соответствовало стандартам Windows, так как это облегчает общение пользователя
с приложением. Так называемая "мода" также играет важную роль при
разработке интерфейса. Подобно тому, как это происходит в автомобильной
промышленности, где новые модели визуально отличаются от прежних, дизайн имеет
большое значение при разработке программного обеспечения. Так, например,
интерфейс приложений для Windows 3х отличается от интерфейса приложений,
разработанных для Windows 95. Интерфейсы различных версий Microsoft Office
также отличаются друг от друга. Чтобы ваше приложение не выглядело
"устаревшим", надо уделять внимание его интерфейсу.
Фирмой Microsoft
выработаны требования, которым должно удовлетворять приложение, чтобы получить
логотип "совместимо с Windows 95". Эти семь пунктов называются
"великолепной семеркой" (fabulous seven).
"Великолепная семерка"
• Приложение должно быть скомпилировано в
32разрядном коде.
Для Visual Basic это
требование не составляет проблемы.
• Поддержка длинных имен файлов.
И это требование
выполняется без труда.
• Поддержка системных цветов.
Этот пункт означает,
что приложение должно не задавать произвольно цвета стандартных элементов
приложения (кнопки, строки меню, заголовки), а использовать системные цвета
Windows. И этот барьер легко преодолим. В Visual Basic 6.0 имеется ряд констант
(vbWindowBackground, vbWindowText, vbActiveTitleBar и т.д.), которые содержат
значения системных цветов. Тем не менее, при задании цвета в окне свойств можно
использовать как вкладку System (системные цвета), так и вкладку Palette
(пользовательские цвета).
• Поддержка больших и малых пиктограмм.
Этот пункт означает,
что пользователь может выбрать размер кнопок на панелях инструментов (или
других пиктограмм): нормальный (16х16 пикселей) или увеличенный (32х32
пикселя). Это требование можно выполнить, воспользовавшись элементом управления
imageList или файлом ресурсов, где данная пиктограмма может содержаться в двух
экземплярах разных размеров.
• Отслеживание системных изменений.
Этот пункт
подразумевает, что приложение должно реагировать на изменения системных
установок во время своего выполнения. Это могут быть изменения в
реестре, изменение
величины экрана и цветовой гаммы, а также добавление компонентов Plug&Play
или отображение состояния аккумулятора. Хотя это требование и выглядит
проблематичным, его можно легко выполнить с помощью элемента управления Sys
Info. Этот элемент управления позволяет обрабатывать некоторые сообщения
операционной системы, посылаемые ею всем приложениям. Таким образом, приложение
может, при необходимости, адаптироваться к изменениям в операционной системе.
• Автоматизированные установка и удаление
приложения.
Эту задачу позволяет
решить мастер инсталляции, управляющий последовательностью действий как для
установки, так и для удаления приложения. Работа с этим мастером подробно
описана в конце данной главы.
• Перетаскивание в пределах всего приложения
с использованием технологии OLE.
Это последнее
требование также легко выполняется в Visual Basic 6.
Некоторые элементы
управления (TextBox, PictureBox и др.) автоматически
выполняют это
требование, для других элементов управления эта
способность может
быть запрограммирована.
Существуют еще три
требования, которым должно удовлетворять приложение в отношении интерфейса
Windows 95. Они носят название "большая тройка" (great three).
"Большая тройка"
• Приложение должно иметь интерфейс Windows
95.
Это значит, что
приложение должно соответствовать текущим требованиям, предъявляемым к
интерфейсу. О них можно прочитать в последнем руководстве по визуальному
дизайну Windows (Visual Design Guide).
• Приложение должно использовать системный
реестр.
32разрядные программы
больше не должны использовать INIфайлы для сохранения установок. Значения
установок должны записываться в реестр Windows. Для этого удобно использовать
функции работы с реестром (SaveSetting и др.)
• Приложение должно использовать передовую
технологию OLE.
Этот пункт
подразумевает, что для обмена данными должны применяться новейшие программные
методы. В этой передовой области любая новая технология должна быть как можно
скорее доступна пользователю.
В
следующих разделах описываются некоторые характерные для Windows приемы.
Перетаскивание (Drag&Drop)
Когда вы хотите
переместить предмет с одного места на другое, вы берете этот предмет и
помещаете его на новое место. Такой способ действий в точности скопирован и в
Windows. Элементы можно "взять" с помощью мыши и расположить в нужном
месте. Этот процесс называется перетаскиванием (технология Drag&Drop). Вам
уже известна такая техника по работе с Проводником, где файлы можно перемещать
и копировать с помощью мыши. Вы использовали эту технику и в Visual Basic,
например при размещении элементов управления в форме. Эту возможность вы можете
реализовать и в ваших приложениях.
Программируемое
перетаскивание
Прежде чем начать
программирование процесса перетаскивания, следует подробно проанализировать
его. Кто участвует в этом процессе? Какие действия при этом происходят? Как видно
из названия — Drag&Drop, — в процессе участвуют два объекта: объект Drag и
объект Drop, другими словами, объектисточник и объект приемник.
Объектисточник
На стартовой стороне
происходит захват элемента, для чего надо нажать кнопку мыши. На целевой стороне
этот объект оставляется, для чего следует отпустить кнопку мыши. Часто этот
процесс делается более наглядным для пользователя путем изменения курсора мыши.
Событие
MouseDown
Чтобы начать процесс
перетаскивания, следует перейти в режим перетаскивания (Drag). Обычно это
происходит в процедуре обработки события MouseDown.
Метод
Drag
Чтобы
"захватить" стартовый объект с помощью курсора мыши, используется
метод Drag. Константу vbBeginDrag при его вызове указывать не обязательно.
После этого объект
становится "привязанным" к курсору мыши, пока кнопка мыши не будет
отпущена:
Private Sub
Filel_MouseDown(Button As Integer, Shift As Integer, _ ,X As Single, Y As
Single) If Button = vbLeftButton Then Filel.Drag vbBeginDrag End If End Sub
В данном примере
начинается процесс перетаскивания для элемента управления FileListBox. Обратите
внимание, что в примере не определено, что должно окончательно произойти с
объектом. Кроме того, используется весь объект, а не какаялибо его отдельная
часть или свойство. Эти уточнения будут сделаны лишь в объектеприемнике.
Объектприемник
Когда переносимый
объект попадает в объектприемник, его следует там оставить. Это должно
происходить после отпускания кнопки мыши (событие MouseUp). Однако можно легко
установить, что событие MouseUp в этом случае не наступает — вместо него в
режиме перетаскивания происходит событие DragDrop.
События
DragDrop
Следует различать
события MouseUp и DragDrop, поскольку простои щелчок мышью (при котором
происходит отпускание кнопки мыши) не производит такого же действия, как
процесс перетаскивания
Объектприемник
определяет действие, которое должно быть совершено над перемещаемым объектом
должен ли он быть скопирован, удален, перемещен, вставлен и т д Это происходит
в процедуре обработки события DragDrop объектаприемника
Private Sub Listi DragDrop(Source As Control,
X
As Single, Y As Single) Li stl.Add.Item Filel. FileName End Sub
В данном примере
принимающая сторона (ListBox) использует свойство File Name стартового объекта
FileListBox, добавляя значение этого свойства в список
Курсор мыши
Этапы процесса
перемещения следует сделать наглядными, устанавливая для каждого из них
соответствующий вид курсора мыши Вначале (для объекта источника) следует
сообщить об успешном получении переносимого объекта Затем для объектов, которые
не могут участвовать в этом процессе (не соответствуют типу объектаприемника),
должен отображаться курсор, сообщающий о невозможности выполнения
перетаскивания, а для объекта приемника — курсор, разрешающий оставить объект
Из рис. 11 3 можно
получить некоторые сведения о текущем процессе перетаскивания По имени файла
около курсора мыши можно узнать, над каким файлом производится действие
Принимающая (целевая) папка выделена, а символ "+" под курсором мыши
позволяет определить, что файл в данную папку копируется Этот пример
показывает, как много информации можно сообщить путем визуализации одного лишь
процесса перетаскивания Об этом также следует помнить при разработке приложений
В Visual Basic можно
управлять видом курсора мыши во время процесса перетас кивания. Для этого,
кроме свойств MousePointer и Mouselcon, существует специальное СВОЙСТВО
Draglcon.
Свойство Draglcon
С помощью этого
свойства можно задать, какой вид должен иметь курсор при выполнении операции
перетаскивания. Это свойство может содержать изображение в формате ICO или CUR
(пиктограмма или курсор), которое можно загрузить, воспользовавшись функцией
LoadPicture.
Событие DragOver
Событие, при
обработке которого следует изменять курсор мыши, наступает при пересечении
границы объекта. Это событие имеет сходство с событием MouseMove и называется
DragOver. Процедуре обработки этого события передаются четыре параметра.
Параметр Source содержит указатель на переносимый объект. Параметр State
определяет положение курсора мыши по отношению к объекту и может принимать
значения vbEnter, vbLeave или vbOver. Параметры X и Y содержат текущие
горизонтальную и вертикальную позиции курсора мыши.
Private Sub Filel_DragOver(Source As Control,
X As Single, _
Y As Single, State As
Integer) Select
Case State Case
vbEnter
Filel.Draglcon =
imgPositiv.Picture Case vbLeave
Filel.Draglcon = imgNegativ.Picture End Select End Sub
Если значение
свойства Draglcon не установлено, то Visual Basic при перетаскивании отображает
рядом с обычным курсором мыши силуэт объекта. Если вы не хотите, чтобы этот
силуэт появлялся, то вам следует перед вызовом метода Drag установить
определенное значение свойства Draglcon:
Private Sub Filel_MouseDown(Button As
Integer, Shift As Integer, _
X As Single, Y As
Single) If Button = vbLeftButton Then Filel.Draglcon = imgPositiv.Picture
Filel.Drag vbBeginDrag End If End Sub
На
стороне приемника также следует отображать соответствующий курсор мыши:
Private Sub Listl_DragOver(Source As Control,
X As Single, _
Y As Single, State As
Integer) Select Case
State Case vbEnter
Filel.Draglcon =
imgPositiv.Picture Case vbLeave
Filel.Draglcon = imgNegativ.Picture End Select End Sub
Обратите внимание,
что свойство Draglcon объектаисточника (FileListBox) изменяется в
процедуре обработки события DragOver объекта приемника (ListBox). Если
бы здесь использовалось свойство Listi. Draglcon, то это повлияло бы на
вид курсора мыши при перетаскивании из ListBox.
Различные объектыисточники
Аргумент Source в
процедурах обработки событий DragDrop и DragOver представляет собой ссылку на
объектисточник и может быть различного типа. Это значит, что объектприемник
может получать данные из различных источников.
Private Sub
Listl_DragDrop(Source As Control, X As Single, _ Y As Single) Listi.Addltem
Source.Filename End Sub
В данном примере
используется свойство Filename объекта Source. Процесс перетаскивания может
быть начат применением метода Drag к произвольному объекту FileListBox.
Оператор Type Of
При использовании произвольного
стартового объекта следует проверить, что этот объект имеет соответствующее
свойство. Это можно осуществить, воспользовавшись оператором TypeOf, который
проверяет соответствие типа конкретного объекта заданному.
Имена типов элементов
управления, присутствующих в данной форме, доступны для просмотра в списке
объектов окна свойств.
Private Sub
Filel_MouseDown(Button As Integer, Shift As Integer, _ X As Single, Y As
Single) Filel.Drag vbBeginDrag End Sub Private Sub Commandl MouseDown(Button As
Integer, Shift As Integer, _ X As Single, Y As Single) Commandl.Drag
vbBeginDrag End Sub
Private
Sub Listl_DragDrop(Source As Control, X As Single, Y As Single)
,. (If .TyyeQf.
Source Is FileListBox Then Listi.Addltem Source.Filename End If End Sub
Private Sub
Form_DragDrop(Source As Control, X As Single, Y As Single) If TypeOf Source Is
CommandButton Then Source.Move X, Y End If End Sub
В этом примере
реализованы два процесса перетаскивания. Первый позволяет скопировать имя файла
из FileListBox в ListBox. С помощью второго можно перемещать кнопку
CommandButton в пределах формы. Так как объект приемник осуществляет проверку
типа объектаисточника, различные процессы перетаскивания не смешиваются.
Другими словами, если попытаться перетащить CommandButton в ListBox, то ничего
не произойдет. Аналогично, перенос имени файла из FileListBox не вызовет
никакой реакции формы.
Возможны и другие
варианты проверки различных свойств объекта источника:
Private Sub
Form_DragDrop(Source As Control, X As Single, Y As Single) If Source.Name =
"Commandl" Then Source.Move X, Y End If End Sub
В данном случае можно перемещать только
объект с именем Commandl.
Private Sub
Form_DragDrop(Source As Control, X As Single, Y As Single) If Source.Tag =
"movable" Then Source.Move X, Y End If End Sub
В этом примере
свойству Tag было предварительно присвоено значение "movable",
которое затем проверяется.
Автоматическое
перетаскивание
Многие элементы
управления обладают свойством DragMode. Изменив его значение с vbManual на
vbAutomatic, можно не вызывать метод Drag для объек таисточника, так как в этом
случае становится возможным автоматическое перетаскивание.
Этим свойством,
однако, следует пользоваться осторожно, так как vpv! автоматическом
перетаскивании инициируемые пользователем события мыши или клавиатуры (KeyDown,
Keypress или KeyUp, MouseDown, MouseMove или MouseUp) распознаваться не будут.
Если в качестве
объектаисточника выступает CommandButton, то процесс перетаскивания практически
не изменится. Но если объектомисточником будет, например, FileListBox, то
процесс перетаскивания начнется до выделения в нем элемента. Поэтому свойство
Filename не будет определено и объект приемник не сможет выполнить никакого
действия. Поскольку автоматическое перетаскивание не всегда имеет преимущества
перед ручным, следует работать в ручном режиме с использованием метода Drag.
Перетаскивание с
использованием OLE
Перетаскивание с
использованием OLEтехнологии использует ту же модель объектов источника и
приемника, что и перетаскивание, управляемое событиями. Однако в случае
перетаскивания с использованием механизма OLE перемещается не элемент
управления, а объект данных, что позволяет реализовать обмен данными с любыми
приложениями, используя OLE интерфейс Windows.
Для перетаскивания с
использованием механизма OLE Visual Basic предоставляет очень хорошую
автоматическую поддержку процесса. Этот процесс предпочтительно применять
всегда, когда надо осуществить простое перетаскивание между элементами
управления или приложениями.
Для управления процессом
OLEперетаскивания все действия, как и при простом перетаскивании, должны быть
запрограммированы.
Автоматическое перетаскивание
Использовать
автоматическое OLEперетаскивание достаточно просто. Если процесс переноса для
этого элемента управления должен начаться автоматически, то свойству
OLEDragMode присваивается значение vbOLEDragAutomatic. С помощью свойства
OLEDropMode можно задать режим приема для объектаприемника.
Значения свойств
OLEDragMode и OLEDropMode можно задать как при разработке (окно свойств), так и
при выполнении приложения:
Private Sub
Form_Load() Text 1.OLEDragMode = vbOLEDragAutomatic
Textl.OLEDropMode = vbOLEDropAutomatic End Sub
В данном примере
показано, как установить автоматический режим OLEDragMode и OLEDropMode для элемента
управления TextBox. В результате такой установки выделяемую в текстовом поле
Textl строку текста можно перемещать с помощью мыши (например, в другое
текстовое поле).
Однако автоматическое
OLEперетаскивание поддерживают не все элементы управления. В табл. 11.1
приведены элементы управления, для которых можно установить автоматический
режим OLEDragMode и OLEDropMode (т.е. элементы могут быть как источником, так и
приемником) или только OLEDragMode (элементы могут быть только источником).
Таблица 10.1.
Элементы управления с автоматическим режимом перетаскивания с использованием
OLE
Поддерживают OLEDragMode и |
Поддерживают OLEDragMode |
OLEDropMode |
|
TextBox |
ListBox |
RichTextBox |
ComboBox |
MaskedEdit |
TreeView |
PictureBox |
ListView |
Image |
DBListBox |
DBGrid |
DBComboBox, FileListBox, DirectoryListBox |
Чтобы узнать, поддерживает ли данный элемент
управления автоматическое OLEперетаскивание, следует посмотреть в окне свойств,
присутствует ли в списке возможньк значений для свойств OLEDragMode и OLEDropMode
значение Automatic.
Процесс переноса в зависимости от типа элемента
управления следует выполнять в соответствии с некоторыми правилами. Если
перетаскивание осуществляется только при нажатой кнопке мыши, то считается, что
данные перемещаются из
объектаисточника в объектприемник и по завершении
переноса ЙеремеЩённые данные в источнике следует удалить. Если перетаскивание
выполняется при нажатой клавише [Ctrl], то данные просто копируются.
Программируемое перетаскивание
Если обычный процесс
OLEперетаскивания необходимо какимлибо образом подкорректировать, то
дополнительные действия следует запрограммировать. Это также необходимо в том
случае, если вы работаете с элементами управления, которые не поддерживают
автоматическое OLEперетаскивание.
Таблица 11.2. Элементы управления с ручным
OLEперетаскиванием
Элемент управления
CoimnandButton
Label Checkbox
OptionButton
Frame
DriveListBox
С помощью целого ряда
свойств, методов и событий можно установить, что должно происходить при захвате
или отпускании объекта.
Таблица 10.3.
Свойства, методы и события OLEперетаскивания
Элемент |
Описание |
Свойства: |
|
OLEDraqMode |
Активизирует элемент
управления в качестве объектаисточника. |
OLEDropMode |
Активизирует элемент
управления в качестве объектаприемника. |
Методы: |
|
OLEDraq |
Начинает процесс
перетаскивания. |
События: |
|
OLEDraqDrop |
Происходит при перетаскивании
объектаисточника в объект |
OLEDraqOver |
Происходит, когда один
компонент перемещают над другим. |
OLEGiveFeedback |
Происходит после каждого
события OLEDraqOver и обеспечивает |
|
визуальную обратную связь
(например, изменение курсора мыши). |
OLEStartDraq |
Происходит при выполнении
метода OLEDrag или при |
|
инициализации автоматического
OLEперетаскивания. |
OLESetData |
Происходит для объектаисточника
после применения объектом |
|
приемником метода GetData для
объекта DataObject источника, при |
|
этом данные для определенного
формата еще не загружены. |
OLECompleteDraq |
Происходит после перемещения
объектаисточника в объект |
|
приемник дляинформированияисточника
о выполнении или отмене |
Эти
события проявляются поразному в начальной и конечной точках процесса
OLEперетаскивания.
При OLEперетаскивании на стартовой стороне формируется
пакет данных в соответствующем формате. Затем определяется, какие действия с
этими данными допустимы: копирование или перемещение. На принимающей стороне
пакет данных принимается и соответствующим образом обрабатывается.
Объектисточник
Как и при обычном
перетаскивании, процесс OLEперетаскивания начинается вызовом метода OLEDrag:
Private Sub
Textl_MouseMove(Button As Integer, Shift As Integer, _ X As Single, Y As
Single) If Button = vbLeftButton Then Textl.OLEDrag End If
End Sub
Метод OLEDrag не
имеет аргументов и не формирует соответствующий пакет данных, а только начинает
процесс перетаскивания.
Объект DataObject
Формирование пакета
данных происходит в процедуре обработки события OLEStartDrag, которой передается параметр Data,
указывающий на объект DataObject:
Private Sub
Textl_OLEStartDrag(Data As DataObject, _ AllowedEffects As Long) AllowedEffects
= vbDropEffectCopy Or vbDropEffectMove , Data.Clear Data.SetData Textl.Text,
vbCFText End Sub
Параметр
AllowedEffects определяет, как будут переноситься данные — какая операция над
данными будет выполняться — копирование или перемещение. Объект DataObject
имеет свойства и методы, аналогичные объекту clipboard.
Таблица 10.4.
Свойства и методы DataObject
Свойства и методы
Свойства:
Files
Методы:
Clear
GetData
GetFormat
SetData ________
С помощью метода SetData
объекту DataObject устанавливают необходимые данные в определенном формате.
Метод Clear используется для удаления содержимого объекта. Метод GetFormat
проверяет, есть ли данные в конкретном формате в DataObject.
Таблица 10.5. Константы
методов GetData и SetData
Константа |
Описание |
vbCFText |
Текст |
vbCFBitmap |
Растровое изображение |
vbCFMetafile |
Метафайл Windows |
vbCFEMetafile |
Расширенный метафайл |
vbCFDIB |
Аппаратнонезависимое растровое изображение |
vbCFPalette |
Палитра |
vbCFFiles |
Список имен файлов |
vbCFRTF |
Расширенный текстовый формат |
Проверка текущего формата позволяет определить, сможет
ли приемник правильно использовать содержащиеся в DataObject данные.
Завершение действия
Когда процесс
перетаскивания завершается оставлением пакета данных в приемнике, источник
также должен предпринять какието действия. Например, при перемещении данные
источника должны быть удалены. По завершении процесса перетаскивания происходит
событие OLECompleteDrag. Параметр Effect сообщает, какое действие было
выполнено приемником:
Private Sub
Textl_OLECompleteDrag(Effect As Long) If (vbDropEffectMove And Effect) Then
Textl.Text = "" End If End Sub
Обратите внимание,
как в примере проверяется значение параметра Effect. Для этого не используется
простое сравнение типа:
If Effect =
vbDropEffectMove Then...
Значение
параметра маскируется при помощи логической операции And:
If Effect And vbDropEffectMove = vbDropEffectMove Then
Это можно записать и короче:
If (vbDropEffectMove
And Effect) Then
Такая конструкция
производит тот же эффект, что и простое сравнение. Если в будущих версиях
Visual Basic появятся другие комбинации эффектов, этот код не надо будет
изменять.
Объектприемник
На принимающей стороне свойство OLEDropMode
должно иметь значение vbOLEDropManual. Если установлено значение
vbOLEDropAutomatic, то дополнительный код не нужен: Если это свойство осталось
с первоначальньм значением ybOLEDropNone, то данный элемент управления не может
быть использован в качестве приемника.
Когда данные
оставляются, для приемника происходит событие OLEDragDrop. При этом объект
DataObj ect передается процедуре обработке события как параметр Data. С помощью
метода Get Data данные в требуемом формате копируются из DataObj ect. При
считывании данных должен быть указан один из приведенных выше форматов. Если
данных в соответствующем формате нет, то никакое действие не выполняется.
Форматы, допустимые для метода GetData, приведены в табл. 11.5.
Private Sub Text
l_OLEDragDrop.( Data As DataObject, Effect As Long, _ Button As Integer, Shift
As Integer, ._ X As .Single, Y As Single) If Data.GetFormat(vbCFText) Then
Textl.SelText
Data.GetData(vbCFText) Effect as
vbDropEffectCopy
Else
Effect = vbDropEffectNone End If End
Sub
Параметр Effect сообщает
объектуисточнику, какое действие было выполнено (например, vbDropEffectMove
или vbDropEffectCopy). Это значение передается в процедуру обработки
события OLECompleteDrag объекта источника.
Параметры
Button и Shift
С помощью параметров
Button и shift можно узнать состояние определенных клавиш на клавиатуре, что
необходимо для определения вида перетаскивания (копирование или перенос):
Private Sub
Textl_OLEDragDrop(Data As DataObject, Effect As Long, _ Button As
Integer, Shift As Integer, _ X As Single, Y'As Single) If
Data.GetFormat(vbCFText) Then If Shift And vbCtrlMask
Then
Textl.SelText = Data.GetData(vbCFText) Effect
=
vbDropEffectCopy Else
Textl.SelText = Data.GetData(vbCFText) Effect =
VbDropEffectMove Else
Effect =
vbDropEffectNone End If End Sub
В этом примере при отпускании кнопки мыши
данные перемещаются в объектприемник, а если перетаскивание происходит при
нажатой клавише [Ctrl], то данные копируются.
Курсор
мыши
Большое значение при
перетаскивании имеет отображение соответствующего курсора мыши.
Событие
OLEDragDrop
Событие OLEDragDrop
происходит после перемещения объекта источника в объектприемник. Процедуре
обработки этого события передаются такие же параметры, что и при обработке
события DragDrop при обычном перетаскивании. Дополнительно передается параметр
Data для контроля форматов данных:
Private Sub Textl
OLEDragOver(Data As DataObject, Effect As Long, _ Button As Integer, Shift As
Integer, _ X As Single, Y As Single, _ State As Integer) If
Data.GetFormat(vbCFText) Then
Effect =
vbDropEffectCopy And Effect Else Effect = vbDropEffectNone End If End Sub
С помощью параметра Effect можно управлять
видом курсора мыши.
В зависимости от вида
окончательного действия может быть отображен соответствующий курсор мыши.
Событие OLEGiveFeedback
Изменение вида курсора
мыши во время OLEперетаскивания происходит при обработке события
OLEGiveFeedback. Параметр Effect содержит значение, установленное при обработке
события OLEDragDrop. В зависимости от его значения можно решить, следует ли
сохранить стандартный курсор мыши. Если установить значение параметра
DefaultCursors равным False, то вместо стандартного может быть отображен
произвольный курсор. Его можно указать с помощью свойств MousePointer И
Mouselcon объекта Screen:
Private Sub Textl_OLEGiveFeedback(Effect As
Long, _
DefaultCursors As Boolean)
DefaultCursors =
False Screen.MousePointer = vbCustom Select Case
True Case Effect =
vbDropEffectNone
Screen.MousePointer =
vbNoDrop Case Effect
vbDropEffectCopy And
Effect
Screen.Mouselcon =
imgCopy.Picture Case Effect =
vbDropEffectMove And Effect
Screen.Mouselcon =
imgMove.Picture Case Else
DefaultCursors
= True End
Select End Sub
В зависимости от
значения параметра Effect будут отображаться различные курсоры мыши. После
окончания процесса перетаскивания следует восстановить прежний курсор мыши:
Private Sub
Textl_OLECompleteDrag(Effect As Long)
If vbDropEffectMove And Effect Then
Textl.Text = "" End If Screen.MousePointer = vbDefault End
Sub
Приложения и документы
В зависимости от вида
приложений желательно иметь разные типы окон. С помощью окон различных типов
можно реализовать различные функциональные возможности.
Один из таких типов
окон можно увидеть на примере панели элементов Visual Basic. Это окно не
перекрывается обычными окнами и может быть "привязано" к краю окна
приложения.
Другой тип окон
используется в Word для Windows или Excel. Здесь каждый открытый файл
отображается в своем собственном окне. Хотя такие окна принципиально не
отличаются от обычных, некоторые их характеристики позволяют отнести их к
другому типу окон. Главное окно приложения содержит в себе окна документов, и
поэтому пользователь не теряет общий контроль над своими документами. Это
главное окно, в свою очередь, представляет собой еще один тип окон.
MDIприложение
Вы уже знакомы с
концепцией "многодокументного интерфейса" (Multiple Document
Interface — MDI). Приложение может одновременно работать с несколькими
документами в дочерних окнах. Окна различного уровня иерархии зависят друг от
друга.
SDIприложение
Противоположность этой
концепции представляет "интерфейс одного документа" (Single Document
Interface — SDI). Здесь все окна находятся на одном и том же уровне иерархии.
Обычно все простые приложения имеют лишь одну форму. В качестве примера можно
привести графический редактор Paint. Более сложные приложения, впрочем, тоже
могут использовать эту концепцию.
Приложение типа Explorer
Третью категорию
образуют приложения, подобные Windows Explorer (Проводник). В этих приложениях
окно разделено на две части. Слева отображается иерархическая структура
(дерево), а справа — список элементов. Этот тип может быть реализован как
SDIприложение (Проводник) или как MDI приложение (Диспетчер Файлов).
Visual Basic
позволяет применять различные типы интерфейса; да и сам Visual Basic можно запустить
как MDI либо как SDIприложение. Таким образом, вы убедились, что в Windows
используются окна различных типов.
MDI — многодокументный интерфейс
Приложения,
позволяющие пользователю работать с несколькими файлами одновременно, должны
заботиться о том, чтобы пользователь не терял контроля над окнами с
документами. Поэтому для приложений типа Word для Windows следует использовать
многодокументный интерфейс. Использование MDI интерфейса предполагает, что
внутри окна приложения отображается несколько окон документов. В терминологии
MDIприложений обрамляющее окно также называется родительской или главной
формой. Окна документов называются формами документов или дочерними формами.
Другой излюбленный,
хотя и устаревший пример — это Program Manager (Диспетчер Программ) в Windows
З.х.
Само по себе окно Program
Manager представляет главную форму. Главная форма может иметь несколько
дочерних форм, которые не могут выходить за пределы главной формы. Оба этих
вида окон всегда связаны друг с другом. В Windows, в частности в Visual Basic,
MDIприложение всегда может иметь только одну главную форму. Число дочерних форм
ограничено лишь физическим объемом памяти.
Если в MDIприложении
закрывается главная форма, все дочерние окна также будут закрыты. Если
открывается главная форма, ни одно дочернее окно не открывается, по крайней
мере, не открывается автоматически. Напротив, если открывается дочернее окно,
главная форма автоматически открывается вместе с ним, если это еще не было
выполнено.
Экземпляры
В главе 7 уже говорилось
об экземплярах классов. Для MDIприложении этот предмет также имеет большое
значение. Например, когда в Microsoft Word для Windows открыто четыре
документа, в действительности в этом приложении существует не четыре разных
типа дочерних окон, а только один. Имеется только один оригинал дочернего окна,
с которого при необходимости делаются копии. После этого дубликат начинает
существовать как самостоятельное дочернее окно с собственным содержимым. Хотя
после окончания программы содержимое дубликата сохраняется, сам он удаляется и
существует в памяти только во время выполнения приложения.
Этап разработки |
Потомок |
||||
|
(оригинал) |
||||
Запуск программы |
|
Потомок |
|||
|
|
(копи |
|||
[Новый документ] |
|
Потомок |
Потомок |
||
|
|
(копи |
(КОП |
||
[Новый документ] |
|
Потомок |
Потомок |
Потомок |
|
|
|
(КОП |
(КОП |
(КОПИ |
|
Конец программы |
Потомок |
|
|
|
|
|
(оригинал |
|
|
|
|
| |||||
Рис. 10.13. Экземпляры окон
На этом рисунке
показано, как приложение работает с окнами. На этапе разработки создается
образ формы. Во время выполнения используются лишь копии исходной формы.
Поэтому все окна документов имеют один и тот же тип. Если необходимо,
создается новая копия оригинала. При завершении программы все копии удаляются
из памяти и остается лишь исходная форма.
Экземпляры объекта
Form могут использоваться не только в MDI приложениях:
Dim oMyForm As Form
Private Sub Conmiandl_Click
Set oMyForm = New
Formi
oMyPorm.Show
oMyForm.Caption =
Time End
Sub
Ключевое слово New
С помощью
зарезервированного слова New можно во время выполнения программы создать
экземпляр предварительно заданного объекта. Этот экземпляр объекта будет иметь
те же свойства, методы и компоненты, что и исходный объект.
Обратите внимание,
что все копии получают имя переменной, указанной после New. Поэтому, чтобы
можно было работать с разными копиями формы, для различения экземпляров этой
формы следует выполнить некоторые дополнительные действия.
При создании новых
экземпляров копируется не только внешний вид формы и ее объектов, но и код,
относящийся к этой форме. Это может вызвать проблемы, если, например, в
исходной форме используется конкретное имя формы (например, Formi). При
создании экземпляров копии формы получают другое имя (например, oMyForm).
Поэтому в коде формы, которая служит образцом для других, не следует
использовать явные имена.
Formi.Caption = "Это форма Formi"
Эта строка,
выполненная в экземпляре, изменит только заглавие исходной формы, хотя
программист намеревался изменить заглавие каждой формы данного типа.
Ключевое слово Me
Поэтому в словарь
Visual Basic было введено новое слово — Me. Оно ведет себя подобно неявно
объявленной переменной и всегда указывает на форму, в которой находится
исполняемый в данный момент код.
Me.Caption = "Это новая форма"
Таким образом, Me заменяет имя формы,
в которой находится данный код.
Так как слово Me
всегда указывает на форму, его нельзя применять в других контейнерах, например
в модулях. Элементы управления всегда принадлежат какойлибо форме, поэтому
перед именем элемента управления указывается имя формы. Это происходит и в том
случае, если разработчик не указал это имя явно. Перед такими элементами
управления Visual Basic помещает неявное, невидимое слово Me. Поэтому обе
приведенные ниже строки выполняют одно и то же действие:
Me.Text
I.Text = "Привет" Textl.Text = "Привет"
При таком обращении
к элементу управления имеется в виду форма, в которой эти строки находятся.
Другой пример:
Formi.Textl.Text =
"Привет"
А эта строка всегда
будет относиться к объекту Formi независимо от того, где она будет
выполняться.
Что же делать, если
необходимо из модуля обратиться к элементу управления в одном из экземпляров?
Ведь заранее неизвестно, какой экземпляр будет активен в данный момент —
первый, последний или пятый.
Свойство ActiveForm
Для решения этой
проблемы используется свойство ActiveForm объекта Screen. Это свойство
содержит ссылку на активную форму:
Screen.ActiveForm.Caption
= "Текущая форма"
Если неизвестно,
какой элемент управления из имеющихся в форме активен в данный момент, к нему
можно обратиться, воспользовавшись свойством ActiveControl:
Screen.ActiveForm.ActiveControl.Text =
"Привет"
Разумеется, этот
пример работает лишь в том случае, если активный элемент управления
(ActiveControl) имеет свойство Text. Для определения типа активного элемента
управления используют оператор TypeOf:
If TypeOf
Screen.ActiveForm.AcfiveControl Is TextBox Then ...
Однако в случае
MDIприложения может возникнуть следующая проблема. Если элементы управления
находятся в главной форме (например, панель инструментов), то они становятся
активными сразу же при щелчке на них мышью. При этом элемент ActiveControl
будет иметь тип, например, CommandButton. В то же время программа будет
считать, что этот элемент управления находится в дочерней форме.
Чтобы избежать
такого недоразумения, в MDIприложениях следует использовать свойство
ActiveForm не объекта Screen, а объекта MDlForm. Свойство ActiveForm объекта
MDlForm указывает на активную дочернюю форму приложения, а не на активную
форму Windows:
MDIFormI.ActiveForm.ActiveControl.Font.Bold
= Not _ MDIForml.ActiveForm.ActiveControl.Font.Bold
Комбинируя имя
главной формы и свойство ActiveForm, можно обратиться К активной дочерней
форме. Таким образом, все барьеры при разработке MDI приложения могут быть
преодолены.
Создание MDIприложений
MDIприложение
включает, как минимум, два типа окон: главную и дочерние формы.
В первую очередь
необходима главная форма. Для ее создания следует
выбрать в меню
Project команду Add MDI Form.
Затем следует
сделать из обычной формы дочернюю MDIформу. Для этого необходимо установить
значение свойства MDichild формы равным True.
Так как в каждом
проекте Visual Basic может присутствовать только одна
главная форма, все
формы, свойство MDichild которых имеет значение True,
являются дочерними
формами главной MDIформы. Команда меню Add MDI
Form, позволяющая
добавить в проект главную форму, после выполнения
блокируется. Поэтому
создать по ошибке вторую главную форму невозможно. В
дальнейшем можно
добавлять и независимые формы, т.е. не являющиеся дочер
ними для главной
формы.
Различные типы формы
(главная, дочерняя, независимая) можно легко определять по разным пиктограммам
в окне проекта.
Меню в MDIприложениях
С меню в
MDIприложениях ситуация особая. Дочерние окна не могут отображать меню, хотя и
могут их иметь. Меню может присутствовать лишь в главном окне. При этом меню
активного дочернего окна всегда отображается на месте меню главного MDIокна.
Меню MDIокна видимо
лишь TOI
тивное
дочернее окно не имеет своего меню или когда все дочерние ок.
Это удобно по двум
причинам. Вопс )работки команд меню находится в дочернем окне и не возникает
проблем при обращении к этому объекту. Во вторых, в приложении появляется
определенная логика. Если не открыт ни один документ, некоторые пункты меню,
такие как Сохранить или Печать, не имеют смысла. Поэтому эти
пункты отсутствуют в меню MDIформы. Напротив, в меню дочернего окна эти пункты
содержатся. Они будут доступны всегда, когда открыто дочернее окно.
Если всегда
требуется только одно меню, то используются дочерние окна без меню. В этом
случае всегда будет отображаться меню MDIформы.
Окно
В стандартный набор
меню MDlприложения должна входить команда Окно. Вопервых, с ее помощью
можно управлять расположением окон; вовторых, она выводит список всех открытых
дочерних окон. Чтобы создать команду меню с такими свойствами, добавьте в меню
новый элемент и в Редакторе меню установите для него флажок WindowList. После
этого Windows будет автоматически создавать список окон при вызове этой
команды.
Теперь можно
включить в меню команду управления расположением окон. Эту команду нужно
снабдить самостоятельно написанным кодом, в котором используется метод
Arrange. С помощью этого метода можно упорядочить расположение дочерних окон в
главной форме:
Private Sub
mnuArrange_Click(Index As Integer) MDIFormI.Arrange Index End Sub
Для этого примера
был создан массив команд меню: Упорядочить по горизонтали, Упорядочить по
вертикали и Каскад. Свойству Index этих элементов управления были
присвоены значения констант vbTileHorizontal, vbTileVertical и vbCascade.
Панели инструментов
Если вы попытаетесь
поместить в главную форму какиелибо элементы управления, то в большинстве
случаев вас постигнет неудача. В главную форму могут быть внесены лишь
элементы управления, имеющие свойство Align, например pictureBox или Toolbar.
Программистам не
стоит особо волноваться по этому поводу. Предположим, текст в элементе TextBox
надо отобразить жирным шрифтом. Для этого на панели инструментов должна быть
соответствующая кнопка. Обычно все подобные функции доступны и через меню.
Не желательно, чтобы
код для выполнения какоголибо действия (в данном случае, изменение вида
шрифта) повторялся в проекте дважды. Эта процедура должна быть доступна для
кнопки в MDIформе точно так же, как для команды меню в дочерней форме. Это
требование может быть выполнено, например, созданием общедоступной процедуры в
модуле.
Особенности
При разработке
MDIприложений следует обратить внимание на некоторые особенности.
Закрытие приложения
При закрытии
MDIприложения, во избежание потери данных, необходимо проверить, все ли
открытые документы сохранены. В MDIприложениях существует опасность того, что
пользователь при закрытии пропустит один из закрытых документов и забудет
сохранить внесенные в него изменения. Эту опасность хорошие программы должны
предотвращать. Для этого приложение должно определять, производились ли в
документе изменения. Если нет, документ можно закрывать без предупреждения, в
противном случае следует предупредить об этом пользователя.
Для выполнения этой
функции служат прежде всего события change. С их помощью можно установить,
были ли внесены изменения в документ:
Dim bChanged As
Boolean
Private Sub
Textl_Change * bChanged = True End Sub
При завершении
работы приложения можно опросить каждое окно, надо ли сохранять их содержимое.
Для этого можно использовать событие QueryUnload. Оно происходит перед
удалением формы из памяти как для дочерних форм, так и для главной. Параметр
UnloadMode, передаваемый процедуре обработки этого события, сообщает, каким
образом была закрыта форма. Второй параметр Cancel позволяет прервать закрытие
формы.
Таблица 10.6. Значения
параметра UnloadMode
Параметр UnloadMode |
Значение |
vbFormControlMenu |
Закрытие с помощью
системного меню или клавиш [Alt+F4] |
vbFormCode |
Оператор unload в коде
приложения |
vbAppWindows |
Завершение сессии Windows |
vbAppTaskManager |
Приложение завершил Менеджер
Задач |
vbFormMDIForm |
Закрыта главная форма |
В процедуре обработки события QueryUnload можно
проверить, предпринималась ли попытка сохранить документ или приложение, и
должным образом прореагировать:
Private Sub Form_QueryUnload(Cancel As Integer,
UnloadMode As Integer) "Внесены изменения If bChanged And Len(Textl.Text)
<> 0 Then If vbOk = MsgBox("Сохранить изменения?", vbOkCancel)
Then Cancel = True Call Save 'Вызов процедуры сохранения End If End If End Sub
Таким образом, каждая форма может определить, следует
ли сохранять ее содержимое, и никакого центрального управления в этом случае
не требуется. Необходимо учитывать, что событие QueryUnload наступает сначала
для всех дочерних окон, а затем для главной формы.
SDI — однодокуметпный интерфейс
Другой возможной
разновидностью интерфейса приложений Windows является SDI (однодокументный
интерфейс). Он отличается от MDI лишь тем, что все окна в нем
независимы друг от
друга. Примером SDIприложения может служить WordPad. Эта программа использует
лишь одну форму, в которой может редактироваться один файл.
Для разработчика
программирование SDIприложений обычно не представляет трудностей. Если создается
приложение с единственной формой, то межконтейнерный обмен данными встречается
редко. Если окно используется как панель инструментов, как это сделано в
Visual Basic, то код и переменные должны быть соответствующим образом
организованы, чтобы обеспечить всем элементам доступ к необходимым структурам.
Интерфейс типа Explorer
Новый для Windows
интерфейс типа Проводника (Explorer) активно перенимается другими
приложениями, так как дает им возможность использовать современный дизайн
Windows.
Особенность
интерфейса Проводника состоит в наличии двух элементов управления: TreeView в
левой части окна и ListView — в правой. Оба этих элемента управления уже были
описаны в главе 3. Таким образом, поскольку они имеются в Visual Basic,
реализация этого типа интерфейса не представляет особой проблемы.
Мастер инсталляции
После долгих недель
планирования, проектирования и тестирования ваше приложение Visual Basic уже
практически готово к передаче пользователям. Распространять приложения вы
можете на дискетах, компактдисках, через локальную сеть или сеть Internet.
Однако в любом случае необходимо подготовить дистрибутивный комплект. Создание
дистрибутивного пакета приложения осуществляется в два этапа. На первом этапе
производится упаковка приложения в один или несколько САВфайлов и создается
программа инсталляции. На втором этапе упакованное приложение и программу
инсталляции следует сохранить таким образом, чтобы пользователи могли получить
дистрибутивный комплект (инсталляционный пакет) на магнитном носителе или
получить возможность доступа к нему по сети.
Для решения этой
задачи можно воспользоваться двумя средствами, входящими в состав пакета
Microsoft Visual Studio: утилитой Package and Deployment Wizard (бывший Setup
Wizard) или Setup Toolkit. Мастер Package and Deployment Wizard автоматизирует
процесс создания инсталляционного пакета, а программа Setup Toolkit позволяет
задать параметры настройки этого процесса.
Для запуска Package
and Deployment Wizard откройте окно AddIns Manager (меню AddIns) и
дважды щелкните на элементе Package and Deployment Wizard.
7й шаг
На первом шаге
мастер попросит задать имя проекта, для которого следует создать
дистрибутивный пакет, и выбрать тип создаваемого мастером пакета. С помощью
мастера можно создать стандартный инсталляционный пакет, запускаемый
программой SETUP.EXE, направить дистрибутивный пакет на узел Internet или
подготовить сценарий инсталляции проекта. Выберите нужный вариант
инсталляционного пакета и внимательно читайте выводимые на экран сообщения.
Сначала мастер
проверяет наличие исполняемого файла и, при необходимости, создает его. Затем
собирает информацию об используемых приложением библиотеках и компонентах;
определяет их местонахождение и подготавливает запуск процесса создания
инсталляционного пакета.
Независимо от выбора
типа создаваемого инсталляционного пакета существует некоторая стандартная
последовательность шагов, которые должны быть выполнены мастером инсталляции.
2й шаг
В списке Package
Type List следующего окна мастера следует определить тип создаваемого
пакета: стандартный пакет инсталляции (Standard Setup Package) или файл
зависимостей (Dependency File).
3й шаг
На третьем шаге
мастер предложит ввести сведения о местоположении инсталляционного пакета.
Проверьте, правильно ли выбран каталог, и нажмите кнопку Next. При этом вы
можете указать сетевой ресурс (кнопка Network) или создать новую папку (кнопка
New Folder).
4й
шаг
Список Files четвертого окна мастера
содержит имена файлов, которые предполагается включить в инсталляционный пакет.
Мастер предоставляет вам возможность выбрать только некоторые из них (если это
возможно) или добавить в приложение новые компоненты. Для удаления файла из
проекта достаточно сбросить флажок слева от имени файла. Однако если удалить
файл нельзя, мастер отобразит окно с соответствующим предупреждением.
Новые компоненты
выбираются в стандартном диалоговом окне открытия файлов, которое вызывается
нажатием кнопки Add.
5й шаг
На пятом шаге мастер
предлагает вам указать количество создаваемых САВ файлов. Можно создать один
большой файл и сохранить его на компактдиске или подготовить несколько файлов
стандартного размера для сохранения на дискетах.
бй шаг
На шестом шаге
мастер предлагает ввести текст надписи, которая будет отображаться п окне при
запуске программы установки приложения.
7й шаг
Создавая
инсталляционный пакет, вы можете указать, необходимо ли включить в главное
меню Windows команды вызова приложения. В большинстве случаев достаточно
связать с приложением одну команду главного меню, но можно выбрать и другие
варианты: например, добавить команды обращения к справочной системе и
деинсталляции программы. Более того, с каждым файлом приложения можно связать
соответствующую команду, комбинацию клавиш и пиктограмму.
8и шаг
В следующем окне
мастера необходимо указать сведения о предполагаемом месте расположения
компонентов, входящих в приложение.
9й шаг
Список Shared FUes
окна мастера содержит имена файлов, которые могут использоваться не только
вашим приложением. Если сделать эти файлы общедоступными (shared), их можно
будет удалить только после удаления всех соответствующих приложений.
10й шаг
В последнем окне
мастер предоставит вам возможность сохранить информацию обо всех установленных
параметрах. Это позволит вам в дальнейшем не только создавать типовые
инсталляционные пакеты, но и сэкономить время.
Затем мастер
начинает свою работу. Указанные файлы сжимаются и размещаются в различных
каталогах. В результате вы получаете ряд файлов в указанном каталоге или ряд
каталогов с именами DISK.1, DISK2 и т.д.
Программа инсталляции
На первой дискете
содержится несколько важных файлов. На компьютере, где никогда не был
установлен Visual Basic, нельзя запускать его приложения. В то же время
необходимые для такого запуска файлы не поместились бы на одной дискете.
Поэтому сначала программа SETUP.EXE копирует необходимые для Visual Basic
файлы на диск и распаковывает их.
После того как
SETUP.EXE скопирует на диск файлы, указанные в SETUP.LST, компьютер может
выполнять приложения для Visual Basic. Для этого SETUP.EXE вызывает
распакованный файл SETUP1.EXE.
Этот файл
представляет собой программу на Visual Basic, исходный код которой находится в
подкаталоге \SETUP1 каталога \SETUP.
Если вам не нравится
внешний вид или функциональные возможности поставляемой программы инсталляции,
среда разработки Visual Basic предоставляет все мыслимые возможности для
модифицирования этой программы по вашему усмотрению.
После завершения
программы инсталляции все необходимые файлы будут скопированы в указанный
каталог, а компоненты общего назначения — в системный каталог Windows. Кроме
того, будет инсталлирован сервер ActiveX, если он имеется, создана программная
группа приложения и процедура деинсталляции.
Используя мастер
инсталляции, вы будете уверены, что все необходимые для работы вашего
приложения компоненты будут перенесены на компьютер пользователя. Не написав
ни одной строки кода, вы можете создать программу инсталляции, простую в
использовании и соответствующую стандартам Windows.
Мастера
Другой характерной
чертой многих приложений для Windows являются мастера (wizard).
Это небольшие
приложения внутри основного приложения, которые избавляют пользователя от
решения хотя и простых, но занимающих много времени задач, а также разбивают
сложные процессы на простые этапы.
Как вы, вероятно,
уже заметили, при использовании мастера инсталляции вам не нужно знать
параметры программы инсталляции — мастер ведет вас от одного этапа к другому.
Таким образом, сведения, которые раньше были рассеяны в документации, могут
быть переданы пользователю в более простом и компактном виде. Поэтому
желательно устанавливать мастера и в ваши собственные приложения. Для этой
цели с Visual Basic поставляется так называемый "мастер мастеров".
Он запускается командой AddIn Manager меню AddIns.
Если мастер мастеров
не находит формы с именем frmWizard, он создает новый проект с использованием
ActiveX и DLL со всеми необходимыми компонентами.
По умолчанию новый
мастер содержит шесть шагов. В окне Wizard Manager можно переключаться
с одного шага на другой. При этом можно изменять внешний вид окна на
данном шаге, добавлять новые шаги и удалять ненужные. Обычные элементы
управления (кнопки Back, Continue и т.д.) уже размещены в диалоговом
окне.
Здесь вы можете дать
волю своей фантазии и разработать собственный мастер, который затем будет
вызываться вашим приложением как сервер ActiveX.
При этом можно
просмотреть, как работают другие мастера Windows и подражать тем образцам,
которые вам больше нравятся. Диалоговые окна следует строить и рамках единой
концепции и поддерживать пользователя в его работе с приложением.