logo search
Объектно-ориентированное программирование и C++

3.6.1.4 Объявления автоматизированных свойств и методов

OLE Automation - это разновидность механизма связи Object Linking and Embedding, позволяющего приложениям для Windows управлять друг другом. Автоматизированный OLE контроллер является приложением, которое способно автоматизировать другое приложение - автоматизированный OLE сервер. По существу, OLE Automation представляет собой протокол обмена, посредством которого контроллер управляет действиями сервера. Все компонентные OLE объекты, экспортируемые автоматизированным сервером своим контроллерам, являются производными от базового класса TAutoObject.

При создании автоматизированного сервера необходимо определить его интерфейс с контроллером, содержащий объявления свойств и методов OLE объекта с тем, чтобы контроллер получил к ним доступ. Никогда не удаляйте уже включенные в интерфейс свойства и методы - это приведет к ошибкам в работе существующих контроллеров. C++Builder использует модификатор _automated в объявлениях автоматизированного метода (Листинг 3.13). Это объявление может заканчиваться еще одним новым ключевым словом _dispid, которое ассоциирует значение идентификатора диспетчеризации OLE Automation с данной функцией.

class MyOLEAutoClass : TAutoObject

{ _automated: void_fastcall function(void) _dispid(1000); };

Листинг 3.13. Объявление автоматизированного метода.

Правила видимости, определяемые этим ключевым словом, не отличаются от правил видимости, объявленных в секции public. Единственное отличие проявляется в том, что генерируемая компилятором информация о типах свойств и методов OLE Automation, делает возможным создание автоматизированных серверов.

C++Builder поставляется вместе с примером (удивительным по внешней простоте и лаконичности кода) взаимодействия приложений контроллера и сервера посредством механизма OLE Automation. Этот пример проливает свет на данную методику, изложенную в системной документации весьма сбивчиво и туманно. Автоматизированный сервер Autosrv демонстрирует использование:

• компонентных объектов TAutoObject и TAutoClassInfo;

• метода RegisterAutoClass автоматизированного объектного класса для регистрации сервера;

• свойств и методов, объявленных с ключевым словом _automated. Контроллер Autocon управляет сервером и демонстрирует:

• установку и выборку свойств объекта сервера;

• использование вариантов (детальная информация об типе Variant содержится в параграфе 3.6.1.6 "Расширенные типы данных Delphi".

Чтобы испытать на практике, что дает взаимодействие приложений OLE Automation, выполните следующие действия:

=> По команде главного меню File [ Open Project откройте диалог выбора проектов. => Войдите в каталог \...\CBuilder\Examples\Apps\Autosrv => Выберите проектный файл с именем Autosrv и нажмите кнопку Open.

=> Командой главного меню Run | Run запустите процесс компиляции и сборки автоматизированного сервера. => Снова откройте диалог выбора проектов, войдите в каталог

\...\CBuilder\Examples\Apps\Autocon, выберите проектный файл с именем

Autocon и нажмите кнопку Open. => Запустите процесс компиляции и сборки контроллера.

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

Рис. 3.4. Контроллер готовит сообщение и посылает его серверу.

Рис. 3.5. Контроллер принимает сообщение, "обработанные" сервером.

Рис. 3.6. Контроллер снимает старое сообщение с сервера.

Чтобы узнать, как реализовано такое взаимодействие, необходимо разобраться в текстах модулей автоматизированного сервера (Листинг 3.14 и Листинг 3.15) и контроллера (Листинг 3.16 и Листинг 3.17), которые заслуживают того, чтобы привести их целиком, снабдив необходимыми комментариями. Сервер содержит единственный объект Edit1 компоненты TEdit для редактируемого ввода и приема сообщений от контроллера в свойство Text. Контроллер записывает введенное пользователем сообщение в свойство Text своего объекта Edit1, а управляет сервером посредством трех кнопок Buttoni, Button2 и Buttons компоненты TButton (с названиями "Послать", "Принять" и "Очистить").

#ifndef Auto2H

#define Auto2H

ftinclude <Classes.hpp> ftinclude <01eAuto.hpp>

#include <System.hpp>

// Класс сервера ButtonServer. производный от TAutoOb-iect class ButtonServer : public TAutoObject {

private: // Приватные свойства и методы AnsiString _fastcall GetEditStr() ;

void _fastcall SetEditStr(AnsiString NewVal);

int _fastcall GetEditNum() ;

void _fastcall SetEditNum(int NewVal);

_automated: // Автоматизированные свойства и методы property AnsiString EditStr = // свойство типа AnsiString / / с атрибутами функции чтения/записи значении {read=GetEditStr, write=SetEditStr} ;

property int EditNum = // свойство типа int / / с атрибутами функций чтения/записи значений {read=GetEditNum, write=SetEditNum); :

void _fastcall Clear (); // метод очистки сообщения void_fastcall SetThreeStr // метод составления текстового / / сообщения из строк в параметрах si, s2, s3 типа AnsiString (AnsiString si, AnsiString s2, AnsiString s3);

void _fastcall SetThreeNum // метод составления текстового / / сообщения из чисел в параметрах п 1, п2, п3 типа int (int п1, int п2, int п3) ;

public: // Общедоступные свойства и методы

_fastcall ButtonServer О; // конструктор объекта сервера

};

//----------------------------------------------------------

#endif

Листинг 3.14. Файл объявлений Auto1.h модуля автоматизированного сервера.

#include <vcl.h>

#pragma hdrstop

#undef RegisterClass

#include "Auto2.h"

#include "Autol.h"

int Initialization();

static int Initializer = Initialization();

// Создание объекта автоматизированного сервера _fastcall ButtonServer::ButtonServer() : TAutoObject()

{ }

// Чтение текстового значения автоматизированного свойства AnsiString _fastcall ButtonServer::GetEditStr() { return Forml->Editl->Text;

// Запись текстового значения автоматизированного свойства void _fastcall ButtonServer:-.SetEditStr (AnsiString NewVal) { Forml->Editl->Text = NewVal;

} // Чтение численного значения автоматизированного свойства

int _fastcall ButtonServer: :GetEditNum()

( int val;

sscanf(Forml->Editl->Text.c_str(), "%d", &val) ;

return val;

// Запись численного значения автоматизированного свойства void _fastcall ButtonServer::SetEditNum(int NewVal) { Forml->Editl->Text = NewVal;

}

// Очистка значения автоматизированного свойства void_fastcall ButtonServer::Clear() { Forml->Editl->Text = "";

// Составление текстового значения свойства из трех строк void _fastcall ButtonServer::SetThreeStr (AnsiString si, AnsiString s2, AnsiString s3) { Forml->Editl->Text = si + ", " + s2 + ", " + s3;

) // Составление текстового значения свойства из трех чисел

void _fastcall ButtonServer::SetThreeNum (int nl, int n2, int n3) { AnsiString sl(nl), s2(n2), s3(n3);

Forml->Editl->Text = si + ", " + s2 + ", " + s3;

// Регистрация объекта автоматизированного сервера void _fastcall RegisterButtonServer() { TAutoClassInfo AutoClassInfo;

// Инициализация полей структуры типа TAutoClassInfo AutoClassInfo.AutoClass = _classid(ButtonServer) ;

AutoClassInfo.ProgID = "BCBAutoSrv.EditServer" ;

AutoClassInfo.ClassID =

"{61E124E1-C869-11CF-9EA7-OOA02429B18A}";

AutoClassInfo.Description =

"Borland C++Builder AutoSrv Example Server Class";

AutoClassInfo.Instancing = acMultiInstance;

// Регистрация класса автоматизированного сервера Automation->RegisterClass(AutoClassInfo) ;

}

// Инициализация объекта автоматизированного сервера

int Initialization()

{ RegisterButtonServer() ;

return 0;

}

Листинг 3.15. Кодовый файл Auto2cpp модуля автоматизированного сервера.

#ifndef AutolH #efine AutolH

class TFormI : public TForm {

published: // IDE-managed Components

TEdit *Editl;

TButton *Buttonl

TButton *Button2

TButton *Button3

TLabel * Label 1;

void _fastcall ButtonlClick(TObject *Sender) ;

void _fastcall Button2Click(TObject * Sender);

void _fastcall Button3Click(TObject * Sender);

private: // User declarations

Variant AutoServer;

public: // User declarations

virtual _fastcall TFormI(TComponent *0wner) ;

extern TFormI *Forml;

#endif

Листинг 3.16. Файл объявлений Auto1.h, все строки которого (за исключением выделенной строки объявления варианта) C++Builder генерирует автоматически при размещении компонент на форме контроллера.

include <vcl.h> #pragma hdrstop

#include "autol.h"

#pragma resource "*.dfm" #ormI *Forml;

_fastcall TFormI::TFormI(TComponent *0wner) : TForm(Owner) { try

{ // Создание автоматизированного сервера как объекта OLE AutoServer = CreateOleObject("BCBAutoSrv.Edit Server");

}

catch (...) { // Обработка исключения

ShowMessage("Сначала компилируйте и запустите AutoSrv");

Application-terminate () ;

}

} // Обработчик события при нажатии кнопки Buttoni

void _fastcall TFormI::ButtonlClick(TObject *Sender) { // Установка автоматизированного свойства сервера AutoServer.OlePropertySet("EditStr", Editl->Text);

)

// Обработчик события при нажатии кнопки Button2

void _fastcall TFormI::Button2Click(TObject *Sender)

{ // Чтение автоматизированного свойства сервера

Editl->Text = AutoServer.OlePropertyGet("EditStr");

// Обработчик события при нажатии кнопки Button3 void _fastcall TFormI::Button3Click(TObject *Sender) { // Очистка автоматизированного свойства сервера AutoServer.OleProcedure("Clear") ;

Листинг 3.17. Кодовый файл Auto1.cpp модуля контроллера.

3.6.1.5 Быстрый вызов функций

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

<возвращаемый тип> _fastcall <name>(<список параметров^

Это ключевое слово определяет, что первые три типизированных параметра функции с именем name (слева направо по списку) передаются не через стек, а через процессорные регистры AX, BX и DX. Регистры не используются, если значение параметра не умещается в регистр, т.е. при передаче через параметр чисел с плавающей точкой, структур и функций.

Строго говоря, быстрый вызов функций не является прерогативой компилятора C++Builder. В предыдущей главе я уже обращал внимание читателя на использование _fastcall в объявлениях функций обработки событий, которые C++Builder генерирует автоматически.