Bagikan melalui


Mentransfer File Gambar atau Musik ke Perangkat

Salah satu operasi paling umum yang dicapai oleh aplikasi adalah transfer konten ke perangkat yang terhubung.

Transfer konten dilakukan menggunakan antarmuka yang dijelaskan dalam tabel berikut.

Antarmuka Deskripsi
Antarmuka IPortableDeviceContent Menyediakan akses ke metode khusus konten.
Antarmuka IPortableDeviceDataStream Digunakan saat menulis konten ke perangkat.
Antarmuka IPortableDeviceValues Digunakan untuk mengambil properti yang menjelaskan konten.
Antarmuka IStream Digunakan untuk menyederhanakan pembacaan konten dan penulisan ke perangkat.

 

Fungsi TransferContentToDevice dalam modul ContentTransfer.cpp aplikasi sampel menunjukkan bagaimana aplikasi dapat mentransfer konten dari PC ke perangkat yang terhubung. Dalam sampel khusus ini, konten yang ditransfer dapat berupa file yang berisi gambar, musik, atau informasi kontak.

Tugas pertama yang diselesaikan oleh TransferContentToDevice fungsi adalah meminta pengguna untuk memasukkan pengidentifikasi objek, yang mengidentifikasi objek yang akan ditransfer.

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");
}

Tugas kedua yang dicapai oleh TransferContentToDevice fungsi adalah membuat objek IPortableDeviceContent dengan memanggil metode IPortableDevice::Content .

if (SUCCEEDED(hr))
{
    hr = pDevice->Content(&pContent);
    if (FAILED(hr))
    {
        printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr);
    }
}

Tugas berikutnya yang diselesaikan oleh TransferContentToDevice fungsi adalah pembuatan dialog FileBuka yang dengannya pengguna dapat menentukan lokasi dan nama file yang akan ditransfer.

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;
    }
}

Fungsi meneruskan TransferContentToDevice string filter (wszFileTypeFilter) ke metode GetOpenFileName, yang menentukan jenis file yang dapat dipilih pengguna. DoMenu Lihat fungsi dalam modul WpdApiSample.cpp untuk contoh tiga filter berbeda yang diizinkan oleh sampel.

Setelah pengguna mengidentifikasi file tertentu untuk ditransfer ke perangkat, fungsi membuka file tersebut TransferContentToDevice sebagai objek IStream dan mengambil properti yang diperlukan untuk menyelesaikan transfer.

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);
    }
}

Properti yang diperlukan diambil dengan memanggil fungsi pembantuGetRequiredPropertiesForContentType , yang beroperasi pada objek IStream. Fungsi pembantu GetRequiredPropertiesForContentType membuat objek IPortableDeviceValues , mengambil properti dalam daftar berikut, dan menambahkannya ke objek ini.

  • Pengidentifikasi objek induk
  • Ukuran aliran dalam byte
  • Nama file konten
  • Nama konten (nama file tanpa ekstensi)
  • Tipe konten (gambar, audio, atau kontak)
  • Format konten (JFIF, WMA, atau vCard2)

Aplikasi sampel menggunakan properti yang diambil untuk membuat konten baru di perangkat. Ini dilakukan dalam tiga fase:

  1. Aplikasi ini memanggil metode IPortableDeviceContent::CreateObjectWithPropertiesAndData untuk membuat objek IStream baru pada perangkat.
  2. Aplikasi menggunakan objek ini untuk mendapatkan objek IPortableDeviceDataStream dari driver WPD.
  3. Aplikasi ini menggunakan objek IPortableDeviceDataStream baru untuk menulis konten ke perangkat (melalui fungsi pembantu StreamCopy). Fungsi pembantu menulis data dari file sumber ke aliran yang dikembalikan oleh IPortableDeviceContent::CreateObjectWithPropertiesAndData.
  4. Aplikasi menyelesaikan operasi dengan memanggil metode Penerapan pada aliran tujuan.
// 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;
    }
}

Antarmuka IPortableDevice

Antarmuka IPortableDeviceContent

Antarmuka IPortableDeviceDataStream

Antarmuka IPortableDeviceValues

Panduan Pemrograman