Разработка интегрированных прикладных программ (Меньшикова К. Г.) (Разработка интегрированных прикладных программ (Меньшикова К. Г.))

Посмотреть архив целиком

Каждый COM-объект является экземпляром некоторого класса, и каждый класс может иметь GUID – идентификатор класса (CLSID). Он нужен в основном для того, чтобы библиотека COM могла найти необходимый сервер в базе объектов (реестре) и создать экземпляр класса (объект). Под классом, в данном случае, понимается конкретная реализация некоторого набора интерфейсов. Понятно, что разные классы могут иметь совершенно одинаковые интерфейсы.

Большинство фирм не разрабатывают собственные интерфейсы, а используют существующие. Например, интерфейс IDispatch предназначен для автоматизации приложений.

  1. OLE-автоматизация

Любое приложение, которое хочет сделать доступными для других программ свои внутренние функции, (т.н. программируемое приложение), может осуществить это, предоставив клиентам объекты, реализующие интерфейс IDispatch. Это обычный COM-интерфейс, который реализован с помощью виртуальной таблицы указателей на его методы, но в его состав входит метод Invoke, который используется для вызова других (диспетчерских) методов. Клиент, которого в данном случае принято называть контроллером автоматизации, может посредством Invoke обращаться к необходимому методу и передавать параметры.

Конечно, современные программные инструментарии предоставляют в распоряжение программистов достаточно удобные средства для создания серверов и контроллеров. Рассмотрим примеры их создания.

    1. Создание сервера автоматизации в Builder C++

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

На рис. 1 представлено главное окно приложения-сервера «День недели».


Рис. 1

Приложение должно выводить на экран текущую дату (в Label2) и день недели (в Label3). В поле ввода (Edit1) можно ввести любую дату, а по щелчку на кнопке (Button1) получить день недели, соответствующий введенной дате.

В класс формы (Form1) главного окна приложения были добавлены следующие функции:

void __fastcall TForm1::day_this(int& n);
void __fastcall TForm1::day_date(AnsiString str,int& n);
void __fastcall TForm1::day_week(int n, AnsiString& str);

В модуль формы следует также добавить строку #include , которая обеспечит обращение к системным функциям.

Функция day_this возвращает номер дня недели (1 – воскресенье):

void __fastcall TForm1::day_this(int& n)
{ n=DayOfWeek(Date()); }

Функция day_date по заданной дате возвращает номер дня недели:

void __fastcall TForm1::day_date(AnsiString str,int& n)
{ TDateTime dtDate = StrToDate(str);
n=dtDate.DayOfWeek(); }

Функция day_week по заданному номеру дня недели возвращает его название:

void __fastcall TForm1::day_week(int n, AnsiString& str)
{ char days[7][12] = {"Воскресенье","Понедельник",
"Вторник","Среда", "Четверг","Пятница","Суббота"};
str=(AnsiString)(days[n-1]); }

Пусть при создании формы Form1 в окне появляется текущая дата:

void __fastcall TForm1::FormCreate(TObject *Sender)
{ int i; AnsiString str;
str = DateToStr(Date()); Label2->Caption=str;
day_this(i); day_week(i,str); Label3->Caption=str; }

При щелчке на кнопке Button1, по дате, введенной в Edit1, определяется день недели:

void __fastcall TForm1::Button1Click(TObject *Sender)
{int i; AnsiString str; str=Edit1->Text;
try
{ day_date(str,i); day_week(i,str);
Label5->Caption=str; }
catch(Exception &e)
{ Application->MessageBoxA (e.Message.c_str(),
"
Ошибка",MB_OK); } Label4->Caption=Edit1->Text; }

Сохранив проект, как обычное Windows-приложение, затем можно превратить его в сервер автоматизации. Для этого следует:

  • на странице ActiveX галереи объектов выбрать элемент Automation Object;

  • в появившемся диалоговом окне ввести имя класса (CoClassName); под этим именем данный класс COM-объектов будет зарегистрирован в реестре. В нашем примере введено имя класса: DayWeek;

  • в редакторе библиотеки типов (Type Library Editor) определить свойства и методы созданного класса;

  • на инструментальной панели редактора библиотеки типов нажать кнопку Refresh Implementation для генерации модуля с заготовками методов (в нашем примере сгенерирован модуль DayWeekImpl).

Обычно описания интерфейсов создаются на языке IDL (Interface Definition Language), а затем по ним строится библиотека типов. При работе в среде Builder C++ и Delphi достаточно в окне редактора библиотеки указать свойства и методы создаваемого COM-объекта. Объект (рис. 2) имеет диспетчерский интерфейс IDayWeek, в состав которого входят два метода (Today, Data_Day) и свойство Visible.

Выбрав кнопку Export To IDL, можно получить описание на языке IDL интерфейса IDayWeek, входящего в состав библиотеки типов “Project_DayWeek Library”:

Project_DayWeek.idl
[ uuid(C55ED6A4-5583-4E88-8317-0539445A5F6E),
version(1.0),
helpstring("Project_DayWeek Library")
]
library Project_DayWeek
{ importlib("stdole2.tlb");
[ uuid(C13BFB8F-C655-43CA-80D9-C53B659E5C85),
version(1.0),
helpstring("Dispatch interface for DayWeek Object"),
dual,
oleautomation
]
interface IDayWeek: IDispatch
{ [ id(0x00000001) ]
HRESULT _stdcall Today([out] BSTR * str );
[ id(0x00000002) ]
HRESULT _stdcall Data_Day([in] BSTR dat, [out] int * n, [out] BSTR * week );
[ propget, id(0x00000003) ]
HRESULT _stdcall Visible([out, retval] VARIANT_BOOL * Value );
[ propput, id(0x00000003) ]
HRESULT _stdcall Visible([in] VARIANT_BOOL Value );
};
[uuid(3E979810-8A64-4EAE-9F1E-8C582079F4AF),
version(1.0), helpstring("DayWeek Object") ]
coclass DayWeek
{ [default] interface IDayWeek; };
};

Рис. 2

Заготовки модуля DayWeekImpl заполняются соответствующим кодом.

Метод Data_Day возвращает номер и название дня недели для заданной даты:

STDMETHODIMP TDayWeekImpl::Data_Day(BSTR dat, int* n, BSTR* week)
{ int i; AnsiString str; str=(AnsiString)dat;
Form1->day_date(str,i); Form1->day_week(i,str);
*n =i; *week= WideString(str.c_str()).c_bstr();
return S_OK; }

Метод Today возвращает текущую дату и название дня недели:

STDMETHODIMP TDayWeekImpl::Today(BSTR* str)
{ AnsiString s;
s=Form1->Label2->Caption + " " + Form1->
Label3->Caption;
*str= WideString(s.c_str()).c_bstr(); return S_OK; }

Два следующих метода get_Visible и set_Visible отвечают за чтение и установку свойства Visible, которое позволяет сделать видимым или невидимым приложение-сервер:

STDMETHODIMP TDayWeekImpl::get_Visible(VARIANT_BOOL* Value)
{ try
{ *Value=Form1->Visible; }
catch(Exception &e)
{ return Error(e.Message.c_str(), IID_IDayWeek); }
return S_OK; };
STDMETHODIMP TDayWeekImpl::set_Visible(VARIANT_BOOL Value)
{try
{ Form1->Visible=Value; }
catch(Exception &e)
{ return Error(e.Message.c_str(), IID_IDayWeek); }
return S_OK; };

При описании параметров методов сервера автоматизации используются типы данных, принятые в IDL. Часто используются типы данных, которым легко можно найти аналог в языке программирования (short - двухбайтовое целое число со знаком, long - четырехбайтовое целое число со знаком, single - четырехбайтовое действительное число, double - восьмибайтовое действительное число, BSTR - двоичная строка, VARIANT_BOOL - true= 1, false = 0). Можно использовать также и другие типы данных.

После компиляции и запуска сервера на выполнение он зарегистрируется в реестре. При необходимости удаления записей рекомендуется запустить его с ключом /unregserver. При переносе сервера автоматизации в другой каталог, можно запустить его снова, при этом записи в реестре обновятся. Записи делаются в разделах реестра HKEY_LOCAL_MASHINE\SOFTWARE и HKEY_CLASSES.

После создания сервера автоматизации, основываясь на информации, содержащейся в библиотеке типов, можно создавать приложения, управляющие этим сервером, т.е. контроллеры автоматизации. Это можно сделать с помощью различных инструментариев, включая Visual C++, Delphi, C++Builder, VBA и т.д.

    1. Контроллер на C++Builder (позднее связывание)

Приложения, управляющие серверами автоматизации, называются контроллерами автоматизации. Создадим контроллер, управляющий сервером «День недели», основываясь на информации о методах класса его объекта автоматизации.

На рис. 3 представлено окно контроллера, содержащее кнопки для установки и разрыва связи с объектом, флажок видимости сервера и кнопки управления свойством Visible, а также кнопки для получения данных, метки для отображения данных в окне, поле Edit1 для ввода даты. После запуска контроллера (при нажатии кнопки Connect) запускается сервер. При нажатии кнопки Disconnect он выгружается. Кнопка SetVisible проявляет и скрывает окно сервера в зависимости от наличия флажка на компоненте CheckBox1, но и будучи невидимым, сервер продолжает выполнять свои функции. Нажатие кнопки GetVisible приводит флажок в соответствие значению свойства Visible сервера.


Рис. 3

Чтобы общение с COM-объектом сервера стало возможно, в модуль следует включить строку #include .

Для управления сервером следует создать переменную Serv типа Variant, во время работы она будет содержать указатель на интерфейс IDispatch COM-объекта. Для создания экземпляра COM-объекта можно использовать функцию CreateOleObject из модуля ComObj библиотеки VCL: Variant Serv;

Serv=CreateOleObject("Project_DayWeek.DayWeek");

Эта функция создаст IDispatch и вернет указатель на него. IDispatch дает доступ к диспетчерскому интерфейсу объекта сервера, методы которого мы хотим вызывать. Для создания объекта CreateOleObject вызывает функцию CoCreateInstance, являющуюся частью спецификации COM Windows API.


Случайные файлы

Файл
ref-16069.doc
175400.rtf
EGIPET.doc
90606.rtf
133251.rtf




Чтобы не видеть здесь видео-рекламу достаточно стать зарегистрированным пользователем.
Чтобы не видеть никакую рекламу на сайте, нужно стать VIP-пользователем.
Это можно сделать совершенно бесплатно. Читайте подробности тут.