Compartir a través de


Cómo: Cree y use las instancias CComPtr y de CComQIPtr

En la programación de Windows clásica, las bibliotecas a menudo se implementan como objetos COM (o más exactamente, como servidores COM).Muchos componentes del sistema operativo Windows se implementan como servidores COM y muchos de los colaboradores proporcionan las bibliotecas en este formulario.Para obtener información acerca de los fundamentos de COM, consulte Component Object Model (COM).

Al crear una instancia de un objeto de modelo de objetos componentes (COM), almacene el puntero de interfaz en un puntero inteligente COM, que realiza la referencia contar mediante llamadas a AddRef y Release en el destructor.Si está utilizando Active Template Library (ATL) o la biblioteca de clase de base de Microsoft (MFC), a continuación, utilice la CComPtr puntero inteligente.Si no utiliza ATL o MFC, a continuación, utilice _com_ptr_t.Porque no hay ningún COM equivalente a std::unique_ptr, utilice estos punteros inteligentes único propietario y propietario de múltiples escenarios.Ambos CComPtr y ComQIPtr soporte mover las operaciones que tienen las referencias de rvalue.

Ejemplo

En el ejemplo siguiente se muestra cómo utilizar CComPtr para crear una instancia de un objeto COM y obtener punteros a sus interfaces.Observe que la CComPtr::CoCreateInstance se utiliza la función miembro para crear el objeto COM, en lugar de la función de Win32 que tiene el mismo nombre.

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

CComPtry sus parientes forman parte de la biblioteca ATL y se definen en atlcomcli.h._com_ptr_tse declara en comip.h.El compilador crea especializaciones de _com_ptr_t cuando genera clases contenedoras para las bibliotecas de tipos.

ATL también proporciona CComQIPtr, que tiene una sintaxis más sencilla para consultar un objeto COM para recuperar una interfaz adicional.Sin embargo, se recomienda CComPtr debido a que hace todo lo que CComQIPtr puede hacer y es semánticamente más coherentes con los punteros de interfaz COM sin formato.Si utiliza un CComPtr para consultar una interfaz, el nuevo puntero de interfaz se coloca en un parámetro de salida.Si se produce un error en la llamada, se devuelve un valor HRESULT, que es el patrón de COM típico.Con CComQIPtr, el valor devuelto es el puntero de sí mismo, y si se produce un error en la llamada, el valor de retorno HRESULT interno no puede tener acceso.Los dos siguientes líneas mostrar cómo los mecanismos de control de errores CComPtr y CComQIPtr son diferentes.

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

CComPtrproporciona una especialización de IDispatch que le permite almacenar punteros a los componentes de automatización COM e invocar los métodos de la interfaz mediante el enlace en tiempo de ejecución.CComDispatchDriveres un typedef para CComQIPtr<IDispatch, &IIDIDispatch>, que es implícitamente convertible a CComPtr<IDispatch>.Por lo tanto, cuando cualquiera de estos tres nombres aparece en el código, es equivalente a CComPtr<IDispatch>.En el ejemplo siguiente se muestra cómo obtener un puntero para el modelo de objetos de Microsoft Word mediante el uso de 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();
}

Vea también

Conceptos

Punteros inteligentes (C++ moderno)