Recuperando propriedades para vários objetos
Alguns drivers de dispositivo dão suporte à recuperação de propriedades para vários objetos em uma única chamada de função; isso é chamado de recuperação em massa. Há dois tipos de operações de recuperação em massa: o primeiro tipo recupera propriedades para uma lista de objetos e o segundo tipo recupera propriedades para todos os objetos de um determinado formato. O exemplo descrito nesta seção demonstra o primeiro.
Seu aplicativo pode executar uma recuperação em massa usando as interfaces descritas na tabela a seguir.
Interface | Descrição |
---|---|
IPortableDeviceContent Interface | Fornece acesso aos métodos específicos do conteúdo. |
IPortableDeviceKeyCollection Interface | Usado para identificar as propriedades a serem recuperadas. |
IPortableDeviceProperties Interface | Usado para determinar se um determinado driver dá suporte a operações em massa. |
IPortableDevicePropertiesBulk Interface | Dá suporte à operação de recuperação em massa. |
IPortableDevicePropVariantCollection Interface | Usado para armazenar os identificadores de objeto para a operação em massa. |
A função ReadContentPropertiesBulk no módulo ContentProperties.cpp do aplicativo de exemplo demonstra uma operação de recuperação em massa.
A primeira tarefa realizada neste exemplo é determinar se o driver determinado dá suporte ou não a operações em massa. Isso é feito chamando QueryInterface na interface IPortableDeviceProperties e verificando a existência de IPortableDevicePropertiesBulk.
HRESULT hr = S_OK;
GUID guidContext = GUID_NULL;
CGetBulkValuesCallback* pCallback = NULL;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDevicePropertiesBulk> pPropertiesBulk;
CComPtr<IPortableDeviceValues> pObjectProperties;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead;
CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
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");
}
}
Se o driver der suporte a operações em massa, a próxima etapa será criar uma instância da interface IPortableDeviceKeyCollection e especificar as chaves que correspondem às propriedades que o aplicativo recuperará. Para obter uma descrição desse processo, consulte o tópico Recuperando propriedades de um único objeto .
Depois que as chaves apropriadas são especificadas, o aplicativo de exemplo cria uma instância da interface IPortableDevicePropertiesBulkCallback. O aplicativo usará os métodos nessa interface para acompanhar o progresso da operação de recuperação em massa assíncrona.
if (SUCCEEDED(hr))
{
pCallback = new CGetBulkValuesCallback();
if (pCallback == NULL)
{
hr = E_OUTOFMEMORY;
printf("! Failed to allocate CGetBulkValuesCallback, hr = 0x%lx\n", hr);
}
}
A próxima função que o aplicativo de exemplo chama é a função auxiliar CreateIPortableDevicePropVariantCollectionWithAllObjectIDs. Essa função cria uma lista de todos os identificadores de objeto disponíveis para fins de exemplo. (Um aplicativo do mundo real limitaria a lista de identificadores a um determinado conjunto de objetos. Por exemplo, um aplicativo pode criar uma lista de identificadores para todos os objetos atualmente em uma determinada exibição de pasta.)
Conforme observado acima, a função auxiliar enumera recursivamente todos os objetos em um determinado dispositivo. Ele retorna essa lista em uma interface IPortableDevicePropVariantCollection que contém um identificador para cada objeto encontrado. A função auxiliar é definida no módulo ContentEnumeration.cpp.
// 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);
}
Depois que as etapas anteriores forem realizadas, o aplicativo de exemplo iniciará a recuperação de propriedade assíncrona. Isso é feito fazendo o seguinte:
- Chamando IPortableDevicePropertiesBulk::QueueGetValuesByObjectList, que enfileira uma solicitação para a recuperação de propriedade em massa. (Observe que, embora a solicitação esteja na fila, ela não foi iniciada.)
- Chamando IPortableDevicePropertiesBulk::Start para iniciar a solicitação na fila.
Essas etapas são demonstradas no trecho de código a seguir do aplicativo de exemplo.
if (SUCCEEDED(hr))
{
hr = pPropertiesBulk->QueueGetValuesByObjectList(pObjectIDs,
pPropertiesToRead,
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("! QueueGetValuesByObjectList Failed, hr = 0x%lx\n", hr);
}
}
Tópicos relacionados