Instrukcje: tworzenie wystąpień CComPtr i CComQIPtr i korzystanie z nich
W klasycznym programowaniu systemu Windows biblioteki są często implementowane jako obiekty COM (lub dokładniej jako serwery COM). Wiele składników systemu operacyjnego Windows jest implementowanych jako serwery COM, a wielu współautorów udostępnia biblioteki w tej formie. Aby uzyskać informacje o podstawach modelu COM, zobacz Model obiektów składników (COM).
Podczas tworzenia wystąpienia obiektu Modelu obiektów składowych (COM) należy przechowywać wskaźnik interfejsu w inteligentnym wskaźniku COM, który wykonuje zliczanie odwołań przy użyciu wywołań do AddRef
i Release
w destruktorze. Jeśli używasz biblioteki Active Template Library (ATL) lub biblioteki klas Microsoft Foundation (MFC), użyj inteligentnego CComPtr
wskaźnika. Jeśli nie używasz atl lub MFC, użyj polecenia _com_ptr_t
. Ponieważ nie ma odpowiednika std::unique_ptr
MODELU COM, należy użyć tych inteligentnych wskaźników zarówno w scenariuszach pojedynczego właściciela, jak i wielu właścicieli. Zarówno operacje CComPtr
przenoszenia, jak i ComQIPtr
obsługują operacje przenoszenia, które mają odwołania rvalue.
Przykład: CComPtr
W poniższym przykładzie pokazano, jak utworzyć CComPtr
wystąpienie obiektu COM i uzyskać wskaźniki do interfejsów. Zwróć uwagę, że CComPtr::CoCreateInstance
funkcja składowa jest używana do tworzenia obiektu COM zamiast funkcji Win32 o tej samej nazwie.
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
i jego względy są częścią ATL i są zdefiniowane w <atlcomcli.h>. _com_ptr_t
jest zadeklarowany w pliku <comip.h>. Kompilator tworzy specjalizacje _com_ptr_t
podczas generowania klas otoki dla bibliotek typów.
Przykład: CComQIPt
AtL udostępnia CComQIPtr
również funkcję , która ma prostszą składnię do wykonywania zapytań względem obiektu COM w celu pobrania dodatkowego interfejsu. Zalecamy CComPtr
jednak, ponieważ robi to wszystko, co CComQIPtr
może zrobić i jest semantycznie bardziej spójne z nieprzetworzonymi wskaźnikami interfejsu COM. Jeśli używasz elementu CComPtr
do wykonywania zapytań dotyczących interfejsu, nowy wskaźnik interfejsu zostanie umieszczony w parametrze out. Jeśli wywołanie nie powiedzie się, zwracany jest element HRESULT, który jest typowym wzorcem MODELU COM. W przypadku CComQIPtr
parametru wartość zwracana jest samym wskaźnikiem, a jeśli wywołanie zakończy się niepowodzeniem, nie można uzyskać dostępu do wewnętrznej wartości zwracanej HRESULT. W poniższych dwóch wierszach pokazano, jak mechanizmy obsługi błędów w CComPtr
systemie i CComQIPtr
różnią się.
// 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*/ }
Przykład: IDispatch
CComPtr
Zapewnia specjalizację IDispatch, która umożliwia przechowywanie wskaźników do składników automatyzacji COM i wywoływanie metod w interfejsie przy użyciu opóźnionego powiązania. CComDispatchDriver
jest typedef dla CComQIPtr<IDispatch, &IIDIDispatch>
, który jest niejawnie konwertowany na CComPtr<IDispatch>
. W związku z tym, gdy dowolna z tych trzech nazw pojawia się w kodzie, jest równoważna .CComPtr<IDispatch>
W poniższym przykładzie pokazano, jak uzyskać wskaźnik do modelu obiektów programu Microsoft Word przy użyciu elementu 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();
}
Zobacz też
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla