Comment : Créer et utiliser les instances de CComPtr et de CComQIPtr
En programmation Windows classique, les bibliothèques sont souvent implémentées en tant qu'objets COM (ou plus précisément, en tant que serveurs COM).De nombreux composants de système d'exploitation Windows sont implémentées en tant que serveurs COM et de nombreux contributeurs disposent de bibliothèques dans ce formulaire.Pour plus d'informations sur les principes fondamentaux de COM, consultez Component Object Model (COM).
Lorsque vous instanciez un objet modèle d'objet composant (COM), stocker le pointeur d'interface dans un pointeur intelligent COM, qui effectue le décompte de références à l'aide d'appels à AddRef et Release dans le destructeur.Si vous utilisez la bibliothèque ATL (Active Template) ou le MFC Microsoft Foundation Class Library (), puis utilisez la CComPtr pointeur intelligent.Si vous n'utilisez pas ATL ou MFC, utilisez _com_ptr_t.Étant donné qu'aucun COM équivalent à std::unique_ptr, utilisez ces pointeurs intelligents pour unique propriétaire et propriétaire de plusieurs scénarios.Les deux CComPtr et ComQIPtr prise en charge de déplacer des opérations qui ont des références de valeur rvalue.
Exemple
L'exemple suivant montre comment utiliser CComPtr pour instancier un objet COM et obtenir des pointeurs sur ses interfaces.Notez que le CComPtr::CoCreateInstance fonction membre est utilisée pour créer l'objet COM, au lieu de la fonction Win32 qui porte le même nom.
void CComPtrDemo()
{
HRESULT hr = CoInitialize(NULL);
// Declare the smart pointer.
CComPtr<IGraphBuilder> pGraph;
// Use its member function CoCreateInstance to
// create the COM object and obtain the IGraphBuilder pointer.
hr = pGraph.CoCreateInstance(CLSID_FilterGraph);
if(FAILED(hr)){ /*... handle hr error*/ }
// Use the overloaded -> operator to call the interface methods.
hr = pGraph->RenderFile(L"C:\\Users\\Public\\Music\\Sample Music\\Sleep Away.mp3", NULL);
if(FAILED(hr)){ /*... handle hr error*/ }
// Declare a second smart pointer and use it to
// obtain another interface from the object.
CComPtr<IMediaControl> pControl;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
if(FAILED(hr)){ /*... handle hr error*/ }
// Obtain a third interface.
CComPtr<IMediaEvent> pEvent;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pEvent));
if(FAILED(hr)){ /*... handle hr error*/ }
// Use the second interface.
hr = pControl->Run();
if(FAILED(hr)){ /*... handle hr error*/ }
// Use the third interface.
long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);
CoUninitialize();
// Let the smart pointers do all reference counting.
}
CComPtret ses parents font partie de la bibliothèque ATL et sont définis dans atlcomcli.h._com_ptr_test déclaré dans comip.h.Le compilateur crée des spécialisations de _com_ptr_t lorsqu'il génère des classes wrapper pour les bibliothèques de types.
ATL fournit également des CComQIPtr, qui a une syntaxe plus simple pour l'interrogation d'un objet COM pour récupérer une interface supplémentaire.Toutefois, nous vous recommandons CComPtr , car il fait tout ce qui CComQIPtr peut faire et sémantiquement plus cohérent avec les pointeurs d'interface COM bruts.Si vous utilisez un CComPtr pour interroger une interface, le pointeur d'interface est placé dans un paramètre out.Si l'appel échoue, un HRESULT est retourné, ce qui est le modèle COM classique.Avec CComQIPtr, la valeur de retour est le pointeur lui-même, et si l'appel échoue, la valeur de retour HRESULT interne n'est pas accessible.Comment afficher les deux suivante les lignes dans des mécanismes de gestion des erreurs CComPtr et CComQIPtr diffèrent.
// CComPtr with error handling:
CComPtr<IMediaControl> pControl;
hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
if(FAILED(hr)){ /*... handle hr error*/ }
// CComQIPtr with error handling
CComQIPtr<IMediaEvent> pEvent = pControl;
if(!pEvent){ /*... handle NULL pointer error*/ }
// Use the second interface.
hr = pControl->Run();
if(FAILED(hr)){ /*... handle hr error*/ }
CComPtrFournit une spécialisation de IDispatch qui lui permet de stocker des pointeurs vers des composants d'automatisation COM et appeler les méthodes sur l'interface à l'aide d'une liaison tardive.CComDispatchDriverest un typedef pour CComQIPtr<IDispatch, &IIDIDispatch>, qui est implicitement convertible en CComPtr<IDispatch>.Par conséquent, lorsqu'un de ces trois noms apparaît dans le code, il est équivalent à CComPtr<IDispatch>.L'exemple suivant montre comment obtenir un pointeur vers le modèle objet Microsoft Word à l'aide d'un CComPtr<IDispatch>.
void COMAutomationSmartPointerDemo()
{
CComPtr<IDispatch> pWord;
CComQIPtr<IDispatch, &IID_IDispatch> pqi = pWord;
CComDispatchDriver pDriver = pqi;
HRESULT hr;
_variant_t pOutVal;
CoInitialize(NULL);
hr = pWord.CoCreateInstance(L"Word.Application", NULL, CLSCTX_LOCAL_SERVER);
if(FAILED(hr)){ /*... handle hr error*/ }
// Make Word visible.
hr = pWord.PutPropertyByName(_bstr_t("Visible"), &_variant_t(1));
if(FAILED(hr)){ /*... handle hr error*/ }
// Get the Documents collection and store it in new CComPtr
hr = pWord.GetPropertyByName(_bstr_t("Documents"), &pOutVal);
if(FAILED(hr)){ /*... handle hr error*/ }
CComPtr<IDispatch> pDocuments = pOutVal.pdispVal;
// Use Documents to open a document
hr = pDocuments.Invoke1 (_bstr_t("Open"), &_variant_t("c:\\users\\public\\documents\\sometext.txt"),&pOutVal);
if(FAILED(hr)){ /*... handle hr error*/ }
CoUninitialize();
}