Transferindo uma imagem ou um arquivo de música para o dispositivo
Uma das operações mais comuns realizadas por um aplicativo é a transferência de conteúdo para um dispositivo conectado.
As transferências de conteúdo são realizadas usando as interfaces descritas na tabela a seguir.
Interface | Descrição |
---|---|
IPortableDeviceContent Interface | Fornece acesso aos métodos específicos do conteúdo. |
IPortableDeviceDataStream Interface | Usado ao gravar o conteúdo no dispositivo. |
IPortableDeviceValues Interface | Usado para recuperar propriedades que descrevem o conteúdo. |
IStream Interface | Usado para simplificar a leitura de conteúdo e gravação no dispositivo. |
A TransferContentToDevice
função no módulo ContentTransfer.cpp do aplicativo de exemplo demonstra como um aplicativo pode transferir conteúdo de um computador para um dispositivo conectado. Neste exemplo específico, o conteúdo transferido pode ser um arquivo que contém uma imagem, música ou informações de contato.
A primeira tarefa realizada pela TransferContentToDevice
função é solicitar que o usuário insira um identificador de objeto, que identifica o objeto a ser transferido.
HRESULT hr = S_OK;
WCHAR szSelection[81] = {0};
WCHAR szFilePath[MAX_PATH] = {0};
DWORD cbOptimalTransferSize = 0;
CComPtr<IStream> pFileStream;
CComPtr<IPortableDeviceDataStream> pFinalObjectDataStream;
CComPtr<IPortableDeviceValues> pFinalObjectProperties;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IStream> pTempStream; // Temporary IStream which we use to QI for IPortableDeviceDataStream
// Prompt user to enter an object identifier for the parent object on the device to transfer.
printf("Enter the identifer of the parent object which the file will be transferred under.\n>");
hr = StringCbGetsW(szSelection,sizeof(szSelection));
if (FAILED(hr))
{
printf("An invalid object identifier was specified, aborting content transfer\n");
}
A segunda tarefa realizada pela TransferContentToDevice
função é criar um objeto IPortableDeviceContent chamando o método IPortableDevice::Content .
if (SUCCEEDED(hr))
{
hr = pDevice->Content(&pContent);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr);
}
}
A próxima tarefa realizada pela TransferContentToDevice
função é a criação de uma caixa de diálogo FileOpen com a qual o usuário pode especificar o local e o nome do arquivo a ser transferido.
if (SUCCEEDED(hr))
{
OPENFILENAME OpenFileNameInfo = {0};
OpenFileNameInfo.lStructSize = sizeof(OPENFILENAME);
OpenFileNameInfo.hwndOwner = NULL;
OpenFileNameInfo.lpstrFile = szFilePath;
OpenFileNameInfo.nMaxFile = ARRAYSIZE(szFilePath);
OpenFileNameInfo.lpstrFilter = pszFileTypeFilter;
OpenFileNameInfo.nFilterIndex = 1;
OpenFileNameInfo.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
OpenFileNameInfo.lpstrDefExt = pszDefaultFileExtension;
if (GetOpenFileName(&OpenFileNameInfo) == FALSE)
{
printf("The transfer operation was canceled.\n");
hr = E_ABORT;
}
}
A TransferContentToDevice
função passa uma cadeia de caracteres de filtro (wszFileTypeFilter
) para o método GetOpenFileName, que determina o tipo de arquivos que o usuário pode escolher. Consulte a DoMenu
função no módulo WpdApiSample.cpp para obter exemplos dos três filtros diferentes permitidos pelo exemplo.
Depois que o usuário identifica um arquivo específico para transferência para o dispositivo, a TransferContentToDevice
função abre esse arquivo como um objeto IStream e recupera as propriedades necessárias para concluir a transferência.
if (SUCCEEDED(hr))
{
// Open the selected file as an IStream. This will simplify reading the
// data and writing to the device.
hr = SHCreateStreamOnFile(szFilePath, STGM_READ, &pFileStream);
if (SUCCEEDED(hr))
{
// Get the required properties needed to properly describe the data being
// transferred to the device.
hr = GetRequiredPropertiesForContentType(guidContentType, // Content type of the data
szSelection, // Parent to transfer the data under
szFilePath, // Full file path to the data file
pFileStream, // Open IStream that contains the data
&pFinalObjectProperties); // Returned properties describing the data
if (FAILED(hr))
{
printf("! Failed to get required properties needed to transfer a file to the device, hr = 0x%lx\n", hr);
}
}
if (FAILED(hr))
{
printf("! Failed to open file named (%ws) to transfer to device, hr = 0x%lx\n",szFilePath, hr);
}
}
As propriedades necessárias são recuperadas chamando aGetRequiredPropertiesForContentType
função auxiliar, que opera no objeto IStream. A GetRequiredPropertiesForContentType
função auxiliar cria um objeto IPortableDeviceValues , recupera as propriedades na lista a seguir e as adiciona a esse objeto.
- Identificador de objeto pai
- Tamanho do fluxo em bytes
- Nome do arquivo de conteúdo
- Nome do conteúdo (o nome do arquivo sem a extensão)
- Tipo de conteúdo (imagem, áudio ou contato)
- Formato de conteúdo (JFIF, WMA ou vCard2)
O aplicativo de exemplo usa as propriedades recuperadas para criar o novo conteúdo no dispositivo. Isso é feito em três fases:
- O aplicativo chama o método IPortableDeviceContent::CreateObjectWithPropertiesAndData para criar um novo objeto IStream no dispositivo.
- O aplicativo usa esse objeto para obter um objeto IPortableDeviceDataStream do driver WPD.
- O aplicativo usa o novo objeto IPortableDeviceDataStream para gravar o conteúdo no dispositivo (por meio da função auxiliar StreamCopy). A função auxiliar grava os dados do arquivo de origem no fluxo retornado por IPortableDeviceContent::CreateObjectWithPropertiesAndData.
- O aplicativo conclui a operação chamando o método Commit no fluxo de destino.
// 4) Transfer for the content to the device
if (SUCCEEDED(hr))
{
hr = pContent->CreateObjectWithPropertiesAndData(pFinalObjectProperties, // Properties describing the object data
&pTempStream, // Returned object data stream (to transfer the data to)
&cbOptimalTransferSize, // Returned optimal buffer size to use during transfer
NULL);
// Once we have the IStream returned from CreateObjectWithPropertiesAndData,
// QI for IPortableDeviceDataStream so we can use the additional methods
// to get more information about the object (i.e. The newly created object
// identifier on the device)
if (SUCCEEDED(hr))
{
hr = pTempStream->QueryInterface(IID_PPV_ARGS(&pFinalObjectDataStream));
if (FAILED(hr))
{
printf("! Failed to QueryInterface for IPortableDeviceDataStream, hr = 0x%lx\n",hr);
}
}
// Since we have IStream-compatible interfaces, call our helper function
// that copies the contents of a source stream into a destination stream.
if (SUCCEEDED(hr))
{
DWORD cbTotalBytesWritten = 0;
hr = StreamCopy(pFinalObjectDataStream, // Destination (The Object to transfer to)
pFileStream, // Source (The File data to transfer from)
cbOptimalTransferSize, // The driver specified optimal transfer buffer size
&cbTotalBytesWritten); // The total number of bytes transferred from file to the device
if (FAILED(hr))
{
printf("! Failed to transfer object to device, hr = 0x%lx\n",hr);
}
}
else
{
printf("! Failed to get IStream (representing destination object data on the device) from IPortableDeviceContent, hr = 0x%lx\n",hr);
}
// After transferring content to the device, the client is responsible for letting the
// driver know that the transfer is complete by calling the Commit() method
// on the IPortableDeviceDataStream interface.
if (SUCCEEDED(hr))
{
hr = pFinalObjectDataStream->Commit(0);
if (FAILED(hr))
{
printf("! Failed to commit object to device, hr = 0x%lx\n",hr);
}
}
// Some clients may want to know the object identifier of the newly created
// object. This is done by calling GetObjectID() method on the
// IPortableDeviceDataStream interface.
if (SUCCEEDED(hr))
{
PWSTR pszNewlyCreatedObject = NULL;
hr = pFinalObjectDataStream->GetObjectID(&pszNewlyCreatedObject);
if (SUCCEEDED(hr))
{
printf("The file '%ws' was transferred to the device.\nThe newly created object's ID is '%ws'\n",szFilePath ,pszNewlyCreatedObject);
}
if (FAILED(hr))
{
printf("! Failed to get the newly transferred object's identifier from the device, hr = 0x%lx\n",hr);
}
// Free the object identifier string returned from the GetObjectID() method.
CoTaskMemFree(pszNewlyCreatedObject);
pszNewlyCreatedObject = NULL;
}
}
Tópicos relacionados