画像または音楽ファイルをデバイスに転送する
アプリケーションによって実行される最も一般的な操作の 1 つは、接続されたデバイスへのコンテンツの転送です。
コンテンツ転送は、次の表で説明するインターフェイスを使用して実行されます。
インターフェイス | 説明 |
---|---|
IPortableDeviceContent インターフェイス | コンテンツ固有のメソッドへのアクセスを提供します。 |
IPortableDeviceDataStream インターフェイス | デバイスにコンテンツを書き込むときに使用されます。 |
IPortableDeviceValues インターフェイス | コンテンツを記述するプロパティを取得するために使用します。 |
IStream インターフェイス | コンテンツの読み取りとデバイスへの書き込みを簡略化するために使用されます。 |
サンプル アプリケーションの ContentTransfer.cpp モジュールの関数は TransferContentToDevice
、アプリケーションが PC から接続されたデバイスにコンテンツを転送する方法を示しています。 この特定のサンプルでは、転送されたコンテンツは、画像、音楽、または連絡先情報を含むファイルであり得る。
関数によって実行される最初の TransferContentToDevice
タスクは、転送するオブジェクトを識別するオブジェクト識別子を入力するようにユーザーに求めます。
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");
}
関数によって実行される 2 番目の TransferContentToDevice
タスクは、 IPortableDevice ::Content メソッドを呼び出して IPortableDeviceContent オブジェクトを作成することです。
if (SUCCEEDED(hr))
{
hr = pDevice->Content(&pContent);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr);
}
}
関数によって TransferContentToDevice
実行される次のタスクは、ユーザーが転送するファイルの場所と名前を指定できる FileOpen ダイアログの作成です。
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;
}
}
この関数は TransferContentToDevice
、ユーザーが選択できるファイルの種類を決定する GetOpenFileName メソッドにフィルター文字列 (wszFileTypeFilter
) を渡します。
DoMenu
サンプルで許可されている 3 つの異なるフィルターの例については、WpdApiSample.cpp モジュールの 関数を参照してください。
ユーザーがデバイスへの転送用の特定のファイルを識別すると、 TransferContentToDevice
関数はそのファイルを IStream オブジェクトとして開き、転送を完了するために必要なプロパティを取得します。
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);
}
}
必要なプロパティは、IStream オブジェクトでGetRequiredPropertiesForContentType
動作するヘルパー関数を呼び出すことによって取得されます。 ヘルパー関数はGetRequiredPropertiesForContentType
、IPortableDeviceValues オブジェクトを作成し、次の一覧のプロパティを取得して、このオブジェクトに追加します。
- 親オブジェクト識別子
- ストリーム サイズ (バイト単位)
- コンテンツ ファイル名
- コンテンツ名 (拡張子のないファイル名)
- コンテンツ タイプ (画像、オーディオ、または連絡先)
- コンテンツ形式 (JFIF、WMA、または vCard2)
サンプル アプリケーションでは、取得したプロパティを使用して、デバイスに新しいコンテンツを作成します。 これは、次の 3 つのフェーズで行われます。
- アプリケーションは IPortableDeviceContent::CreateObjectWithPropertiesAndData メソッドを呼び出して、デバイスに新しい IStream オブジェクトを作成します。
- アプリケーションはこのオブジェクトを使用して、WPD ドライバーから IPortableDeviceDataStream オブジェクトを取得します。
- アプリケーションでは、新しい IPortableDeviceDataStream オブジェクトを使用して、(StreamCopy ヘルパー関数を使用して) コンテンツをデバイスに書き込みます。 ヘルパー関数は、ソース ファイルから IPortableDeviceContent::CreateObjectWithPropertiesAndData によって返されるストリームにデータを書き込みます。
- アプリケーションは、宛先ストリームで Commit メソッドを呼び出して操作を完了します。
// 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;
}
}
関連トピック