Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Роджерсон Д. - Основы COM - 2000.pdf
Скачиваний:
411
Добавлен:
13.08.2013
Размер:
2.4 Mб
Скачать

86

#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE

что раскрывается в

extern “C” HRESULT __stdcall

С помощью программы REGSVR32.EXE эти функции можно вызвать для регистрации компонента. Эта вездесущая утилита, вероятно, уже есть на Вашем компьютере. В примерах программ ряда последующих глав этой книги make-файлы будут вызывать REGSVR32.EXE для регистрации соответствующих компонентов.

Большинство программ установки вызывают DllRegisterServer в процессе своей работы. Для этого нужно просто загрузить DLL с помощью LoadLibrary, получить адрес функции с помощью GetProcAddress и потом, наконец, вызвать функцию.

Реализация DllRegisterServer

Реализация DllRegisterServer — простой код обновления Реестра. Win32 содержит множество функций, добавляющих и удаляющих разделы Реестра. Для регистрации наших компонентов и удаления их из Реестра понадобятся только шесть функций:

RegOpenKeyEx

RegCreateKeyEx

RegSetValueEx

RegEnumKeyEx

RegDeleteKey

RegCloseKey

Об этих функциях много написано в других книгах, поэтому я не собираюсь детально рассматривать их здесь. Чтобы использовать эти функции, включите в Ваш исходный файл WINREG.H и WINDOWS.H и скомпонуйте программу с ADVAPI32.LIB. Увидеть эти функции в действии Вы сможете в файлах REGISTRY.H и REGISTRY.CPP из примера следующей, седьмой главы.

Категории компонентов

Минималистский взгляд на Реестр Windows состоит в том, что это длинный список CLSID, с каждым из которых связано имя файла. Клиент может просмотреть эти CLSID и выбрать подходящий компонент. Но как клиент определяет, какой именно компонент следует использовать? Один из вариантов — вывести список дружественных имен компонентов и предоставить пользователю выбирать. Однако пользователю вряд ли понравится, если, выбрав компонент из длинного списка, он в итоге узнает, что тот не работает. Загружать каждый из компонентов, упомянутых в Реестре, и запрашивать у них необходимые нам интерфейсы — слишком затяжное мероприятие. Надо как-то уметь определять, поддерживает ли компонент нужные интерфейсы, до создания экземпляра этого компонента.

Решение этой проблемы дают категории компонентов (component categories). Категория компонентов — это набор интерфейсов, которым присвоен CLSID, называемый в данном случае CATID. Компоненты, реализующие все интерфейсы некоторой категории, могут зарегистрироваться как члены данной категории. Это позволяет клиентам более осмысленно выбирать компоненты из реестра, рассматривая только те, которые принадлежат к некоторой категории.

Категория компонентов — тоже своего рода договор между компонентом и клиентом. Регистрируя себя в некоторой категории, компонент тем самым гарантирует, что поддерживает все входящие в категорию интерфейсы. Категории могут использоваться для типизации компонентов. Использование категорий аналогично использованию абстрактных базовых классов в С++. Абстрактный базовый класс — это набор функций, которые производный класс обязан реализовать; поэтому можно сказать, что производный класс — конкретная реализация данного абстрактного базового класса. Категория компонентов — набор интерфейсов, которые должны быть реализованы компонентом, чтобы тот относился к данной категории. Компонент, принадлежащий категории, — конкретная реализация данной категории.

Компонент может входить в произвольное число категорий. Компонент не обязан поддерживать исключительно те интерфейсы, которые определены категорией; он может поддерживать любой интерфейс в дополнение к ним.

Одно из применений категорий — задание набора интерфейсов, которые компонент обязан поддерживать. Альтернативой служит задание набора интерфейсов, которые компонент требует от своего клиента. Компоненту для нормальной работы могут потребоваться от клиента некоторые сервисы. Например, трехмерному графическому объекту для работы может потребоваться определенная графическая библиотека (graphic engine).

Соседние файлы в предмете Программирование на C++