кие команды, как Edit и Play. Когда пользователь выбирает объект в составном доку-
менте, приложение-клиент читает список команд для данного класса объектов и
помещает соответствующие опции в меню. Пользователь манипулирует объектом, вы-
полняя его команды. Различные объекты откликаются на разные команды.
Добавление объекта в документ-контейнер - это очень простой процесс. Из прило-
жения-клиента пользователь выбирает тип вставляемого объекта. Например, в поле спи-
ска пользователю может предлагаться выбор изображения, электронной таблицы, видео-
клипа и т.д. Этот список изменяется в зависимости от доступных серверов.
Предположим, вы работаете в Microsoft Word и решили внедрить в свой документ
графическое изображение. Для этого запускается программа Paint - зарегистрированный
сервер растровых изображений. Затем открывается BMP-файл, выбирается необходимая
часть рисунка и копируется в буфер обмена. В Microsoft Word открывается файл доку-
мента и вызывается меню Edit. В этом меню можно выбрать одну из трех команд: Paste,
Paste Link и Paste Special. Все три команды предназначены для вставки графического
изображения в текстовый файл. Простейшая команда Paste осуществляет внедрение
объекта. (Если бы программа Paint не поддерживала механизм OLE, команда Paste про-
сто скопировала бы объект, а не внедрила его.)
В составной документ можно также внедрять AVI- или WAV-файлы (видео- и зву-
ковые вставки). Но каким образом внедренный видеоклип или звуковая вставка отобра-
жаются на экране? В таких случаях приложение создает специальное графическое пред-
ставление, называемое пакетом.
Пакет представляет собой значок, который указывает положение OLE-объекта в
документе. При двойном щелчке на этом значке система определяет, какой тип данных
содержится в пакете, и выполняет соответствующую команду.
Для некоторых типов данных, таких как AVI- или WAV-файлы, представление
данных на экране имеет смысл только в виде пакета. По умолчанию значок пакета пере-
дается из программы, в которой были созданы соответствующие данные.
Когда объект попадает в документ, клиент обеспечивает способы его активизации.
Обычно активизация осуществляется двойным щелчком на объекте или его значке.
Так, например, при редактирования изображения в документе Microsoft Word.
OLE-библиотеки обеспечивают непосредственное (т.е. непосредственно в составном до-
кументе) редактирование изображения с помощью программы Paint. Для этого в меню
Edit появляется подменю Bitmap Image Object с тремя командами: Edit, Open и Con-
vert, которые передаются программой Paint. Для редактирования изображения с помо-
щью программы Paint вызывается команда Edit, являющаяся основной командой. При
этом в окне Word появляются меню, палитра и панели инструментов программы Paint,
что позволяет редактировать изображение, не покидая документа. При выборе команды
Open происходит открытие программы Paint, в которую загружается внедренный доку-
мент. Внесенные изменения отобразятся в документе Word при выходе из программы
Paint, что послужит сигналом для обновления составного документа.
Составные документы можно передавать от одного пользователя к другому и чи-
тать на разных компьютерах с помощью одной и той же программы. Если в новой сис-
теме отсутствуют некоторые серверы, объекты все равно отображаются правильно, по-
скольку OLE-библиотеки самостоятельно обрабатывают стандартные форматы буфера
обмена, например растровые изображения или метафайлы. Однако активизировать объ-
екты без вызова сервера невозможно. Например, вы ничего не сможете сделать с WAV-
пакетами без программы-проигрывателя.
Может показаться, что два разных механизма встраивания накладывают противо-
речивые требования на объекты данных. Чтобы объект отображался в любом приложе-
нии, независимо от присутствия в системе исходной программы-сервера, объект должен
содержать данные в некоем общем, легко распознаваемом формате, например в формате
метафайла или растрового изображения.
С другой стороны, механизм OLE позволяет пользователю продолжить редактиро-
вание объекта даже после того, как объект вставлен в новый документ. Чтобы сервер
мог редактировать объекты, они должны содержать данные в том формате, который ис-
пользуется для внутреннего представления объектов на сервере. Например, Excel не
сможет продолжить редактирование ячеек электронной таблицы, которые были преоб-
разованы в формат метафайла, но мало какая из программ-клиентов будет понимать
внутренний формат данных Excel так хорошо, что отобразит электронную таблицу в
системе, где Excel не установлен.
Решение этой проблемы заключается в предоставлении двух экземпляров данных
для каждого OLE-объекта. Чуть позже вы увидите, как эта задача реализуется средства-
ми сервера, но вкратце можно сказать, что почти каждый OLE-объект содержит данные
в собственном (платформно-зависимом) формате, в том виде, в котором эти данные бы-
ли созданы сервером, а также в одном из нескольких стандартных форматовпредстав-
ления - обычно в виде метафайла, - которые могут отображаться любыми программами-
клиентами.
Технология OLE организована с помощью функций высокого уровня, реализую-
щих низкоуровневые процессы совместного использования данных. OLE-функции раз-
мещены в трех DLL-модулях. Библиотека OleCli32.DLL содержит все функции, которые
используются OLE-клиентами, а библиотека OleSvr32.DLL содержит все функции, ко-
торые используются OLE-серверами. В технологии OLE 1.0 эти библиотеки обменива-
ются данными и командами с помощью DDE-сообщений. Третья библиотека,
Shell32.DLL, поддерживает базу данных серверов и типов данных и обеспечивает пра-
вильную обработку OLE-запросов.
OLE-приложения взаимодействуют друг с другом с помощью функций OLE-
библиотек. Например, если клиент хочет отредактировать изображение, он передает за-
прос библиотеке OleCli32.DLL. Та направляет его библиотеке OleSvr32.DLL. Последняя
находит сервер и передает ему команду начать сеанс редактирования. Когда пользова-
тель активизирует объект, библиотека OleSvr32 должна определить, какое приложение-
сервер соответствует указанному формату данных. Для поиска соответствующего серве-
ра OleSvr32 консультируется с библиотекой Shell32. Функции библиотеки Shell32
управляют системным реестром, в котором для каждого приложения записаны соответ-
ствующие форматы данных. При инициализации серверы вносят в системный реестр
свое имя и другую информацию.
После выполнения операции библиотека OleSvr32 передает результаты назад
библиотеке OleCli32, а та возвращает их клиенту. Схема взаимодействия клиента и сер-
вера с помощью OLE-библиотек изображена на рис.8.5 [12].
Рис.8.5. Взаимодействие клиента и сервера с помощью трех OLE-библиотек
Подобно DDEML, OLE-библиотеки используют в своей работе протокол DDE.
OLE-команды посылают DDE-сообщения. Базовые DDE-процессы выполняются неза-
метно для OLE-приложения. Поскольку Microsoft разрабатывала технологии DDEML и
OLE параллельно, они не опираются друг на друга.
Как уже упоминалось выше, при инсталляции или при первом запуске OLE-сервер
регистрируется в системном реестре. Среди прочего регистрируются имя и местополо-
жение сервера, а также типы предоставляемых им услуг.
В свою очередь, OLE-клиент может найти в реестре необходимый ему сервер и ус-
лугу. Непосредственный доступ к реестру обеспечивается с помощью редактора реестра
(файл RegEdit.EXE или RegEdit32.EXE в папке \WINDOWS или \WINDOWS\SYSTEM).
В качестве примера на рис.8.6 показано окно редактора реестра после выполнения
функции Find из меню Edit для нахождения информации о приложении Excel. В реестре
имеется несколько записей для Excel, но одна их них представляет для нас особый инте-
рес. Это идентификатор класса. Он находится в разделе HKEY_CLASSES_ROOT\CLSID
и выглядит следующим образом: 00020810-0000-0000-С0000-000000000046. Как и для
большинства остальных записей, эту информацию можно также найти в разделе
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID и в некоторых других разделах.
Как видно на рис.8.6, в реестр помещена информация о формате данных, опциях преоб-
разования, стандартном расширении и значке, программном идентификаторе, а также об
OLE-командах, которые поддерживаются соответствующим OLE-сервером.
Рис.8.6. Окно редактора реестра с информацией о программе Excel
В большинстве случаев нет необходимости в прямом доступе к реестру. Существу-
ет много механизмов, обеспечивающих безопасный (хотя и ограниченный) косвенный
доступ к информации, записанной в реестре. Один из них, а именно класс COleInsertDia-
log, будет рассмотрен ниже.
Среда разработки Visual C++ содержит утилиту OLE View, которая предоставляет
альтернативный способ просмотра информации об OLE-приложениях.
Прежде чем OLE-клиент сможет воспользоваться услугами сервера, он должен вы-
брать сам сервер. Способ выбора сервера зависит от конкретной программной реализа-
ции. Например, в продуктах MS Offise в качестве OLE-серверов автоматически исполь-
зуются продукты, зарегистрированные для данного приложения в Windows. В других
программах используются специальные настройки меню.
Полнофункциональные серверные приложения регистрируют себя автоматически
при первом запуске. Если приложение было создано с помощью библиотеки MFC и мас-
тера AppWizard, сервер автоматически регистрируется в процедуре InitInstance при вы-
полнении метода COleTemplateServer::RegisterAll.
Для мини-серверов, которые не могут запускаться в виде независимых программ,
необходимо применять иной подход. Мастер AppWizard обеспечивает регистрацию ми-
ни-сервера путем создания REG-сценария для серверного приложения.
Обычно при инсталляции приложения утилита Setup выполняет REG-сценарий. В
процессе разработки можно выполнить этот сценарий непосредственно с помощью ре-
дактора реестра. Для этого в меню Registry редактора реестра выберите команду Import
Registry File, которая открывает диалоговое окно выбора файла. Выберите REG-
сценарий для регистрации приложения.
8.5.2. Технологии разработки OLE-приложения
Раньше создание OLE-приложений было сложным и запутанным процессом, тре-
бовавшим написания сотен строк программного кода для реализации только лишь самых
элементарных клиентских операций. С помощью библиотеки MFC и мастера AppWizard
(или его эквивалента в других компиляторах) процесс создания OLE-клиентов становит-
ся почти тривиальной задачей. Кроме того, эти же инструменты позволяют создавать
несложные OLE-серверы.
Разработка OLE-клиента. На третьем этапе формирования заготовки программы-
клиента с помощью мастера AppWizard вам будет предоставлена возможность включить
в приложение поддержку составных документов, как показано на рис.8.7. (На первом
этапе процесса работы с мастером вы должны выбрать поддержку многодокументного
интерфейса.) По умолчанию установлена опция None. Для реализации OLE-клиента
нужно выбрать опцию Container.
Рис.8.7. Реализация OLE-клиента
При создании OLE-клиента следует учитывать одно ограничение. Не задавайте для
программы названий "OLE Client" или "OLEClient" (допускается имя "OLE_Client" с
символом подчеркивания). Применение любого из указанных имен приводит к созданию
класса COleClientDoc в качестве класса приложения, что вызывает конфликт с одно-
именным стандартным классом библиотеки, необходимым для поддержки OLE-
клиентов.
По завершении работы мастера AppWizard библиотека MFC создает приложение с
многодокументным интерфейсом, в котором содержится дополнительный класс, реали-
зующий поведение OLE-контейнера: COle_ClientCntrItem.
Теперь OLE-клиент полностью готов к компиляции, компоновке и запуску. Еще
более важно то, что программа готова к работе без дополнительных мер по обеспечению
поддержки технологии OLE. Это совсем не мало, учитывая сложность процесса созда-
ния OLE-клиента "с нуля". Если приказать мастеру AppWizard обеспечить поддержку
OLE-клиента, он создаст класс COle_ClientView.
Разработка OLE-сервера. Библиотека MFC и мастер AppWizard позволяют созда-
вать не только клиентские, но и серверные OLE-приложения (мини-серверы и полные
серверы).
OLE-серверы создаются на основе трех базовых классов. Классы COleServerDoc и
COleServerItem применяются всеми серверными приложениями. Класс COleTemplate-
Server используется полнофункциональными серверными приложениями.
Наиболее распространенным и вместе с тем простейшим в реализации типом OLE-
серверов являются SDI-серверы (серверы однодокументного интерфейса). В каждом
SDI-сервере имеется один объект сервера и один объект документа. В ответ на каждый
запрос клиента запускается новый экземпляр сервера. Поскольку мини-серверы не под-
держивают многократных соединений, мини-сервер SDI содержит только один рабочий
объект. В отличие от мини-сервера, полное серверное приложение создает несколько
объектов, когда несколько клиентов устанавливают связь с одним и тем же документом.
MDI-серверы (серверы многодокументного интерфейса) используются в том случае, ко-
гда загружать несколько экземпляров сервера нерационально или когда полное сервер-
ное приложение имеет многодокументный интерфейс. К MDI-серверам с несколькими
экземплярами относятся такие приложения, как Excel и Quattro Pro, которые позволяют
работать как с диаграммами (графическими объектами), так и с электронными таблица-
ми. Каждый серверный класс содержит только один класс документа, а каждый объект
сервера содержит только один объект документа. Каждый документ может предоставить
несколько объектов, а каждый класс документа может поддерживать несколько классов
объектов.
Для создания OLE-сервера на третьем этапе процесса работы с мастером
AppWizard можно выбрать между созданием мини-сервера, полного сервера или прило-
жения клиент/сервер (рис.8.8).
С точки зрения поддержки технологии OLE, создание мини-сервера и полного сер-
вера выглядит совершенно одинаково. Но в процессе разработки гораздо проще тести-
ровать полный сервер, поскольку он может работать в автономном режиме. При созда-
нии комбинированного клиент-серверного приложения происходит автоматическое
создание полного сервера, а не мини-сервера, поскольку клиентская часть "настаивает"
на работе приложения в автономном режиме (мини-сервер не может выступать в роли
клиента, не имея пользовательского интерфейса).
Рис.8.8. Реализация полного сервера
Сформировав заготовку программы, мастер AppWizard, в дополнение к классам
приложения, главного окна, окна документа и окна просмотра, включает в приложение
класс окна редактирования CInPlaceFrame и класс сервера CxxxSrvrItem, который явля-
ется производным от COleServerItem.