Визуальное программирование и MFC

       

Главный класс модуля OCX-объекта


Объявление класса

Файл Name.h является основным файлом заголовков для элемента управления Name Control, в нем объявляется класс CNameApp. Этот класс является потомком класса COleControlModule, а не класса CWinApp. Это справедливо обычно для всех элементов управления, построенных на основе MFC.

Класс же COleControlModule библиотеки MFC в свою очередь просто является производным от класса CWinApp, в котором для удобства переопределены методы InitInstance и ExitInstance.

Методы класса

Файл Name.cpp - это основной исходный файл для элемента управления Name Control. Функциями этого файла являются: регистрация элемента управления; обеспечение инициализации элемента управления; удаление регистрации элемента управления, когда он больше не нужен.

В этом файле происходит создание глобального объекта класса CNameApp, порожденного от класса ColeControlModule. В проекте может быть только один объект приложения, т.е. один объект класса, порожденного от COleControlModule.

MFC ActiveX ControlWizard сгенерировал GUID (уникальный идентификатор) для библиотеки типов элемента управления с именем _tlid и принял, что старший номер версии библиотеки равен 1, а младший номер – 0. Эта информация будет записана в реестр во время выполнения макроса INPLEMENT_OLETYPELIB, находящего в NameCtl.cpp.

Файл Name.cpp содержит реализацию методов класса CNameApp. Метод InitInstance отвечает за инициализацию DLL-файла: Он вызывается системой при первой загрузке элемента управления в память. Также этот метод вызывается при создании каждого экземпляра Name Control. В этом методе можно выполнить собственные методы инициализации, однако необходимо всегда в первую очередь вызвать метод InitInstance базового класса COleControlModule.

Метод ExitInstance вызывается непосредственно перед тем, как элемент управления выгружается из памяти, и очищает память, освобождает дескрипторы, удаляет GDI-объекты и т.д:

Регистрация элемента управления



В файле Name.cpp кроме методов класса CNameApp определены две функции: DllRegisterServer (заносит данные в системный реестр) и DllUnregisterServer (удаляет данные из системного реестра):


Элементы управления OLE являются саморегистрирующимися. Это означает, что они способны записывать информацию о себе в системный реестр Windows. Им не нужны ни файлы регистрации (имеющие расширение reg), ни какой-либо другой внешний механизм.

Функция DllRegisterServer реализована во всех OLE-элементах управления. Она представляет собой экспортируемую функцию, которая служит точкой входа при регистрации элемента. Это глобальная функция, вызов которой осуществляют внешние функции или приложения.

При вызове функция DllRegisterServer выполняет следующие действия. Сначала она регистрирует библиотеку типов элемента управления посредством вызова функции AfxOleRegisterTypeLib. (Этот этап включает создание и обновление параметров элемента управления в ключе HKEY_CLASSES_ROOT\TypeLib. Исходный файл библиотеки типов автоматически генерируется MFC ActiveX ControlWizard. В нем описываются свойства, методы, события элемента управления и специфическая для данного класса информация). Затем функция DllRegisterServer регистрирует все фабрики классов данного приложения в системном реестре посредством метода COleObjectFactoryEx::UpdateRegistryAll. ( Фабрика классов представляет собой COM-объект, реализующий интерфейс IClassFactory и отвечающий за производство COM-серверов заданного типа (CLSID). Библиотеки OLE не могут создавать серверы без участия фабрики классов. Понятие фабрики классов рассматривается при исследовании файла NameCtl.cpp.)

При компиляции элемента управления с использованием Microsoft Developer Studio последнее, что делает программа, - это вызывает функцию DllRegisterServer, что приводит к автоматической регистрации элемента управления на данной машине. Если необходимо инсталлировать элемент управления на другой машине, нужно каким-то образом вызвать его функцию DllRegisterServer. Обычно это делает регистрационная программа, которую необходимо предоставить. Зарегистрировать OCX-объект можно и при помощи утилиты regsvr32.exe, которая обычно находится в каталоге C:\WINDOWS\SYSTEM.



Функция DllUnregisterServer является дополнением к функции DllRegisterServer. Элементы управления OLE самостоятельно удаляют свою регистрацию. Это значит, что библиотека типов, фабрика классов и информация об элементе может быть автоматически удалена из системного реестра. Функция DllUnregisterServer не вызывается автоматически из Developer Studio. Ее должны вызывать исключительно внешние функции или приложения, которые хотят полностью удалить элемент из системы. Например, эту функцию могла бы вызвать программа деинсталляции.



Макрос AFX_MANAGE_STATE(p)



Макрос AFX_MANAGE_STATE встречается в функциях DllRegisterServer и DllUnregisterServer. Этот макрос необходим некоторым методам управления OLE для выполнения переключения состояния модуля.

Для начала уточним понятие “состояние модуля”. Во время выполнения MFC-программы библиотека хранит информацию о состоянии приложения. Эта информация включает дескрипторы окон, таблицы связей дескрипторов и MFC-объектов и др. Если выполняется только базовый модуль (DLL-файлы не подгружаются), то может существовать лишь один набор данных о состоянии.

Однако при подключении DLL-файлов, использующих библиотеку MFC (как в случае элементов управления OLE), могут возникать проблемы. Каждый элемент управления сохраняет свою информацию о состоянии. Когда поток выполнения “входит” в элемент управления, последний должен сообщить MFC о том, что наступила его очередь выполняться и следует изменить указатель на набор данных о состоянии так, чтобы он указывал на набор данных элемента управления. Элемент управления делает это с помощью макроса AFX_MANAGE_STATE. Такая переадресация должна происходить во всех точках входа в DLL, то есть во всех функциях, экспортируемых библиотекой, поскольку именно там она получает управление.

Поскольку все элементы управления OLE экспортируют функции DllRegisterServer и DllUnregisterServer, тоне удивительно, что первым оператором в теле обеих функций является макрос AFX_MANAGE_STATE. Если не выполнить изменение состояния, результат работы программы может быть непредсказуемым.Наличие такого макроса в функциях, которые не экспортируются, необязательно.


Содержание раздела