Postupy: Vytváření a používání instancí CComPtr a CComQIPtr

V klasickém programování systému Windows se knihovny často implementují jako objekty MODELU COM (přesněji jako servery COM). Mnoho součástí operačního systému Windows se implementuje jako servery COM a mnoho přispěvatelů poskytuje knihovny v tomto formuláři. Informace o základech modelu COM naleznete v tématu Model com (Component Object Model).

Když vytvoříte instanci objektu MODELU COM (Component Object Model), uložte ukazatel rozhraní do inteligentního ukazatele MODELU COM, který provádí počítání odkazů pomocí volání a AddRefRelease destruktoru. Pokud používáte knihovnu ATL (Active Template Library) nebo knihovnu tříd Microsoft Foundation (MFC), použijte CComPtr inteligentní ukazatel. Pokud nepoužíváte knihovnu ATL nebo MFC, použijte _com_ptr_t. Vzhledem k tomu, že neexistuje žádný ekvivalent std::unique_ptrmodelu COM, použijte tyto inteligentní ukazatele pro scénáře s jedním vlastníkem i více vlastníky. Operace CComPtr přesunu, které mají odkazy na rvalue, a ComQIPtr podporují je.

Příklad: CComPtr

Následující příklad ukazuje, jak použít CComPtr k vytvoření instance objektu COM a získání ukazatelů na jeho rozhraní. Všimněte si, že členová CComPtr::CoCreateInstance funkce slouží k vytvoření objektu COM místo funkce Win32 se stejným názvem.

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.
}

CComPtr a jeho příbuzní jsou součástí knihovny ATL a jsou definovány v <atlcomcli.h>. _com_ptr_t je deklarován v <souboru comip.h>. Kompilátor vytváří specializace _com_ptr_t při generování tříd obálky pro knihovny typů.

Příklad: CComQIPtr

ATL také poskytuje CComQIPtr, která má jednodušší syntaxi pro dotazování objektu COM na načtení dalšího rozhraní. Doporučujeme ale, protože dělá vše, CComPtr co CComQIPtr může dělat a je sémanticky konzistentnější s nezpracovanými ukazateli rozhraní MODELU COM. Pokud použijete CComPtr dotaz na rozhraní, nový ukazatel rozhraní se umístí do výstupního parametru. Pokud volání selže, vrátí se hodnota HRESULT, což je typický vzor modelu COM. S CComQIPtr, návratová hodnota je samotný ukazatel, a pokud volání selže, interní vrácená hodnota HRESULT nelze získat přístup. Následující dva řádky ukazují, jak se mechanismy zpracování chyb liší CComPtrCComQIPtr .

// 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*/ }

Příklad: IDispatch

CComPtr poskytuje specializaci pro IDispatch, která umožňuje ukládat ukazatele na komponenty automatizace modelu COM a vyvolat metody v rozhraní pomocí pozdní vazby. CComDispatchDriver je typedef pro CComQIPtr<IDispatch, &IIDIDispatch>, který je implicitně konvertibilní na CComPtr<IDispatch>. Proto, pokud se některý z těchto tří názvů zobrazí v kódu, je ekvivalentní CComPtr<IDispatch>. Následující příklad ukazuje, jak získat ukazatel na objektový model aplikace Microsoft Word pomocí 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();
}

Viz také

Chytré ukazatele (moderní verze jazyka C++)