Загадочные
макросы
Вернемся в
файл ATLGLcpp, где кроме функций, перечисленных выше, присутствуют загадочные
макросы. Их смысл довольно прозрачен, но разработчика не должны устраивать догадки,
ему нужны более точные знания. Сопровождающая документация, особенно бета-версий,
не всегда дает нужные объяснения, поэтому приходится искать их самостоятельно
в заголовочных файлах, расположенных по адресу: ...\Microsoft Visual Studio.Net\Vc7\indude
или ...\Microsoft Visual Studio.Net\ Vc7\atlmfc\include.
Покажем, как
это делается на примере. Нас интересует смысл функциеподобной макроподстановки:
DECLARE_LIBID(LIBID_ATLGLLib)
В результате
поиска в файлах по указанному пути (маска поиска должна быть *.h) находим (в
файле ATLBase.h), что при разворачивании препроцессором этот макрос превратится
в статическую функцию класса CATLGLModule:
static
void InitLibldO
throw ()
{
CAtlModule::m_libid
= LIBID_ATLGLLib;
}
Теперь возникает
желание узнать, что кроется за идентификатором LiBiD_ATLGLLib. Во вновь созданном
коде файла ATLGM.c находим макрос:
MIDL_DEFINE_GUID(IID,
LIBID_ATLGLLib,ОхЕбОбОЗВС,Ox9DE2,
0x4563,
OxA7,0xAF,Ox8A,Ox8C,Ox4E,0x80,0x40,0x58);
узнав смысл
которого мы сможем понять, чем является LiBiD_ATLGLLib. В вашем проекте цифры
будут другими, но я привожу здесь те, которые вижу сейчас, для того чтобы быть
более конкретным и не загружать вас абстракциями, которых и так хватает. В этом
случае поиск не нужен, так как объявление макроса расположено двумя строчками
выше. Вот оно:
#define
MIDL_DEFINE_GUID(type,name,1,wl,w2,bl,b2,b3,Ь4,
\ Ь5,Ьб,b7,b8)
const
type name = \ {I,wl,w2, {b1,b2,bЗ,b4,b5,b6,b7,b8}
}
Подставив значения
параметров из предыдущего макроса, получим определение LiBiD_ATLGLLib, которое
увидит компилятор:
const
IID LIBID_ATLGLLib
=
{
0xE60605BC,
0x9DE2, 0x4563,
{
0xA7,0xAF,0x8A, 0x8C,Ox4E, 0x80, 0x40, 0x58 }
}
Отсюда ясно,
что LIВID_АТLGLLib — это константная структура типа IID. Осталось узнать, как
определен тип данных II D.
В хорошо знакомом
файле afxwin.h находим определение typedef GUID IID;. Про Globally Unique Identifier
(GUID) сказано очень много, в том числе и в документации Studio.Net. Как мы
только что выяснили, изучив работу макросов и LiBio_ATLGLLib, тип IID также
используется для идентификации библиотек типов. Система применяет два типа GUID:
строковый в реестре, и числовой в клиентских приложениях. Второй макрос, который
вы видели в классе
CATLGLModule:
DECLARE_REGISTRY_APPID_RESOURCEID(IDR_ATLGL,
"{E4541023-7425-4AA7-998C-D016DF796716}")
(цифры мои,
ваши будут другими) создает строковый GUID. При расширении он превратится в
три статические функции класса, две из которых готовят текстовую строку того
или иного типа, а третья регистрирует, в случае если bRegister==TRUE, или убирает
из реестра эту строку по адресу HKEY_CLASSES_ROOT\APPID\:
static
LPCOLESTR GetAppId
()
throw ()
{
//======
Преобразование к формату OLE-строки
return
OLESTR("{E4541023-7425-4AA7-998C-D016DF796716}")
;
}
static
TCHAR* GetAppIdTO
throw ()
{
//======
Преобразование к Unicode или char* строке
return
_T("{E4541023-7425-4AA7-998C-D016DF796716}") ;
}
//
Если bRegister==TRUE, то происходит запись в реестр,
//
иначе - удаление записи
static
HRESULT WINAPI UpdateRegistryAppId(BOOL bRegister)
throw()
{
_ATL_REGMAP_ENTRY
aMapEntries [] =
{
{
OLESTRC'APPID") , GetAppIdO }, { NULL, NULL }
};
return
ATL::_pAtlModule->UpdateRegistryFromResource( IDR ATLGL, bRegister, aMapEntries);
В данный момент
вы сможете найти в реестре свой ключ и ассоциированную с ним строку (ATLGL)
по адресу:
HKEY_CLASSES_ROOT\AppID\
{E4541023-7425-4AA7-998C-D016DF796716}
При запуске
приложения вышеописанные функции были вызваны каркасом приложения и произвели
записи в реестр. Отметьте также, что в реестре появилась еще одна (симметричная)
запись по адресу HKEY_CLASSES_ROOT \APPID\ATLGL.DLL. Она ассоциирует строковый
GUID с библиотекой ATLGL.DLL. Рассматриваемая строка-идентификатор встречается
еще в нескольких разделах проекта, найдите их, чтобы получить ориентировку:
в ресурсе "REGISTRY" > IDR_ATLGL (см. окно Resource View) и в файле сценария
регистрации ATL.GL.rgs (см. окно Solution Explorer).
Возвращаясь
к первому макросу DECLARE_LIBID(LiBiojvTLGLLib), отметим, что скрытая за ним
функция initLibid тоже была вызвана каркасом и использована для регистрации
библиотеки типов будущего СОМ-объекта. Вы можете найти эту, значительно более
подробную, запись по ключу (цифры мои):
HKEY_CLASSES_ROOT\TypeLib\
{E60605BC-9DE2-4563-A7AF-8A8C4E804058}