Partager via


Demande d’un objet pour une interface

Nous avons vu précédemment qu’un objet peut implémenter plusieurs interfaces. L’objet Common Item Dialog en est un exemple réel. Pour prendre en charge les utilisations les plus courantes, l’objet implémente l’interface IFileOpenDialog . Cette interface définit des méthodes de base pour afficher la boîte de dialogue et obtenir des informations sur le fichier sélectionné. Toutefois, pour une utilisation plus avancée, l’objet implémente également une interface nommée IFileDialogCustomize. Un programme peut utiliser cette interface pour personnaliser l’apparence et le comportement de la boîte de dialogue, en ajoutant de nouveaux contrôles d’interface utilisateur.

Rappelez-vous que chaque interface COM doit hériter, directement ou indirectement, de l’interface IUnknown . Le diagramme suivant montre l’héritage de l’objet Common Item Dialog.

diagramme montrant les interfaces exposées par l’objet de boîte de dialogue d’élément commun

Comme vous pouvez le voir dans le diagramme, l’ancêtre direct de IFileOpenDialog est l’interface IFileDialog , qui hérite à son tour de IModalWindow. À mesure que vous remontez la chaîne d’héritage de IFileOpenDialog à IModalWindow, les interfaces définissent des fonctionnalités de fenêtre de plus en plus généralisées. Enfin, l’interface IModalWindow hérite de IUnknown. L’objet Common Item Dialog implémente également IFileDialogCustomize, qui existe dans une chaîne d’héritage distincte.

Supposons maintenant que vous disposez d’un pointeur vers l’interface IFileOpenDialog . Comment obtenir un pointeur vers l’interface IFileDialogCustomize ?

diagramme montrant deux pointeurs d’interface vers des interfaces sur le même objet

Le simple cast du pointeur IFileOpenDialog vers un pointeur IFileDialogCustomize ne fonctionnera pas. Il n’existe aucun moyen fiable de « passer en croix » dans une hiérarchie d’héritage, sans une certaine forme d’informations de type d’exécution (RTTI), qui est une fonctionnalité fortement dépendante du langage.

L’approche COM consiste à demander à l’objet de vous donner un pointeur IFileDialogCustomize , en utilisant la première interface comme conduit dans l’objet . Pour ce faire, appelez la méthode IUnknown::QueryInterface à partir du premier pointeur d’interface. Vous pouvez considérer QueryInterface comme une version indépendante du langage du mot clé dynamic_cast en C++.

La méthode QueryInterface a la signature suivante :

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

D’après ce que vous savez déjà sur CoCreateInstance, vous pourrez peut-être deviner le fonctionnement de QueryInterface .

  • Le paramètre riid est le GUID qui identifie l’interface que vous demandez. Le type de données REFIID est un typedef pour const GUID&. Notez que l’identificateur de classe (CLSID) n’est pas obligatoire, car l’objet a déjà été créé. Seul l’identificateur d’interface est nécessaire.
  • Le paramètre ppvObject reçoit un pointeur vers l’interface. Le type de données de ce paramètre est void**, pour la même raison que CoCreateInstance utilise ce type de données : QueryInterface peut être utilisé pour interroger n’importe quelle interface COM, de sorte que le paramètre ne peut pas être fortement typé.

Voici comment appeler QueryInterface pour obtenir un pointeur IFileDialogCustomize :

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

    pCustom->Release();
}
else
{
    // Handle the error.
}

Comme toujours, case activée la valeur de retour HRESULT en cas d’échec de la méthode. Si la méthode réussit, vous devez appeler Release lorsque vous avez terminé d’utiliser le pointeur, comme décrit dans Gestion de la durée de vie d’un objet.

Suivant

Allocation de mémoire dans COM