將影像或音樂檔案傳輸至裝置
應用程式完成的其中一個最常見作業是將內容傳輸到連線的裝置。
使用下表所述的介面來完成內容傳輸。
介面 | 描述 |
---|---|
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
helper-function 會建立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;
}
}
相關主題