Bagikan melalui


Cara: Membuat dan menggunakan instans CComPtr dan CComQIPtr

Dalam pemrograman Windows klasik, pustaka sering diimplementasikan sebagai objek COM (atau lebih tepatnya, sebagai server COM). Banyak komponen sistem operasi Windows diimplementasikan sebagai server COM, dan banyak kontributor menyediakan pustaka dalam bentuk ini. Untuk informasi tentang dasar-dasar COM, lihat Model Objek Komponen (COM).

Saat Anda membuat instans objek Model Objek Komponen (COM), simpan penunjuk antarmuka di penunjuk pintar COM, yang melakukan penghitungan referensi dengan menggunakan panggilan ke AddRef dan Release di destruktor. Jika Anda menggunakan Pustaka Templat Aktif (ATL) atau Pustaka Kelas Microsoft Foundation (MFC), gunakan penunjuk CComPtr cerdas. Jika Anda tidak menggunakan ATL atau MFC, maka gunakan _com_ptr_t. Karena tidak ada COM yang setara std::unique_ptrdengan , gunakan pointer pintar ini untuk skenario pemilik tunggal dan beberapa pemilik. Baik CComPtr dan ComQIPtr mendukung operasi pemindahan yang memiliki referensi rvalue.

Contoh: CComPtr

Contoh berikut menunjukkan cara menggunakan CComPtr untuk membuat instans objek COM dan mendapatkan penunjuk ke antarmukanya. Perhatikan bahwa CComPtr::CoCreateInstance fungsi anggota digunakan untuk membuat objek COM, bukan fungsi Win32 yang memiliki nama yang sama.

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 dan kerabatnya adalah bagian dari ATL dan didefinisikan dalam <atlcomcli.h>. _com_ptr_t dinyatakan dalam <comip.h>. Pengkompilasi membuat spesialisasi _com_ptr_t ketika menghasilkan kelas pembungkus untuk pustaka jenis.

Contoh: CComQIPt

ATL juga menyediakan CComQIPtr, yang memiliki sintaks yang lebih sederhana untuk mengkueri objek COM untuk mengambil antarmuka tambahan. Namun, kami sarankan CComPtr karena melakukan semua yang CComQIPtr dapat dilakukan dan secara semantik lebih konsisten dengan penunjuk antarmuka COM mentah. Jika Anda menggunakan untuk mengkueri CComPtr antarmuka, penunjuk antarmuka baru ditempatkan dalam parameter keluar. Jika panggilan gagal, HRESULT dikembalikan, yang merupakan pola COM khas. Dengan CComQIPtr, nilai yang dikembalikan adalah penunjuk itu sendiri, dan jika panggilan gagal, nilai pengembalian HRESULT internal tidak dapat diakses. Dua baris berikut menunjukkan bagaimana mekanisme penanganan kesalahan dan CComPtrCComQIPtr berbeda.

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

Contoh: IDispatch

CComPtr menyediakan spesialisasi untuk IDispatch yang memungkinkannya menyimpan pointer ke komponen otomatisasi COM dan memanggil metode pada antarmuka dengan menggunakan pengikatan terlambat. CComDispatchDriver adalah typedef untuk CComQIPtr<IDispatch, &IIDIDispatch>, yang secara implisit dapat dikonversi ke CComPtr<IDispatch>. Oleh karena itu, ketika salah satu dari ketiga nama ini muncul dalam kode, nama tersebut setara dengan CComPtr<IDispatch>. Contoh berikut menunjukkan cara mendapatkan penunjuk ke model objek Microsoft Word dengan menggunakan 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();
}

Baca juga

Penunjuk Cerdas (Modern C++)