class ATL_NO_VTABLE CSay :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CSay, &CLSID_Say>,
public ISay
{
public:
CSay() { }
DECLARE_REGISTRY_RESOURCEID(IDR_SAY)
DECLARE_NOT_AGGREGATABLE(CSay)
BEGIN_COM_MAP(CSay)
COM_INTERFACE_ENTRY(ISay)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease(){ }
public:
};
Первые два класса предоставил мастер библиотеки ATL. Шаблон классов CComObjectRootEx кроит родительский класс по образцу и подобию класса CComSingleThreadModel. От него CSay автоматически наследует реализацию методов IUnknown. Второй класс (CComCoClass) реализует функциональность IClassFactory. Кроме того, по умолчанию он объявляет всему миру, что в класс CSay может быть вложен (агрегирован) какой-то другой ко-класс. Но наличие макроса DECLARE_NOT_AGGREGATABLE опровергает эту установку. Он говорит о том, что в наш объект нельзя агрегировать другие ко-классы.
Далее следует пустое тело конструктора. Здесь уместно наполнить его кодом инициализации строки текста, которую выводит наш тестовый сервер:
CoSay() { m_word = "Hi, there. This is ATL test speaking"; }
Для того, чтобы присвоение имело смысл, введите в состав CoSay новый элемент private-данных:
private: CComBSTR m_word;
Новый для вас класс CComBSTR, хоть и не такой мощный как CString в MFC, но все же здорово упрощает жизнь в рамках ATL. Возвращаясь к анализу класса CSay, отметим, что макросы, которые вы видите после конструктора, работают примерно по тому же принципу, что и в MFC-классах. Например, COM-карта содержит список всех интерфейсов, поддерживаемых классом. Мы экспонируем лишь один. Именно здесь происходит связывание интерфейса ISay с его предком IUnknown. Если из списка:
BEGIN_COM_MAP(CSay)
COM_INTERFACE_ENTRY(ISay)
END_COM_MAP()
убрать COM_INTERFACE_ENTRY(ISay), то клиент не сможет получить адрес интерфейса ISay с помощью метода QueryInterface. Чтобы понять смысл макроса DECLARE_REGISTRY_RESOURCEID (IDR_SAY), откройте дерево ресурсов и рассмотреть новый узел "REGISTRY", а также его элемент IDR_SAY. Это — сценарий или, как теперь принято говорить, скрипт процедуры регистрации. В нем содержится та же логика, что и в файле Say.rgs. Но, в отличие от файла Say.rgs, ресурс IDR_SAY не предназначен для ручного редактирования.
Еще один макрос DECLARE_PROTECT_FINAL_CONSTRUCT содержит код, который защищает COM-объект от уничтожения в случае, когда вложенный (агрегированный) объект обнуляет счетчик числа пользователей внешнего объекта.
Вы можете построить DLL, дав команду Build4Build ATest. Затем вы можете даже запустить приложение (Ctrl+F5). В этот момент студия запросит имя exe-файла, то есть модуля или процесса, в пространство которого должна быть загружена созданная компоновщиком DLL. Воспользуйтесь выпадающим списком для выбора стандартного контейнера для отладки элементов ActiveX (tstcon32.exe), поставляемого вместе со студией по адресу: ..\Microsoft Visual Studio\ Common\ Tools.
В рамках тестового контейнера можно отлаживать работу элементов ActiveX, OLE-controls и других COM-объектов. Дайте команду Edit4Insert New Control. После некоторой паузы, в течение которой контейнер собирает информацию из реестра обо всех элементах OLE Controls, вы увидите диалог с длинным списком элементов, о которых есть информация. Однако, в окне тестового контейнера вы не увидите признаков нашего элемента, так как он не элемент управления, а всего лишь "Simple COM-Object".
Процедура вставки нового метода в существующий интерфейс в рамках проекта ATL тоже автоматизирована. Поставьте фокус на интерфейс ISay в дереве классов и вызовите контекстное меню. Затем дайте команду Add Method. В поле Method Name введите имя метода Say. Если хотите, то нажмите кнопку Attributes и подправьте helpstring, заменив ее, например, на "Launches Message Box". После этого нажмите Finish.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.