    188	Обзор компонентов Actr 

    Глава 8.   Создание программных компонентов ActiveX 
    ve| 

    Visual Basic версии 5.0 позволяет создавать программные компоненты ActiveX 
(ранее известные как OLE серверы). Программный компонент ActiveX — 
приложение-cejDBep, обеспечивающее функциональные возможности, которые могут 
многократно использоваться другими приложениями через механизмы Автоматики. 
    В этой главе дается краткий обзор программных компонентов ActiveX и 
показано, как п можно создавать в Visual Basic. 

    8.1. Обзор компонентов ActiveX 

    Компонент ActiveX — единица исполняемого программного кода (например, файл 
.ехе, или-.dll или .осх); которая отвечает спецификации ActiveX в части 
предоставления объектоА которые могут использоваться другими приложениями. 
    В Visual Basic можно создавать три типа компонентов ActiveX: элементы 
управления ActiveX, документы ActiveX и программные компоненты ActiveX. 

    8.1.1. Элементы управления ActiveX 

    Элементы управления ActiveX (прежде известные как элементы управления OLE) 
— стандартные элементы пользовательского интерфейса многократного 
использования, которое позволяют быстро строить формы и окна диалога. 
    Информацию о порядке создания элементов управления ActiveX см. в главе 9 
"Создание элементов управления ActiveX". 

    8.1.2. Документы ActiveX 

    Документы ActiveX (ранее известные как объекты-документы) — компоненты 
ActiveX, которые должны создаваться или внедряться и активизироваться внутри 
приложения-клиента Технология документа ActiveX — расширение концепций 
документов OLE. Она расширяет функциональные возможности визуального 
редактирования внедренных объектов, активации приложений-оболочек, таких как 
Internet Explorer, применение разных типов документов 
    Информацию относительно разработки документов ActiveX см. в главе 10 
"Создание и использование документов ActiveX". 

    8.1.3. Программные компоненты ActiveX 

    Программные компоненты — библиотеки объектов. Приложения-клиенты 
используют программные компоненты, создавая объекты из классов, обеспечиваемых 
компонентом. Кл.1-енты вызывают свойства, методы и события, предоставляемые объектом. 
    Любое приложение, которое поддерживает стандарты Автоматики, может 
использовать "программный компонент ActiveX, созданный в Visual Basic. Это 
Visual Basic, Microsoft Excel. Microsoft Access, Microsoft Project, Microsoft 
Visual FoxPro, Microsoft Visual C++ и другие инструменты. 
    Visual Basic обеспечивает средства для решения многих сложных задач 
создания программного компонента ActiveX, таких, как создание библиотеки типов 
и автоматическая регистрация компонента. 


    Глава 8. Создание программных компонентов ActiveX	189 


    8.1.4. Преимущества использования компонентов ActiveX 

    Преимущества использования программных компонентов ActiveX включают: 
    •  ясно определенные интерфейсы. Функциональные возможности, реализованные 
в программном компоненте ActiveX, доступны через его свойства, методы и 
события. Эти интерфейсы само-документируемы в том смысле, что они 
автоматически предоставляются программным компонентом, j/уэазработчик и 
пользователь может добавлять для каждого интерфейса описательную и 
контекстно-чувствительную информацию Help, ко-тораябудёт сохранена программным 
компонентом. Пользователи могут просматривать эту информацию для каждого 
интерфейса, используя Object Browser или другие инструментальные средства; 
    •   простота создания, использования и обновления. Программные компоненты 
ActiveX можно создавать, скрывая сложность программной реализации от других 
программистов. Другим программистам требуется знать только, какую информацию 
обеспечить этому объекту и какую информацию можно отобрать. Можно создавать 
программный компонент ActiveX, который инкапсулирует бизнес-правила (правила и 
стандарты реальной работы, например с данными). Если бизнес-правила 
изменяются, потребуется модифицировать только программный компонент, а не все 
приложение, в котором этот компонент исполь-"зуется~~ 

    8.2. Создание объектов в Visual Basic 

    Процедура создания программных компонентов ActiveX включает работу с 
модулями класса, в которых определяются объекты, обеспечиваемые компонентом. 
Классы инкапсулируют внутреннюю функциональность компонента, а клиенты в 
период выполнения создают объекты из экземпляров классов. В этом разделе 
описывается использование модулей класса для определения и создания экземпляра 
класса. Здесь также показано, как работать со свойствами, методами и событиями 
объектов, создаваемых при инициализации класса. 
    Вначале модули класса создаются и используются внутри проекта Visual 
Basic. Затем эти йтассьГмогут быть превращены в программный код ActiveX. 

    8.2.1. Модули классов 

    При создании программных компонентов ActiveX первый шаг состоит в 
определении объектов внутри проекта Visual Basic. Для определения объектов для 
компонентов используются модУпТГкласса" * 

    Назначение модуля класса 

    Модуль класса — один из типов модулей программного кода, обеспечиваемых 
Visual Basic. Каждый модуль класса'дёЙСТвуёт каГпроект для объекта. Иными 
словами, каждый модуль класса определяет один тип объекта. В приложении может 
быть создано несколько модулей класса. В период выполнения через создание 
экземпляра класса создается объект. 
    Модули класса полезны при создании любого вида программных компонентов 
ActiveX. Модули класса представляют логические объекты компонента. Например, 
можно создать класс Служащий, который имеет такие свойства, как 
Служащий.Фамилия и Служащий.Имя, или такой метод, как Служащий.Принять. 
Приложение может работать с несколькими экземплярами объекта Служащий и 
создавать семейство объектов Служащий. 

    Добавление модуля класса к проекту 

    Для добавления в проект нового модуля класса нужно в меню Project выбрать 
команду Add Class Module. Методы, свойства и события можно добавлять к классам 
вручную или исполь


    190	Создание объектов в Visual Basic 

    зуя мастер Class Builder в Visual Basic. Надстройка Class Builder 
автоматизирует процедуры работы с классами. 
    Дополнительную информацию относительно расширения Class Builder Visual 
Basic CMJ ниже, в разделе "Использование Class Builder". 

    8.2.2. Создание экземпляра класса 

    Модули класса отличаются от стандартных модулей следующими характеристиками: 
    •   модули класса должны быть явно созданы прежде, чем они могут использоваться; 
    •   можно создавать несколько экземпляров модуля класса. 
    В проекте, который определяет класс, экземпляр класса можно создавать 
операторами Dim и Set, как показано в следующем примере: 

    Dim  objObjectl   As   Classl Dim  objObject2   As   Classl 
    Set   objObjectl   =  New  Classl Set   obObject2   =  New  Classl 

    Примечание: Класс — шаблон для объекта. Объект — экземпляр класса. В 
примере приведенной выше, objObjectl и objObject2 — объекты типа Classl. Можно 
использовать также более,- компактный синтаксис Dim objObjectl As New Classl, 
но, чтобы ясно показать, где инициируется экземпляр класса, рекомендуется 
использовать оператор Set. 
    Информацию относительно использования оператора Set см. в разделе "Третий 
шаг: создание объектов" главы 7 "СОМ и создание клиентов ActiveX". 

    8.2.3. События модуля класса 

    Модули класса имеют два встроенных события: Initialize и Terminate. 
    Чтобы добавить программный код к событиям модуля класса, нужно открыт^ 
окно программного кода для класса и щелкнуть Class в раскрывающемся списке Object. 

    Событие Initialize 

    Событие Initialize происходит при создании экземпляра класса, но до 
установки значения любого свойства. Событие Initialize используется для 
инициализации используемых классом данных, как показано в следующем коде: 

    Private   Sub  Class_Initialize() 
    '   Инициализация   данных 
    i   =   5 End  Sub 

    Событие Initialize можно использовать также для загрузки форм, 
используемых классом. 

    Событие Terminate 

    Событие Terminate происходит, когда объектная переменная выходит из 
области определения или устанавливается в Nothing. Это событие можно 
использовать для сохранения информации, выгрузки формы или выполнения 
действий, которые должны произойти при завершении существования объекта. 
    Private   Sub  Class_Terminate() 
    '   Любой  код   завершения. End   Sub 


    Глава 8. Создание программных компонентов ActiveX 191 

    8.2.4. Создание методов 

    Для создания метода для объекта необходимо внутри модуля класса описать 
процедуры Public Sub или Function. При создании экземпляра модуля класса 
процедуры Public Sub и Function будут доступны как методы результирующего объекта. 
    В следующем фрагменте кода создается метод, который выводит на экран дату. 
Это описание следует поместить в модуль класса: 

    Public   Sub   ShowDateO 
    MsgBox   "Сегодня:    "   &  Now () End  Sub 

    В одну из процедур формы можно внести вызов процедуры ShowDate() уже как 
метода класса: 

    Private   Sub   Form_Load() Dim  objObjectl   As  New  Classl 
objGbjectl.ShowDate End   Sub 

    При загрузке формы будет выведено сообщение с текущей датой. 

    ^6м5Р. 
    [(General) 
    J   JshowDate 
    d 
    Public Sub ShowDateO 
    MsgBox "Сегодня: End 
    • Project! - Forml (Code) 
    & Nou( 
    И 
    Uiapt] 
    Form 
    d 
    Load 
    ZJ 
    Priuate  Sub  Form_Load() Din objObjectl  fis New Class' 
objObjectl.ShowDate End  Sub| 
    Project! 
    Сегодня: 06.10.9716:12:08 
    OK 

    Рис. 8.1. Сообщение из метода класса. 

    В этом примере создается метод, который принимает число и возвращает 
квадрат числа: 

    Public Function SquareNum(Num As Integer) _ 
    As Integer 
    SquareNum = Num * Num End Function 

    В этом фрагменте создается экземпляр класса и вызываются методы ShowDate и SquareNum: 

    Dim Demol As Classl 
    Set Demol = New Classl 
    Demol.ShowDate 
    i = Demol.SquareNum(Num:=5) 


    192     Создание объектов в Visual Basic 


    Методы можно создавать вручную или с помощью мастера Class Builder. 
Добавить метод мож% также, открыв окно программного кода и затем выбрав 
команду Add Procedure в меню То Откроется окно диалога Add Procedure, в 
котором вводятся общие атрибуты создаваем процедуры. После закрытия этого окна 
диалога в модуле создается заготовка для процедуры^ 

    Add Procedure 

    Name; j NewProcl туре-.-	.-.---
    ' <*** Sub	(" Property ' (* lynctton!        (~ Event. 
    ,scope - (• Public	'"*" Private 
    J~" All Local variables as Statics 
    OK 
    Cancel 
    I 
    Щ Projectl - Class 1 (Code) 
    (General) 
    j»J JNewProd 
    ZJ 
    Public Function NewProcl() ~j] End Function 
    IMJj 
    —j 
    Т I 
    >Г^ 

    Рис. 8.2. Окно диалога Add Procedure и заготовка для новой процедуры. 

    В окне Object Browser можно просмотреть свойства и методы, которые 
определены для класс 

    _ Object Browser	ИНИИИИИННДКИИ |i i   1 
    я^^^^^^^^^^^^^^^^^^^^^^яи^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    Jprojectl	d   Ч   I ^U;*l fl 
    1    ...........	diiliJ 
    • Classes		Members of 'ClassV 
    э <globals>		^ NevuProc! 
    •ЛЩЕЖВИИИВ	1	•A* ShovuDate 
    Щ Forml	,	•s SquareNum 
    : Private Class Class 1 I    Member of 'joivji.si                          
                                                      '   : 

    Рис. 8.З. Методы нового класса в окне Object Browser. 


    8.2.5. Создание свойств 

    Описать свойство для объекта можно двумя способами: 
    определить переменные public или 
    создать внутри модуля класса public процедуры Property. 


    Глава 8. Создание программных компонентов ActiveX	193 


    Переменные Public обеспечивают сохранение значения свойства. Процедуры 
Property позволяют выполнить программный код, когда значение свойства 
устанавливается или отбирается. 
    Использование для создания свойств переменных Public 
    В следующем фрагменте кода определяется строковое свойство User 
(переменные public определяются в разделе General Declarations модуля класса): 

    Public   User  As   String 

    В следующем примере создается экземпляр Classl и устанавливается значение 
свойства User: 

    Dim Demol As Classl Set Demol = New Classl Demol.User = "Степанков" 


    Создание умолчательного свойства 

    Установить значение умолчательного свойства для объекта можно без явного 
обращения к этому свойству. Например, свойство Text в Visual Basic — 
умолчательное свойство для элемента управления TextBox. Установить его можно так: 

    Textl.Text   =   "Visual   Basic" 
    ИЛИ 
    Text   =   "Visual   Basic" 

    Чтобы создать умолчательное свойство: 
    1. Открыть модуль класса, содержащий свойство. 
    2. В меню Tools выбрать Procedure Attributes. 
    3. В окне диалога Procedure Attributes щелкнуть кнопку Advanced. 
    4. В раскрывающемся списке Name выбрать свойство, которое требуется 
установить как умолчательное. 
    5. В раскрывающемся списке Procedure ID выбрать (Default) (рис. 8.4). 

    8.2.6. Использование процедур Property для создания свойств 

    Процедуры Property используются, если при установке или отборе значений 
свойства требуется выполнить некоторый программный код. При помощи процедур 
Property можно решать следующие задачи: 
    •	выполнить процедуру при изменении или чтении значения свойства; 
    •	ограничить свойство некоторым набором допустимых значений; 
    •	сделать свойство доступным только для чтения. 
    Процедуры Property чаще всего создаются парами. Например, можно создать 
процедуру Set или Let, предназначенную для установки значения свойства, и 
процедуру Get, которая будет возвращать значение. Этим двум процедурам дается 
одинаковое имя, которое является также именем свойства. 

    Создание свойства 

    В следующем фрагменте кода создаются процедуры Property Let и Property 
Get, которые назначают строковое значение и возвращают значение свойства User 
(процедуры описываются в модуле класса): 

    7  Зак.   I36 


    194 Создание объектов в Visual Basic 


    Рис. 8.4. Окно диалога Procedure Attributes. 


    Private gsUser As String Public Property Let User (s As String) 
    gsUser = Ucase(s) End Property 
    Public Property Get User () As String 
    User = gsUser End Property 

    Установка и получение значения свойства 

    В следующем примере создается экземпляр Classl и устанавливается и 
возвращается свойство User: 

    Dim Demol As Classl 
    Set Demol = New Classl 
    Demol.User = "Степанков" ' Вызов процедуры Let 
    Print Demol.User ' Вызов процедуры Get 

    Для создания свойства, которое возвращает стандартный тип данного, 
определяются процедуры Property Get и Property Let. Для создания свойства тип 
данного Object необходимо определить процедуры Property Get и Property Set. 
    При чтении свойства выполняется процедура Property Get. При установке 
свойства выполняется процедура Property Let. 
    Процедура Property Let всегда содержит по крайней мере один параметр, 
который представляет значение для свойства. Этот параметр должен всегда быть 
последним в списке параметров. 


    Глава 8. Создание программных компонентов ActiveX 195 


    Для создания свойства только для чтения необходимо определить процедуру 
Property Get без соответствующей процедуры Property Let или Property Set. 

    8.2.7. Использование Class Builder 

    В Visual Basic имеется надстройка Class Builder, которая автоматизирует 
процесс формирования классов. С помощью Class Builder можно визуально 
определять классы и их интерфейсы. 
    ^ 

    Рис. 8.5. Окно надстройки Class Builder. 

    I !орядок подключения и использования Class Builder: 
    1. В меню Add-lns выбрать Add-In Manager. 
    2. В списке Available Add-lns выбрать Visual Basic Class Builder Utility и 
щелкнуть ОК. 
    3. В меню Add-lns выбрать Class Builder Utility. 
    4. Добавить новый класс к проекту и затем добавить к классу методы, 
свойства и события. При нажатии соответствующей кнопки или выборе команды меню 
File | New открываются окна построителей семейства классов, классов, методов, 
свойств и событий (рис. 8.6). 

    8.3. Работа с программными компонентами ActiveX 

    В этом разделе показывается, как сделать модули класса доступными 
приложениям-клиентам, таким, как ActiveX EXE и ActiveX DLL. Когда модули 
класса становятся доступными внешним приложениям-клиентам, они превращаются в 
программные компоненты ActiveX. 

    8.3.1. Выбор типа программного компонента 

    В Visual Basic можно формировать программные компоненты, которые будут 
работать как in-process (ActiveX DLL) или out-of-process (ActiveX EXE). 

    Компоненты in-process и out-of-process 

    Компоненты in-process позволяют получить более быстрый доступ к их 
объектам, чем компоненты out-of-process. Это объясняется тем, что компоненты 
in-process подключаются к адресному пространству приложения-клиента и 
выполнять маршаллинг вызываемых свойств и методов через границу процесса не 
требуется. Компоненты out-of-process исполь-v-ют отдельные потоки выполнения, 
нежели их клиенты. Они, однако, могут быть более гибкими, так как выполняются 
вне адресного пространства процесса клиента. 


    196 Работа с программными компонентами ActiveX 


    Рис. 8.6. Окно построителя метода Method Builder с окном описания параметров. 

    Дополнительную информацию относительно различий между компонентами 
in-process и out-of-process см. в разделе "Определение расположения 
компонентов сервера" главы 7 "СОМ и создание клиентов ActiveX". 

    Шаблоны проектов компонентов 

    При создании нового проекта Visual Basic можно выбирать среди ряда 
шаблонов проектов. Для создания программного компонента нужно в окне диалога 
New Project выбрать шаблон ActiveX EXE или ActiveX DLL (рис. 8.7). При выборе 
типа проекта устанавливается ряд умолчательных значений свойств проекта, 
важных для создания программных компонентов. 

    Примечание: Впоследствии тип проекта можно изменить, изменяя свойства проекта. 

    8.3.2. Установка свойств проекта 

    При создании нового проекта ActiveX DLL или ActiveX EXE можно установить 
ряд свойств проекта, установки которых воздействуют при выполнении компонента. 
Устано-   I вить свойства можно в окне диалога Project Properties (команда 
меню Project | Project   | Properties) (рис. 8.8). Все описанные ниже опции 
находятся на вкладке General. 

    Project Type 

    Список Project Type обеспечивает четыре опции: Standard EXE, ActiveX EXE, 
ActiveX DLL и ActiveX Control. При создании нового проекта ActiveX DLL или 
ActiveX EXE Visual Basic устанавливает свойство Project Type автоматически. 


    Глава 8. Создание программных компонентов ActiveX     197 


    Рис. 8.7. Стандартные шаблоны Visual Basic. 
    Рис. 8.8. Вкладка General окна диалога Project Properties. 


    198	Работа с программными компонентами ActiveX 

    Тип проекта определяет порядок использования некоторых других опций 
проекта. Например, когда выбран тип проекта Standard EXE, установки на вкладке 
Component недоступны. 

    Startup Object 

    Для большинства компонентов ActiveX EXE и ActiveX DLL в поле Startup 
Object устанавливается (None). Если требуется, чтобы код выполнялся при 
загрузке компонента, а не при создании экземпляра класса, для свойства Startup 
Object можно установить Sub Main. При этом к проекту потребуется добавить 
стандартный модуль и в этом модуле описать проце-; дуру Sub под именем Main. 

    Project Name 

    Поле Project Name указывает имя, которое приложение-клиент будет 
использовать для обращения к компоненту. 
    В следующем примере показан фрагмент кода из приложения-клиента, в котором 
создается j экземпляр класса clsPassWord в программном компоненте Server2:	I 

    ' Приложение-клиент поддерживает библиотеки типов Dim x As 
Server2.clsPassWord Set x = New Server2.clsPassWord 
    ' Приложение-клиент не поддерживает библиотеки типов 
    Dim x As Object 
    Set x = CreateObject ( "Server2.clsPassWord") 
    Project Description 

    Поле Project Description позволяет ввести краткое описание программного 
компонента ActiveX и объектов, которые он обеспечивает. Содержимое этого поля 
появляется внизу окна диалога References для любого компонента, который выбран 
в списке Available References. Эта строка также появляется в панели описания 
внизу окна Object Browser (см. рис. 1.7). 

    Unattended Execution 

    Флажок Unattended Execution указывает, что компонент предназначен для 
выполнения без взаимодействия с пользователем. Автоматические компоненты не 
имеют пользовательского интерфейса. Функции и действия периода выполнения, 
такие как сообщения, которые обычно требуют взаимодействия с пользователем, в 
этом режиме записываются в журнал событий. 

    8.3.3. Установка свойств модуля класса 

    После установки свойств проекта для программного компонента ActiveX можно 
установить свойства для каждого модуля класса в компоненте, чтобы определить 
характер действия классов. 

    Свойство Name 

    Свойство Name используется приложениями-клиентами при создании экземпляра 
класса Например, если класс называется Class'1 и находится в проекте Projectl, 
код создания экземпляра этого класса в приложении-клиенте мог бы выглядеть 
следующим образом: 

    Dim  x  As   Projectl.Classl Set   x  =  New   Projectl.Classl 


    Свойство Instancing 

    Свойство Instancing определяет, может ли приложение, внешнее по отношению 
к проекту создавать новые экземпляры класса, и если да, то как будут 
создаваться эти экземпляры 


    Глава 8. Создание программных компонентов ActiveX 199 


    Примечание: Свойство Instancing в Visual Basic 5.0 включает все 
функциональные возможности свойства Public из Visual Basic 4.0. 

    Для компонентов ActiveX EXE и ActiveX DLL доступные значения свойства 
Instancing различны, как показано на следующей иллюстрации: 

    ActiveX DLL 

    Рис. 8.9. Опции свойства Instancing для компонентов ActiveX EXE и ActiveX DLL. 

    Описание каждой из установок свойства Instancing см. в разделе 
"Характеристики компонентов сервера" главы 7. 

    8.3.4. Компиляция компонента 

    После формирования программного компонента ActiveX его можно 
скомпилировать. Компонент компилируется как файл .ехе или .dll, в зависимости 
от установок в окне диалога Project Properties. 

    Идентификатор библиотеки типов 

    При компиляции компонента ActiveX EXE или ActiveX DLL Visual Basic создает 
для него уникальный идентификатор библиотеки типов, который записывается в 
системный реестр при регистрации компонента. 
    Значение поля Project Compatibility на вкладке Component окна диалога 
Project Properties устанавливается по умолчанию. Эта установка побуждает 
Visual Basic повторно использовать тот же идентификатор библиотеки типов при 
каждой компиляции программного компонента. 
    Если проводится изменение, которое является несовместимым с версией 
сервера, специфицированной в поле Project Compatibility (например, при 
удалении свойства), Visual Basic выводит на экран предупреждение и генерирует 
новый идентификатор библиотеки типов. 
    Информацию относительно типов совместимости, доступных в Visual Basic, см. 
в разделе "Совместимость версий". 

    ActiveX EXE 

    200	Тестирование программных компонентов ActiveX 


    8.3.5. Регистрация компонента 

    Прежде чем программный компонент ActiveX может быть использован, его 
необходимо зарегистрировать в системе. 
    При запуске компонента ActiveX в режиме разработки происходит его 
временная регистрация. Окончательно компонент регистрируется при: 
    •	первом запуске; 
    •	установке с помощью программы Setup; 
    •	при запуске из командной строки с параметром /Regserver. 
    Visual Basic регистрирует файл ActiveX DLL при его компиляции. Для 
регистрации файла DLL можно также использовать программу Regsvr32.exe, как 
показано в следующей строке 

    Regsvr32.exe   dlll.dll 

    Для установки ссылки на файл DLL в приложении-клиенте можно использовать 
окно д| га References. 

    Чтобы удалить вхождение системного реестра для компонента ActiveX EXE, 
необходимой запустить его с командной строки с параметром /UnRegserver; 

    Serverl.Exe   /UnRegserver 

    Для удаления из системного реестра вхождения ActiveX DLL можно запустить 
Regsvr32.e с опцией /и и именем файла DLL, как показано в следующем примере: 

    Regsvr32.exe   /u  dlll.dll 

    8.4. Тестирование программных компонентов ActiveX 

    Microsoft Visual Basic предлагает два сценария для тестирования и отладки 
компонентов один для компонентов in-process и другой — для компонентов 
out-of-process. По первому сценарию выполняется тестирование компонента внутри 
единственного экземпляра Visual Basic. Во втором сценарии необходимо запустить 
две копии среды разработки. 
    В этом разделе показано, как тестировать компоненты ActiveX DLL и ActiveX 
EXE, а также преимущества установки ссылки на библиотеку типов. Здесь же 
рассматривается инициирование ошибки в приложении-клиенте с целью обеспечения 
клиента информацией ошибки 

    8.4.1. Установка испытательного проекта 

    Первый шаг в тестировании программного компонента ActiveX — создать 
испытательный проект, в котором будет использоваться этот компонент. 

    Тестирование ActiveX DLL 

    Чтобы протестировать компонент ActiveX DLL, можно добавить к группе 
проекта ActiveX DLL проект Standard EXE и протестировать компонент in-process 
внутри единственного экземпляра Visual Basic. Затем можно перейти 
непосредственно от испытательного компонентного кода к программному коду 
компонента in-process. 

    Тестирование ActiveX EXE 

    Для тестирования компонента ActiveX EXE необходимо запустить компонент 
внутри одного экземпляра Visual Basic, а испытательное приложение запустить во 
втором экземпляре Visual Basic. В этом случае непосредственно перейти от 
одного компонента к другому нельзя, но можно использовать все инструментальные 
средства отладки другого экземпляра Visual Basic. 


    Глава 8. Создание программных компонентов ActiveX	201 


    8.4.2. Установка ссылки на библиотеку типов 

    При формировании компонента и обеспечении классов для использования 
клиентами компилятор Visual Basic автоматически генерирует библиотеку типов. 
    Разработчики клиента могут использовать Object Browser для просмотра 
предоставляемых компонентом возможностей. Подключиться к компонентам в клиенте 
можно, используя библиотеку типов и окно диалога References. 
    Преимущества установки ссылки на библиотеку типов 
    При установке ссылки на библиотеку типов компонента для разработчиков 
клиента обеспечивается три преимущества: 
    •   раннее связывание. Установка ссылки на библиотеке типов во время 
разработки активирует раннее связывание. Раннее связывание позволяет Visual 
Basic получить информацию относительно методов и свойств, доступных из 
компонента во время компиляции, а не в период выполнения. (Связывание — 
процесс перевода объекта в состояние выполнения так, чтобы могли быть вызваны 
операции (например, редактирование), обеспечиваемые приложением объекта. Тип 
связывания определяет быстродействие обращения к методам объекта с 
использованием объектной переменной). Когда используется раннее связывание, 
вызовы компонента очень эффективны, так как при этом может использоваться 
быстрый тип связывания vtable; 
    •   контроль синтаксиса. Синтаксис вызовов компонента активируется во 
время разработки; 
    •  доступ к Help. Разработчики клиента имеют доступ к любой контекстно — 
чувствительной помощи, которую обеспечил разработчик компонента. 
    Информацию относительно использования раннего связывания и связывания 
vtable см. в разделе "Введение в связывание" главы 7 "СОМ и создание клиентов ActiveX". 

    8.4.3. Отладка компонента 

    После открытия испытательного проекта и установления ссылки на компонент 
его можно отлаживать, как любое другое приложение Visual Basic. При этом можно 
перемещаться между приложением-клиентом и компонентом и использовать 
стандартные средства отладки: устанавливать точки останова, проходить через 
код пошагово, использовать контрольные выражения и так далее. 

    Обработка потери ссылки 

    В ходе отладки компонентов можно будет видеть следующее сообщение об 
ошибке: "Connection to type library or object library for remote process has 
been lost. Press OK for dialog to remove reference" (Связь с библиотекой типов 
или библиотекой объектных модулей для _ удаленного процесса прервана. Нажмите 
ОК для вывода окна диалога удаления ссылки). 
    Это сообщение указывает, что глобальный уникальный идентификатор (GUID) 
библиотеки типов компонента изменился и испытательный проект не может найти 
библиотеку типов. 
    Чтобы очистить отсутствующую ссылку, нужно нажать ОК в окне сообщения. В 
окне диалога References рядом с именем компонента появится MISSING. Нужно 
очистить флажок отсутствующего компонента и затем нажать ОК. 
    Информацию относительно библиотек типов и средств просмотра объектов см. 
раздел "Объекты Автоматики" в главе 7 "СОМ и создание клиентов ActiveX". 
    Информацию относительно того, как СОМ использует идентификаторы GUID, см. 
раздел "Взаимодействие клиента с сервером" в главе 7. 


    202	Тестирование программных компонентов ActiveX 


    8.4.4. Способы обработки ошибок 

    Управление ошибками требует тесной связи между клиентами и компонентами. 
Если возможно, компонент и клиенты должны сами обрабатывать ошибки, вместо 
вывода на экран сообщений пользователю. 
    Когда приложение-клиент вызывает метод объекта, обеспечиваемого 
компонентом, в методе могут использоваться следующие два способа обеспечения 
информации ошибки: 
    •   инициирование ошибки, которую должно обработать приложение-клиент. В 
этом случае в клиенте используются стандартные операторы обработки ошибок или: 
    •   возвращение кода ошибки, которую приложение-клиент должно 
протестировать и обработать. 

    Инициирование ошибок 

    В программном компоненте метод, вызываемый приложением-клиентом, вызывает 
метод Raise объекта Err, чтобы инициировать ошибку в приложении-клиенте. 
Клиент после этого выполняет процедуру обработки ошибки. 
    Разработчики приложений-клиентов могут также реализовать оперативную 
обработку ошибок, используя оператор On Error Resume Next или подпрограммы 
обработки ошибок с оператором On Error Goto. 

    Использование возвращаемого значения 

    В программном компоненте метод, вызываемый приложением-клиентом, 
возвращает значение клиенту. Клиент исследует возвращаемое значение, чтобы 
определить, произошла ли ошибка и если да, то какая. 
    Применяя этот тип обработки ошибок, разработчики приложений-клиентов 
должны использовать оперативную обработку ошибок. После вызова метода 
программный код всегда должен тестировать возвращаемое значение. 

    8.4.5. Инициирование ошибок выполнения 

    В этом разделе рассматривается инициирование и обработка ошибок выполнения 
с использованием метода Raise объекта Err. 
    Также показано, как опции, устанавливаемые для режима прерывания 
(останова), могут воздействовать на обработку ошибок при передаче ошибок клиенту. 

    Инициирование ошибки в клиенте 

    При создании компонента ActiveX можно обеспечивать передачу сообщения об 
ошибке приложению-клиенту. Для инициирования ошибки в клиенте нужно вызвать 
метод Raise из подпрограммы обработки ошибок метода компонента. 
    Метод Raise имеет следующий синтаксис: 

    объек/n.Raise номер, источник, описание, Ье1р_файл, Ье1р_контекст 

    Элементы синтаксиса метода Raise: 


    Глава 8. Создание программных компонентов ActiveX 203 

    В следующем примере кода показана обработка ошибок от компонента: 
    Код в компоненте: 

    Dim Salaryl As Single 
    Public Property Let Salary(ByVal newSalary As Single) If newSalary < 0 Then 
    Err.Raise 12345 + vbObjectError, , "Жалование должно быть положительным" Else 
    Salaryl = newSalary End If End Property 
    Public Property Get Salary () As Single 
    Salary = Salaryl End Property 

    Код в приложении-клиенте: 

    Private Sub Commandl__Click () Dim x As Company.Employee 

    Объектная переменная нового служащего компании 

    On Error GoTo HandleError Set x = New Company.Employee 

    Элемент              Описание объект               Обязательный. 

    Всегда объект Err. номер                   
    Обязательный. Целое число Long, 
которое представляет идентификатор и происхождение ошибки. Ошибки Visual Basic 
(встроенные и пользовательские) располагаются в интервале номеров 0 — 65535. 
При установке в модуле класса для свойства Number значения пользовательской    
ошибки,     номер    ошибки     прибавляется     к    константе vbObjectError. 
Например, чтобы сгенерировать ошибку номер 999, следует назначить для свойства 
Number объекта Err значение vbObjectError + 999. Результирующий номер 
возвращается в приложение-клиент. Это гарантирует, что пользовательские номера 
ошибок не пересекутся со встроенными ошибками Visual Basic. источник           
    Необязательный. Строковое выражение, содержащее имя объекта или приложения, 
которое генерирует ошибку. Если значение не установлено, используется 
программный идентификатор текущего проекта Visual Basic. описание             
    Необязательный. Строковое выражение, содержащее описание ошибки. Если не указа 
но, проверяется номер ошибки. Если номер может быть сопоставлен с ошибкой 
выполнения Visual Basic, возвращается описание этой ошибки Visual Basic. Если 
такого соответствия не найдено, возвращается сообщение "Application-defined or 
object-defined error" (Ошибка, определенная в приложении или объекте). 
Ье1р_файл           
    Необязательный. Полный путь к файлу, содержащему помощь по 
данной ошибке. Если не указано, Visual Basic использует полный путь к файлу 
помощи Visual Basic. help_KOHmeKcm 1 Необязательный. Идентификатор контекста 
помощи по данной ошибке 1 в файле помощи. 


    204 Использование событий 


    х.Salary = -50 ' Оклад нового служащего 
    MsgBox x.Salary 
    Exit Sub HandleError: If Err.Number = 12345 + vbObjectError Then 
    MsgBox "Жалованье должно быть положительным" End If End Sub 

    Останов на ошибке 

    Порядок ввода Visual Basic режима останова при возвращении программным 
компонентом ошибки можно изменить установкой опций Error Trapping на вкладке 
General окна диалога Options. Значения этих опций полезно знать, так как они 
могут обусловливать останов приложения на ошибке, даже если для данной ошибки 
создана процедура обработки. 
    В следующей таблице приведены три опции установки точек прерывания: 

    Опция	Описание 

    Break on All Errors	Перевод проекта  в  режим  прерывания обусловливает 
любая ошибка 
    Break in Class Module	Перевод проекта в режим прерывания обусловливает 
любая необрабатываемая ошибка, возникшая в строке программного кода в модуле 
класса. При отладке проекта сервера ActiveX путем запуска испытательной 
программы-клиента ActiveX из другого проекта следует установить эту опцию в 
проекте сервера ActiveX, чтобы вводить режим останова на ошибках в модулях 
класса, вместо передачи ошибок в испытательную программу. 
    Break on Unhandled Errors	Если процедура обработки ошибки активна, ошибка 
обрабатывается без ввода режима останова. Если активной процедуры обработки 
ошибок не имеется, ошибка обусловливает перевод проекта в режим останова. 
Необрабатываемая ошибка в модуле класса обусловит перевод проекта в режим 
останова в строке кода класса. 

    8.5. Использование событий 

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

    8.5.1. Создание событий класса 

    Для инициирования события из программного компонента необходимо проделать 
следующие шаги: 
    1. Объявить событие. 
    2. Сгенерировать событие. 

    Глава 8. Создание программных компонентов ActiveX	205 
    Объявление события 
    Событие объявляется в разделе Declarations модуля класса с помощью 
ключевого слова Event. Это делает событие видимым для клиентов, которые 
используют компонент: 
    Public Event Status(ByVal StatusText As String) 
    Инициирование события 
    Когда требуется сгенерировать событие для приложения-клиента, вызывается 
оператор RaiseEvent и передается имя события и все требуемые для события 
параметры. В следующем фрагменте кода инициируется событие Status: 
    '   Метод,   выполняющий  обработку  заказа Public   Sub  SubmitOrder() 
    RaiseEvent  Status ("Проверка  состояния  кредита...") 
    '   Задержка,   моделирующая   проверку 
    EndTime   =  Timer   +   2 
    Do  While   Timer  <   EndTime 
    DoEvents Loop 
    RaiseEvent   Status ("Обработка   заказа...") 
    '   Некоторая  обработка 
    EndTime   =   Timer  +   2 
    Do  While   Timer   <   EndTime 
    DoEvents Loop End  Sub 
    Этот подход можно использовать для передачи информации статуса в 
приложение-клиент при выполнении долготекущего метода. 
    8.5.2. Обработка событий в приложении-клиенте 
    При обработке события, которое обеспечивается программным компонентом 
ActiveX, необходимо проделать следующие шаги: 
    1. Объявить переменную WithEvents. 
    2. Создать процедуру обработки события. 
    3. Создать экземпляр класса, который определяется переменной WithEvents. 
    Объявление переменной WithEvents 
    Переменная WithEvents объявляется для хранения ссылки на объект, который 
будет обеспечивать уведомление о событии. Для этого вводится стандартный 
оператор Dim и ключевое слово WithEvents, как в следующем примере: 
    Dim WithEvents Order As Projectl.Classl 
    После объявления переменной WithEvents она появляется в окне программного 
кода как объект, вместе с ассоциированными событиями (рис. 8.10). 
    Написание программного кода события 
    В процедуры, ассоциируемые с переменной WithEvents, вносится программный 
код, предназначенный для обработки сообщений событий: 


    206 Использование событий 


    Рис. 8.10. После объявления переменной With Events она появляется в окне 
редактора кода как объект. 

    Private   Sub  Order_Status(ByVal   StatusText  As   String) 
    Debug.Print   StatusText   '	Печать   в   окне   Immediate End  Sub 

    Создание экземпляра объекта 

    При создании экземпляра объекта, который обеспечивает события, и при 
сохранении этого экземпляра в переменной, описанной с ключевым словом 
WithEvents, любые событие генерируемые объектом, будут автоматически переданы 
в соответствующую процедуру обработки события. В следующем фрагменте кода 
создается экземпляр объекта Order;« вызывается метод SubmitOrder, который 
затем инициирует события (рис. 8.11): 

    Private   Sub Commandl_Click() Set Order = New Projectl.C Order.SubmitOrder 
    End  Sub 
    :iassl 

    Информацию относительно использования асинхронных сообщений в клиентах см. 
в разделе "Сообщения сервера с использованием событий" главы 7 "СОМ и создание 
клиентов ActiveX" 

    8.5.3. Выполнение с помощью событий асинхронных вызовов 

    Если предвидится выполнение программным компонентом долготекущих операций, 
эти операции можно реализовать как асинхронный метод. 
    Обычно, когда клиент выполняет метод в компоненте, клиент должен дождаться 
завершения обработки, прежде чем он может продолжать выполнение. Когда 
используется асинхронный метод, клиент может продолжать работать, в то время 
как компонент также работает в фоновом режиме. 
    Для создания асинхронного метода: 
    1. Создать метод в компоненте, который активирует таймер на форме. 
    Это позволит немедленно возвращать управление приложению-клиенту, если в 
процеду ре не выполняется никакой обработки. 


    Глава 8. Создание программных компонентов ActiveX 207 


    Рис. 8.11. Генерирование событий экземпляром объекта. 

    2. В событии Timer вызвать другой метод компонента, который выполняет 
операцию, требуемую компонентом. 
    3. Когда этот метод заканчивает обработку, сгенерировать для клиента 
событие, чтобы сообщить ему, что метод завершил обработку. 
    4. В клиенте добавить программный код к процедуре возвращаемого события. 
    Приложение-клиент вызывает метод сервера, который запускает фоновый 
процесс. Затем по завершении обработки клиент от программного компонента 
получает событие. 

    Примечание: Асинхронные программные компоненты, предназначенные для 
автоматического выполнения, не могут содержать формы. В этих компонентах для 
реализации функциональных возможностей таймера без использования в форме 
элемента управления Timer можно применить функции Windows API SetTimer и KHITimer. 

    Отмена процедуры события 

    Когда программный компонент обеспечивает асинхронные методы, требуется 
предоставить пользователям способ отменить выполнение этих методов до их завершения. 
    Чтобы позволить в клиенте отменить продолжительный асинхронный метод, 
можно добавить метод статуса или прогресса, который принимает параметр Cancel. 
Если, например, 


    208	Реализация интерфейса 

    клиент во время выполнения метода устанавливает параметр Cancel в True, 
компонент останавливает асинхронный метод. Например, можно в 
приложении-клиенте добавить следующий программный код:	'• 

    Dim WithEvents   x  As   Objectl Sub.... 
    x.DoAsynchronousTask 
    CancelDialog.Show   '   Вывести  на  экран  форму  с   кнопкой _ "Отмена" 
    End  Sub 
    Sub x_InProgress(PercentDone, bCancel) 
    ' В процессе выполнения изменять строку прогресса 
    bCancel = CancelDialog.bCancel 
    End Sub 

    В компоненте соответствующий программный код будет выглядеть примерно так: 

    Dim bCancel   as   Boolean Event   InProgress(ByVal  pd  as   Long, ByRef  
 cancel   as   Boolean) 
    Private   Sub   ...(...) 
    bCancel = False 
    RaiseEvent InProgress(percent, bCancel) If bCancel Then ' Снять задачу End If 
    End Sub 

    В коде, приведенном выше, принимается, что пользовательский интерфейс 
приложения-клиента включает окно диалога, содержащее кнопку "Отмена". В обоих 
примерах кода переменная Boolean bCancel используется для установки флага, 
который указывает, нажал ли пользователь кнопку "Отмена". Если в любое время 
пользователь нажимает кнопку "Отмена", флаг bCancel в процедуре Sub 
устанавливается в True и логика оператора If в процедуре события InProgress 
отменяет выполнение задачи. 

    Примечание: В событии InProgress использование ключевого слова ByVal для 
передачи параметра означает, что изменение параметра, которое производится в 
клиенте, не будет замечено компонентом. Использование ключевого слова ByRef, 
наоборот, означает, что компонент будет видеть изменение значения. 

    8.6. Реализация интерфейса 

    Интерфейсы — группы функций, формирующие механизмы связи, через которые 
сообщаются компоненты клиента и сервера. Интерфейсы предоставляют 
стандартизованный доступ к методам и свойствам (функциональным возможностям), 
обеспечиваемым серверами. Интерфейс определяет поведение объекта, создаваемого 
из класса. 
    Реализация этих функциональных возможностей включает три задачи: 1. 
Создание абстрактного класса. 


    Глава 8. Создание программных компонентов ActiveX	209 

    2. Разработка компонента, который использует абстрактный класс. 
    3. Разработка приложения-клиента, которое использует компонент. 
    В этом разделе показано, как определять и реализовывать интерфейсы и как 
через интерфейсы обеспечить преемственность функций компонента, позволяющую 
ему продолжать работать с клиентами после модернизаций. 

    8.6.1. Использование интерфейсов 

    Для определения интерфейса используется абстрактный класс, а при его 
реализации интерфейс применяется к дополнительным классам, в которых разными 
способами конкретизируется поведение интерфейса. 

    Использование абстрактных классов 

    Назначение абстрактного класса — обеспечить шаблон для интерфейса, который 
затем применяется в других классах. Абстрактный класс не содержит никакого 
программного кода реализации интерфейса — он содержит лишь объявления. 
    При конкретизации интерфейса вводится ключевое слово Implements и имя 
абстрактного класса в разделе Declarations других модулей класса. Фактическая 
реализация интерфейса выполняется уже внутри этих классов. 
    Выгоды реализации интерфейса абстрактного класса: 
    •   это позволяет многократно использовать программный код; 
    •  это позволяет получать неограниченное количество разных реализаций для 
сходных видов объектов (полиморфизм классов); 
    •   это позволяет начать разработку объектов с минимальными 
функциональными возможностями, постепенно в ходе эксплуатации объектов 
придавая им дополнительные функции. 

    Поддержка более поздних версий компонентов 

    При использовании для создания интерфейса абстрактного класса разработчик 
специфицирует, какие функции сможет предоставить объект. При этом должно быть 
гарантировано, что приложения-клиенты, разрабатываемые с использованием 
компонента, всегда будут работать, так как оригинальный интерфейс будет поддерживаться. 
    Оригинальный интерфейс может расширяться, но оригинальные возможности, на 
которые первоначально ориентировался разработчик приложения-клиента, останутся 
доступными клиенту. Это защитит авторов клиента от проблем, вызванных 
модернизацией компонента, и в то же время позволит разработчикам расширять компоненты. 
    Информацию, связанную с версиями компонентов, см. в разделе "Совместимость версий". 
    Информацию относительно работы интерфейсов см. в разделе "Использование 
интерфейсов" главы 7 "Создание клиентов ActiveX". 

    Шаги реализации интерфейса 

    Шаги реализации интерфейса на базе абстрактных классов в Visual Basic: 1. 
Создание абстрактных классов. 
    а)  Открыть новый проект ActiveX EXE или ActiveX DLL. 
    б) В модуле класса добавить требуемые свойства и методы интерфейса. 
    в) Специфицировать имя класса для интерфейса. 
    г)   В меню File выбрать команду Make < проект >, чтобы построить 
исполняемый файл проекта. 


    210	Реализация интерфейса 

    Библиотека типов для результирующего файла .ехе или DLL будет удержать 
инс} мацию, требуемую оператором Implements в классах компонента, создаваемого 
абстрактного класса. 
    В следующем фрагменте кода для класса создаются шаблоны для двух 
пользователо-ских методов: 
    '   Программный  код  методов  для   абстрактного  модуля   класса 
    IPayroll 
    Public Sub Calculate() 
    ' Здесь пока нет никакой программной реализации End Sub 
    Public Sub Deposit() 
    ' Здесь - некоторая общая программная реализация 
    End Sub 
    2. Разработка компонента с использованием абстрактных классов. 
    а) Добавить в компоненте ссылку на библиотеку типов для абстрактных классов. 
    б) Используя оператор Implements, применить интерфейс, определенный в 
абстрактном классе, к другим классам. 
    в) Во вторичных классах добавить к процедурам свойств и методов 
программный код : реализации. 
    г)   Скомпилировать компонент. 
    В следующем примере показан программный код реализации для класса, в 
котором используются пользовательские методы, объявленные в предыдущем примере: 

    '   Этот   класс   обеспечивает   создание   объектов,   в   которых 
    '   реализуется 
    '   абстрактный  класс   IPayroll 
    Implements   IPayroll 
    Private   Sub   IPayroll_Calculate() 
    '   Программный  код реализации метода  абстрактного  класса 
    End   Sub 
    Private   Sub   IPayroll_Deposit() 
    '   Здесь   -  расширение   программной  реализации метода 
    '   применительно   к  этому  типу  объекта End  Sub	, 

    Таким образом, можно разрабатывать разные классы, в которых различными 
способами ' реализуются пользовательские свойства и методы, но используется 
один абстрактный класс. 

    3. Разработка приложения-клиента, в котором используется компонент. 

    а)  В приложении-клиенте добавить ссылку на компонент. 
    б) В приложении-клиенте добавить ссылку на библиотеку, которая содержит 
абстрактные классы. 
    в) Скомпилировать приложение. 
    г)   Создать программу Setup, которая установит клиент, компонент и 
библиотеку типов, если компонент работает в режиме out-of-process. 


    Глава 8. Создание программных компонентов ActiveX	211 


    8.7. Прочие аспекты программных компонентов 

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

    8.7.1. Использование именованных констант 

    Именованная константа — именованный программный элемент, который сохраняет 
постоянное значение в течение выполнения программы и может использоваться 
вместо литеральных значений. 
    Например, если требуется создать окно сообщения, которое включает кнопки 
Yes и No, для параметра можно использовать именованную константу vbYesNo 
вместо литерального значения. Именованные константы упрощают чтение и 
сопровождение программного кода. 

    Создание именованных констант 

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

    '   Объявление   константы  перечисляемого   типа Public   Enum  Temp	' 
    Cold  =   -5 
    Warm  =18 
    Hot   =30 End  Enum 
    Public   Sub  ReportTemp (x  As   Temp) If  x   <   Cold  Then MsgBox   
"Оденьтесь   потеплей" 
    End   If End   Sub 

    Члены перечисления могут быть доступны пользователям компонента, если 
перечисление объявлено как Public и включено в один из модулей public, который 
определяет класс. 
    Хотя перечисление объявляется в модуле, который определяет класс, в 
библиотеке типов он имеет глобальную область определения. 

    Примечание: Значения членов перечисления могут не быть последовательными 
или непрерывными. 

    Примечание: Во избежание конфликтов имен членов перечисления, в имя члена 
рекомендуется вводить уникальный префикс из символов нижнего регистра, который 
идентифицирует тип и компонент, которому принадлежит перечисление. Например, 
встроенное перечисление VbDayof-Week в Visual Basic содержит числовые 
константы с английскими названиями дней недели — vbMonday, vbTuesday и т. д. 

    8.7.2. Информация о компоненте и Help 

    В целях облегчения использования программных компонентов для каждой из 
функций — членов класса можно добавлять описательную текстовую и 
контекстно-чувствительную подсказку. 
    Примечание: Функция-член — одна из группы связанных функций, которые 
формируют интерфейс класса. 


    212	Прочие аспекты программных компонентов 


    Для обеспечения этой информации необходимо заполнить соответствующие поля 
в окнах диалога Procedure Attributes и Project Properties (см. рис. 8.4). 
    Эта информация будет после этого доступна как контекстно-чувствительная 
подсказка в окне Object Browser для текущего проекта и в любом 
приложении-клиенте, которое использует данный программный компонент. 
    Примечание: Если свойство определено как переменная Public, установить для 
него описания нельзя, но можно ввести описания для свойств, определенных через 
процедуры Property. 
    Чтобы ввести информацию помощи для метода или свойства: 
    1. Открыть проект для программного компонента ActiveX. 
    2. Открыть окно редактора кода для модуля класса. 
    3. В меню Tools выбрать Procedure Attributes. 
    4. Заполнить поля Description и Help Context ID для каждой процедуры. 

    8.7.3. Глобальность данных 

    В приложении Visual Basic данные, объявленные как Public в стандартном 
модуле, становятся глобальными и будут доступны в любом месте приложения. 
    Глобальные данные компонента могут или не могут использоваться 
приложением-клиентом, в зависимости от того, как компилируется сервер — как 
исполняемый файл или DLL, и в зависимости от значения свойства Instancing класса. 

    Исполняемый модуль ActiveX 

    При создании исполняемого файла ActiveX и установке для свойства 
Instancing класса значения MultiUse исполняемый файл может обслуживать 
несколько клиентов. 
    При первом запросе экземпляра этого класса сервер будет запущен. При 
следующем запросе экземпляра этого класса сервер уже будет выполняться и 
просто создаст новый экземпляр класса. Оба экземпляра класса будут работать с 
одними и теми же глобальными данными. 
    Если создается исполняемый файл ActiveX и для свойства Instancing класса 
устанавливается значение SingleUse, при каждом последующем запросе нового 
экземпляра данного класса будет запускаться новая копия сервера. Глобальные 
данные в данном случае не могут разделяться между экземплярами исполняемого файла. 

    ActiveX DLL 

    Если создается ActiveX DLL, для свойства Instancing необходимо установить 
значение MultiUse (или PublicNotCreatable). Компонент-сервер выполняется в том 
же пространстве процесса, что и приложение-клиент. 
    Для каждого приложения-клиента используется отдельный экземпляр DLL, и 
глобальные данные не могут быть разделены между клиентами. Однако, если одно 
приложение-клиент создает несколько экземпляров класса, все экземпляры 
используют один экземпляр DLL и совместно используют все глобальные данные. 

    8.7.4. Объявление методов Friend 

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


    Глава 8. Создание программных компонентов ActiveX 213 


    Методы Public в классе могут вызываться другими объектами, но они могут 
также вызываться клиентами. Методы Private не могут вызываться снаружи 
компонента, и они также невидимы для других объектов внутри компонента. 
    Методы, объявленные с ключевым словом Friend ("друзья"), видимы другим 
объектам в компоненте, но невидимы для клиентов, так как методы Friend не 
добавляются к библиотеке типов и не становятся частью public интерфейса. 

    Примечание: С ключевым словом Friend можно объявлять также процедуры 
Property. Процедуры Property, которые формируют свойство, могут иметь разные 
уровни видимости. 

    В следующем примере метод VB класса Class'1 вызывается процедурой в классе Class2: 

    '   Программный код в  Classl 
    '   может   вызываться  из  других  модулей  класса, 
    '   но   не  извне   проекта 
    Friend  Sub  VB () 
    MsgBox "Visual Basic" End Sub 
    ' Код в Class2 Public Sub HiVB() 
    Dim x As New Classl 
    x.VB End Sub 
    ' Код в модуле формы (модуль класса, ' имеющий внешнее представление) 
Private Sub Form_Load() 
    Dim xl As New Class2 
    xl .HiVB End Sub 

    Рис. 8.12. Вызов метода Friend. 


    214	Прочие аспекты программных компоненте» 


    8.7.5. Создание объектной модели 

    Объектная модель определяет отношение между объектами в программном 
компоненте Некоторые объекты зависят от других объектов. Эти зависимые объекты 
существуют только внутри контекста другого объекта. Например, в Microsoft 
Excel объект Button (кнопка) не может существовать сам по себе. Он существует 
только внутри объекта Worksheet (рабочий лист). Для создания объекта Button в 
приложении-клиенте не может использоваться функция CreateObject или оператор 
Set объект = New класс. Новый объект Button создается методом Add, который 
обеспечивает объект Worksheet. 
    В Visual Basic можно создавать программный компонент ActiveX, который 
формирует некоторую объектную модель. Определяя отношения между объектами, 
которые используются в программе, объектная модель организует объекты, упрощая программирование. 
    Создание объектной модели для компонента ActiveX включает следующие шаги: 
    1. Создать объект высшего уровня, установив для свойства Instancing класса 
значение SingleUse или MultiUse. 
    2. Создать зависимые объекты, установив свойство Instancing класса равным PublicNotCreatable. 
    Для объекта высшего уровня можно описать метод, который создает зависимый 
объект и возвращает ссылку на вновь созданный объект. 

    8.7.6. Хранение объектов в семействах 

    Создание семейства объектов позволяет хранить связанные элементы вместе. В 
Visuai Basic объект Collection — стандартный объект. Он может быть создан 
таким же образом, как и другие объекты: 

    Dim Employees  As  New  Collection 

    Объекты типа Collection имеют стандартные методы Add и Remove (добавить и 
удалить) и свойство Count (количество объектов в семействе). В следующем 
фрагменте кода создается новый объект Employee, который добавляется к 
семейству Employees: 

    Public Sub AddEmp (s As String, i As Integer) 
    Dim Emp As New Employee ' Создать объект для нового служащего 
    Emp.FName = s 
    Emp.ID = i 
    Employees.Add Item:=Emp, Key:=Emp.ID ' Добавить служащего с его номере:: 
End Sub 

    Хранение связанных объектов в семействе позволяет работать с этими 
объектами как с единицей или группой. Например, как показано в следующем 
примере, семейство Employees из предыдущего примера можно использовать для 
распечатки списка всех служащих: 

    Private   Sub   cmdPrintEmployees_Click() 
    For  Each  x   In  Employees Print  x.FName,   x.ID 
    Next   x End  Sub 


    8.7.7. Совместимость версий 

    Visual Basic обеспечивает совместимость версий, что позволяет 
модернизировать компоненты, поддерживая совместимость с программами, 
скомпилированными с более ранними версиями компонента. Опции совместимости 
можно установить, выбрав Project Properties в меню Project и затем открыв 
вкладку Component окна диалога Project Properties. 


    Глава 8. Создание программных компонентов ActiveX 215 


    Project2 - Project Properties 

    Рис. 8.13. Вкладка Component окна диалога Project Properties. 

    В разделе Version Compatibility можно выбрать одну из трех опций, 
перечисленных в следующей таблице: 

    Опция         | Результат__ ___________	___  ______ 

    No	Каждый раз при компиляции компонента генерируется новая информация 
Compatibility j библиотеки типов, включая новые идентификаторы классов 
интерфейсов. Между версиями компонента не сохраняется никакого наследования. 
Приложения, которые компилировались с предыдущей версией компонента, не смогут 
использовать последующие версии. Эту опцию совместимости следует включать при 
открытии нового проекта или если устанавливать совмести-| мость с более ранней 
версией компонента не требуется. 

    Project Compatibility 

    При каждой компиляции компонента генерируется новая информация библиотеки 
типов, но идентификатор библиотеки типа остается прежним, поэтому 
испытательные проекты могут обрабатывать ссылки на проект компонента. Эту 
опцию совместимости следует включать при открытии нового проекта. 
    Binary	При компиляции компонента Visual Basic создает новые идентификаторы 
Compatibility | классов и интерфейсов, только в случае необходимости, и 
сохраняет информацию идентификаторов классов и интерфейсов из предыдущей 
версии. Программы, скомпилированные с более ранней версией, продолжают 
работать. Эту опцию совместимости следует использовать, когда необходимо 
гарантировать, что модернизации компонента не повлияют на работу клиентов, 
скомпилированных с более ранней версией компонента. Visual Basic предупреждает 
разработчика, когда изменения в программном коде могут обусловить 
несовместимость новой версии с ранее скомпилированными приложениями. 


    216 Пример: Создание программного компонента 

    Информацию относительно идентификаторов интерфейсов см. в разделе 
"Взаимодействие клиента с сервером" главы 7 "СОМ и создание клиентов ActiveX". 

    8.7.8. Управление занятым компонентом 

    При вызове программного компонента приложение-клиент может получить 
сообщение "Component Busy", означающее, что сервер занят. Например, это 
происходит, когда компонент выполняет продолжительную операцию, а клиент также 
пытается загрузить его заданием. 
    Настроить вывод этого сообщения пользователям можно, используя свойства 
объекта Арр (например, OLEServerBusyRaiseError, OLEServerBusyTimeout или OLEServerBusyMsgText) 
    В следующем фрагменте кода показано, как установить пользовательский 
заголовок и текст сообщения. Эти установки переопределяют установки в окне 
диалога Component Busy. 

    Public  Const  App_Title  =   "Приложение   проверки  кредита" 
    App.OLEServerBusyMsgTitle  =  App_Title 
    Арр.OLEServerBusyMsgText   =   "Приложение   не   отвечает  _ по   причине 

 чрезмерной  загрузки  сети.   __ Если  пауза   продлится   более   пяти  
минут,   можно  _ отменить   этот   запрос  и повторить   попытку  позже" 

    8.8. Пример: Создание программного компонента 

    В этом примере создается программный компонент, который предоставляет один 
объет Объект CreditCard будет использоваться для моделирования проверки и 
подтверждения приобретения товара через кредитную карточку. 
    В следующей таблице представлены используемые интерфейсы: 

    Имя	Назначение	Тип 

    CardNumber	Номер карточки	Свойство 
    ExpireDate	Дата закрытия карточки	Свойство 
    PurchaseAmount	Сумма покупки	Свойство 
    Approve	Подтверждение кредита	Метод 

    8.8.1. Создание программного компонента 

    1. Создать новый проект ActiveX DLL. При выборе проекта ActiveX DLL 
автоматически устанавливаются свойства модуля класса и проекта. 
    2. Установить свойства проекта, как показано в следующей таблице: 

    Свойство	Установка 

    Project Name	CC 
    Project Description	Объект "Кредитная карточка" 
    Unattended Execution	Установить флажок 
    3. Установить для свойства Name модуля класса значение CreditCard. 
    4. Сохранить модуль класса как Cc.cls и проект как Cc.vbp. 


    Глава 8. Создание программных компонентов ActiveX	217 


    8.8.2. Создание свойств и методов 

    1. В модуле класса, используя переменные Public, создать два свойства с 
информацией из следующей таблицы: 

    |Имя свойства	Тип данного 
    CardNumber	Integer 
    ExpireDate	Date 

    Информацию относительно создания свойств и методов см. в разделе "Создание Свойств". 
    2. Используя процедуры Property, создать свойство под именем PurchaseAmount: 
    а)  Создать private переменную уровня модуля, которая будет хранить 
значение суммы покупки. 
    б) В процедуре Property Get вернуть значение этой переменной. 
    в) В процедуре Property Let проверить, чтобы возвращаемое значение 
переменной было больше нуля. Если значение больше нуля, присвоить переменной 
сумму приобретения. Если оно меньше нуля, установить переменную в ноль. 
    Дополнительную информацию относительно процедур свойств см. в разделе 
"Использование процедур Property для создания свойств". 
    3. Используя функцию Public, создать метод Approve, который возвращает 
значение типа Boolean. 
    Если проверка кредитной карточки прошла успешно, этот метод должен вернуть 
значение True; если с кредитом имеются проблемы — значение False. 
    Для проверки кредитной карточки можно использовать следующую логику: Если 
... то ... 
    PurchaseAmount   <   1000  And  ExpireDate   >  Now()      Approve  =  
True PurchaseAmount   >=   1000  And  ExpireDate   <=  Now()      Approve  =   False 
    4. Сделать CardNumber умолчательным свойством для класса CreditCard (в 
окне Procedure Attributes). 
    Программный код для модуля класса CreditCard должен выглядеть примерно 
следующим образом: 

    Option Explicit 
    Public CardNumber As Integer 
    Public ExpireDate As Date	..t1 
    Private msngAmount As Single 
    Public Property Get PurchaseAmount() As Single 
    PurchaseAmount = msngAmount End Property 
    Public Property Let PurchaseAmount(ByVal sngAmount As Single) If sngAmount 
> 0 Then 
    msngAmount = sngAmount ' Сохранить в private переменной модуля Else ' 

Сумма покупки меньше нуля недействительна; сбросить в ноль 

    msngAmount = О End If End Property 
    Public Function Approve() As Boolean 


    218	Пример: Определение и использование событий 


    ' Логика для проверки операции по кредитной карточке If msngAmount < 1000 
And ExpireDate > Now() Then 
    Approve = True Else 
    MsgBox "С вашим кредитом - проблемы" 
    Approve = False End If End Function 

    5. Сохранить проект. 
    6. Скомпилировать проект как Cc.dll. 

    Этот файл .dll автоматически активирует опцию Project Compatibility в окне 
диалога Project Properties. Это гарантирует, что в случае проведения изменений 
в проекте, GU;C останется тем же и ссылки из приложения-клиента не будут потеряны. 

    8.8.3. Создание приложения-клиента 

    1. Чтобы добавить новый проект к проекту CreditCard, выбрать Add Project в 
меню File. 
    2. Когда будет запрошен тип проекта, выбрать Standard EXE и затем щелкнуть 
Open. Этот проект будет использоваться как клиент, который тестирует компонент. 
    3. В окне диалога References добавить ссылку на проект Сс. 
    4. Объявить переменную уровня модуля под именем сс1 типа Сс.CreditCard. 
    5. Добавить к форме кнопку "Подтверждение" (элемент управления 
CommandButton ,1 текстовое поле "Сумма покупки" (TextBox). 
    6. В процедуре обработки события Click для элемента управления 
CommandButton доен-вить следующий программный код: 

    Set   ccl   =  New  Сс.CreditCard   '   Объект   класса   CreditCard  из   проэ;.^ 
    Cc.dll	..      . 
    ccl.ExpireDate  =   "1/1/99" 
    ccl.PurchaseAmount   =  Textl.Text 
    ccl.CardNumber  =   1234 
    MsgBox  ccl.Approve 

    7. В окне Project Group (Project Explorer) щелкнуть правой кнопкой мыши 
Projectl и затем выбрать Set as Start Up в контекстном меню (рис. 8.14). 
    Эта команда устанавливает Forml как форму запуска для проекта. 
    8. Запустить приложение, ввести значение в поле "Сумма покупки" и нажать 
кнопку "Пщ-тверждение". Можно также нажать F8, чтобы запустить 
приложение-клиент в режиме "L «• с заходом" (Step Into) и пройти пошагово 
через программный код. 
    В момент установки свойства PurchaseAmount и вызова метода Approve 
выполнение фактически заходит в проект CreditCard. 
    9. Попытайтесь ввести значение PurchaseAmount на 2000. Метод Approve 
должен вернув False (рис.8.15). 

    8.9. Пример: Определение и использование событий 

    В этом примере события используются для передачи приложению-клиенту 
информации прогресса выполнения обработки методом Approve. 


    Глава 8. Создание программных компонентов ActiveX 219 


    Рис. 8.14. Установка проекта запуска для группы проектов. 

    Рис. 8.15. Сообщение из метода компонента. 

    8.9.1. Определение и использование события Status 

    1. В модуле класса CreditCard в начало процедуры Approve добавить 
следующий программный код: 

    Public Event Status(ByVal StatusText As String) ' В разделе _ Declaration 
    Dim sngEndTime As Single 
    RaiseEvent Status ("Дозвон в банк...") 
    ' Моделирование задержки при дозвоне в банк 
    sngEndTime = Timer + 2 


    220 Пример: Определение и использование событий 


    Do While Timer < sngEndTime 
    DoEvents ' Уступить ресурсы другим процессам Loop 
    RaiseEvent Status("Обработка кредитной карточки...") ' Моделирование 
задержки при обработке карточки sngEndTime = Timer + 2 Do While Timer < sngEndTime 
    DoEvents ' Уступить ресурсы другим процессам Loop 

    В этом коде вводятся две двухсекундные задержки, моделирующие время, 
необходимое для дозвона в банк и обработки информации кредитной карточки. 
Перед каждой задержкой генерируется событие, сообщающее приложению-клиенту 
относительно текущего статуса обработки. 
    2. В модуле класса CreditCard объявить событие Status с одним строковым параметром. 
    3. Создать новую версию Cc.dll. 
    4. В приложении-клиенте добавить надпись, в которой будет отображаться 
информация статуса (см. рис. 8.16) 
    5. В приложении-клиенте добавить объявление переменной сс1 с ключевым 
словом With Events: 

    Dim WithEvents  ccl As  CC.CreditCard  '   В разделе  Declaration модуля фсг.:1:. 

    При этом Visual Basic добавляет в окно редактора кода новый объект с одной 
новой процедурой события, именованной Status (см. рис. 8.16). 
    6. В событии Status вывести на экран текст статуса в элементе управления 
Надпись (в примере — Label2): 

    Private   Sub  ccl_Status(ByVal   StatusText  As   String) 
    Label2.Caption   =   StatusText End  Sub 

    7. Сохранить группу проектов и протестировать приложение. 
    Каждое из сообщений статуса должно быть показано в надписи в течение двух секунд. 

    Рис. 8.16. Создание события в программном компоненте. 

