2. Использование OLE-документов в приложениях C++BuilderПоследняя из спецификаций COM, рассматриваемая в данном цикле статей, — OLE-документы. Это составные документы, содержащие внедренные или связанные объекты, созданные другими приложениями, выступающими в этом случае в качестве OLE-серверов. Данная спецификация описывает правила создания контейнеров для таких документов с "активацией по месту". Для создания и использования в приложениях таких внедренных или связанных объектов предназначен компонент TOleContainer. |
2.1 Создание OLE-объектовКомпонент TOleContainer позволяет поместить OLE-объект на поверхности формы. Основные свойства этого компонента: AutoActivate — определяет, каким образом активизируется OLE-объект, OleClassName — имя класса OLE-объекта, содержащегося в контейнере. Основные методы: InsertObjectDialog — выводит стандартную диалоговую панель Object для выбора типа объекта или загрузки его из файла, CreateObject — создает OLE-объект, DestroyObject — уничтожает объект. Создадим простейший пример использования OleContainer. С этой целью поместим на форму компонент TPanel со свойством Align, равным alClient, на него — компонент TOleContainer, кнопку и главное меню (можно создать в нем один пункт). Панель и меню нужны для отображения инструментальных панелей и меню OLE-серверов, обслуживающих отображаемые в TOleContainer объекты.
Рис.7. Форма с TOleContainer Создадим обработчик события, связанный с нажатием на кнопку: void __fastcall TForm1::Button1Click(TObject *Sender) { OleContainer1->InsertObjectDialog(); } Запустив приложение и нажав на кнопку, получим диалог для вставки объекта:
Рис.8. Диалог вставки объекта В списке перечислены все OLE-серверы, зарегистрированные на данном компьютере. Можно выбрать один из них (например, документ Word). Теперь после двойного щелчка на объекте TOleContainer получим на компоненте TPanel инструментальную панель MS Word, главное меню и сам документ.
Рис.9. Активный объект в OleContainer Если тип объекта, включаемого в TOleContainer, известен заранее, можно использовать метод CreateObject: void __fastcall TForm1::Button1Click(TObject *Sender) { OleContainer1->CreateObject("Word.Document",True); } Второй параметр этого метода указывает, отображать ли объект внутри OleContainer в виде пиктограммы. Модифицируем приложение, добавив еще две кнопки с надписями "Свойства" и "Вставка", и создадим соответствующие обработчики событий: void __fastcall TForm1::Button2Click(TObject *Sender) { OleContainer1->ObjectPropertiesDialog(); } //-------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { OleContainer1->PasteSpecialDialog(); } Скомпилируем приложение. Добавим какой-нибудь объект в OLEContainer. Нажав на кнопку "Свойства", получим стандартный диалог с описанием свойств объекта.
Рис.10. Диалог с описанием свойств объекта Нажав кнопку "Вставить", получим диалог вставки объекта:
Рис.11. Диалог специальной вставки Выбрав тип вставки объекта, можем вставить его в OLEContainer: |
2.2 Хранение OLE-объектов в базах данныхДля хранения OLE-объектов могут быть использованы как поля специальных типов (поддерживаемые, например, Paradox или dBase)., так и обычные blob-поля. Основная идея такого приложения заключается в том, что OleContainer позволяет сохранить содержащийся в нем объект в файле или в памяти, а затем поместить его в blob-поле. Модифицируем созданное приложение, добавив компоненты TTable, TdataSource и TDBNavigator и заменив надписи на кнопках на "Сохранить" и "Показать". Создадим копию таблицы biolife.db из набора демонстрационных примеров, свяжем с ней компонент TTable и создадим набор объектов TFields. Свяжем TDataSource c TTable и TDBNavigator с TDataSource. Изменим обработчики событий: void __fastcall TForm1::Button2Click(TObject *Sender) { if (OleContainer1->OleObjectInterface!=NULL)// определим, не пуст ли контейнер {OleContainer1->SaveToFile("aaa.dat"); Table1->Edit(); Table1Graphic->LoadFromFile("aaa.dat");} } //----------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { Table1Graphic->SaveToFile("aaa.dat"); OleContainer1->LoadFromFile("aaa.dat"); } Теперь, если TOleContainer не пуст, при нажатии на кнопку "Сохранить" его содержимое сохранится в blob-поле таблицы, а при нажатии на кнопку "Показать" OLE-объект из blob-поля отобразится в TOleContainer.
Рис.12. Неактивный OLE-объект, изъятый из blob-поля при нажатии на кнопку "Показать" |
2.3 Использование свойств OleContainerКак определить характеристики OLE-объекта, помещенного в OleContainer, и управлять им? Имя класса OLE-объекта можно получить с помощью свойства OleClassName. Список доступных команд доступен с помощью свойства ObjectVerbs. Метод DoVerb позволяет вызвать одну из этих команд, ссылаясь на ее порядковый номер в спискe. Целочисленное свойство PrimaryVerb содержит номер команды из этого списка, выполняющейся при активации OLE-объекта. Состояние контейнера можно определить с помощью свойства State. Для иллюстрации их работы на панель с OleContainer поместим компоненты TComboBox и TEdit и изменим обработчики событий: void __fastcall TForm1::Button1Click(TObject *Sender) { OleContainer1->CreateObject("Word.Document",True); Edit1->Text=OleContainer1->OleClassName; ComboBox1->Items=OleContainer1->ObjectVerbs; } //--------------------------------------------------------------------------- void __fastcall TForm1::ComboBox1Click(TObject *Sender) { if (OleContainer1->State!=osEmpty) OleContainer1->DoVerb(ComboBox1->ItemIndex); } //---------------------------------------------------------------------------
Рис.13 Пример использования свойств TOleContainer |
2.4 Вместо заключенияЭтой статьей заканчивается цикл, посвященный использованию COM-технологии в C++Builder. Мы рассмотрели создание различных типов COM-серверов и COM-клиентов (элементы управления ActiveX и содержащие их контейнеры, серверы и контроллеры автоматизации, OLE-документы и OLE-контейнеры) и наиболее типичные примеры их использования. Хотелось бы обратить внимание на то, что COM реализует концепции объектно-ориентированного подхода и повторного использования кода не на уровне наследования реализации классов внутри одного приложения, как при традиционном использовании C++, а на уровне разных приложений и операционной системы. Это позволяет создавать "классы" объектов, предоставляющих различные сервисы другим приложениям и самой операционной системе, с помощью довольно широкого спектра средств разработки. Отметим, однако, что, помимо COM, существуют и другие технологии, позволяющие создавать и использовать объекты, предоставляющие сервисы другим приложениям. В общем случае, например, при использовании технологии CORBA(Common Object Request Broker Architecture) или DCE (Distributed Computing Environment) такие объекты могут функционировать не только под управлением празличных версий Windows, как в случае COM, но и под управлением других операционных систем, что позволяет повторно использовать код не только на уровне операционной системы, но и на уровне всей сети, реализуя тем самым распределенную обработку данных. Но это тема уже другого цикла статей... |