- •Проблемы, решаемые с помощью технологии com
- •Основные понятия
- •Именование com-объектов
- •Понятие интерфейса
- •Основы компиляции
- •Простейший пример использования
- •Интерфейс iUnknown
- •Еще один пример
- •Com-сервер
- •Создание "настоящего" com-сервера.
- •Фабрика классов
- •Использование фабрики классов
- •ITypeLib, iTypeInfo, библиотеки типов и информация о методах сервера. Язык idl.
- •IDispatch и вызов методов "по имени"
- •IMarshall, маршалинг и взаимодействие клиента с внутренними, локальными и удаленными серверами
- •Технология ole Внедрение и связывание объектов - ole
- •Использование ole-документов в приложениях
- •Использование свойств OleContainer
- •Создание элементов управления ActiveX Понятие ActiveX.
- •Создание элементов управления ActiveX на основе vcl-компонентов
- •Создание страниц свойств
- •Создание активных форм
- •Создание локальных серверов и контроллеров автоматизации Понятие автоматизации.
- •Создание приложения, подлежащего автоматизации
- •Превращение приложения в сервер автоматизации
- •Библиотека типов
- •Реализация методов объекта автоматизации
- •Создание контроллера
- •Раннее и позднее связывание
- •Создание контроллеров для произвольных серверов автоматизации
- •Коллекции объектов внутри серверов автоматизации
- •Использование информации из библиотек типов
- •Создание коллекций объектов
- •Экспонируемые свойства и методы
- •Процессы в Windows Процессы
- •Планирование потоков
- •Приоритеты
- •Привязка к процессорам
- •Создание процессов
- •Завершение процессов
- •Создание потоков
- •Завершение потоков
- •Wait функции
- •Синхронизация потоков
- •Синхронизация процессов
- •Взаимодействие между процессами
- •Создание внутренних серверов и контроллеров автоматизации Внутренний сервер автоматизации и передача данных
- •Создание внутреннего сервера автоматизации
- •Манипуляция ресурсами в dll
- •Работа внутреннего сервера автоматизации в многопоточном режиме Понятие многопоточности. Синхронизация
- •Класс tThread
- •Пример многопоточного приложения
- •Применение com-объектов, входящих в состав Windows Создание ярлыков
- •Использование Internet Explorer в приложениях
Раннее и позднее связывание
Рассмотренный выше пример создания контроллера использовал так называемое позднее связывание (late binding), или связывание на этапе выполнения. В этом случае, как было сказано выше, анализ существования методов и свойств объекта автоматизации не производится до момента обращения к ним на этапе выполнения. Поэтому при создании контроллера таким образом высока вероятность незамеченных ошибок в написании названий методов и свойств.
Контроллер автоматизации может быть создан и несколько другим способом - с помощью импорта библиотеки типов. В этом случае в адресном пространстве контроллера создается набор классов для управления сервером, обладающих теми же самыми методами, которыми обладает и подлежащий автоматизации объект. Это позволяет непосредственно обращаться к методам данных классов, а также выявить на этапе компиляции ошибки в названиях методов сервера.
Чтобы иметь возможность создать такой контроллер, следует из меню C++Builder выбрать опцию "Project/Import Type Library". В результате будут созданы файлы в подкаталоге Imports. Эти файлы следует включить в проект контроллера, чтобы сделать доступными описания классов для управления сервером (C++Builder делает это автоматически).
В этом случае код контроллера можно создать двумя способами. Один их этих способов реализует так называемое раннее связывание (early binding) клиента с сервером, то есть создание и использование в клиентском приложении таблицы виртуальных методов, полностью аналогичной таблице виртуальных методов сервера.
Пример кода контроллера автоматизации, реализующего раннее связывание, приведен ниже:
IMyAuto *serv;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
serv = CoMyAuto::Create ();
}
void __fastcall TForm1::Button2Click(TObject *Sender)
{
serv = NULL;
}
void __fastcall TForm1::Button3Click(TObject *Sender)
{
if (serv)
{
Edit1->Text = IntToStr (serv->Width);
}
}
void __fastcall TForm1::Button4Click(TObject *Sender)
{
if (serv)
{
serv->Width = atoi (Edit1->Text.c_str ());
}
}
void __fastcall TForm1::Button8Click(TObject *Sender)
{
if (serv)
{
CheckBox1->Checked = serv->Visible;
}
}
void __fastcall TForm1::Button9Click(TObject *Sender)
{
if (serv)
{
serv->Visible = CheckBox1->Checked;
}
}
void __fastcall TForm1::Button5Click(TObject *Sender)
{
if (serv)
if (OpenDialog1->Execute ())
{
serv->OpenFile (WideString((OpenDialog1->FileName).c_str ()).c_bstr ());
}
}
void __fastcall TForm1::Button6Click(TObject *Sender)
{
if (serv)
if (SaveDialog1->Execute ())
{
serv->SaveFile (WideString((SaveDialog1->FileName).c_str ()).c_bstr ());
}
}
void __fastcall TForm1::Button7Click(TObject *Sender)
{
if (serv)
{
serv->NewFile ();
}
}
void __fastcall TForm1::Button10Click(TObject *Sender)
{
if (serv)
{
serv->AddLine (WideString((Edit1->Text).c_str ()).c_bstr ());
}
}
При использовании раннего связывания поиск необходимого метода при попытке обращения к нему контроллера происходит заметно быстрее, чем в предыдущем случае. Однако при замене версии сервера на более новую соответствие между таблицами виртуальных методов может быть нарушено и контроллер окажется неработоспособным. В предыдущем же случае, основанном на позднем связывании и использовании вариантных переменных, этого не произойдет, если, конечно, автор сервера не нарушит спецификацию СОМ, которая содержит требование совместимости версий на уровне существования свойств и методов предыдущих версий сервера,
Есть еще и третий способ, основанный также на импорте библиотеки типов, но использующий позднее связывание:
IMyAuto3Disp V;
...
void __fastcall TForm1::Button1Click (TObject *Sender)
{
V = (IMyAuto3Disp) CreateOleObject ("Autoserv.MyAuto3");
}
В этом случае контроллер автоматизации работает медленнее, чем при использовании раннего связывания, однако на этапе компиляции производится синтаксическая проверка кода контроллера на предмет существования свойств и методов объекта автоматизации, к которым он обращается, применяя свойства и методы классов для управления сервером, созданных при импорте библиотеки типов.
Хотелось бы обратить внимание на то, что, хотя мы и смогли протестировать свойства и методы сервера автоматизации с помощью созданного контроллера, у нас еще не было возможности произвести отладку части кода, связанного с автоматизацией. Естественно, если клиент запускается под управлением среды разработки C++Builder, использовать тот же самый экземпляр среды разработки для отладки сервера невозможно. Поэтому следует открыть проект сервера в отдельном экземпляре среды разработки и запустить его на выполнение. Если после этого запустить приложение-контроллер (неважно, под управлением другого экземпляра среды разработки или просто средствами операционной системы) и нажать кнопку "Connect", контроллер соединится с уже запущенным экземпляром сервера. Если в исходном тексте сервера отмечены точки останова, при их достижении выполнение кода сервера прекращается и управление передается среде разработки.
Отметим один очевидный факт: СОМ-сервер и СОМ-клиент могут быть написаны с использованием любых средств разработки, поддерживающих СОМ-технологию. Поэтому в принципе не возбраняется написать сервер автоматизации с помощью Delphi, а контроллер - с помощью C++Builder (или наоборот).