Windows桌面应用程序(1-2-3-7th) 询问接口指向的对象

我们之前看到一个对象可以实现多个接口。Common Item对话框是一个真实的例子。为了支持最典型的用途,该对象实现了IFileOpenDialog接口。该界面定义了显示对话框和获取选定文件信息的基本方法。然而,为了更高级的使用,该对象还实现了一个名为IFileDialogCustomize的接口。程序可以使用此界面通过添加新的UI控件来自定义对话框的外观和行为。

回想一下,每个COM接口都必须直接或间接地从IUnknown接口继承。下图显示了Common Item对话框的继承。
这里写图片描述
显示Common Item对话框公开的接口的图

从图中可以看到,IFileOpenDialog的直接祖先是IFileDialog接口,继而继承IModalWindow。当你继续从IFileOpenDialogIModalWindow的继承链时,接口定义了越来越广义的窗口功能。最后,IModalWindow接口继承IUnknown。Common Item Dialog对象还实现了IFileDialogCustomize,它存在于一个单独的继承链中。

现在假设你有一个指向IFileOpenDialog接口的指针。你将如何获得一个指向IFileDialogCustomize接口的指针?
这里写图片描述
显示同一对象上两个接口指针的图

简单地将IFileOpenDialog指针转换为IFileDialogCustomize指针将不起作用。没有可靠的方法来跨越继承层次“交叉转换”,而没有某种形式的运行时类型信息(RTTI),这是一种高度依赖于语言的功能。

COM方法是让对象给你一个IFileDialogCustomize指针,使用第一个接口作为对象的管道。这是通过从第一个接口指针调用IUnknown::QueryInterface方法完成的。您可以将QueryInterface视为C ++中dynamic_cast关键字的语言无关版本。

QueryInterface方法具有以下特征:

HRESULT QueryInterface(REFIID riid,void **ppvObject);

根据您对CoCreateInstance的了解,您可能会猜到QueryInterface的工作原理。

  • RIID参数是标识你所要求的接口的GUID。数据类型REFIID是一个typedef对const GUID&。请注意,类标识符(CLSID)不是必需的,因为该对象已经创建。只有接口标识符是必需的。
  • 所述ppvObject参数接收指向该接口。该参数的数据类型为void **,这与CoCreateInstance使用此数据类型的原因相同:QueryInterface可用于查询任何COM接口,因此参数不能强类型化。

以下是您将如何调用QueryInterface以获取IFileDialogCustomize指针的方法:

hr=pFileOpen->QueryInterface(IID_IFileDialogCustomize,reinterpret_cast<void**>(&pCustom));
if(SUCCEEDED(hr)){
    // Use the interface. (Not shown.)
    // ...
    pCustom->Release();
}
else{
    // Handle the error.
}

与往常一样,检查HRESULT返回值,以防方法失败。如果方法成功,则必须在完成使用指针时调用Release,如管理对象的生存期中所述。

下一个
COM中的内存分配


原文链接:Asking an Object for an Interface

猜你喜欢

转载自blog.csdn.net/qq_37422196/article/details/79770509
今日推荐