이미지 또는 음악 파일을 디바이스로 전송
애플리케이션에서 수행하는 가장 일반적인 작업 중 하나는 연결된 디바이스로 콘텐츠를 전송하는 것입니다.
콘텐츠 전송은 다음 표에 설명된 인터페이스를 사용하여 수행됩니다.
인터페이스 | Description |
---|---|
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");
}
함수에서 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
작동하는 도우미 함수를 호출하여 검색됩니다. 도우미 함수는 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;
}
}
관련 항목