Разработка сервера
Примечание 1 Это же действие можно выполнить более сложным способом, но зато сход-ным с тем, как это делалось в Visual Studio 6. Дайте команду File > New > File, выберите тип файла и нажмите кнопку Open. Кроме этих действий придется записать новый файл в папку с проектом и подключить его. Для этого используется команда Project > Add Existing Item с последующим поиском файла. Альтернативой этому является перетаскивание существующего файла в окне Solution Explorer из папки Resource Files в папку Header Files. //=== Эти директивы нужны для того, чтобы не допустить //=== повторное подключение файла #if !defined(MY_ISAY_INTERFACE) #define MY__ISAY_INTERFACE #pragma once //====== Для того, чтобы были доступны COM API #include <windows.h> //====== Для того, чтобы был виден lUnknown #include <initguid.h> // Интерфейс ISay мы собираемся зарегистрировать и // показать миру. Он, как и положено, происходит от // IUnknown и содержит чисто виртуальные функции interface ISay : public lUnknown { //=== 2 метода, которые интерфейс //=== предоставляет своим клиентам virtual HRESULT _stdcall Say 0=0; virtual HRESULT _stdcall SetWord (BSTR word)=0; } #endif Абстрактный интерфейс не может жить сам по себе. Он должен иметь класс-оболочку (wrapper class), который на деле реализует виртуальные методы Say и SetWord. Этот так называемый ко-класс (класс СОМ-компонента) производится от интерфейса ISay и предоставляет тела всем унаследованным (чисто) виртуальным методам своего родителя. Так как у интерфейса ISay, в свою очередь, имеется родитель (lUnknown), то класс должен также дать реальные тела всем трем методам IUnknown. Примечание 2 Примечание 2 Если вы хотите, чтобы класс реализовывал несколько интерфейсов, то вы должны использовать множественное наследование. Такой подход проповедует ATL (Active Template Library). MFC реализует другой подход к реализации интерфейсов. Он использует вложенные классы. Каждому интерфейсу соответствует новый класс, вложенный в один общий класс СОМ-объекта. Для того чтобы быть доступным тем приложениям, которые захотят воспользоваться услугами СОМ-объекта, сам класс тоже должен иметь дом (в виде inproc-сервера DLL). Сейчас, разрабатывая проект типа Win32 DLL, мы строим именно этот дом. С помощью механизма DLL класс будет доступен приложению-клиенту, в адресное пространство процесса которого он загружается. Вы знаете, что DLL загружается в пространство клиента только при необходимости. Нам неоднократно понадобятся услуги инструмента Studio.Net под именем GuidGen, поэтому целесообразно ввести в меню Tools (Инструментальные средства) Studio.Net новую команду для его запуска. GuidGen, так же как и UuidGen, умеет генерировать уникальные 128-битовые идентификаторы, но при этом он использует удобный Windows-интерфейс. А идентификаторы понадобятся нам для регистрации сервера и класса CoSay. Для введения новой команды:
DEFINE_GUID («name», 0xl70368d0, 0x85be, 0x43af, 0xae, 0x71, 0x5, Ox3f, 0x50, 0x66, 0x57, Oxa2); Замените аргумент «name» на HD_ISay. Повторите всю процедуру и создайте идентификатор для ко-класса CoSay, который вставьте сразу за идентификатором интерфейса ISay. На сей раз замените аргумент «name» на CLSiD_CoSay, например: // {9B865820-2FFA-lld5-98B4-OOE0293F01B2} DEFINE_GUID(CLSID_CoSay, 0х9b865820, 0x2ffa, 0xlldS, 0x98, 0xb4, 0x0, 0xe0, 0x29, 0x3f, 0xl, 0xb2); Сохраните и закройте файл interfaces.h, так как мы больше не будем вносить в него изменений. Если вы хотите знать, что делает макроподстановка DEFINE_GUID, то за ней стоит такое определение: #define DEFINE_GUID (name, 1, wl, w2, \ b1, b2, bЗ, b4, b5, b6, b7, b8) \ EXTERN_C const GUID name \ = { 1, wl, w2, { b1, b2, bЗ,b4, b5, b6, b7, b8 } } Оно означает, что макрос создает структуру с именем <name> типа GUID, которая служит для хранения уникальных идентификаторов СОМ-объектов, интерфейсов, библиотек типов и других реалий причудливого мира СОМ. |