要求物件取得介面
我們稍早發現物件可以實作多個介面。 Common Item Dialog 物件是這個的實際範例。 為了支援最常見的用途,物件會實作 IFileOpenDialog 介面。 此介面會定義用來顯示對話方塊和取得所選檔案相關資訊的基本方法。 不過,為了進階使用,物件也會實作名為 IFileDialogCustomize 的介面。 程式可以使用這個介面來自訂對話方塊的外觀和行為,方法是新增 UI 控制項。
回想一下,每個 COM 介面都必須直接或間接繼承自 IUnknown 介面。 下圖顯示通用專案對話方塊物件的繼承。
如您從圖表中所見, IFileOpenDialog 的直接上階是 IFileDialog 介面,接著會繼承 IModalWindow。 當您將繼承鏈結從 IFileOpenDialog 向上移至 IModalWindow時,介面會定義逐漸一般化的視窗功能。 最後, IModalWindow 介面繼承 IUnknown。 通用專案對話方塊物件也會實作存在於個別繼承鏈結中的 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是 的
const GUID&
typedef。 請注意, (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 ,如 管理物件的存留期中所述。
下一個