オブジェクトへのリソースの追加
オブジェクトをデバイスに転送するだけでなく、オブジェクトにリソースを追加することもできます。 たとえば、アプリケーションは、特定の連絡先の既存の情報に写真を追加できます。
リソースは、次の表で説明するインターフェイスを使用して追加されます。
インターフェイス | 説明 |
---|---|
IPortableDeviceContent インターフェイス | コンテンツ固有のメソッドへのアクセスを提供します。 |
IPortableDeviceResources インターフェイス | リソースのプロパティとデータをデバイスに書き込むときに使用されます。 |
IPortableDeviceValues インターフェイス | リソースを記述するプロパティを記述するために使用されます。 |
IStream インターフェイス | デバイスへのリソースの書き込みを簡略化するために使用されます。 |
サンプル アプリケーションの ContentTransfer.cpp モジュールの CreateContactPhotoResourceOnDevice 関数は、アプリケーションが連絡先オブジェクトに写真リソースを追加する方法を示しています。 この関数は、写真リソースが追加されるデバイス上の連絡先のオブジェクト識別子をユーザーに求めます。 次に、[ファイルを開く] ダイアログ ボックスが表示され、ユーザーは追加するイメージを選択できます。 このデータが収集されると、アプリケーションはリソースをデバイスに書き込みます。
CreateContactPhotoResourceOnDevice 関数によって実行される最初のタスクは、写真を追加する連絡先のオブジェクト識別子を入力するようにユーザーに求めるメッセージを表示することです。
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
次の手順では、 IPortableDeviceContent オブジェクトを取得します。このオブジェクトを使用して 、IPortableDeviceResources オブジェクトを取得します。 (アプリケーションでは、この後者のオブジェクトを使用して、新しいリソースを作成および書き込みます。
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);
}
}
この後、サンプルでは [ファイルを 開く ] ダイアログ ボックスが表示されます。これにより、ユーザーは連絡先情報に追加する写真を含む画像ファイルの名前を指定できます。
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;
}
}
サンプルに IPortableDeviceResources オブジェクトとイメージ ファイルの名前が含まれると、実際にデバイスにデータを転送する準備として次の処理が行われます。
- 選択したファイルの IStream オブジェクトを読み取り操作用に開きます。
- IPortableDeviceValues オブジェクトが作成されます。このオブジェクトには、イメージのサイズや形式などの情報が含まれます。
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);
}
}
書き込み操作用に IStream オブジェクトと IPortableDeviceValues オブジェクトを準備した後、サンプルはイメージをデバイスに転送します。 このサンプルでは、次の 3 つの手順で転送を完了します。
- IPortableDeviceResources::CreateResource メソッドを呼び出して、デバイス上にリソースを作成します。
- StreamCopy ヘルパー関数を呼び出して、ソース ストリームをコピー先ストリームにコピーします。
- 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);
}
}
}
関連トピック