Unterstützen geräteseitiger WPD-Inhalte
Da auf geräteseitige Inhalte nicht über das Dateisystem in Windows Vista zugegriffen werden kann, müssen Sie entweder die Windows Shell-API oder die WPD-API verwenden, um Daten für Geräteobjekte abzurufen. Dies ist der Hauptunterschied zwischen einem normalen Kontextmenühandler und einem WPD-Kontextmenühandler. Der folgende Beispielcode veranschaulicht das Abrufen von geräteseitigem Inhalt mithilfe der Windows Shell-API.
Der erste Schritt ist die Initialisierung der Elementbezeichnerliste oder PIDL. (Diese Liste enthält den eindeutigen Bezeichner für das angegebene Geräteobjekt.)
HRESULT CWPDContextMenu::_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};
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_pida = pida;
_ExaminePIDLArray();
}
else
{
hr = E_UNEXPECTED;
}
}
else
{
hr = E_OUTOFMEMORY;
}
ReleaseStgMedium(&medium);
}
return hr;
}
Die Initialisierungsfunktion ruft die _ ExaminePIDLArray-Funktion auf, die die Eigenschaften für das Objekt abruft, das von einer PIDL im PIDL-Array identifiziert wird.
HRESULT CWPDContextMenu::_ExaminePIDLArray()
{
CComPtr<IShellFolder2> spParentFolder;
CComVariant variant;
LPITEMIDLIST pidl = NULL;
HRESULT hr = S_OK;
UINT index = 0;
pidl = GetPIDL(m_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_pida, ++index);
} while (pidl != NULL && index < m_pida->cidl);
Exit:
UI_SAFE_ILFREE(pidl);
return hr;
}