Exemple de code : extensions Shell pour les gestionnaires de protocoles
L’exemple de code suivant montre comment créer des extensions Shell pour un gestionnaire de protocole personnalisé.
Exemple de code
Remarque
CE CODE ET CES INFORMATIONS SONT FOURNIS « EN L’ÉTAT » SANS GARANTIE D’AUCUNE SORTE, EXPRESSE OU IMPLICITE, Y COMPRIS, MAIS DE MANIÈRE NON LIMITATIVE, LES GARANTIES IMPLICITES DE QUALITÉ MARCHANDE ET/OU D’ADAPTATION À UN USAGE PARTICULIER.
Copyright (c) Microsoft Corporation. Tous droits réservés.
// ********************** IDL structure **********************
#include <pshpack1.h>
typedef struct
{
WORD cbSize;
WORD cchUrl; // Store the length of the URL.
WCHAR pwszUrl[1]; // Store the URL.
} URLIDL;
#include <poppack.h>
class ATL_NO_VTABLE CSampleShellFolder :
public CComTearOffObjectBase<CSampleSearchProtocol>,
public IPersistFolder,
public IShellFolder
{
public:
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CSampleShellFolder)
COM_INTERFACE_ENTRY(IPersistFolder)
COM_INTERFACE_ENTRY(IShellFolder)
END_COM_MAP()
CSampleShellFolder();
virtual ~CSampleShellFolder();
HRESULT FinalConstruct() {return S_OK;};
void FinalRelease() {};
// IPersist
STDMETHOD(GetClassID)(CLSID* pCLSID);
// IPersistFolder
STDMETHOD(Initialize)(const ITEMIDLIST* pidl);
// IShellFolder
STDMETHOD(ParseDisplayName)
(HWND hwnd, IBindCtx* pbc, OLECHAR* pszName,
ULONG* pchEaten, ITEMIDLIST** ppidl, ULONG* pdwAttributes);
STDMETHOD(EnumObjects)
(HWND hwnd, DWORD grfFlags, IEnumIDList** ppenmIDList);
STDMETHOD(BindToObject)
(const ITEMIDLIST* pidl, IBindCtx* pbc, REFIID riid, void** ppvObj);
STDMETHOD(BindToStorage)
(const ITEMIDLIST* pidl, IBindCtx* pbc, REFIID riid, void** ppvObj);
STDMETHOD(CompareIDs)
(LPARAM lParam, const ITEMIDLIST* pidl1, const ITEMIDLIST* pidl2);
STDMETHOD(CreateViewObject)
(HWND hwndOwner, REFIID riid, void** ppvObj) ;
STDMETHOD(GetAttributesOf)
(UINT cidl, const ITEMIDLIST** ppidl, SFGAOF* prgfInOut);
STDMETHOD(GetUIObjectOf)
(HWND hwndOwner, UINT cidl, const ITEMIDLIST** ppidl,
REFIID riid, UINT* prgfInOut, void** ppvObj);
STDMETHOD(GetDisplayNameOf)
(const ITEMIDLIST* pidl, DWORD dwFlags, STRRET* pstrName);
STDMETHOD(SetNameOf)
(HWND hwnd, const ITEMIDLIST* pidl, const OLECHAR* pszName,
DWORD dwFlags, ITEMIDLIST** ppidlOut);
// IDL Helper Routines
private:
static HRESULT CreateIDL(CString & strUrl, ITEMIDLIST** ppidl);
static SampleIDL *IsURLIDL(const ITEMIDLIST* pidl);
static HRESULT GetUrlFromIDL (const ITEMIDLIST *pidl, CString & strUrl);
};
// ******************* IDL Helper routines *******************
//------------------------------------------------------------
// GetUrlFromIDL()
//
// Return the URL for the specified PIDL.
//------------------------------------------------------------
HRESULT CSampleShellFolder::GetUrlFromIDL(
const ITEMIDL * pidl,
CString &strUrl)
{
if (IsURLIDL(pidl) == NULL)
return E_FAIL;
URLIDL *pURLIDL=(URLIDL *)pidl;
strUrl.SetString(pURLIDL->pwszUrl,pURLIDL->cchUrl);
return S_OK;
}
//------------------------------------------------------------
// CreateIDL()
//
// Create a PIDL for the specified URL.
//------------------------------------------------------------
HRESULT CSampleShellFolder::CreateIDL(
CString &strUrl,
ITEMIDL** ppidl)
{
HRESULT hr = S_OK;
// Check assertions.
_ASSERTE(ppidl);
// Initialize the return value.
*ppidl = NULL;
// Get the size of the URL
WORD cb;
WORD cbUrl = strUrl.GetLength() * sizeof(WCHAR);
cb = (WORD)sizeof(URLIDL) + cbUrl;
// Allocate an additional WORD, which is the "next"
// PIDL (one of cb==0).
URLIDL* pURLIDL = (URLIDL*)LocalAlloc(LPTR, cb + sizeof(WORD));
hr = (pURLIDL ? S_OK : E_FAIL);
if (SUCCEEDED(hr))
{
pURLIDL->cbSize = cb;
// Store the number of characters in the URL.
pURLIDL->cchUrl = (WORD)strUrl.GetLength();
// NOTE: CopyChars copies the exact number of characters
// *including* the terminating null character.
CString::CopyChars(
pURLIDL->pwszUrl,
(LPCTSTR)strUrl,
strUrl.GetLength() + 1);
// Terminate the IDL.
ITEMIDL *pidlNext = (ITEMIDL *)
(((LPBYTE)pURLIDL) + pURLIDL->cbSize);
*((WORD *)pidlNext) = 0;
// Return a clone of the IDL.
*ppidl = ILClone((ITEMIDL*)pURLIDL);
hr = (*ppidl ? S_OK : E_OUTOFMEMORY);
// Free the IDL.
LocalFree((HLOCAL)pURLIDL);
}
return hr;
}
//------------------------------------------------------------
// IsURLIDL()
//
// Check the validity of a PIDL, returning a pointer to the
// URLIDL portion of the PIDL.
//------------------------------------------------------------
URLIDL *CSampleShellFolder::IsURLIDL(const ITEMIDL* pidl)
{
URLIDL * pURLIDL = NULL;
CString strSample = L"sample:";
// Check for the presence and length of a PIDL.
// If the PIDL is present and of sufficient length,
// compare it to the start URL.
if (pidl &&
(ILGetSize(pidl) > strSample.GetLength()*sizeof(WCHAR)) )
{
pURLIDL = (URLIDL *)pidl;
CString strUrl;
strUrl.SetString(pURLIDL->pwszUrl, 7);
if (strUrl.CompareNoCase(strSample) == 0)
{
return pURLIDL;
}
}
return NULL;
}
// ************************ IPersist *************************
//------------------------------------------------------------
// IPersist::GetClassID
//
// Retrieve the class identifier (CLSID) of an object. The
// CLSID is a unique value that identifies the code that can
// manipulate the persistent data.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::GetClassID(CLSID* pCLSID)
{
if (pCLSID == NULL)
return E_POINTER;
*pCLSID = CLSID_SampleProtocol;
return S_OK;
}
// ********************* IPersistFolder **********************
//------------------------------------------------------------
// IPersistFolder::Initialize
//
// Instruct a ShellFolder object to initialize itself based
// on the information provided.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::Initialize(const ITEMIDL* pidl)
{
// Since we have only one folder in this sample, there
// is nothing to store.
return S_OK;
}
// ******************** IShellFolder *************************
//------------------------------------------------------------
// IShellFolder::ParseDisplayName
//
// Translate a file object's display name or a folder's
// display name into an item identifier list.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::ParseDisplayName(
HWND hwnd, IBindCtx* pbc,
OLECHAR* pszName,
ULONG* pchEaten,
ITEMIDL** ppidl,
ULONG* pdwAttributes)
{
HRESULT hr = E_FAIL;
if ((pszName == NULL) || (ppidl == NULL))
return E_POINTER;
*ppidl = NULL;
CString strName = L"";
// Get the first seven bytes of the name.
strName.SetString(pszName, 7);
// Determine whether the name starts with "outlook",
// the first seven characters of outlookexpress.
if (strName.CompareNoCase(L"sample:") == 0)
{
// If TRUE, we can assume this is an outlookexpress URL.
CString strUrl = pszName;
// Create the PIDL.
hr = CSampleShellFolder::CreateURLIDL(strUrl, ppidl);
if (SUCCEEDED(hr))
{
if (pchEaten != NULL)
*pchEaten = strUrl.GetLength();
if (pdwAttributes != NULL)
*pdwAttributes = 0;
}
}
return hr;
}
//------------------------------------------------------------
// IShellFolder::EnumObjects
//
// Enable a client to determine the contents of a folder by
// creating an item identifier enumeration object and returning
// its IEnumIDL interface. The methods supported by that
// interface can then be used to enumerate the folder's contents.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::EnumObjects(
HWND hwnd,
DWORD grfFlags,
IEnumIDL** ppenmIDL)
{
return E_NOTIMPL;
}
//------------------------------------------------------------
// IShellFolder::BindToObject
//
// Retrieve an IShellFolder object for a subfolder.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::BindToObject(
const ITEMIDL* pidl,
IBindCtx* pbc,
REFIID riid, void** ppvObj)
{
return E_NOTIMPL;
}
//------------------------------------------------------------
// IShellFolder::BindToStorage
//
// Request a pointer to an object's storage interface.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::BindToStorage(
const ITEMIDL* pidl,
IBindCtx* pbc,
REFIID riid, void** ppvObj)
{
// NOTE: Although this code is not implemented in the sample,
// it is possible to bind to IUrlAccessor->BindToStream()
// to bind to the storage.
return E_NOTIMPL;
}
//------------------------------------------------------------
// IShellFolder::CompareIDs
//
// Determine the relative order of two file objects or folders,
// given their item identifier lists.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::CompareIDs(
LPARAM lParam,
const ITEMIDL* pidl1,
const ITEMIDL* pidl2)
{
if ((pidl1 == NULL) || (pidl2 == NULL))
return E_POINTER;
// Ensure that these are our PIDLs
URLIDL * pURLIDL1 = IsURLIDL(pidl1);
URLIDL * pURLIDL2 = IsURLIDL(pidl2);
if (!pURLIDL1 || !pURLIDL2)
{
return S_FALSE;
}
// Check the query for equality
CString strUrl1;
CString strUrl2;
strUrl1.SetString(pURLIDL1->pwszUrl, pURLIDL1->cchUrl);
strUrl2.SetString(pURLIDL2->pwszUrl, pURLIDL2->cchUrl);
return (strUrl1.CompareNoCase(strUrl2));
}
//------------------------------------------------------------
// IShellFolder::CreateViewObject
//
// Request an object that can be used to obtain information
// from or interact with a folder object.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::CreateViewObject(
HWND hwndOwner,
REFIID riid,
void** ppvObj)
{
return E_NOTIMPL;
}
//------------------------------------------------------------
// IShellFolder::GetAttributesOf
//
// Retrieve the attributes of one or more file objects or
// subfolders.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::GetAttributesOf(
UINT cidl,
const ITEMIDL** ppidl,
SFGAOF* prgfInOut)
{
for ( UINT i = 0; i < cidl; i++)
{
DWORD dwAttrs = 0;
// SFGAO_FOLDER | SFGAO_CANLINK;
dwAttrs |= SFGAO_NONENUMERATED|SFGAO_READONLY;
*prgfInOut &= dwAttrs;
}
return S_OK;
}
//------------------------------------------------------------
// IShellFolder::GetUIObjectOf
//
// Retrieve an OLE interface that can be used to carry out
// actions on the specified file objects or folders.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::GetUIObjectOf(
HWND hwndOwner,
UINT cidl,
const ITEMIDL** ppidl,
REFIID riid,
UINT* prgfInOut,
void** ppvObj)
{
if ((ppidl == NULL) || (ppvObj == NULL))
return E_POINTER;
*ppvObj = NULL;
// Create the appropriate object.
HRESULT hr=S_OK;
// By design, we handle only one object at a time.
if (cidl > 1)
return E_INVALIDARG;
CString strUrl;
hr = GetUrlFromIDL(*ppidl, strUrl);
if (SUCCEEDED(hr))
{
if (riid == __uuidof(IContextMenu))
{
// Return the IContextMenu for this URL
}
else
if (riid == __uuidof(IExtractIcon))
{
// Return the IExtractIcon for this URL
}
else
Hr = E_NOINTERFACE;
}
return hr;
}
//------------------------------------------------------------
// IShellFolder::GetDisplayNameOf
//
// Retrieve the display name for the specified file object
// or subfolder.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::GetDisplayNameOf(
const ITEMIDL* pidl,
DWORD dwFlags,
STRRET* pstrName)
{
HRESULT hr = S_OK;
URLIDL * pURLIDL = IsURLIDL(pidl);
if (pURLIDL)
{
pstrName->uType = STRRET_OFFSET;
pstrName->uOffset = sizeof(WORD) + sizeof(WORD);
}
return hr;
}
//------------------------------------------------------------
// IShellFolder::SetNameOf
//
// Set the display name of a file object or subfolder,
// changing the item identifier in the process.
//------------------------------------------------------------
STDMETHODIMP CSampleShellFolder::SetNameOf(
HWND hwnd,
const ITEMIDL* pidl,
const OLECHAR* pszName,
DWORD dwFlags,
ITEMIDL** ppidlOut)
{
return E_NOTIMPL;
}
Ressources complémentaires
- Pour obtenir des exemples de code Search, consultez Exemples de code Windows Search.
- Pour obtenir des exemples de code Shell, consultez Exemples du Kit de développement logiciel (SDK) Shell.
Rubriques connexes