Страница 3 из 9 Класс OLE-элемента управления Объявление класса Класс OLE-элемента управления объявлен в файле NameCtl.h и реализуется в файле NameCtl.cpp. Базовый класс элемента управления наследуется от класса COleControl - стандартного базового класса библиотеки MFC, который используется элементами управления OLE. Этот класс, будучи потомком класса CWnd , наследует все функции объекта окна, а также располагает дополнительными, специфическими для OLE функциями, такими как генерация событий и поддержка методов и свойств OLE-элемента управления. В классе COleControl реализованы все интерфейсы, необходимые для работы элемента управления. Он скрывает детали реализации элемента и имеет понятный, объектно-ориентированный интерфейс, который используется элементами управления при выполнении собственных функций. Конструктор и деструктор класса В конструкторе класса CNameCtrl происходит вызов функции InitializeIIDs . Эта функция должна вызываться только в конструкторе элемента управления. Она сообщает базовому классу идентификаторы интерфейсов (IID) элемента управления. В данном случае класс COleControl получает идентификатор базового интерфейса автоматизации и идентификатор интерфейса диспетчеризации. Конструктор класса в своем первоначальном виде ничего не делает, но в него можно по мере необходимости добавить код, очищающий все данные экземпляра элемента управления. Методы класса Класс CNameCtrl переопределяет некоторые методы базового класса: OnDraw, DoPropExchange, OnResetState . Метод OnDraw вызывается операционной системой, когда элемент управления должен быть перерисован. Вызов метода DoPropExchange происходит, когда элемент управления записывается или считывается из постоянного хранилища (с диска). Эта функция отвечает за сохранение (запись на диск) и восстановление (чтение с диска) информации о свойствах элемента и его версии. Вызов метода OnResetState осуществляет система, когда элемент управления должен сбросить свои свойства (установить их в первоначальные значения). Если ранее сохраненный элемент управления не может быть правильно воссоздан в памяти (то есть не могут быть правильно восстановлены значения его свойств), то система дает указание вновь созданному элементу управления (в который помещаются данные, считанные с диска) присвоить своим свойствам значения, имеющие хоть какой-то смысл, т.е. значения по умолчанию. Поддержка элементов управления Объявление класса CNameCtrl включает в себя несколько макросов, обеспечивающих поддержку элементов управления OLE. Макрос DECLARE_OLECREATE_EX (CNameCtrl) объявляет фабрику классов и метод GetClassID для класса элемента управления. Метод GetClassID (объявляемый в этом макросе) вызывается системой, когда ей необходимо получить CLSID элемента. CLSID используется библиотеками OLE для регистрации, создания элемента управления и т.д. Фабрика классов представляет собой OLE-объект, который используется для производства экземпляров других объектов. Фабрики классов элемента управления располагаются внутри OCX-файла, вместе с самим элементом. Библиотека MFC сама обеспечивает реализацию фабрики классов (разработчику не нужно о ней беспокоиться). В основном фабрика классов реализована в базовом классе COleObjectFactoryEx . Фактически конструктор фабрики классов для элемента управления просто передает свои параметры базовому классу, в котором скрыты детали реализации. Рассмотрим подробнее назначение класса COleObjectFactoryEx. Класс COleObjectFactoryEx является синонимом класса COleObjectFactory. Он реализует фабрику классов OLE и содержит методы для: - управления регистрации объектов;
- обновления системного реестра, а также регистрации элемента управления во время выполнения программы (это необходимо для информирования библиотек OLE о том, что объект находится в режиме выполнения и готов к приему сообщений);
- принудительного лицензирования путем задания ограничений на использование элемента зарегистрированными разработчиками (на этапе проектирования) и зарегистрированными приложениями (на этапе выполнения);
- регистрации фабрики классов элемента управления в системном реестре.
Инициализация фабрики классов элемента управления и формирование GUID (CLSID) производятся в файле реализации. Эти действия выполняет макрос IMPLEMENT_OLECREATE_EX . В этом макросе реализуется фабрика классов элемента управления и метод GetClassID. Фабрика классов создает экземпляры элемента управления. Метод GetClassID возвращает CLSID элемента всем, кто его запрашивает, например библиотекам OLE. В объявлении класса присутствует макрос DECLARE_OLETYPELIB (CNameCtrl), который объявляет метод GetTypeLib для класса элемента управления.. Этот макрос должен присутствовать в файле заголовков элемента управления. Метод GetTypeLib элемента управления реализуется макросом IMPLEMENT_OLETYPELIB в файле реализации класса. Библиотека типов представляет собой файл, содержащий информацию о типе элемента управления, его интерфейсах и элементах автоматизации (к ним относятся свойства, методы и события). Сгенерированный метод GetTypeLib вызывается системой, когда ей нужна информация о библиотеке типов элемента. Эти данные сравниваются с данными из системного реестра, и если обнаруживается совпадение, то информация передается системе . Элемент управления OLE использует страницы свойств, чтобы дать пользователю возможность просматривать и изменять свойства элемента управления. Страницы свойств реализуются в виде диалоговых окон с закладками (tabs). В макросе DECLARE_PROPPAGEIDS(CNameCtr l) объявляются идентификаторы и методы, используемые этим механизмом. Макрос DECLARE_OLECTLTYPE (CNameCtrl) объявляет методы, которые обрабатывают информацию о типе элемента и данные флагов MiscStatus. Информация о типе элемента управления записана в переменной типа const с именем _dwNameOleMisc А макрос IMPLEMENT_OLECTLTYPE в реализации класса определяет два метода элемента управления GetUserTypeNameID и GetMiscStatus . Метод GetUserTypeNameID возвращает идентификатор ресурса строки (константа IDS_Name), содержащей имя типа элемента управления. Метод GetMiscStatus вызывается внешними объектами, например контейнером, для получения информации об элементе управления. Значения, записанные в переменной _dwNameOleMisc, генерируются при создании проекта и являются выбором установок проекта. Идентификаторы интерфейсов (IID) автоматизации Строки файла реализации класса, объявляющие IID_Dname и IID_DNameEvents определяют идентификаторы интерфейсов элемента управления. Первый из них идентифицирует реализацию IDispatch - базовый интерфейс диспетчеризации класса. Этот интерфейс используется клиентами автоматизации для редактирования и просмотра элемента управления и выполнения его методов. Второй идентификатор определяет интерфейс диспетчеризации событий класса. Этот интерфейс используется элементом управления для генерации событий. Оба идентификатора хранятся в системном реестре в ключе HKEY_CLASSES_ROOT\Interface. Таблица сообщений класса Класс CNameCtrl c помощью макроса DECLARE_MESSAGE_MAP объявляет привычную уже таблицу сообщений (схему сообщений) класса, при помощи чего сообщает системе, что класс будет обрабатывать сообщения. Сама таблица сообщений объявляется в файле реализации класса. За реализацию технологии OLE-автоматизации, то есть за предоставление внешнему миру методов и свойств элемента, отвечает OLE-интерфейс IDispatch. Библиотека MFC обеспечивает поддержку этой технологии с помощью конструкции под названием “схема диспетчеризации” (dispatch map). Эта схема представляет собой эквивалент знакомой уже схемы сообщений (message map). Подобно тому, как схемы сообщений скрывают детали взаимодействия с каналом сообщений Windows, схемы диспетчеризации скрывают детали OLE-автоматизации. В этой таблице сообщений в файле реализации изначально присутствует только одна строка - макрос ON_OLEVERB(). Этот макрос связывает указанный глагол idsVerbName (сообщение, которое элемент управления будет обрабатывать) с конкретным методом memberFxn элемента управления. Схема диспетчеризации класса В объявлении класса присутствует макрос DECLARE_DISPATCH_MAP , который объявляет схему диспетчеризации. Посредством нее элемент управления связывает свои свойства с соответствующими методами записи, чтения и оповещения (последние вызываются при изменении значения свойства). Дополнительно устанавливается связь между идентификаторами диспетчеризации (DISPID) и фактическими методами. Сначала схема диспетчеризации в файле реализации имеет одну запись, сделанную при помощи макроса DISP_FUNCTION_ID , который связывает между собой следующие элементы: имя класса; внешнее имя метода; идентификатор (DISPID) метода; метод C++, соответствующий вызову метода автоматизации; список параметров метода (тип VARIANT); тип значения, возвращаемого методом (тип VARIANT). Эта информация необходима системе для того, чтобы направлять вызовы методов автоматизации по правильному пути. Когда контроллер автоматизации вызывает метод при помощи его внешнего имени, такой вызов преобразуется в вызов внутренней функции элемента управления. В основе этого механизма лежит DISPID. Каждому объявленному свойству или методу должен соответствовать свой макрос в схеме диспетчеризации класса. Схема диспетчеризации событий класса В объявлении класса макрос DECLARE_EVENT_MAP , который объявляет схему событий (event map). Подобно тому, как доступ к свойствам и методам элемента управления осуществляется с помощью схемы диспетчеризации, доступ к событиям элемента осуществляется посредством схемы событий. В ней имена и идентификаторы событий связываются с функциями, ответственными за генерацию событий. На этапе проектирования у элемента нет событий по умолчанию, поэтому этот схема событий в файле реализации пуста. Идентификаторы DISPID Различные идентификаторы свойств, методов и событий (DISPID) располагаются между макросами AFX_DISP_ID. Эти идентификаторы используются в ODL-файле элемента управления. По мере добавления в элемент свойств, методов и событий этот раздел будет заполняться средством ClassWizard. |