Aggiunta di una risorsa a un oggetto
Oltre a trasferire oggetti in un dispositivo, è anche possibile aggiungere risorse agli oggetti. Ad esempio, un'applicazione potrebbe aggiungere una foto alle informazioni esistenti per un determinato contatto.
Le risorse vengono aggiunte usando le interfacce descritte nella tabella seguente.
Interfaccia | Descrizione |
---|---|
Interfaccia IPortableDeviceContent | Fornisce l'accesso ai metodi specifici del contenuto. |
Interfaccia IPortableDeviceResources | Usato durante la scrittura delle proprietà e dei dati delle risorse nel dispositivo. |
Interfaccia IPortableDeviceValues | Consente di scrivere proprietà che descrivono la risorsa. |
Interfaccia IStream | Usato per semplificare la scrittura della risorsa nel dispositivo. |
La funzione CreateContactPhotoResourceOnDevice nel modulo ContentTransfer.cpp dell'applicazione di esempio illustra come un'applicazione potrebbe aggiungere una risorsa foto a un oggetto contatto. Questa funzione richiede all'utente l'identificatore dell'oggetto del contatto nel dispositivo, a cui verrà aggiunta la risorsa foto. Visualizza quindi una finestra di dialogo FileApri in modo che l'utente possa selezionare l'immagine da aggiungere. Dopo aver raccolto questi dati, l'applicazione scrive la risorsa nel dispositivo.
La prima attività eseguita dalla funzione CreateContactPhotoResourceOnDevice consiste nel chiedere all'utente di immettere un identificatore di oggetto per il contatto a cui verrà aggiunta la foto.
HRESULT hr = S_OK;
WCHAR wszSelection[81] = {0};
WCHAR wszFilePath[MAX_PATH] = {0};
DWORD cbOptimalTransferSize = 0;
CComPtr<IStream> pFileStream;
CComPtr<IStream> pResourceStream;
CComPtr<IPortableDeviceValues> pResourceAttributes;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceResources> pResources;
printf("Enter the identifer of the object to which we will add an Audio annotation.\n>");
hr = StringCbGetsW(wszSelection,sizeof(wszSelection));
if (FAILED(hr))
{
printf("An invalid object identifier was specified, aborting resource creation\n");
}do
Il passaggio successivo è il recupero di un oggetto IPortableDeviceContent , che a sua volta viene usato per ottenere un oggetto IPortableDeviceResources . L'applicazione usa questo secondo oggetto per creare e scrivere la nuova risorsa.
HRESULT hr = S_OK;
WCHAR wszSelection[81] = {0};
WCHAR wszFilePath[MAX_PATH] = {0};
DWORD cbOptimalTransferSize = 0;
CComPtr<IStream> pFileStream;
CComPtr<IStream> pResourceStream;
CComPtr<IPortableDeviceValues> pResourceAttributes;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceResources> pResources;
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->Transfer(&pResources);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceResources from IPortableDeviceContent, hr = 0x%lx\n",hr);
}
}
Successivamente, nell'esempio viene visualizzata la finestra di dialogo FileApri , che consente all'utente di specificare il nome del file di immagine che contiene la foto da aggiungere alle informazioni di contatto.
HRESULT hr = S_OK;
WCHAR wszSelection[81] = {0};
WCHAR wszFilePath[MAX_PATH] = {0};
DWORD cbOptimalTransferSize = 0;
CComPtr<IStream> pFileStream;
CComPtr<IStream> pResourceStream;
CComPtr<IPortableDeviceValues> pResourceAttributes;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceResources> pResources;
if (SUCCEEDED(hr))
{
OPENFILENAME OpenFileNameInfo = {0};
OpenFileNameInfo.lStructSize = sizeof(OPENFILENAME);
OpenFileNameInfo.hwndOwner = NULL;
OpenFileNameInfo.lpstrFile = wszFilePath;
OpenFileNameInfo.nMaxFile = ARRAYSIZE(wszFilePath);
OpenFileNameInfo.lpstrFilter = L"JPEG (*.JPG)\0*.JPG\0JPEG (*.JPEG)\0*.JPEG\0JPG (*.JPE)\0*.JPE\0JPG (*.JFIF)\0*.JFIF\0\0";;
OpenFileNameInfo.nFilterIndex = 1;
OpenFileNameInfo.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
OpenFileNameInfo.lpstrDefExt = L"JPG";
if (GetOpenFileName(&OpenFileNameInfo) == FALSE)
{
printf("The transfer operation was cancelled.\n");
hr = E_ABORT;
}
}
Dopo che l'esempio ha un oggetto IPortableDeviceResources e il nome del file di immagine, esegue le operazioni seguenti in preparazione per il trasferimento effettivo dei dati nel dispositivo.
- Apre un oggetto IStream nel file selezionato per le operazioni di lettura.
- Crea un oggetto IPortableDeviceValues , che conterrà informazioni come le dimensioni e il formato dell'immagine.
HRESULT hr = S_OK;
WCHAR wszSelection[81] = {0};
WCHAR wszFilePath[MAX_PATH] = {0};
DWORD cbOptimalTransferSize = 0;
CComPtr<IStream> pFileStream;
CComPtr<IStream> pResourceStream;
CComPtr<IPortableDeviceValues> pResourceAttributes;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceResources> pResources;
if (SUCCEEDED(hr))
{
// Open the selected file as an IStream. This will simplify reading the
// data and writing to the device.
hr = SHCreateStreamOnFile(wszFilePath, STGM_READ, &pFileStream);
if (SUCCEEDED(hr))
{
// CoCreate the IPortableDeviceValues to hold the resource attributes
hr = CoCreateInstance(CLSID_PortableDeviceValues,
NULL,
CLSCTX_INPROC_SERVER,
IID_IPortableDeviceValues,
(VOID**) &pResourceAttributes);
if (SUCCEEDED(hr))
{
// Fill in the necessary information regarding this resource
// Set the WPD_OBJECT_ID. This informs the driver which object this request is intended for.
hr = pResourceAttributes->SetStringValue(WPD_OBJECT_ID, wszSelection);
if (FAILED(hr))
{
printf("! Failed to set WPD_OBJECT_ID when creating a resource, hr = 0x%lx\n",hr);
}
// Set the WPD_RESOURCE_ATTRIBUTE_RESOURCE_KEY to WPD_RESOURCE_CONTACT_PHOTO
if (SUCCEEDED(hr))
{
hr = pResourceAttributes->SetKeyValue(WPD_RESOURCE_ATTRIBUTE_RESOURCE_KEY, WPD_RESOURCE_CONTACT_PHOTO);
if (FAILED(hr))
{
printf("! Failed to set WPD_RESOURCE_ATTRIBUTE_RESOURCE_KEY to WPD_RESOURCE_CONTACT_PHOTO, hr = 0x%lx\n",hr);
}
}
// Set the WPD_RESOURCE_ATTRIBUTE_TOTAL_SIZE by requesting the total size of the
// data stream.
if (SUCCEEDED(hr))
{
STATSTG statstg = {0};
hr = pFileStream->Stat(&statstg, STATFLAG_NONAME);
if (SUCCEEDED(hr))
{
hr = pResourceAttributes->SetUnsignedLargeIntegerValue(WPD_RESOURCE_ATTRIBUTE_TOTAL_SIZE, statstg.cbSize.QuadPart);
if (FAILED(hr))
{
printf("! Failed to set WPD_RESOURCE_ATTRIBUTE_TOTAL_SIZE, hr = 0x%lx\n",hr);
}
}
else
{
printf("! Failed to get file's total size, hr = 0x%lx\n",hr);
}
}
// Set the WPD_RESOURCE_ATTRIBUTE_FORMAT to WPD_OBJECT_FORMAT_JFIF because we are
// creating a contact photo resource with JPG image data.
if (SUCCEEDED(hr))
{
hr = pResourceAttributes->SetGuidValue(WPD_RESOURCE_ATTRIBUTE_FORMAT, WPD_OBJECT_FORMAT_JFIF);
if (FAILED(hr))
{
printf("! Failed to set WPD_RESOURCE_ATTRIBUTE_FORMAT to WPD_OBJECT_FORMAT_JFIF, hr = 0x%lx\n",hr);
}
}
}
}
if (FAILED(hr))
{
printf("! Failed to open file named (%ws) to transfer to device, hr = 0x%lx\n",wszFilePath, hr);
}
}
Dopo aver preparato gli oggetti IStream e IPortableDeviceValues per l'operazione di scrittura, l'esempio trasferisce l'immagine al dispositivo. L'esempio completa il trasferimento in tre passaggi, come indicato di seguito:
- Crea la risorsa nel dispositivo chiamando il metodo IPortableDeviceResources::CreateResources .
- Chiama una funzione helper StreamCopy per copiare il flusso di origine nel flusso di destinazione.
- Informa il driver di dispositivo che il trasferimento è stato completato chiamando il metodo IPortableDeviceDataStream::Commit.
HRESULT hr = S_OK;
WCHAR wszSelection[81] = {0};
WCHAR wszFilePath[MAX_PATH] = {0};
DWORD cbOptimalTransferSize = 0;
CComPtr<IStream> pFileStream;
CComPtr<IStream> pResourceStream;
CComPtr<IPortableDeviceValues> pResourceAttributes;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceResources> pResources;
if (SUCCEEDED(hr))
{
hr = pResources->CreateResource(pResourceAttributes, // Properties describing this resource
&pResourceStream, // Returned resource data stream (to transfer the data to)
&cbOptimalTransferSize, // Returned optimal buffer size to use during transfer
NULL);
// 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(pResourceStream, // Destination (The resource 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 = pResourceStream->Commit(0);
if (FAILED(hr))
{
printf("! Failed to commit resource to device, hr = 0x%lx\n",hr);
}
}
}
Argomenti correlati