次の方法で共有


オブジェクトにインターフェイスを要求する

先ほど、オブジェクトが複数のインターフェイスを実装できることを確認しました。 Common Item Dialog オブジェクトは、この実際の例です。 最も一般的な用途をサポートするために、 オブジェクトは IFileOpenDialog インターフェイスを実装します。 このインターフェイスは、ダイアログ ボックスを表示し、選択したファイルに関する情報を取得するための基本的なメソッドを定義します。 ただし、より高度に使用するために、 オブジェクトには IFileDialogCustomize という名前のインターフェイスも実装されています。 プログラムでは、このインターフェイスを使用して、新しい UI コントロールを追加することで、ダイアログ ボックスの外観と動作をカスタマイズできます。

すべての COM インターフェイスは、 IUnknown インターフェイスから直接または間接的に継承する必要があることを思い出してください。 次の図は、共通項目ダイアログ オブジェクトの継承を示しています。

共通項目ダイアログ オブジェクトによって公開されるインターフェイスを示す図

図からわかるように、 IFileOpenDialog の直接の先祖は IFileDialog インターフェイスであり、 IModalWindow を継承します。 継承チェーンを IFileOpenDialog から IModalWindow に上げると、インターフェイスはますます一般化されたウィンドウ機能を定義します。 最後に、 IModalWindow インターフェイスは IUnknown を継承します。 Common Item Dialog オブジェクトは、個別の継承チェーンに存在する IFileDialogCustomize も実装します。

次に、 IFileOpenDialog インターフェイスへのポインターがあるとします。 IFileDialogCustomize インターフェイスへのポインターを取得するにはどうすればよいですか?

同じオブジェクト上のインターフェイスへの 2 つのインターフェイス ポインターを示す図

IFileOpenDialog ポインターを IFileDialogCustomize ポインターにキャストするだけでは機能しません。 言語に依存する高度な機能である何らかの形式のランタイム型情報 (RTTI) を使用せずに、継承階層全体で "クロス キャスト" する信頼性の高い方法はありません。

COM アプローチでは、最初のインターフェイスをオブジェクトへの導管として使用して、IFileDialogCustomize ポインターをオブジェクトに渡すように求めます。 これは、最初のインターフェイス ポインターから IUnknown::QueryInterface メソッドを呼び出すことによって行われます。 QueryInterface は、C++ のdynamic_cast キーワード (keyword)の言語に依存しないバージョンと考えることができます。

QueryInterface メソッドには、次のシグネチャがあります。

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

CoCreateInstance について既に知っていることに基づいて、QueryInterface のしくみを推測できる場合があります。

  • riid パラメーターは、要求するインターフェイスを識別する GUID です。 データ型 REFIID は の typedefconst 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 でのメモリ割り当て