Большинство действительно полезных компонентов достаточно сложны. Слишком мало предоставить только несколько базовых методов, которые способны вызывать клиенты. Компоненты должны обеспечивать гораздо более разнообразные формы взаимодействия со своими клиентами. Например, почему бы не определить стандартный способ отображения компонентами собственного пользовательского интерфейса? Компонентам может потребоваться и механизм для посылки событий своим клиентам или механизм, позволяющий клиенту читать и изменять свойства компонента. Учитывая, что у многих компонентов будут, вероятно, схожие потребности в плане взаимодействия с клиентами, стоит определить общий способ удовлетворения этих потребностей. Подобные стандарты значительно облегчат жизнь и программному обеспечению, использующему компоненты. Вместо того, чтобы разбираться в особенностях большого числа разных компонентов, такое программное обеспечение могло бы поддерживать единый набор стандартов, которому следуют все компоненты.
Определение стандартов для программных компонентов и является задачей спецификации управляющих элементов ActiveX (ActiveX Controls). Путем установления стандартных интерфейсов, способных поддерживать СОМ-объекты для выполнения определенных действий, спецификация управляющих элементов ActiveX предоставляет общую схему построения мощных компонентов. А так как компонентам нужен способ эффективного взаимодействия с использующим их кодом, то спецификация управляющих элементов ActiveX определяет и правила создания контейнеров управляющих элементов (control containers) — клиентских программ, знающих как работать с этими элементами.
Управляющие элементы ActiveX могут быть весьма сложны. Чтобы понять, что они из себя представляют и как работают, стоит рассмотреть их с точки зрения трех групп: конечных пользователей, разработчиков приложений, которые применяют управляющие элементы ActiveX, и с точки зрения создателей управляющих элементов.
Все чаще и чаще то, что пользователь видит единым целым, на самом деле является контейнером с управляющими элементами ActiveX. Контейнер управляющих элементов подобен контейнеру составных документов OLE, но поддерживает несколько дополнительных интерфейсов для работы с управляющими элементами ActiveX. Каждый управляющий элемент подключен к контейнеру и обычно представляет свой собственный пользовательский интерфейс как внедренный объект, поддерживающий активизацию "на месте". Например, кнопка на экране может быть пользовательским интерфейсом некоего управляющего элемента ActiveX. Щелкая ее и взаимодействуя с исполняющимся в результате кодом, пользователь фактически активизирует элемент управления ActiveX. To, что пользователь видит как одно приложение, представляющее один интегрированный пользовательский интерфейс, на самом деле — контейнер управляющих элементов, полный различных дискретных управляющих элементов ActiveX, каждый из которых выполняет часть общей работы.
Чтобы при создании приложения использовать управляющие элементы, разработчик вначале должен принять решение относительно их контейнера. В числе популярных инструментов создания контейнеров Microsoft Visual Basic и Developer Studio и множество других средств третьих фирм. Кроме того, в качестве контейнера можно использовать средство просмотра WWW, при этом управляющий элемент должен быть встроен в HTML-файл.
Затем следует решить, какие управлющие элементы ActiveX включить для обеспечения предполгаемых функциональных возможностей. В состав Visual Basic и Developer Studio входит множество управляющих элементов, так что программист без труда найдет нужный. Если нет, то проблему решит большой и быстро растущий рынок управляющих элементов ActiveX третьих фирм, где представлена продукция сотен компаний.
Если подходящего управляющего элемента нет ни в Visual Basic, ни на рынке третьих фирм, его можно разработать самостоятельно. Для этого необходима совершенно иная квалификация, чем для создания приложения, использующего управляющий элемент. В среде, где в основе создания программ лежит применение компонентов, более вероятно разделение программистов на две группы: одна сосредоточится на разработке специализированных управляющих элементов ActiveX, а другая займется сборкой из них законченных приложений. Эти две группы — их иногда называют создателями (creators) и сборщиками (assemblers) — выполняют взаимодополняющие функции в разработке программного обеспечения на основе компонентов.
Программисту приложения-контейнера предоставляется комплект управляющих элементов, из которого разработчик может выбирать. Для создания приложения разработчик, выбрав управляющий элемент, задает его местоположение и размеры на бланке (или шаблоне диалогового окна). Tо, что конечный пользователь видит, работая с приложением, определяется управляющими элементами, задействованными программистом при создании этого бланка.
Практически каждый управляющий элемент ActiveX определяет некоторый набор свойств (property). Задавая значения этих свойств, разработчик может изменить цвет управляющего элемента, цвет и толщину рамки вокруг него и т.д.
В дополнение к своим свойствам управляющий элемент обычно определяет набор событий (events). Посылка и прием этих событий осуществляется с помощью механизма на основе СОМ, но как именно это происходит, для разработчика, собирающего данное приложение, значения не имеет.
Обычно контейнеры управляющих элементов позволяют программисту задать действие (в виде кода функции или метода), которое должно быть выполнено в ответ на сообщение, полученное от управляющего элемента. В общем случае контейнер может делать с событием что угодно, в том числе игнорировать его.
Кроме набора поддерживаемых свойств и набора событий, которые он может посылать своему контейнеру, у типичного управляющего элемента есть и методы. Поскольку управляющие элементы ActiveX — это СОМ-объекты, можно предполагать, что у их клиентов — контейнеров управляющих элементов — имеется возможность выдачи запросов. Что именно может запросить контейнер у управляющего элемента, определяется методами, поддерживаемыми последним.
Доступ к методам управляющих элементов ActiveX всегда осуществляется через диспинтерфейсы и IDispatch. С точки зрения разработчика приложения, вызов методов управляющего элемента ActiveX осуществляется точно так же, как и вызов методов диспинтерфейса любого СОМ-объекта. Использование методов управляющих элементов ActiveX не содержит никаких особенностей — процесс тот же, как и для всех СОМ-объектов.
Таким образом, для разработчика приложения три элемента — свойства, события и методы — определяют возможности управляющего элемента ActiveX. Обеспечение их правильной работы — задача создателя управляющего элемента.
Простой управляющий элемент, поддерживающий ограниченный набор возможностей, лучше всего, вероятно, разработать целиком вручную — так можно получить более быстрый и компактный код. Но реализация даже весьма сложного управляющего элемента может оказаться простой, если в распоряжении программиста есть мощный набор инструментов. Например, в состав Microsoft Developer Studio входит Control Development Kit (CDK — набор инструментов для разработки управляющих элементов) и ControlWizard (мастер управляющих элементов), сочетание которых позволяет опытным программистам на C++ разрабатывать управляющие элементы, даже не зная большей части деталей реализации управляющих элементов.
Может показаться, что понять, как работают управляющие элементы, сложно, но эта сложность исчезает при систематическом подходе. Функциональность, определяемая спецификацией управляющих элементов ActiveX, распадается на 4 основных аспекта, для реализации каждого предназначена особая группа интерфейсов:
Количество страниц галереи компонентов и набор компонент зависит от версии Visual C++ и постоянно расширяется. При работе с галереей можно создать собственную категорию, переименовать ее, добавлять или перемещать компоненты из одной категории в другую. В галерею компонентов можно включать компоненты, разработанные другими фирмами, а также собственные компоненты, разработанные самим программистом (в простейшем случае, в качестве таких компонент могут выступать классы созданных приложений). Главное, что любой компонент можно вставить в собственное приложение.
На странице Developer Studio Components расположены компоненты, разработанные фирмой Microsoft. Среди них содержатся много компонент, добавляющих к приложению различные возможности практически без дополнительных затрат со стороны программиста. Среди них - компонент, позволяющих приложениям использовать обменный буфер Clipboard, компонент, выполняющий фоновые работы во время бездействия приложения, компонент, содержащий готовые диалоговые панели для ввода пароля и отображения хода различных процессов и многое другое.
Некоторые компоненты, расположенные на странице компонент Microsoft, дублируют возможности приложения, которыми можно управлять в ходе создания приложения средствами MFC AppWizard. Поэтому, например, если во время начального создания проекта приложения не было указано, что приложение будет работать с сокетами Windows, то вместо кропотливого исправления проекта вручную можно просто добавить в него компонент Windows Sockets.
На странице Registered ActiveX Controls галереи представлены органы управления OCX (OLE Controls), зарегистрированные в реестре Windows. Количество их очень обычно велико, поэтому рассмотрим только некоторые элементы, которые поставляются вместе с Microsoft Visual C++: Grid Control - сетка или таблица, в каждой ячейке которой можно вывести текст или изображение; Microsoft Comm Control - элемент управления, который позволяет обмениваться информацией через последовательный порт; Video Play Control - элемент управления, который позволяет воспроизводить видео, записанное в форматах AVI, MPEG или QuickTime; Anibutton Control - кнопка с рисунком; Microsoft Multimedia Control - набор кнопок для приложений мультимедиа; ASP Arrow (Non Rectangle OLE Control) - кнопки, имеющие нестандартные формы.
При работе с галереей можно создать собственную категорию, переименовать ее, добавлять или перемещать компоненты из одной категории в другую. При удалении компонента из галереи файлы, содержащие его, не удаляются. Их удаление при необходимости проводится вручную
Компонент можно добавить в галерею четырьмя способами:
Первая задача решается остаточно просто. Чтобы проект мог использовать OLE-элементы управления, на шаге работы AppWizard, где речь идет о поддержки OLE, следует включить флажок “OLE controls”. Это же свойство можно добавить и в уже созданный, работающий проект. Для этого в начало работы метода InitInstance() главного класса приложения следует вписать вызов AfxEnableControlContainer(). В файл stdafx.h включить строку #include <afxdisp.h>.
О том как добавлять OCX-объекты в проект приложения, было рассказано в пункте “Вставка компонентов в проект приложения”.
Предположим, что создан проект, допускающий использование OCX-объектов, а в галерее компонентов выбраны подходящие OLE-элементы управления, добавленные в проект. Возникает ряд вопросов: как использовать эти объекты и ведут ли они себя так же, как и обычные элементы управления Windows?
Так как сходств здесь больше, чем отличий, то в большинстве случаев можно полагать, что поведение и технология работы с этими элементами управления такие же, как и для обычных элементов управления.
При проектировании диалогового окна в нем, кроме обычных элементов управления, размещаются и OLE-элементы управления. Для них точно также открывается страница свойств, и на этапе проектирования можно задать нужные значения тех или иных свойств элемента. Средство ClassWizard позволяет связать элемент управления с объектом соответствующего класса (который добавляется в проект при встраивании OCX-элемента), а также создать обработчики сообщений для OLE-элемента управления точно так же как и для обычных элементов управления. Итак, работать с OCX-объектами можно точно так же как и с обычными элементами управления Windows.
Однако в реализации отличия большие. Например, при проектировании OCX-элемента управления для него можно определить свойства, методы и события (events). Свойства и методы - это привычные понятия для объекта, хотя в данном случае видимые в контейнере свойства и методы OCX-объекта создаются не совсем обычным путем (о проектировании OCX-объекта речь будет идти в следующем разделе).
Что касается событий, то в данном контексте речь идет о новом понятии - одной из характеристик OLE-элемента управления. При возникновении некоторой ситуации, чаще всего связанной с действиями пользователя, OCX-объект может “зажечь” событие, вызвав связанную с ним специальную функцию с именем FireNameEvent(), где NameEvent - имя события. Когда объект “зажигает” событие, посылается соответствующее сообщение OLE-контейнеру (содержащему OCX-объект), который может это сообщение обработать. Таким образом, схема взаимодействия получается более сложной: пользователь взаимодействует с OCX-объектом; тот, “зажигая” событие, посылает сообщение контейнеру, который и обрабатывает событие.