COM_INTERFACE_ENTRY 宏
这些宏将对象的接口输入到其 COM 映射中,以便 QueryInterface
可以访问这些接口。 COM 映射中的入口顺序是在 QueryInterface
期间根据匹配的 IID 检查接口的顺序。
要求
标头:atlcom.h
COM_INTERFACE_ENTRY
将接口输入到 COM 接口映射。
语法
COM_INTERFACE_ENTRY( x )
参数
x
[in] 类对象直接派生自的接口的名称。
注解
通常,这是最常用的入口类型。
示例
BEGIN_COM_MAP(CThisExample)
COM_INTERFACE_ENTRY(IThisExample)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
要求
标头:atlcom.h
COM_INTERFACE_ENTRY2
使用此宏可以消除两个继承分支的歧义。
COM_INTERFACE_ENTRY2(x, x2)
参数
x
[in] 要从对象公开的接口的名称。
x2
[in] 从中公开 x 的继承分支的名称。
注解
例如,如果从两个双重接口派生类对象,请使用 COM_INTERFACE_ENTRY2 公开 IDispatch
,因为可以从任一接口获取 IDispatch
。
示例
class ATL_NO_VTABLE CEntry2Example :
public CEntry2ExampleBase, // CEntry2ExampleBase derives from IDispatch
public IDispatchImpl<IEntry2Example, &IID_IEntry2Example, &LIBID_NVC_ATL_WindowingLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public CComCoClass<CEntry2Example, &CLSID_Entry2Example>
{
public:
CEntry2Example()
{
}
BEGIN_COM_MAP(CEntry2Example)
COM_INTERFACE_ENTRY(IEntry2Example)
COM_INTERFACE_ENTRY2(IDispatch, IEntry2Example)
END_COM_MAP()
};
COM_INTERFACE_ENTRY_IID
使用此宏可将接口输入到 COM 映射并指定其 IID。
COM_INTERFACE_ENTRY_IID(iid, x)
参数
iid
[in] 公开的接口的 GUID。
x
[in] 其 vtable 将公开为 iid 标识的接口的类的名称。
示例
BEGIN_COM_MAP(CExample)
COM_INTERFACE_ENTRY(IExample)
COM_INTERFACE_ENTRY_IID(IID_IDispatch, CExampleDispatch)
COM_INTERFACE_ENTRY(IExampleBase)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
COM_INTERFACE_ENTRY2_IID
与 COM_INTERFACE_ENTRY2 相同,唯一的差别是你可以指定不同的 IID。
COM_INTERFACE_ENTRY2_IID(iid, x, x2)
参数
iid
[in] 为接口指定的 GUID。
x
[in] 类对象直接派生自的接口的名称。
x2
[in] 类对象直接派生自的另一个接口的名称。
COM_INTERFACE_ENTRY_AGGREGATE
查询 iid 标识的接口时,COM_INTERFACE_ENTRY_AGGREGATE 将转发到 punk。
COM_INTERFACE_ENTRY_AGGREGATE(iid, punk)
参数
iid
[in] 查询的接口的 GUID。
punk
[in] IUnknown
指针的名称。
备注
假设 punk 参数指向聚合的内部未知成员或 NULL,在这种情况下,将忽略该入口。 通常,你会对 FinalConstruct
中的聚合运行 CoCreate
。
示例
BEGIN_COM_MAP(COuter1)
COM_INTERFACE_ENTRY_AGGREGATE(__uuidof(IAgg), m_punkAgg)
END_COM_MAP()
COM_INTERFACE_ENTRY_AGGREGATE_BLIND
与 COM_INTERFACE_ENTRY_AGGREGATE 相同,唯一的差别是查询任何 IID 会导致将查询转发到 punk。
COM_INTERFACE_ENTRY_AGGREGATE_BLIND(punk)
参数
punk
[in] IUnknown
指针的名称。
备注
如果接口查询失败,则继续处理 COM 映射。
示例
BEGIN_COM_MAP(COuter2)
COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_punkAggBlind)
END_COM_MAP()
COM_INTERFACE_ENTRY_AUTOAGGREGATE
与 COM_INTERFACE_ENTRY_AGGREGATE 相同,唯一的差别是,如果 punk 为 NULL,则此宏会自动创建 clsid 描述的聚合。
COM_INTERFACE_ENTRY_AUTOAGGREGATE(iid, punk, clsid)
参数
iid
[in] 查询的接口的 GUID。
punk
[in] IUnknown
指针的名称。 必须是包含 COM 映射的类的成员。
clsid
[in] punk 为 NULL 时要创建的聚合的标识符。
备注
示例
BEGIN_COM_MAP(COuter3)
COM_INTERFACE_ENTRY_AUTOAGGREGATE(__uuidof(IAutoAgg), m_punkAutoAgg, CLSID_CAutoAgg)
END_COM_MAP()
COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND
与 COM_INTERFACE_ENTRY_AUTOAGGREGATE 相同,唯一的差别是,查询任何 IID 会导致将查询转发到 punk,如果 punk 为 NULL,则自动创建 clsid 描述的聚合。
COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND(punk, clsid)
参数
punk
[in] IUnknown
指针的名称。 必须是包含 COM 映射的类的成员。
clsid
[in] punk 为 NULL 时要创建的聚合的标识符。
备注
如果接口查询失败,则继续处理 COM 映射。
示例
BEGIN_COM_MAP(COuter4)
COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND(m_punkAutoAggB, CLSID_CAutoAggB)
END_COM_MAP()
COM_INTERFACE_ENTRY_BREAK
查询指定的接口时导致程序调用 DebugBreak。
COM_INTERFACE_ENTRY_BREAK(x)
参数
x
[in] 用于构造接口标识符的文本。
注解
通过将 x 追加到 IID_
来构造接口 IID。 例如,如果 x 为 IPersistStorage
,则 IID 为 IID_IPersistStorage
。
COM_INTERFACE_ENTRY_CACHED_TEAR_OFF
保存每个实例的接口特定数据。
COM_INTERFACE_ENTRY_CACHED_TEAR_OFF(iid, x, punk)
参数
iid
[in] 分离式接口的 GUID。
x
[in] 实现接口的类的名称。
punk
[in] IUnknown
指针的名称。 必须是包含 COM 映射的类的成员。 应在类对象的构造函数中初始化为 NULL。
备注
如果未使用接口,则这会降低对象的整体实例大小。
示例
BEGIN_COM_MAP(COuter)
COM_INTERFACE_ENTRY(IOuter)
COM_INTERFACE_ENTRY_CACHED_TEAR_OFF(IID_ITearOff, CTearOff, punkTearOff)
END_COM_MAP()
COM_INTERFACE_ENTRY_TEAR_OFF
公开分离式接口。
COM_INTERFACE_ENTRY_TEAR_OFF(iid, x)
参数
iid
[in] 分离式接口的 GUID。
x
[in] 实现接口的类的名称。
备注
分离式接口将实现为一个单独的对象,每次查询该对象所代表的接口时,都会实例化该对象。 通常,如果极少使用该接口,则可以将其生成为分离式接口,因为这会在主对象的每个实例中保存一个 vtable 指针。 当分离的引用计数变为零时,将删除该接口。 实现分离式接口的类应派生自 CComTearOffObjectBase
并具有自身的 COM 映射。
示例
BEGIN_COM_MAP(CBeeper)
COM_INTERFACE_ENTRY(IBeeper)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY_TEAR_OFF(IID_ISupportErrorInfo, CBeeper2)
END_COM_MAP()
COM_INTERFACE_ENTRY_CHAIN
当处理到达 COM 映射中的此入口时处理基类的 COM 映射。
COM_INTERFACE_ENTRY_CHAIN(classname)
参数
classname
[in] 当前对象的基类。
备注
例如,在以下代码中:
BEGIN_COM_MAP(COuterObject)
COM_INTERFACE_ENTRY2(IDispatch, IOuterObject)
COM_INTERFACE_ENTRY_CHAIN(CBase)
END_COM_MAP()
请注意,COM 映射中的第一个入口必须是包含 COM 映射的对象上的接口。 因此,不能使用 COM_INTERFACE_ENTRY_CHAIN 作为 COM 映射入口的开头,这会导致在对象的 COM 映射中出现 COM_INTERFACE_ENTRY_CHAIN(COtherObject
) 的位置搜索不同对象的 COM 映射。 如果你想要先搜索另一个对象的 COM 映射,请将 IUnknown
的接口入口添加到 COM 映射,然后链接另一个对象的 COM 映射。 例如:
BEGIN_COM_MAP(CThisObject)
COM_INTERFACE_ENTRY(IUnknown)
COM_INTERFACE_ENTRY_CHAIN(CBase)
END_COM_MAP()
COM_INTERFACE_ENTRY_FUNC
一个用于挂接到 ATL 的 QueryInterface
逻辑的常规机制。
COM_INTERFACE_ENTRY_FUNC(iid, dw, func)
参数
iid
[in] 公开的接口的 GUID。
dw
[in] 传递给 func 的参数。
func
[in] 将返回 iid 的函数指针。
备注
如果 iid 与查询的接口的 IID 匹配,则调用 func 指定的函数。 函数的声明应该是:
HRESULT WINAPI func(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw);
调用你的函数时,pv
指向你的类对象。 riid 参数引用要查询的接口,ppv
是指向位置的指针(函数应在此位置存储指向接口的指针),dw 是在入口中指定的参数。 如果函数选择不返回接口,则应将 * ppv
设置为 NULL 并返回 E_NOINTERFACE 或 S_FALSE。 如果返回 E_NOINTERFACE,则 COM 映射处理将会终止。 如果返回 S_FALSE,则 COM 映射处理将继续,即使未返回接口指针。 如果函数返回接口指针,则应返回 S_OK。
COM_INTERFACE_ENTRY_FUNC_BLIND
与 COM_INTERFACE_ENTRY_FUNC 相同,唯一的差别是,查询任何 IID 会导致调用 func。
COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func)
参数
dw
[in] 传递给 func 的参数。
func
[in] 处理 COM 映射中的此入口时调用的函数。
注解
发生任何失败都会导致在 COM 映射上继续处理。 如果函数返回接口指针,则应返回 S_OK。
COM_INTERFACE_ENTRY_NOINTERFACE
返回 E_NOINTERFACE 并在查询指定的接口时终止 COM 映射处理。
COM_INTERFACE_ENTRY_NOINTERFACE(x)
参数
x
[in] 用于构造接口标识符的文本。
备注
可以使用此宏来防止在特定情况下使用接口。 例如,可以在 COM 映射中紧靠在 COM_INTERFACE_ENTRY_AGGREGATE_BLIND 的前面插入此宏,以防止将接口查询转发到聚合的内部未知成员。
通过将 x 追加到 IID_
来构造接口 IID。 例如,如果 x 为 IPersistStorage
,则 IID 为 IID_IPersistStorage
。