将图像或音乐文件传输到设备
应用程序完成的最常见操作之一是将内容传输到连接的设备。
内容传输是使用下表中所述的接口完成的。
接口 | 说明 |
---|---|
IPortableDeviceContent 接口 | 提供对特定于内容的方法的访问。 |
IPortableDeviceDataStream 接口 | 在将内容写入设备时使用。 |
IPortableDeviceValues 接口 | 用于检索描述内容的属性。 |
IStream 接口 | 用于简化内容读取和写入设备。 |
TransferContentToDevice
示例应用程序的 ContentTransfer.cpp 模块中的函数演示了应用程序如何将内容从电脑传输到连接的设备。 在此特定示例中,传输的内容可以是包含图像、音乐或联系信息的文件。
函数完成 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");
}
函数完成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
将筛选器字符串 (wszFileTypeFilter
) 传递给 GetOpenFileName 方法,该方法确定用户可以选择的文件类型。 有关 DoMenu
示例允许的三个不同筛选器的示例,请参阅 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
helper-function 来检索所需的属性。 帮助 GetRequiredPropertiesForContentType
程序函数创建 IPortableDeviceValues 对象,检索以下列表中的属性,并将其添加到此对象。
- 父对象标识符
- 流大小(以字节为单位)
- 内容文件名
- 内容名称 (没有扩展名的文件名)
- 内容类型 (图像、音频或联系人)
- 内容格式 (JFIF、WMA 或 vCard2)
示例应用程序使用检索到的属性在设备上创建新内容。 此操作分三个阶段完成:
- 应用程序调用 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;
}
}
相关主题