STDMETHODIMP TMyObjectlmpl::Add(long Numberl, long Number2)




{

return Number1 + Number2;

}

.STDMETHODIMP TMyObjectlmpl::Div(long Numberl, long Number2, float* Res)

{

*Result = (float)Number1 / Number2;

return S_OK;

}

Приведенный код вряд ли нуждается в комментариях. В методе Add просто возвращается сумма значений двух параметров. А в методе Div результат деления заносится в выходной параметр. При делении используется явное приведение типа одного из параметров, чтобы получить результат в виде действительного числа. Возвращается в методе константа S_OK, свидетельствующая о благополучном завершении метода.

Теперь все сделано, объект в составе сервера СОМ создан. Осталось зарегистрировать сервер в системе. Это можно сделать командой Run|Register ActiveX Server главного меню C++Builder. To же самое можно выполнить второй справа быстрой кнопкой в окне рис.

 

 

При регистрации вашему серверу и объекту в нем присвоятся уникальные идентификаторы uuid, а информация о сервере запишется в реестр Windows. Если в дальнейшем потребуется удалить его (вряд ли этот тестовый сервер представляет какую-то ценность), то через главное меню нужно выполнить команду

 

Run|Unregister ActiveX Server.

 

Отметим еще, что для распространения вашего проекта между пользователями потребуется библиотека типов на языке IDL Трансляция ее осуществляется быстрой кнопкой Export To IDL — крайняя правая на рис..

Осталось проверить работу созданного сервера, создав для него клиентское приложение. Начните новый проект. Разместите на форме два окна Edit, в которых пользователь сможет задавать числа. Добавьте две кнопки, одна из которых (назовите ее BAdd) будет выполнять сложение, а другая (BDiv) — деление, выполняя соответственно методы первого и второго интерфейсов. Введите также в приложение метку Label, в которой будут отображаться результаты эти вычислений. Теперь нам надо обеспечить связь нашего клиентского приложения с сервером. Поскольку вы сами разработали сервер и все его файлы у вас имеются, это можно было бы сделать очень просто. Но мы рассмотрим более общий путь, обеспечивающий связь с любым сторонним сервером. Выполните команду Project|Import Type Library. Перед вами откроется окно, показанное на рис.

 

 

В верхнем списке вы увидите все зарегистрированные на вашем компьютере библиотеки типов. Если какой-то библиотеки вы не найдете, можно щелкнуть на кнопке Add и выбрать требуемый файл. В нашем случае, если вы не забыли зарегистрировать ваш сервер, вы найдете его библиотеку в списке, как показано на рис. Выключите индикатор Generate Component Wrappers. Это исключит генерацию оболочки, которая нам не нужна. Щелкните по имени созданного типа. Кнопка Create Unit - создать модуль, станет активной. Далее щелкните на кнопке Create Unit. В результате в проект включится модуль Mycomserv_tlb. Это модуль описания вашей библиотеки типов, файлы которого мы пока не смотрели. Собственно, можете и сейчас в них не всматриваться. В файле Mycomserv_tlb.cpp вы увидите список идентификаторов GUID библиотеки, объекта и интерфейсов. А в файле Мусотserv_tlb.h вы найдет описание класса с многочисленными объявлениями методов и, в частности, объявлениями введенных вами методов Add и Div.

 

Чтобы связать основной модуль вашего клиентского приложения с сервером, введите в заголовочный файл модуля директиву

 

#include <MyComServ_TLB.h>

 

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

 

#include <MyComServ_TLB.h>

...

public:. // User declarations

fastcall TForml(TComponent* Owner);

TCOMIMyObject Interfacel;

IntDivPtr Interface2;

};

Тип переменной Interface1 задан как TCOMIMyObject. Это класс так называемого интеллектуального (smart) интерфейса. Вы можете найти имя этого класса (точнее, имя частной реализации соответствующего шаблона класса) в заголовочном файле MyComSeru_TLB.h. Впрочем, не обязательно вдаваться в тонкости реализации. Достаточно знать, что интересующее вас имя складывается из имени интерфейса, перед которым добавляется префикс ТСОМ. Интеллектуальный интерфейс автоматически осуществляет операции по установлению и разрыву связи с сервером. Так что предпочтительнее использовать именно его, а не сам интерфейс. Тип переменной Interface2 задан равным IntDivPtr. Это указатель на сооветствующий интерфейс. Он представляет собой реализацию одного из шаблонов класса, который вы можете найти в файле MyComServ_TLI}.h. Имя типа указателя складывается из имени интерфейса и суффикса Ptr.

В обработчик события формы OnCreate вставьте код:

 

Interfacel = CoMyObject::Create ();

Interface2 = Interfacel;

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

Второй из приведенных операторов задает переменной Interface2 значение указателя на второй интерфейс. Вам даже не требуется вызывать метод QueryInterface. Его вызов осуществится автоматически.

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

 

void fastcall TForml::BAddClick(TObject *Sender)

{

Label1->Caption = Interfacel.Add(StrToInt(Edit1->Text),

StrToInt(Edit2->Text));

и

 

void fastcall TForml::BDivClick(TObject *Sender)

float R;

(*Interface2).Div(StrToInt(Edit1->Text),

StrToInt(Edit2->Text), &R);

Label1->Caption = R;

}

Как видно в приведенном коде, вызов метода Add осуществляется непосредственно через объект Interface1. Причем результат этого вызова возвращаемое методом значение, в нашем случае — сумма чисел. Вызов метода второго интерфейса осуществляется с учетом того, что переменная Interface2 — указатель на интерфейс. Кроме того, в приложение приходится вводить дополнительную переменную R, указатель на которую передается в метод Div. В переменную R заносится результат — значение выходного параметра метода.

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

 

Реализация и использование локальных серверов СОМ

Ранее рассматривалось построение внутреннего сервера СОМ в виде файла DLL. Теперь рассмотрим построение сервера, реализуемого исполняемым файлом.ехе. С точки зрения пользователя основное отличие этого варианта заключается в том, что сервер представляет собой отдельное приложение. За его состоянием можно наблюдать, можно управлять его работой, переключать его в различные режимы и т.п.

Попробуем построить простой локальный сервер СОМ и его клиентов. Пусть этот сервер будет содержать окно редактирования, в которое можно заносить какой-то текст сообщения. А клиенты сервера смогут читать это сообщение и заносить на сервер собственные сообщения. Таким образом, клиенты смогут общаться друг с другом. Чтобы дополнительно обсудить создание и использование методов интерфейсов, добавим на сервер метод, который по запросу клиента может управлять видимостью сервера. Начните новое приложение, перенесите на форму окно редактирования Edit и задайте заголовок формы Сервер MyServer. Больше можете в серверное приложение ничего не вносить. А можете добавить какие-то органы управления по своему желанию.

 

 

Сохраните ваш проект под каким-нибудь именем. Учтите, что это имя станет именем исполняемого файла вашего сервера. Но дальнейший текст в данном разделе ориентирован на имя Project1.

Пока создаy обычный проект C++Builder. Теперь давайте превратим его в локальный сервер СОМ. Выполните команду File | New | Other и на странице ActiveX Депозитария выберите пиктограмму Automation Object — объект автоматизации. С ним вы уже умеете работать, поскольку точно так же создавали объект во внутреннем сервере, рассмотренном ранее. В окне, которое откроется перед вами в окошке CoClass Name укажите имя класса MyObject.

 

После щелчка на кнопке ОК перед вами откроется знакомое окно РедактораБиблиотеки Типов

 

 

Что нужно вам внести в интерфейс? Имя этого интерфейса в нашем примере IMyServer, а класс его родительского интерфейса надо установить равным IDispatch. Прежде всего, введите в этот интерфейс метод SetVis. Этот метод будет управлять видимостью сервера. Задайте в методе один параметр с именем Vis, типом VARIANT_BOOL (это булев тип, используемый в СОМ) и спецификатором [ in ]. Этот параметр будет указывать, должен ли сервер быть видимым (при значении true) или невидимым (при значении false).

Теперь давайте введем в интерфейс свойство с именем Mess. Оно будет представлять читаемые или записываемый текст сервера. Поскольку пока мы не добавляли свойств в интерфейс, рассмотрим эту операцию подробнее. Нажмите кнопочку выпадающего списка рядом с кнопкой Property (четвертая справа). Откроется меню с разделами Read | Write (для чтения и записи), Read Only (только для чтения), Write Only (только для записи), Read | Write | Write By Ref (для чтения, записи и записи по ссылке). Нам надо и читать, и записывать значения Mess. Так что выберите раздел Read | Write. В результате в левой панели Редактора Библиотеки Типов появятся две вершины: одна для функции записи, другая для функции чтения. Задайте одной из них имя Megs. Это же имя автоматически присвоится и второй вершине. На странице Attributes задайте тип свойства — BSTR. Это тип строк, используемый в СОМ.

Для функции чтения на странице Parameters задайте имя параметра функции Text, тип параметра BSTR * — указатель на BSTR, спецификатор параметра [out, retval]. Для функции записи имя параметра Text, тип параметра BSTR, спецификатор параметра [in]. Возвращаемый тип в обеих функциях HRESULT.

Формирование свойств и методов интерфейса закончено. Теперь можно их реализовывать. Щелкните на кнопке Refresh Implementation (Обновить реализацию) — третья справа на рис.. Перейдите в Редактор Кода. В файле MyServerlmpl.cpp вы увидите заготовки функций записи и чтения get_Mess, set_Mess и метода SetVis. Вам остается только добавить по одному оператору в каждую из этих заготовок. В результате они должны выглядеть так:

 

STDMETHODIMP TMyServerlmpl::get_Mess(BSTR* Text)

{

Try

(

*Text = WideString((Forml->Editl->Text).c_str()). cjDstr();

}

catch(Exception &e)

(

return Error(e.Message.c_str(), IID_IMyServer);

}

return SJDK;



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: