이미지 또는 음악 파일을 디바이스로 전송

애플리케이션에서 수행하는 가장 일반적인 작업 중 하나는 연결된 디바이스로 콘텐츠를 전송하는 것입니다.

콘텐츠 전송은 다음 표에 설명된 인터페이스를 사용하여 수행됩니다.

인터페이스 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 작동하는 도우미 함수를 호출하여 검색됩니다. 도우미 함수는 GetRequiredPropertiesForContentTypeIPortableDeviceValues 개체를 만들고, 다음 목록의 속성을 검색하고, 이 개체에 추가합니다.

  • 부모 개체 식별자
  • 스트림 크기(바이트)
  • 콘텐츠 파일 이름
  • 콘텐츠 이름(확장명을 사용하지 않는 파일 이름)
  • 콘텐츠 형식(이미지, 오디오 또는 연락처)
  • 콘텐츠 형식(JFIF, WMA 또는 vCard2)

샘플 애플리케이션은 검색된 속성을 사용하여 디바이스에 새 콘텐츠를 만듭니다. 이 작업은 다음 세 단계로 수행됩니다.

  1. 애플리케이션은 IPortableDeviceContent::CreateObjectWithPropertiesAndData 메서드를 호출하여 디바이스에 새 IStream 개체를 만듭니다.
  2. 애플리케이션은 이 개체를 사용하여 WPD 드라이버에서 IPortableDeviceDataStream 개체를 가져옵니다.
  3. 애플리케이션은 새 IPortableDeviceDataStream 개체를 사용하여 StreamCopy 도우미 함수를 통해 디바이스에 콘텐츠를 씁니다. 도우미 함수는 원본 파일의 데이터를 IPortableDeviceContent::CreateObjectWithPropertiesAndData에서 반환된 스트림에 씁니다.
  4. 애플리케이션은 대상 스트림에서 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;
    }
}

IPortableDevice 인터페이스

IPortableDeviceContent 인터페이스

IPortableDeviceDataStream 인터페이스

IPortableDeviceValues 인터페이스

프로그래밍 가이드