Bagikan melalui


Mendukung konten di perangkat

Karena konten sisi perangkat tidak dapat diakses melalui sistem file di Windows Vista, Anda harus menggunakan Windows Shell API atau WPD API untuk mengambil data untuk objek perangkat. Ini adalah perbedaan utama antara handler lembar properti normal dan handler lembar properti WPD. Kode sampel berikut menunjukkan pengambilan konten sisi perangkat menggunakan Windows Shell API.

Langkah pertama adalah inisialisasi daftar pengidentifikasi item atau PIDL. (Daftar ini berisi pengidentifikasi unik untuk objek perangkat yang diberikan.)

HRESULT CWPDPropSheet::_InitializePIDLArray(IDataObject *pDataObj)
{
    if (m_cfHIDA == 0)
    {
        m_cfHIDA = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_SHELLIDLIST);
    }

    STGMEDIUM   medium;
    FORMATETC   fmte = {m_cfHIDA, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};

    m_pPropInfo = (PROPINFO*)LocalAlloc(LPTR, sizeof(PROPINFO));
    if (m_pPropInfo == NULL)
        return E_OUTOFMEMORY;

    AddRef_PropInfo(m_pPropInfo);

    HRESULT hr = pDataObj->GetData(&fmte, &medium);
    if (SUCCEEDED(hr))
    {
        SIZE_T cb = GlobalSize(medium.hGlobal);
        CIDA *pida = (CIDA*)GlobalAlloc(GPTR, cb);
        if (pida)
        {
            void *pv = GlobalLock(medium.hGlobal);
            if (pv != NULL)
            {
                CopyMemory(pida, pv, cb);
                GlobalUnlock(medium.hGlobal);
                m_pPropInfo->pida = pida;
                _ExaminePIDLArray();
            }
            else
            {
                hr = E_UNEXPECTED;
            }
        }
        else
        {
            hr = E_OUTOFMEMORY;
        }
        ReleaseStgMedium(&medium);
    }

    return hr;
}

Fungsi inisialisasi memanggil fungsi _ExaminePIDLArray, yang mengambil properti untuk objek yang diidentifikasi oleh PIDL dalam array PIDL.

HRESULT CWPDPropSheet::_ExaminePIDLArray()
{
    CComPtr<IShellFolder2> spParentFolder;

    CComVariant  variant;

    LPITEMIDLIST pidl = NULL;
    HRESULT      hr = S_OK;
    UINT         index = 0;

    pidl = GetPIDL(m_pPropInfo->pida, index);
    if (pidl)
    {
        hr = SHBindToParent(pidl, IID_PPV_ARGS(&spParentFolder), NULL);
        IF_FAILED_JUMP(hr, Exit);
    }

    do
    {
        CComPtr<IPropertySetStorage> spSetStorage;
        CComPtr<IPropertyStorage>    spPropStorage;

        // Get the IpropertySetStorage interface for this PIDL. This method could also
        // be used to retrieve an IPortableDevice interface to allow more low-level interaction
        // with the WPD API.
        hr = spParentFolder->BindToObject(ILFindLastID(pidl), NULL, IID_PPV_ARGS(&spSetStorage));
        if (SUCCEEDED(hr))
        {
            hr = spSetStorage->Open(WPD_FUNCTIONAL_OBJECT_PROPERTIES_V1, STGM_READ, &spPropStorage);
            if (SUCCEEDED(hr))
            {
                PROPVARIANT PropVar = {0};
                PROPSPEC    PropSpec = {0};

                PropSpec.ulKind = PRSPEC_PROPID;
                PropSpec.propid = 2; // WPD_FUNCTIONAL_OBJECT_CATEGORY

                PropVariantInit(&PropVar);

                hr = spPropStorage->ReadMultiple(1, &PropSpec, &PropVar);
                if (SUCCEEDED(hr) && PropVar.vt == VT_CLSID)
                {
                    // The PIDL array contains a non-file object.
                    // This means we don't want to take over the
                    // default menu action.
                    m_bPIDAContainsOnlyFiles = FALSE;
                    PropVariantClear(&PropVar);
                    break;
                }
                else
                {
                    CComPtr<IPropertyStorage>    spObjectProperties;
                    hr = spSetStorage->Open(WPD_OBJECT_PROPERTIES_V1, STGM_READ, &spObjectProperties);
                    if (SUCCEEDED(hr))
                    {
                        PropSpec.ulKind = PRSPEC_PROPID;
                        PropSpec.propid = 7; // WPD_OBJECT_CONTENT_TYPE
                        
                        PropVariantClear(&PropVar);
                        hr = spObjectProperties->ReadMultiple(1, &PropSpec, &PropVar);
                        if (SUCCEEDED(hr) && PropVar.vt == VT_CLSID)
                        {
                            if (IsEqualGUID(*PropVar.puuid, WPD_CONTENT_TYPE_FOLDER))
                            {
                                // The PIDL array contains a folder object.
                                // This means we don't want to take over the
                                // default menu action.
                                m_bPIDAContainsOnlyFiles = FALSE;
                                PropVariantClear(&PropVar);
                                break;
                            }
                        }
                    }
                }

                PropVariantClear(&PropVar);
            }
        }

        UI_SAFE_ILFREE(pidl);

        pidl = GetPIDL(m_pPropInfo->pida, ++index);
    } while (pidl != NULL && index < m_pPropInfo->pida->cidl);

Exit:
    UI_SAFE_ILFREE(pidl);
    return hr;
}

Selain inisialisasi dan pemrosesan daftar pengidentifikasi item, aplikasi Anda harus menerapkan metode IShellPropSheetExt::ReplacePage dan menyisipkan penangan pengganti yang sesuai. Windows Shell memanggil metode ini setiap kali akan menampilkan lembar properti yang dapat diganti, memberi aplikasi Anda kesempatan untuk memanggil handler pengganti yang sesuai. Bagian bawah dari parameter pertama dari metode ReplacePage adalah sebuah pengidentifikasi untuk lembar properti tertentu yang akan ditampilkan oleh Windows. Nilai yang diteruskan pada bagian bawah dari kata pertama parameter sesuai dengan nilai yang ditentukan dalam file WpdShellExtension.h. Nilai-nilai ini dan deskripsinya muncul dalam tabel berikut.

Nilai Deskripsi
WPDNSE_PROPSHEET_DEVICE_GENERAL Sesuai dengan tab umum untuk perangkat.
Properti Umum Penyimpanan WPDNSE Sesuai dengan tab umum untuk objek penyimpanan yang ditemukan di perangkat.
WPDNSE_LEMBAR_PROPISI_KONTEN_UMUM Sesuai dengan tab umum untuk objek konten yang ditemukan di perangkat.
WPDNSE_PROPSHEET_CONTENT_REFERENCES Sesuai dengan tab referensi untuk objek konten yang ditemukan di perangkat.
WPDNSE_PROPSHEET_CONTENT_RESOURCES Sesuai dengan tab sumber daya untuk objek konten yang ditemukan di perangkat.
WPDNSE_SHEET_PROPSISI_KONTEN_DETIL Merujuk ke tab detail untuk objek konten yang ditemukan di perangkat.

 

Dalam ekstensi lembar properti sampel, metode ReplacePage memanggil dua handler pengganti: _ReplaceDeviceGeneral dan _ReplaceContentReferences. Handler ini menggantikan perangkat umum dan tab referensi konten di lembar properti yang dapat diperluas.

STDMETHODIMP CWPDPropSheet::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplacePage, LPARAM lParam)
{
    HRESULT       hr = S_OK;

    if (LOWORD(uPageID) == WPDNSE_PROPSHEET_DEVICE_GENERAL)
    {
        hr = _ReplaceDeviceGeneral(HIWORD(uPageID), lpfnReplacePage, lParam);
    }
    else if (LOWORD(uPageID) == WPDNSE_PROPSHEET_CONTENT_REFERENCES)
    {
        hr = _ReplaceContentReferences(HIWORD(uPageID), lpfnReplacePage, lParam);
    }

    return hr;
}

Karena pengguna dapat memilih beberapa perangkat, aplikasi harus menyimpan array PIDL yang dikembalikan oleh IShellExtInit::Initialize dan kemudian memeriksa bagian kata tertinggi dari parameter pertama ke ReplacePage. Nilai nol dalam kata tinggi ini sesuai dengan elemen pertama dalam array PIDL, nilai satu sesuai dengan elemen kedua, dan seterusnya. Dalam fungsi ReplacePage aplikasi sampel, nilai kata tinggi ini diteruskan ke kedua handler pengganti. Handler ini, pada gilirannya, menggunakan nilai ini untuk mengidentifikasi perangkat tertentu.

Panduan Pemrograman