TN038: реализация MFC/OLE IUnknown
Примечание |
---|
Следующая техническая заметка не была обновлена со времени сначала была включена в подключенной документации.В результате некоторые процедуры и разделы могут оказаться устаревшей или неверны.Последние новости, рекомендуется поиск раздела процента в подключенном индексу документации. |
В основе OLE 2 «ЯВЛЯЕТСЯ модель COM» или модели COM.Модель COM определяет стандарт, как кооперируя объекты взаимодействуют друг с другом.Это включает сведения, «объект» похожее, включая как методы посланы на объект.Модель COM определяет также базовый класс, от которого наследуются все классы модели COM совместимые.Этот базовый класс IUnknown.Хотя интерфейс IUnknown называется класс C++, COM, не относящихся к любому одному языку — его можно реализовать в c#, ПАСКАЛЕ или любом другом языке, который может поддерживать бинарную структуру COM-объект.
OLE относится ко всем классам, производным от IUnknown как «интерфейсы». Это важное отличие, поскольку «интерфейс» IUnknown не содержит с ним реализации.Он просто указывается протокол, которые передают объекты, не зависящие от которого эти реализации.Это разумно система, позволяющая для максимальной гибкости.Задание MFC реализации по умолчанию расширение функциональности для программ MFC/C++.
Чтобы понять реализации MFC IUnknown сначала необходимо понимать, что этот интерфейс.Упрощенная версия IUnknown определен ниже:
class IUnknown
{
public:
virtual HRESULT QueryInterface(REFIID iid, void** ppvObj) = 0;
virtual ULONG AddRef() = 0;
virtual ULONG Release() = 0;
};
Примечание |
---|
Соглашение о вызовах один необходимые сведения, такие как __stdcall слева на этом рисунке. |
Функции-члены AddRef и Выпуск контролируют управление памятью объекта.Модель COM использует ссылку подсчитывая схему отслеживания объектов.Объект никогда не ссылаются непосредственно как ссылка в C++.Вместо этого com-объекта всегда ссылается посредством указателя.Для освобождения объекта, когда владелец осуществляется с помощью его вызывается член Выпуск объекта (в отличие от использования оператора delete, например, для традиционного объектов C++).Ссылка подсчитывая механизм позволяет несколько ссылок на один объект, который необходимо управлять.Реализация AddRef и Выпуск поддерживает счетчика ссылок на объект — объект не будет удален до его счетчик ссылок достигает нуля.
AddRef и Выпуск достаточно прямодушны с точки зрения реализации.Здесь тривиальная реализация:
ULONG CMyObj::AddRef()
{
return ++m_dwRef;
}
ULONG CMyObj::Release()
{
if (--m_dwRef == 0)
{
delete this;
return 0;
}
return m_dwRef;
}
Функция-член QueryInterface некоторые интересные.Не очень интересно иметь функции-члены которого являются единственными AddRef объект и Выпуск — было бы славно указать, что объект выполнил несколько вещей, чем IUnknown.Это полезно, когда QueryInterface.Он позволяет получить другой «интерфейс» в одном объекте.Эти интерфейсы обычно наследуются от IUnknown и добавляют дополнительную функциональность путем добавления новых функций-членов.Интерфейсы модель COM не имеющих переменные, объявленные в интерфейсе член, а все функции элементов декларируются как чисто-виртуальный.Например:
class IPrintInterface : public IUnknown
{
public:
virtual void PrintObject() = 0;
};
Получить IPrintInterface если имеется только IUnknown, то вызов IUnknown::QueryInterface с помощью IIDIPrintInterface.IID 128 Бита, которое однозначно определяет интерфейс чисел.IID Для каждого интерфейса, либо определяют или OLE.Если панк указатель на объект IUnknown, то код для получения IPrintInterface от него может быть:
IPrintInterface* pPrint = NULL;
if (pUnk->QueryInterface(IID_IPrintInterface,
(void**)&pPrint) == NOERROR)
{
pPrint->PrintObject();
pPrint->Release();
// release pointer obtained via QueryInterface
}
То кажетесь довольно легко, но способ реализации бы объект, поддерживающий и IPrintInterface и интерфейс IUnknown ?В этом случае оно простым, поскольку IPrintInterface выводится непосредственно из IUnknown — путем реализации IPrintInterface, IUnknown автоматически поддерживается.Примеры.
class CPrintObj : public CPrintInterface
{
virtual HRESULT QueryInterface(REFIID iid, void** ppvObj);
virtual ULONG AddRef();
virtual ULONG Release();
virtual void PrintObject();
};
Реализации AddRef и Выпуск будет явным том, как эти реализованные выше.CPrintObj::QueryInterface посмотрело бы примерно так:
HRESULT CPrintObj::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
if (iid == IID_IUnknown || iid == IID_IPrintInterface)
{
*ppvObj = this;
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
Как можно видеть, если идентификатор интерфейса (IID), указатель возвращается к конкретному объекту; в противном случае возникает ошибка.Также обратите внимание, что успешное QueryInterface результате выполняется неявное AddRef.Конечно, необходимо также реализовать CEditObj::Print.Просто, поскольку IPrintInterface непосредственно было производным от интерфейса IUnknown.Однако если требуется поддерживать 2 различных интерфейса, то оба производные от IUnknown, проверяет следующее:
class IEditInterface : public IUnkown
{
public:
virtual void EditObject() = 0;
};
Хотя существует несколько разных способов реализовать класс, поддерживающий и IEditInterface и IPrintInterface, включая использование множественного наследования C++, эта заметка сконцентрирует на использовании вложенных классов реализации этой функции.
class CEditPrintObj
{
public:
CEditPrintObj();
HRESULT QueryInterface(REFIID iid, void**);
ULONG AddRef();
ULONG Release();
DWORD m_dwRef;
class CPrintObj : public IPrintInterface
{
public:
CEditPrintObj* m_pParent;
virtual HRESULT QueryInterface(REFIID iid, void** ppvObj);
virtual ULONG AddRef();
virtual ULONG Release();
} m_printObj;
class CEditObj : public IEditInterface
{
public:
CEditPrintObj* m_pParent;
virtual ULONG QueryInterface(REFIID iid, void** ppvObj);
virtual ULONG AddRef();
virtual ULONG Release();
} m_editObj;
};
Реализация включена вся ниже:
CEditPrintObj::CEditPrintObj()
{
m_editObj.m_pParent = this;
m_printObj.m_pParent = this;
}
ULONG CEditPrintObj::AddRef()
{
return ++m_dwRef;
}
CEditPrintObj::Release()
{
if (--m_dwRef == 0)
{
delete this;
return 0;
}
return m_dwRef;
}
HRESULT CEditPrintObj::QueryInterface(REFIID iid, void** ppvObj)
{
if (iid == IID_IUnknown || iid == IID_IPrintInterface)
{
*ppvObj = &m_printObj;
AddRef();
return NOERROR;
}
else if (iid == IID_IEditInterface)
{
*ppvObj = &m_editObj;
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
ULONG CEditPrintObj::CEditObj::AddRef()
{
return m_pParent->AddRef();
}
ULONG CEditPrintObj::CEditObj::Release()
{
return m_pParent->Release();
}
HRESULT CEditPrintObj::CEditObj::QueryInterface(
REFIID iid, void** ppvObj)
{
return m_pParent->QueryInterface(iid, ppvObj);
}
ULONG CEditPrintObj::CPrintObj::AddRef()
{
return m_pParent->AddRef();
}
ULONG CEditPrintObj::CPrintObj::Release()
{
return m_pParent->Release();
}
HRESULT CEditPrintObj::CPrintObj::QueryInterface(
REFIID iid, void** ppvObj)
{
return m_pParent->QueryInterface(iid, ppvObj);
}
Обратите внимание, что большая часть реализации IUnknown помещается в класс CEditPrintObj, а не дублирующ код в CEditPrintObj::CEditObj и CEditPrintObj::CPrintObj.Это уменьшает объем кода и избежать ошибки.Узловой укажите здесь из интерфейса IUnknown QueryInterface можно вызвать для получения любой объект может поддерживать интерфейс и из каждого из этих интерфейсов можно сделать.Это означает, что все функции QueryInterface, доступные из каждого интерфейса должны работать один и тот же способом.Для этого такие внедренные объекты для вызова реализация в «внешнем объекте», используемый Назад-указатель (m_pParent).M_pParent указатель инициализирован CEditPrintObj во время разработки.Затем реализации бы CEditPrintObj::CPrintObj::PrintObject и CEditPrintObj::CEditObj::EditObject.Довольно бит кода был добавлен для добавления одной функции — возможность изменения объекта.К счастью, а неупотребительно для интерфейсов иметь только один функции-члена (хотя его происходит) и в этом случае EditObject и PrintObject обычно будут объединены в один интерфейс.
Это множество объяснение и множество код для этого простого скрипта.Классы MFC/OLE обеспечивают более простой альтернативой.Реализация MFC использует метод, аналогичный способа создания окна сообщения программу-оболочкуы с сопоставлениями сообщения.Эта функция вызывается Интерфейсом Сопоставления и описано в следующем разделе.
Сопоставления интерфейсов MFC
MFC/OLE включает реализацию интерфейса сопоставляет», аналогичную MFC «сообщению сопоставляет» и «диспетчер сопоставляет» в концепции и выполнении.Базовые функции сопоставления интерфейсов MFC следующим образом:
Стандартная реализация IUnknown, построенная в CCmdTarget класс.
Обслуживание счетчика ссылок, измененное AddRef и Выпуск
Реализация управляемой данными QueryInterface
Кроме того, сопоставления интерфейса поддерживают следующие расширенные функции:
Поддержка создания aggregatable com-объекты
Поддержка использования статистических объектов в реализации com-объекта
Реализация hookable и может быть расширена
Дополнительные сведения см. в разделе Справочник по OLE-программированию.
Поддержка сопоставления интерфейсов MFC укоренена в классе CCmdTarget.CCmdTarget «имеет-» счетчик ссылок а также все функций-членов, связанные с реализацией IUnknown (счетчик ссылок например в CCmdTarget).Чтобы создать класс, поддерживающий OLE модели COM, необходимо создать производный класс от CCmdTarget и использовать другие макросы, а также функции-члены CCmdTarget для реализации необходимые интерфейсы.Реализация MFC использует вложенные классы для задания каждой реализации интерфейса больше, как в примере выше.Это можно сделать более простым с стандартной реализацией интерфейса IUnknown, а также нескольких макросов, исключить некоторые из повторяющихся кода.
Реализация класса с помощью сопоставления интерфейсов MFC
Создайте класс прямо или косвенно от CCmdTarget.
Используйте функцию DECLARE_INTERFACE_MAP в определении производного класса.
Для каждого интерфейса необходимо поддерживать, использовать макросы BEGIN_INTERFACE_PART и END_INTERFACE_PART в определении класса.
В файле реализации, используйте макрос BEGIN_INTERFACE_MAP и END_INTERFACE_MAP чтобы указать сопоставление интерфейса типа.
Для каждого поддерживаемого IID, используйте макрос INTERFACE_PART между BEGIN_INTERFACE_MAP и макросами END_INTERFACE_MAP для сопоставления то IID к определенной части» класса «.
Реализуйте каждый из вложенных классов, представляющих интерфейсы требуется поддержка.
Используйте макрос METHOD_PROLOGUE для доступа к родительскому CCmdTarget- производный объект.
AddRef, Выпуск и QueryInterface может делегировать CCmdTarget на реализацию этих функций (ExternalAddRef, ExternalRelease и ExternalQueryInterface).
В приведенном выше примере CPrintEditObj может быть реализован следующим образом:
class CPrintEditObj : public CCmdTarget
{
public:
// member data and member functions for CPrintEditObj go here
// Interface Maps
protected:
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(EditObj, IEditInterface)
STDMETHOD_(void, EditObject)();
END_INTERFACE_PART(EditObj)
BEGIN_INTERFACE_PART(PrintObj, IPrintInterface)
STDMETHOD_(void, PrintObject)();
END_INTERFACE_PART(PrintObj)
};
Приведенное выше объявление создает класс, производный от CCmdTarget.Макрос DECLARE_INTERFACE_MAP сообщает рамкам, что этот класс будет иметь пользовательское сопоставление интерфейса.Кроме того, макросы BEGIN_INTERFACE_PART и END_INTERFACE_PART определяют вложенные классы, в данном случае с именами CEditObj и CPrintObj (x используется только для различения вложенные классы из глобальных классов, начинающиеся с «c» и классов интерфейса, начинающиеся с «i»).2 Вложенных элементов этих классов создаются: m_CEditObj и m_CPrintObj соответственно.Макросы автоматически объявляют AddRef, Выпуск и функции QueryInterface; поэтому только объявления функции, относящиеся к этому интерфейсу. EditObject и PrintObject (OLE STDMETHOD используется макрос тем, что _stdcall и фактически ключевые слова будут этот по мере необходимости для платформы целевого объекта).
Чтобы реализовать сопоставление интерфейса для данного класса:
BEGIN_INTERFACE_MAP(CPrintEditObj, CCmdTarget)
INTERFACE_PART(CPrintEditObj, IID_IPrintInterface, PrintObj)
INTERFACE_PART(CPrintEditObj, IID_IEditInterface, EditObj)
END_INTERFACE_MAP()
Это IID_IPrintInterface IID m_CPrintObj и соединяется с IID_IEditInterface с m_CEditObj соответственно.Реализация CCmdTargetQueryInterface (CCmdTarget::ExternalQueryInterface) использует эти сопоставления для возвращения указатели на m_CPrintObj и m_CEditObj при запрошенном объекте.Нет необходимости включать запись для IID_IUnknown; платформа будет использоваться первый интерфейс в сопоставлении (в этом случае m_CPrintObj) при IID_IUnknown запросе.
Даже если макрос BEGIN_INTERFACE_PART автоматически в котором объявлен AddRef, Выпуск и функции QueryInterface, все же нужно их реализации:
ULONG FAR EXPORT CEditPrintObj::XEditObj::AddRef()
{
METHOD_PROLOGUE(CEditPrintObj, EditObj)
return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CEditPrintObj::XEditObj::Release()
{
METHOD_PROLOGUE(CEditPrintObj, EditObj)
return pThis->ExternalRelease();
}
HRESULT FAR EXPORT CEditPrintObj::XEditObj::QueryInterface(
REFIID iid, void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(CEditPrintObj, EditObj)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
void FAR EXPORT CEditPrintObj::XEditObj::EditObject()
{
METHOD_PROLOGUE(CEditPrintObj, EditObj)
// code to "Edit" the object, whatever that means...
}
Реализация CEditPrintObj::CPrintObj, будет аналогична в предыдущем определения для CEditPrintObj::CEditObj.Хотя можно создать макрос, который может быть использован для автоматического создания этих функций (но ранее в MFC/OLE разработка это регистр), будет трудно задавать точки останова, если макрос создает несколько строк кода.По этой причине данный код развернуть вручную.
С помощью реализации архитектуры сопоставления сообщения, несколько задач, которые не были обязательными, чтобы сделать:
Реализуйте QueryInterface
Реализуйте AddRef и выпуска
Объявите один из этих встроенных методов для обоих пользовательских интерфейсов
Кроме того, инфраструктура использует сопоставления сообщения для внутреннего использования.Это позволяет производным от класса платформы, сообщает COleServerDoc, который уже поддерживает некоторые интерфейсы и предоставляет или замены или сложения интерфейсы, предоставляемые платформой.Это разрешено факт, что границы полностью поддерживают наследование от базового класса — сопоставление интерфейса, который стал причиной ошибки, почему BEGIN_INTERFACE_MAP принимает в качестве второго параметра имя базового класса.
Примечание |
---|
Обычно невозможно повторно использовать реализацию реализаций MFC встроенных интерфейсов OLE путем наследования внедренную специализацию этого интерфейса от версии MFC.Это невозможно, поскольку использование макроса METHOD_PROLOGUE получить доступ к CCmdTarget, содержащий производный объект предполагает fixed offset внедренного объекта из CCmdTarget- производный объект.Это означает, например, нельзя создать внедренный XMyAdviseSink от реализации MFC в COleClientItem::XAdviseSink, поскольку XAdviseSink полагается на быть в определенное возмещенном из вершин объекта COleClientItem. |
Примечание |
---|
Однако можно делегировать к реализации MFC для всех функций, расширения функциональности MFC по умолчанию.Это делается в реализации MFC IOleInPlaceFrame (XOleInPlaceFrame) в классе COleFrameHook (его в m_xOleInPlaceUIWindow делегатов для реализации многих функций).Эта структура была выбрана для уменьшения размера среды выполнения объектов, реализующих несколько интерфейсов. она устраняет необходимость Назад-указателя (как способ m_pParent, используемого в предыдущем разделе). |
Сопоставления статистической обработки и интерфейса
Помимо поддержки изолированные com-объекта, MFC также поддерживает агрегирование.Сам является слишком сложный раздел для обсуждения здесь; справочник по программированию OLE см. дополнительные сведения в агрегате.Эта заметка просто опишет поддержку для статистической обработки, встроенные в сопоставлении границ и интерфейса.
2 Способа использования статистической обработки: (1) с использованием com-объектов, который поддерживает агрегирование и (2) реализация объект, который может быть статистически вычислены другими.Этими возможностями можно назвать «, используя статистический объект» и «это объект aggregatable».MFC поддерживает оба.
Использование aggregate, объект
Для статистического объекта, требуется способ связывания агрегат в механизм QueryInterface.Иначе говоря, aggregate, объект должен вести себя так, как если бы собственная рамках объекта.Так как эта ссылка в интерфейс MFC сопоставляет механизм?В дополнение к макросу INTERFACE_PART, где сопоставляется вложенных объект на IID, можно также объявить aggregate объект как часть производного класса CCmdTarget.Для этого используется макрос INTERFACE_AGGREGATE.Это позволяет определить переменную-член (которая должна быть указателем на IUnknown или в производном классе), интегрированным в механизм сопоставления интерфейса.Если указатель НЕ равно null, то при вызове метода CCmdTarget::ExternalQueryInterface платформа автоматически вызывает функцию-член QueryInterface aggregate объекта, если запрашиваемый IID не является одним из собственного IID s, поддерживаемого объектом данного CCmdTarget.
Использовать макрос INTERFACE_AGGREGATE
Объявите переменную участника ( IUnknown*), которая будет содержать указатель к статистическим объектом.
Включить макрос INTERFACE_AGGREGATE в сопоставлении интерфейса, который относится к переменной элемента по имени.
Рано или поздно (обычно во время CCmdTarget::OnCreateAggregates), инициализируйте переменную участника на отличный от NULL.
Примеры.
class CAggrExample : public CCmdTarget
{
public:
CAggrExample();
protected:
LPUNKNOWN m_lpAggrInner;
virtual BOOL OnCreateAggregates();
DECLARE_INTERFACE_MAP()
// "native" interface part macros may be used here
};
CAggrExample::CAggrExample()
{
m_lpAggrInner = NULL;
}
BOOL CAggrExample::OnCreateAggregates()
{
// wire up aggregate with correct controlling unknown
m_lpAggrInner = CoCreateInstance(CLSID_Example,
GetControllingUnknown(), CLSCTX_INPROC_SERVER,
IID_IUnknown, (LPVOID*)&m_lpAggrInner);
if (m_lpAggrInner == NULL)
return FALSE;
// optionally, create other aggregate objects here
return TRUE;
}
BEGIN_INTERFACE_MAP(CAggrExample, CCmdTarget)
// native "INTERFACE_PART" entries go here
INTERFACE_AGGREGATE(CAggrExample, m_lpAggrInner)
END_INTERFACE_MAP()
m_lpAggrInner инициализируется в конструкторе null.Границы не учитывают значения null переменная-член в реализации по умолчанию QueryInterface.Фактически OnCreateAggregates удобен для создания статистические объекты.Можно вызвать явным образом при создании объекта вне реализации MFC COleObjectFactory.Рассматривается причина создания агрегатов в CCmdTarget::OnCreateAggregates, а также потребление CCmdTarget::GetControllingUnknown станет ясной создать aggregatable объекты.
Этот метод передает свой объект все интерфейсы, aggregate, поддерживаемых объектом, плюс собственные интерфейсы.Если необходимо только подмножество интерфейсов, которые поддерживает агрегирование можно переопределить CCmdTarget::GetInterfaceHook.Это позволяет намного нижний уровень hookability, аналогичное QueryInterface.Обычно необходимо, чтобы все интерфейсы, которые оно поддерживает.
Это реализация Aggregatable объекта
Для объекта, который должен быть aggregatable реализация AddRef, Выпуск и QueryInterface должны делегировать управление» на «неизвестный тип. Иначе говоря, для него, который должен быть частью объекта, он должен делегировать AddRef, Выпуск и QueryInterface к другому объекту, кроме того, производный от IUnknown.Это неизвестное «управление» реализуется объект при его создания, т е реализуется реализация COleObjectFactory.Не реализует это имеет минимальный объем служебных данных, и в некоторых случаях нежелательно, поэтому MFC выполняет этот необязательный.Чтобы разрешить объект для aggregatable, следует вызвать CCmdTarget::EnableAggregation из конструктора объектов.
Если объект также использует агрегаты также необходимо быть уверенным загрузить правильный неизвестно «управление» на статистические объекты.Обычно этот указатель IUnknown передается объекту при создании агрегата.Например, параметр pUnkOuter «управление» неизвестное для объектов, созданных с CoCreateInstance.Управление правильный «unknown» указатель может быть получен путем вызова CCmdTarget::GetControllingUnknown.Значение, возвращаемое из этой функции, но недопустима во время разработки.По этой причине предложено, что создании агрегаты только в переопределенном методе CCmdTarget::OnCreateAggregates, где возвращаемое значение из GetControllingUnknown достоверно, даже если создан из реализации COleObjectFactory.
Важно также, что объект, управляющий правильный счетчика ссылок при добавлении или освобождение искусственние счетчики ссылок.Предоставить этом случае всегда вызов ExternalAddRef и ExternalRelease вместо InternalRelease и InternalAddRef.Он редок вызвать InternalRelease или InternalAddRef в классе, который поддерживает агрегирование.
Справочные материалы
Дополнительно потребление OLE, например определение собственные интерфейсы платформы или переопределить реализацию интерфейсов OLE требует использования основного механизма сопоставления интерфейса.
Этот раздел описывает каждый макрос и API, используемый для реализации этих расширенных функций.
CCmdTarget::EnableAggregation — описание функции
void EnableAggregation();
Заметки
Эта функция вызывается в конструкторе производного класса, если нужно поддерживать агрегирование объектов OLE для данного типа.Это подготавливает специальную реализацию интерфейса IUnknown, необходимые для aggregatable объектов.
CCmdTarget::ExternalQueryInterface — описание функции
DWORD ExternalQueryInterface(
const void FAR* lpIID,
LPVOID FAR* ppvObj
);
Заметки
Параметры
lpIID
Далекий указатель на идентификатор IID (первый аргумент QueryInterface)ppvObj
Указатель на IUnknown* (второму аргументу с QueryInterface)
Заметки
Эта функция вызывается при реализации интерфейса IUnknown для каждого класс реализует.Эта функция обеспечивает стандартную реализацию QueryInterface управляемого данными на основе сопоставлении интерфейса объекта.Необходимо привести возвращаемое значение к HRESULT.Если объект статистически вычислены, то это вызывать функции «управление IUnknown» вместо использования локального сопоставления интерфейса.
CCmdTarget::ExternalAddRef — описание функции
DWORD ExternalAddRef();
Заметки
Эта функция вызывается при реализации IUnknown::AddRef для каждого интерфейса класс реализует.Возвращаемое значение новый счетчик ссылок в объекте CCmdTarget.Если объект статистически вычислены, то это вызывать функции «управление» IUnknown, а не управлять локальными счетчика ссылок.
CCmdTarget::ExternalRelease — описание функции
DWORD ExternalRelease();
Заметки
Эта функция вызывается при реализации IUnknown::Release для каждого интерфейса класс реализует.Возвращаемое значение показывает новый счетчик ссылок на объект.Если объект статистически вычислены, то это вызывать функции «управление» IUnknown, а не управлять локальными счетчика ссылок.
Описание DECLARE_INTERFACE_MAP - макрос
DECLARE_INTERFACE_MAP
Заметки
Используйте этот макрос в любом классе, производном от CCmdTarget, которое будет содержать сопоставление интерфейса.Используется точно так же, как DECLARE_MESSAGE_MAP.Этот вызов макроса следует поместить в определении класса (обычно в заголовке. файл h).Класс с DECLARE_INTERFACE_MAP должен указывать сопоставление интерфейса в файле реализации (.CPP) с макросами BEGIN_INTERFACE_MAP и END_INTERFACE_MAP.
BEGIN_INTERFACE_PART и описания END_INTERFACE_PART — макрос
BEGIN_INTERFACE_PART(
localClass,
iface
);
END_INTERFACE_PART(
localClass
)
Заметки
Параметры
localClass
Имя класса, реализующего интерфейсiface
Имя интерфейса, этот класс реализует
Заметки
Для каждого интерфейса, класс будет реализовывать, необходимо иметь пару BEGIN_INTERFACE_PART и END_INTERFACE_PART.Эти макросы определяются локальными класс, производный от интерфейса OLE, а также внедренной переменную-член этого класса.AddRef, Выпуск и члены QueryInterface объявлены автоматически.Необходимо включить объявления для других функций элементов, которые являются частью, снабжанными (объявления интерфейса помещаются между макросами BEGIN_INTERFACE_PART и END_INTERFACE_PART ).
Аргумент iface ole-интерфейс, который нужно реализовать, как IAdviseSink или IPersistStorage (или собственный пользовательский интерфейс).
Аргумент localClass имя локального класса, который будет определен.«X» будет автоматически добавляется к его имени.Это соглашение об именовании используется, чтобы избежать конфликтов с глобальным классами с таким же именем.Кроме того, имя внедренного элемента этого же, что и имя localClass за исключением того, что он присоединен префикс «m_x».
Примеры.
BEGIN_INTERFACE_PART(MyAdviseSink, IAdviseSink)
STDMETHOD_(void,OnDataChange)(LPFORMATETC, LPSTGMEDIUM);
STDMETHOD_(void,OnViewChange)(DWORD, LONG);
STDMETHOD_(void,OnRename)(LPMONIKER);
STDMETHOD_(void,OnSave)();
STDMETHOD_(void,OnClose)();
END_INTERFACE_PART(MyAdviseSink)
задан локальный класс с именем XMyAdviseSink производным от IAdviseSink и член класса, в котором он объявлен, называемого m_xMyAdviseSink.Note:
Примечание |
---|
Линии начиная с STDMETHOD_, по существу, копируемых из OLE2.H и немного изменены.Скопировать их из OLE2.H может уменьшить ошибок, которые трудно разрешения. |
BEGIN_INTERFACE_MAP и описания END_INTERFACE_MAP — макрос
BEGIN_INTERFACE_MAP(
theClass,
baseClass
)
END_INTERFACE_MAP
Заметки
Параметры
theClass
Класс, в котором сопоставление интерфейса быть определеныbaseClass
Класс, от которого наследуется от theClass.
Заметки
Макросы BEGIN_INTERFACE_MAP и END_INTERFACE_MAP используются в файле реализации виртуального, чтобы указать сопоставление интерфейса.Для каждого интерфейса, реализованного один или несколько вызовов макроса INTERFACE_PART.Для каждого агрегата, класс использует один вызов макроса INTERFACE_AGGREGATE.
Описание INTERFACE_PART - макрос
INTERFACE_PART(
theClass,
iid,
localClass
)
Заметки
Параметры
theClass
Имя класса, который содержит сопоставление интерфейса.iid
IID, Сопоставленным на внедренный классу.localClass
Имя локального класса (меньше «x»).
Заметки
Этот макрос используется между макросом BEGIN_INTERFACE_MAP и макросом END_INTERFACE_MAP для каждого интерфейса объект будет поддерживать.Он позволяет сопоставлять идентификатор IID к члену класса, отображаемого theClass и localClass.«M_x» будет добавлено в localClass автоматически.Обратите внимание, что несколько IID может быть связан с единственным членом.Это очень удобно при реализации только наиболее производные» интерфейс «и желание, чтобы обеспечить все промежуточные интерфейсы.Хорошим примером этого интерфейса IOleInPlaceFrameWindow.Его иерархия выглядит следующим образом:
IUnknown
IOleWindow
IOleUIWindow
IOleInPlaceFrameWindow
Если объект реализует IOleInPlaceFrameWindow клиент может QueryInterface на любом из этих интерфейсов: IOleUIWindow, IOleWindow или IUnknown, за исключением «наиболее производного» интерфейса IOleInPlaceFrameWindow фактически реализации (один).Для обработки этого можно использовать несколько макрос INTERFACE_PART для сопоставления каждого базовый интерфейс к интерфейсу IOleInPlaceFrameWindow:
в файле определения класса.
BEGIN_INTERFACE_PART(CMyFrameWindow, IOleInPlaceFrameWindow)
в файле реализации класса:
BEGIN_INTERFACE_MAP(CMyWnd, CFrameWnd)
INTERFACE_PART(CMyWnd, IID_IOleWindow, MyFrameWindow)
INTERFACE_PART(CMyWnd, IID_IOleUIWindow, MyFrameWindow)
INTERFACE_PART(CMyWnd, IID_IOleInPlaceFrameWindow, MyFrameWindow)
END_INTERFACE_MAP
Границы позаботятся об интерфейсе IUnknown, поскольку всегда является обязательным.
Описание INTERFACE_PART - макрос
INTERFACE_AGGREGATE(
theClass,
theAggr
)
Заметки
Параметры
theClass
Имя класса, который содержит сопоставление интерфейсаtheAggr
Имя переменной-члена, которая должна статистической обработке.
Заметки
Этот макрос используется, чтобы сообщить рамкам, что класс использует статистические объект.Он должен появиться между макросами BEGIN_INTERFACE_PART и END_INTERFACE_PART.Статистический объект отдельный объект, производный от IUnknown.С помощью пользователем агрегатных функций и макросов INTERFACE_AGGREGATE можно выполнить все интерфейсы, отображаемых напрямую поддерживается обработка поддерживается объектом.Аргумент theAggr просто имя переменной члена класса, производного от IUnknown (напрямую или косвенно).Все макросы INTERFACE_AGGREGATE должны следовать макросами INTERFACE_PART помещенный в сопоставлении интерфейса.