Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Niektóre sterowniki urządzeń obsługują właściwości ustawień dla wielu obiektów w jednym wywołaniu funkcji — jest to nazywane zapisem zbiorczym. Aplikacja może wykonywać operacje zapisu zbiorczego przy użyciu interfejsów opisanych w poniższej tabeli.
| Interfejs | Opis |
|---|---|
| interfejsu IPortableDeviceContent | Zapewnia dostęp do metod specyficznych dla zawartości. |
| Interfejs IPortableDeviceProperties | Zapewnia dostęp do metod specyficznych dla właściwości. |
| Interfejs IPortableDevicePropertiesBulk | Obsługuje operację zapisu zbiorczego. |
| Interfejs IPortableDevicePropVariantCollection | Służy do przechowywania identyfikatorów obiektów dla operacji zbiorczej. |
| Interfejs IPortableDeviceValuesCollection | Jest używane do identyfikowania właściwości, które mają być zapisane. |
Funkcja WriteContentPropertiesBulk w module ContentProperties.cpp przykładowej aplikacji demonstruje operację zapisu zbiorczego.
Pierwsze zadanie wykonane w tym przykładzie określa, czy dany sterownik obsługuje operacje zbiorcze. Jest to realizowane przez wywołanie elementu QueryInterface w obiekcie IPortableDeviceProperties i sprawdzenie istnienia obiektu IPortableDevicePropertiesBulk.
HRESULT hr = S_OK;
GUID guidContext = GUID_NULL;
CSetBulkValuesCallback* pCallback = NULL;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDevicePropertiesBulk> pPropertiesBulk;
CComPtr<IPortableDeviceValues> pObjectProperties;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceValuesCollection> pPropertiesToWrite;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
DWORD cObjectIDs = 0;
if (SUCCEEDED(hr))
{
hr = pDevice->Content(&pContent);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr);
}
}
if (SUCCEEDED(hr))
{
hr = pContent->Properties(&pProperties);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr);
}
}
if (SUCCEEDED(hr))
{
hr = pProperties->QueryInterface(IID_PPV_ARGS(&pPropertiesBulk));
if (FAILED(hr))
{
printf("This driver does not support BULK property operations.\n");
}
}
Następne zadanie wiąże się z utworzeniem obiektu IPortableDeviceValuesCollection. Jest to obiekt, który zawiera wartości właściwości, które zapisze przykład.
HRESULT hr = S_OK;
GUID guidContext = GUID_NULL;
CSetBulkValuesCallback* pCallback = NULL;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDevicePropertiesBulk> pPropertiesBulk;
CComPtr<IPortableDeviceValues> pObjectProperties;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceValuesCollection> pPropertiesToWrite;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
DWORD cObjectIDs = 0;
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_PortableDeviceValuesCollection,
NULL,
CLSCTX_INPROC_SERVER,
IID_IPortableDeviceValuesCollection,
(VOID**) &pPropertiesToWrite);
if (FAILED(hr))
{
printf("! Failed to CoCreate IPortableDeviceValuesCollection for bulk property values, hr = 0x%lx\n", hr);
}
}
Następnie przykład tworzy wystąpienie interfejsu IPortableDevicePropertiesBulkCallback. Aplikacja będzie używać metod w tym interfejsie do śledzenia postępu asynchronicznej operacji zapisu zbiorczego.
HRESULT hr = S_OK;
GUID guidContext = GUID_NULL;
CSetBulkValuesCallback* pCallback = NULL;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDevicePropertiesBulk> pPropertiesBulk;
CComPtr<IPortableDeviceValues> pObjectProperties;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceValuesCollection> pPropertiesToWrite;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
DWORD cObjectIDs = 0;
if (SUCCEEDED(hr))
{
pCallback = new CSetBulkValuesCallback();
if (pCallback == NULL)
{
hr = E_OUTOFMEMORY;
printf("! Failed to allocate CSetBulkValuesCallback, hr = 0x%lx\n", hr);
}
}
Następną funkcją wywoływaną przez przykładową aplikację jest funkcja pomocnika CreateIPortableDevicePropVariantCollectionWithAllObjectIDs. Ta funkcja rekursywnie wylicza wszystkie obiekty na danym urządzeniu i zwraca interfejs IPortableDevicePropVariantCollection zawierający identyfikator każdego znalezionego obiektu. Ta funkcja jest zdefiniowana w ContentEnumeration.cpp modułu.
// 7) Call our helper function CreateIPortableDevicePropVariantCollectionWithAllObjectIDs
// to enumerate and create an IPortableDevicePropVariantCollection with the object
// identifiers needed to perform the bulk operation on.
if (SUCCEEDED(hr))
{
hr = CreateIPortableDevicePropVariantCollectionWithAllObjectIDs(pDevice,
pContent,
&pObjectIDs);
}
Obiekt IPortableDevicePropVariantCollection zawiera kolekcję indeksowanych wartości typu PROPVARIANT o tym samym VARTYPE. W takim przypadku te wartości zawierają określony identyfikator obiektu dla każdego obiektu znalezionego na urządzeniu.
Identyfikatory obiektów i ich odpowiednie właściwości nazw są przechowywane w obiekcie IPortableDeviceValuesCollection. Właściwości nazwy są zorganizowane w taki sposób, że pierwszy obiekt ma przypisaną właściwość o nazwie "NewName0", drugi obiekt ma przypisaną właściwość o nazwie "NewName1" i tak dalej.
Poniższy fragment z przykładu pokazuje, jak obiekt IPortableDeviceValuesCollection został zainicjowany przy użyciu identyfikatorów obiektów i nowych ciągów nazw.
HRESULT hr = S_OK;
GUID guidContext = GUID_NULL;
CSetBulkValuesCallback* pCallback = NULL;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDevicePropertiesBulk> pPropertiesBulk;
CComPtr<IPortableDeviceValues> pObjectProperties;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceValuesCollection> pPropertiesToWrite;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
DWORD cObjectIDs = 0;
if (SUCCEEDED(hr))
{
hr = pObjectIDs->GetCount(&cObjectIDs);
if (FAILED(hr))
{
printf("! Failed to get number of objectIDs from IPortableDevicePropVariantCollection, hr = 0x%lx\n", hr);
}
}
if (SUCCEEDED(hr))
{
for(DWORD dwIndex = 0; (dwIndex < cObjectIDs) && (hr == S_OK); dwIndex++)
{
CComPtr<IPortableDeviceValues> pValues;
PROPVARIANT pv = {0};
PropVariantInit(&pv);
hr = CoCreateInstance(CLSID_PortableDeviceValues,
NULL,
CLSCTX_INPROC_SERVER,
IID_IPortableDeviceValues,
(VOID**) &pValues);
if (FAILED(hr))
{
printf("! Failed to CoCreate CLSID_PortableDeviceValues, hr = 0x%lx\n", hr);
}
// Get the Object ID whose properties we will set
if (hr == S_OK)
{
hr = pObjectIDs->GetAt(dwIndex, &pv);
if (FAILED(hr))
{
printf("! Failed to get next Object ID from list, hr = 0x%lx\n", hr);
}
}
// Save them into the IPortableDeviceValues so the driver knows which object this proeprty set belongs to
if (hr == S_OK)
{
hr = pValues->SetStringValue(WPD_OBJECT_ID, pv.pwszVal);
if (FAILED(hr))
{
printf("! Failed to set WPD_OBJECT_ID, hr = 0x%lx\n", hr);
}
}
// Set the new values. In this sample, we attempt to set the name property.
if (hr == S_OK)
{
CAtlStringW strValue;
strValue.Format(L"NewName%d", dwIndex);
hr = pValues->SetStringValue(WPD_OBJECT_NAME, strValue.GetString());
if (FAILED(hr))
{
printf("! Failed to set WPD_OBJECT_NAME, hr = 0x%lx\n", hr);
}
}
// Add this property set to the collection
if (hr == S_OK)
{
hr = pPropertiesToWrite->Add(pValues);
if (FAILED(hr))
{
printf("! Failed to add values to collection, hr = 0x%lx\n", hr);
}
}
PropVariantClear(&pv);
}
}
Gdy przykład utworzy obiekt IPortableDeviceValuesCollection zawierający identyfikator obiektu i pary nazw, może rozpocząć operację asynchroniczną.
Asynchroniczna operacja zapisu rozpoczyna się, gdy przykład wywołuje metodę IPortableDevicePropertiesBulk::QueueSetValuesByObjectList. Ta metoda powiadamia sterownik, że operacja zbiorcza zaraz się rozpocznie. Następnie przykład wywołuje metodę IPortableDeviceBulk::Start, aby rozpocząć pisanie nowych wartości nazw.
HRESULT hr = S_OK;
GUID guidContext = GUID_NULL;
CSetBulkValuesCallback* pCallback = NULL;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDevicePropertiesBulk> pPropertiesBulk;
CComPtr<IPortableDeviceValues> pObjectProperties;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceValuesCollection> pPropertiesToWrite;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
DWORD cObjectIDs = 0;
if (SUCCEEDED(hr))
{
hr = pPropertiesBulk->QueueSetValuesByObjectList(pPropertiesToWrite,
pCallback,
&guidContext);
if(SUCCEEDED(hr))
{
// Cleanup any previously created global event handles.
if (g_hBulkPropertyOperationEvent != NULL)
{
CloseHandle(g_hBulkPropertyOperationEvent);
g_hBulkPropertyOperationEvent = NULL;
}
// In order to create a simpler to follow example we create and wait infinitly
// for the bulk property operation to complete and ignore any errors.
// Production code should be written in a more robust manner.
// Create the global event handle to wait on for the bulk operation
// to complete.
g_hBulkPropertyOperationEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (g_hBulkPropertyOperationEvent != NULL)
{
// Call Start() to actually being the Asynchronous bulk operation.
hr = pPropertiesBulk->Start(guidContext);
if(FAILED(hr))
{
printf("! Failed to start property operation, hr = 0x%lx\n", hr);
}
}
else
{
printf("! Failed to create the global event handle to wait on for the bulk operation. Aborting operation.\n");
}
}
else
{
printf("! QueueSetValuesByObjectList Failed, hr = 0x%lx\n", hr);
}
}
Należy pamiętać, że próbka czeka nieskończenie długi czas na ukończenie operacji. Gdyby była to aplikacja produkcyjna, należy zmodyfikować kod.
Tematy pokrewne
-
interfejs IPortableDevice
-
Interfejs IPortableDeviceProperties
-
interfejs IPortableDevicePropVariantCollection