Implémentation des interfaces de base de l'objet dossier

La procédure de mise en œuvre d'une extension d'espace de noms est similaire à celle de tout autre objet COM (Component Object Model) en cours de traitement. Toutes les extensions doivent prendre en charge trois interfaces primaires qui fournissent à l'Explorateur Windows les informations de base nécessaires à l'affichage des dossiers de l'extension dans l'arborescence. Toutefois, pour exploiter pleinement les capacités de l'Explorateur Windows, votre extension doit également exposer une ou plusieurs interfaces optionnelles qui prennent en charge des fonctionnalités plus sophistiquées, telles que les menus contextuels ou le glisser-déposer, et fournissent une vue des dossiers.

Ce document explique comment mettre en œuvre les interfaces principales et facultatives que l'Explorateur Windows appelle pour obtenir des informations sur le contenu de votre extension. Pour savoir comment mettre en œuvre une vue de dossier et comment personnaliser l'Explorateur Windows, voir Mise en œuvre d'une vue de dossier.

Mise en œuvre et enregistrement de base

En tant que serveur COM in-process, votre DLL doit exposer plusieurs fonctions et interfaces standard :

Ces fonctions et interfaces sont mises en œuvre de la même manière que pour la plupart des autres objets COM. Pour plus de détails, consultez la documentation de COM.

Enregistrement d'une extension

Comme pour tous les objets COM, vous devez créer un identifiant de classe (CLSID) GUID pour votre extension. Enregistrez l'objet en créant une sous-clé de HKEY_CLASSES_ROOTCLSID\ portant le nom du CLSID de votre extension. La DLL doit être enregistrée en tant que serveur in-process et doit spécifier le modèle de threading de l'appartement. Vous pouvez personnaliser le comportement du dossier racine d'une extension en ajoutant une série de sous-clés et de valeurs à la clé CLSID de l'extension.

Plusieurs de ces valeurs ne s'appliquent qu'aux extensions dotées de points de jonction virtuels. Ces valeurs ne s'appliquent pas aux extensions dont les points de jonction sont des dossiers du système de fichiers. Pour plus d'informations, voir Spécifier l'emplacement d'une extension de l'espace noms. Pour modifier le comportement d'une extension dotée d'un point de jonction virtuel, ajoutez une ou plusieurs des valeurs suivantes à la clé CLSID de l'extension :

  • WantsFORPARSING. Le nom d'analyse pour une extension avec un point de jonction virtuel aura normalement la forme ::{GUID}. Les extensions de ce type contiennent normalement des éléments virtuels. Cependant, certaines extensions, telles que Mes documents, correspondent en fait à des dossiers du système de fichiers, même si elles ont des points de jonction virtuels. Si votre extension représente des objets du système de fichiers de cette manière, vous pouvez définir la valeur WantsFORPARSING. L'Explorateur Windows demandera alors le nom d'analyse de votre dossier racine en appelant la méthode IShellFolder::GetDisplayNameOf de l'objet dossier avec uFlags réglé sur SHGDN_FORPARSING et pidl réglé sur un pointeur vide unique vers une liste d'identifiants d'éléments (PIDL). Un PIDL vide ne contient qu'un terminateur. Votre méthode doit alors renvoyer le nom d'analyse ::{GUID} du dossier racine.
  • HideFolderVerbs. Les verbes enregistrés sous HKEY_CLASSES_ROOT\Folder sont normalement associés à toutes les extensions. Elles apparaissent dans le menu contextuel de l'extension et peuvent être invoquées par ShellExecute. Pour éviter que l'un de ces verbes ne soit associé à votre extension, définissez la valeur HideFolderVerbs.
  • HideAsDelete. Si un utilisateur tente de supprimer votre extension, l'Explorateur Windows masquera l'extension.
  • HideAsDeletePerUser. Cette valeur a le même effet que HideAsDelete, mais pour chaque utilisateur. L'extension n'est masquée que pour les utilisateurs qui ont tenté de la supprimer. L'extension est visible pour tous les autres utilisateurs.
  • QueryForOverlay. Définissez cette valeur pour indiquer que l'icône du dossier racine peut avoir une icône superposée. L'objet dossier doit prendre en charge l'interface IShellIconOverlay. Avant que l'Explorateur Windows n'affiche l'icône du dossier racine, il demande une icône superposée en appelant l'une des deux méthodes IShellIconOverlay avec pidlItem défini sur un PIDL vide.

Les autres valeurs et sous-clés s'appliquent à toutes les extensions :

  • Pour spécifier le nom d'affichage du dossier du point de jonction de l'extension, définissez la valeur par défaut de la sous-clé CLSID de l'extension sur une chaîne appropriée.
  • Lorsque le curseur survole un dossier, une infobulle décrivant le contenu du dossier s'affiche généralement. Pour fournir une infobulle pour le dossier racine de votre extension, créez une valeur REG_SZ InfoTip pour la clé CLSID de l'extension et définissez-la sur une chaîne appropriée.
  • Pour spécifier une icône personnalisée pour le dossier racine de votre extension, créez une sous-clé de la sous-clé CLSID de l'extension nommée DefaultIcon. Définissez la valeur par défaut de DefaultIcon sur une valeur REG_SZ contenant le nom du fichier qui contient l'icône, suivi d'une virgule, suivi d'un signe moins, suivi de l'index de l'icône dans ce fichier.
  • Par défaut, le menu contextuel du dossier racine de votre extension contient les éléments définis sous HKEY_CLASSES_ROOT\Folder. Les éléments Supprimer, Renommer et Propriétés sont ajoutés si vous avez défini les indicateurs SFGAO_XXX appropriés. Vous pouvez ajouter d'autres éléments au menu contextuel du dossier racine ou remplacer les éléments existants, comme vous le feriez pour un type de fichier. Créez une sous-clé Shell sous la clé CLSID de l'extension et définissez les commandes comme indiqué dans Extension des menus de raccourcis.
  • Si vous avez besoin d'une méthode plus souple pour gérer le menu contextuel du dossier racine, vous pouvez mettre en œuvre un gestionnaire de menu contextuel. Pour enregistrer le gestionnaire de menu contextuel, créez une clé ShellEx sous la clé CLSID de l'extension. Enregistrez le CLSID du gestionnaire comme vous le feriez pour un gestionnaire d'extension Shell classique.
  • Pour ajouter une page à la feuille de propriétés du dossier racine, attribuez au dossier l'attribut SFGAO_HASPROPSHEET et mettez en œuvre un gestionnaire de feuille de propriétés. Pour enregistrer le gestionnaire de feuille de propriétés, créez une clé ShellEx sous la clé CLSID de l'extension. Enregistrez le CLSID du gestionnaire comme vous le feriez pour un gestionnaire d'extension Shell classique.
  • Pour spécifier les attributs du dossier racine, ajoutez une sous-clé ShellFolder à la sous-clé CLSID de l'extension. Créez une valeur Attributs et attribuez-lui la combinaison appropriée d'indicateurs SFGAO_XXX.

Le tableau suivant répertorie certains attributs couramment utilisés pour les dossiers racine.

Indicateur Valeur Description
SFGAO_FOLDER 0x20000000 Le dossier racine de l'extension contient un ou plusieurs éléments.
SFGAO_HASSUBFOLDER 0x80000000 Le dossier racine de l'extension contient un ou plusieurs sous-dossiers. L'Explorateur Windows placera un signe plus ( + ) à côté de l'icône du dossier.
SFGAO_CANDELETE 0x00000020 Le dossier racine de l'extension peut être supprimé par l'utilisateur. Le menu contextuel du dossier comporte un élément Supprimer. Cet indicateur doit être activé pour les points de jonction placés sous l'un des dossiers virtuels.
SFGAO_CANRENAME 0x00000010 Le dossier racine de l'extension peut être renommé par l'utilisateur. Le menu contextuel du dossier comporte un élément Renommer.
SFGAO_HASPROPSHEET 0x00000040 Le dossier racine de l'extension possède une feuille de propriétés. Le menu contextuel du dossier comporte un élément Propriétés. Pour fournir la feuille de propriétés, vous devez mettre en œuvre un gestionnaire de feuille de propriétés. Enregistrez le gestionnaire sous la clé CLSID de l'extension, comme indiqué précédemment.

 

L'exemple suivant montre l'entrée de registre CLSID pour une extension dont le nom d'affichage est MonExtension. L'extension possède une icône personnalisée qui est contenue dans la DLL de l'extension avec un index de 1. Les attributs SFGAO_FOLDER, SFGAO_HASSUBFOLDER et SFGAO_CANDELETE sont définis.

HKEY_CLASSES_ROOT
   CLSID
      {Extension CLSID}
         (Default) = MyExtension
         InfoTip = Some appropriate text
      DefaultIcon
         (Default) = c:\MyDir\MyExtension.dll,-1
      InProcServer32
         (Default) = c:\MyDir\MyExtension.dll
         ThreadingModel = Apartment
      ShellFolder
         Attributes = 0xA00000020

Gestion des PIDL

Chaque élément de l'espace de noms du Shell doit avoir un PIDL unique. L'Explorateur Windows attribue un PIDL à votre dossier racine et transmet la valeur à votre extension lors de l'initialisation. Votre extension est alors responsable de l'attribution d'une PIDL correctement construite à chacun de ses objets et de la fourniture de ces PIDL à l'Explorateur Windows sur requête. Lorsque l'interpréteur de commandes utilise un PIDL pour identifier l'un des objets de votre extension, cette dernière doit être en mesure d'interpréter le PIDL et d'identifier l'objet en question. Votre extension doit également attribuer un nom d'affichage et un nom d'analyse à chaque objet. Comme les PIDL sont utilisés par pratiquement toutes les interfaces de dossiers, les extensions implémentent généralement un gestionnaire PIDL unique pour gérer toutes ces tâches.

Le terme PIDL est l'abréviation d'une structure ITEMIDLIST ou d'un pointeur vers une telle structure, selon le contexte. Telle qu'elle est déclarée, une structure ITEMIDLIST a un seul membre, une structure SHITEMID. La structure ITEMIDLIST d'un objet est en fait un tableau de deux structures SHITEMID ou plus. L'ordre de ces structures définit un chemin dans l'espace de noms, de la même manière que c:\NMyDirectory\NMyFile définit un chemin dans le système de fichiers. En règle générale, le PIDL d'un objet se compose d'une série de structures SHITEMID correspondant aux dossiers qui définissent le chemin de l'espace de noms, suivies de la structure SHITEMID de l'objet, puis d'un terminateur.

Le terminateur est une structure SHITEMID dont le membre cb vaut NULL. Le terminateur est nécessaire car le nombre de structures SHITEMID dans la PIDL d'un objet dépend de l'emplacement de l'objet dans l'espace de noms Shell et du point de départ du chemin. En outre, la taille des différentes structures SHITEMID peut varier. Lorsque vous recevez un PIDL, vous n'avez aucun moyen simple de déterminer sa taille ou même le nombre total de structures SHITEMID. Au lieu de cela, vous devez « parcourir » le tableau, structure par structure, jusqu'à ce que vous atteigniez le terminateur.

Pour créer un PIDL, votre application doit :

  1. Créer une structure SHITEMID pour chacun de ses objets.
  2. Assembler les structures SHITEMID pertinentes dans un PIDL.

Création d'une structure SHITEMID

La structure SHITEMID d'un objet identifie de manière unique l'objet dans son dossier. En fait, un type de PIDL utilisé par de nombreuses méthodes IShellFolder se compose uniquement de la structure SHITEMID de l'objet, suivie d'un terminateur. La définition d'une structure SHITEMID est la suivante :

typedef struct _SHITEMID { 
    USHORT cb; 
    BYTE   abID[1]; 
} SHITEMID, * LPSHITEMID;

Le membre abID est l'identifiant de l'objet. La longueur de abID n'étant pas définie et pouvant varier, le membre cb est fixé à la taille de la structure SHITEMID, en octets.

Comme ni la longueur ni le contenu d'abID ne sont normalisés, vous pouvez utiliser le schéma de votre choix pour attribuer des valeurs abID à vos objets. La seule exigence est que vous ne pouvez pas avoir deux objets dans le même dossier avec des valeurs identiques. Toutefois, pour des raisons de performance, votre structure SHITEMID doit être alignée sur les DWORD. En d'autres termes, vous devez construire vos valeurs abID de telle sorte que cb soit un multiple entier de 4.

En règle générale, abID pointe vers une structure définie par l'extension. Outre l'ID de l'objet, cette structure est souvent utilisée pour contenir diverses informations connexes, telles que le type ou les attributs de l'objet. Les objets de dossier de votre extension peuvent alors extraire rapidement les informations de la PIDL au lieu de devoir les rechercher.

Remarque

L'un des aspects les plus importants de la conception d'une structure de données pour une PIDL est de rendre la structure persistante et transportable. Dans le contexte des PIDL, la signification de ces termes est la suivante :

  • Persistante. Le système place fréquemment les PIDL dans divers types de stockage à long terme, tels que les fichiers de raccourcis. Il peut ensuite récupérer ces PIDL de la mémoire, éventuellement après un redémarrage du système. Une PIDL qui a été récupérée doit toujours être valide et significative pour votre poste. Cela signifie, par exemple, que vous ne devez pas utiliser de pointeurs ou de poignées dans votre structure PIDL. Les PIDL contenant ce type de données n'auront normalement plus de sens lorsque le système les récupérera ultérieurement.
  • Transportable. Une PIDL doit rester utile lorsqu'elle est transportée d'un ordinateur à un autre. Par exemple, une PIDL peut être écrite dans un fichier de raccourci, copiée sur une disquette et transportée sur un autre ordinateur. Ce PIDL doit rester significatif pour votre extension fonctionnant sur le second ordinateur. Par exemple, pour vous assurer que vos PIDL sont transportables, utilisez explicitement des caractères ANSI ou Unicode. Évitez les types de données tels que TCHAR ou LPTSTR. Si vous utilisez ces types de données, un PIDL créé sur un ordinateur exécutant une version Unicode de votre extension ne sera pas lisible par une version ANSI de cette extension exécutée sur un autre ordinateur.

 

La déclaration suivante montre un exemple simple de structure de données.

typedef struct tagMYPIDLDATA {
  USHORT cb;
  DWORD dwType;
  WCHAR wszDisplayName[40];
} MYPIDLDATA, *LPMYPIDLDATA;

Le membre cb est défini à la taille de la structure MYPIDLDATA. Ce membre fait de MYPIDLDATA une structure SHITEMID valide en soi. Les autres membres sont équivalents au membre abID d'une structure SHITEMID et contiennent des données privées. Le membre dwType est une valeur définie par l'extension qui indique le type d'objet. Dans cet exemple, dwType est défini à TRUE pour les dossiers et à FALSE dans les autres cas. Ce membre vous permet, par exemple, de déterminer rapidement si l'objet est un dossier ou non. Le membre wszDisplayName contient le nom d'affichage de l'objet. Comme vous n'attribuerez pas le même nom d'affichage à deux objets différents du même dossier, le nom d'affichage sert également d'ID à l'objet. Dans cet exemple, wszDisplayName est fixé à 40 caractères pour garantir que la structure SHITEMID sera alignée sur DWORD. Pour limiter la taille de vos PIDL, vous pouvez utiliser un tableau de caractères de longueur variable et ajuster la valeur de cb en conséquence. Remplissez la chaîne d'affichage avec suffisamment de caractères '\0' pour maintenir l'alignement DWORD de la structure. D'autres membres qu'il peut être utile de placer dans la structure comprennent la taille de l'objet, ses attributs ou son nom d'analyse.

Construction d'un PIDL

Une fois que vous avez défini les structures SHITEMID pour vos objets, vous pouvez les utiliser pour construire une PIDL. Les PIDL peuvent être construits à des fins diverses, mais la plupart des tâches utilisent l'un des deux types de PIDL. La plus simple, une PIDL à un seul niveau, identifie l'objet par rapport à son dossier parent. Ce type de PIDL est utilisé par de nombreuses méthodes IShellFolder. Une PIDL à un niveau contient la structure SHITEMID de l'objet, suivie d'un terminateur. Une PIDL entièrement qualifiée définit un chemin dans la hiérarchie de l'espace de noms, depuis le bureau jusqu'à l'objet. Ce type de PIDL commence au bureau et contient une structure SHITEMID pour chaque dossier du chemin, suivie de l'objet et du terminateur. Un PIDL entièrement qualifié identifie de manière unique l'objet dans l'ensemble de l'espace de noms Shell.

La manière la plus simple de construire une PIDL est de travailler directement avec la structure ITEMIDLIST elle-même. Créez une structure ITEMIDLIST, mais allouez suffisamment de mémoire pour contenir toutes les structures SHITEMID. L'adresse de cette structure pointera vers la structure SHITEMID initiale. Définissez les valeurs des membres de cette structure initiale, puis ajoutez autant de structures SHITEMID que nécessaire, dans l'ordre approprié. La procédure suivante explique comment créer un PIDL à un seul niveau. Elle contient deux structures SHITEMID - une structure MYPIDLDATA suivie d'un terminateur :

  1. Utilisez la fonction CoTaskMemAlloc pour allouer de la mémoire à la PIDL. Allouez suffisamment de mémoire pour vos données privées et un USHORT (deux octets) pour le terminateur. Faites passer le résultat à LPMYPIDLDATA.
  2. Définissez le membre cb de la première structure MYPIDLDATA à la taille de cette structure. Dans cet exemple, vous devez attribuer à cb la valeur sizeof(MYPIDLDATA). Si vous souhaitez utiliser une structure de longueur variable, vous devrez calculer la valeur de cb.
  3. Attribuez les valeurs appropriées aux membres de données privées.
  4. Calculez l'adresse de la prochaine structure SHITEMID. Transformez l'adresse de la structure MYPIDLDATA actuelle en LPBYTE et ajoutez cette valeur à la valeur de cb déterminée à l'étape 3.
  5. Dans ce cas, la structure SHITEMID suivante est le terminateur. Attribuez la valeur zéro au membre cb de la structure.

Pour les PIDL plus longs, allouez suffisamment de mémoire et répétez les étapes 3 à 5 pour chaque structure SHITEMID supplémentaire.

L'exemple de fonction suivant prend le type et le nom d'affichage d'un objet et renvoie le PIDL à un seul niveau de l'objet. La fonction suppose que le nom d'affichage, y compris le caractère null qui le termine, ne dépasse pas le nombre de caractères déclarés pour la structure MYPIDLDATA. Si cette hypothèse s'avère erronée, la fonction StringCbCopyW tronquera le nom d'affichage. La variable g_pMalloc est un pointeur IMalloc créé ailleurs et stocké dans une variable globale.

LPITEMIDLIST CreatePIDL(DWORD dwType, LPCWSTR pwszDisplayName)
{
    LPMYPIDLDATA   pidlOut;
    USHORT         uSize;

    pidlOut = NULL;

    //Calculate the size of the MYPIDLDATA structure.
    uSize = sizeof(MYPIDLDATA);

    // Allocate enough memory for the PIDL to hold a MYPIDLDATA structure 
    // plus the terminator
    pidlOut = (LPMYPIDLDATA)m_pMalloc->Alloc(uSize + sizeof(USHORT));

    if(pidlOut)
    {
       //Assign values to the members of the MYPIDLDATA structure
       //that is the PIDL's first SHITEMID structure
       pidlOut->cb = uSize;
       pidlOut->dwType = dwType;
       hr = StringCbCopyW(pidlOut->wszDisplayName, 
                          sizeof(pidlOut->wszDisplayName), pwszDisplayName);
       
       // TODO: Add error handling here to verify the HRESULT returned 
       // by StringCbCopyW.

       //Advance the pointer to the start of the next SHITEMID structure.
       pidlOut = (LPMYPIDLDATA)((LPBYTE)pidlOut + pidlOut->cb);

       //Create the terminating null character by setting cb to 0.
       pidlOut->cb = 0;
    }

    return pidlOut;

Un PIDL entièrement qualifié doit comporter des structures SHITEMID pour chaque objet, du bureau à votre objet. Votre extension reçoit une PIDL entièrement qualifiée pour votre dossier racine lorsque l'interpréteur de commande appelle IPersistFolder::Initialize. Pour construire une PIDL entièrement qualifiée pour un objet, prenez la PIDL que le shell a attribuée à votre dossier racine et ajoutez-y les structures SHITEMID nécessaires pour passer du dossier racine à l'objet.

Interprétation des PIDL

Lorsque l'interpréteur de commandes ou une application appelle l'une des interfaces de votre extension pour demander des requêtes sur un objet, il identifie généralement l'objet par une PIDL. Certaines méthodes, telles que IShellFolder::GetUIObjectOf, utilisent des PIDL relatifs au dossier parent et sont faciles à interpréter. Cependant, votre extension recevra probablement aussi des PIDLs entièrement qualifiés. Votre gestionnaire de PIDL doit alors déterminer à quel objet de votre système le PIDL fait référence.

Ce qui complique la tâche d'associer un objet à une PIDL pleinement qualifiée, c'est qu'une ou plusieurs des structures SHITEMID initiales de la PIDL peuvent appartenir à des objets qui se trouvent en dehors de votre extension, dans l'espace de noms Shell. Vous n'avez aucun moyen d'interpréter la signification du membre abID de ces structures. Ce que votre extension doit faire, c'est « parcourir » la liste des structures SHITEMID, jusqu'à ce que vous atteigniez la structure qui correspond à votre dossier racine. Dès lors, vous saurez comment interpréter les informations contenues dans les structures SHITEMID.

Pour parcourir la PIDL, prenez la première valeur de cb et ajoutez-la à l'adresse de la PIDL pour avancer le pointeur au début de la structure SHITEMID suivante. Il pointera alors sur le membre cb de cette structure, que vous pourrez utiliser pour avancer le pointeur au début de la structure SHITEMID suivante, et ainsi de suite. Chaque fois que vous faites avancer le pointeur, examinez la structure SHITEMID pour déterminer si vous avez atteint la racine de l'espace de noms de votre extension.

Implémentation des interfaces primaires

Comme pour tous les objets COM, la mise en œuvre d'une extension consiste essentiellement à mettre en œuvre un ensemble d'interfaces. Cette section traite des trois interfaces principales qui doivent être implémentées par toutes les extensions. Elles sont utilisées pour l'initialisation et pour fournir à l'Explorateur Windows des informations de base sur le contenu de l'extension. Ces interfaces, plus une vue de dossier, sont tout ce qui est nécessaire pour une extension fonctionnelle. Toutefois, pour exploiter pleinement les fonctionnalités de l'Explorateur Windows, la plupart des extensions implémentent également une ou plusieurs des interfaces optionnelles.

Interface IPersistFolder

L'interface IPersistFolder est appelée pour initialiser un nouvel objet dossier. La méthode IPersistFolder::Initialize attribue un PIDL complet au nouvel objet. Conservez ce PIDL pour une utilisation ultérieure. Par exemple, un objet dossier doit utiliser ce PIDL pour construire des PIDL entièrement qualifiés pour les enfants de l'objet. Le créateur de l'objet dossier peut également appeler IPersist::GetClassID pour demander le CLSID de l'objet.

En règle générale, un objet dossier est créé et initialisé par la méthode IShellFolder::BindToObject de son dossier parent. Cependant, lorsqu'un utilisateur parcourt votre extension, l'Explorateur Windows crée et initialise l'objet dossier racine de l'extension. Le PIDL que l'objet dossier racine reçoit par l'intermédiaire de IPersistFolder::Initialize contient le chemin d'accès du bureau au dossier racine dont vous aurez besoin pour construire des PIDL entièrement qualifiés pour votre extension.

Interface IShellFolder

Le Shell interprète une extension comme une collection d'objets dossiers ordonnés hiérarchiquement. L'interface IShellFolder est au cœur de la mise en œuvre de toute extension. Elle représente un objet dossier et fournit à l'Explorateur Windows la plupart des informations nécessaires pour afficher le contenu du dossier.

IShellFolder est généralement la seule interface de dossier autre que IPersistFolder qui est directement exposée par un objet dossier. Bien que l'Explorateur Windows utilise une variété d'interfaces obligatoires et facultatives pour obtenir des informations sur le contenu du dossier, il obtient des pointeurs vers ces interfaces par l'intermédiaire de IShellFolder.

L'Explorateur Windows obtient le CLSID du dossier racine de votre extension de différentes manières. Pour plus de détails, voir Spécifier l'emplacement d'une extension d'espace noms ou Afficher une vue autonome d'une extension d'espace noms. L'Explorateur Windows utilise ensuite ce CLSID pour créer et initialiser une instance du dossier racine et rechercher une interface IShellFolder. Votre extension crée un objet dossier pour représenter le dossier racine et renvoie l'interface IShellFolder de l'objet. Une grande partie du reste de l'interaction entre votre extension et l'Explorateur Windows se fait alors par l'intermédiaire de IShellFolder. L'Explorateur Windows appelle IShellFolder pour :

  • Requérir un objet capable d'énumérer le contenu du dossier racine.
  • Obtenir divers types d'informations sur le contenu du dossier racine.
  • Requérir un objet qui expose l'une des interfaces optionnelles. Ces interfaces peuvent ensuite être interrogées pour obtenir des informations supplémentaires, telles que des icônes ou des menus de raccourcis.
  • Requérir un objet dossier qui représente un sous-dossier du dossier racine.

Lorsqu'un utilisateur ouvre un sous-dossier du dossier racine, l'Explorateur Windows appelle IShellFolder::BindToObject. Votre extension crée et initialise un nouvel objet dossier pour représenter le sous-dossier et renvoie son interface IShellFolder. L'Explorateur Windows appelle ensuite cette interface pour obtenir divers types d'informations, et ainsi de suite jusqu'à ce que l'utilisateur décide de naviguer ailleurs dans l'espace de noms Shell ou de fermer l'Explorateur Windows.

Le reste de cette section aborde brièvement les méthodes IShellFolder les plus importantes et la manière de les mettre en œuvre.

EnumObjects

Avant d'afficher le contenu d'un dossier dans l'arborescence, l'Explorateur Windows doit d'abord déterminer le contenu du dossier en appelant la méthode IShellFolder::EnumObjects. Cette méthode crée un objet d'énumération OLE standard qui expose une interface IEnumIDList et renvoie le pointeur de cette interface. L'interface IEnumIDList permet à l'Explorateur Windows d'obtenir les PIDL de tous les objets contenus dans le dossier. Ces PIDL sont ensuite utilisés pour obtenir des informations sur les objets contenus dans le dossier. Pour plus de détails, voir l'interface IEnumIDList.

Remarque

La méthode IEnumIDList::Next ne doit renvoyer que des PIDL relatives au dossier parent. La PIDL ne doit contenir que la structure SHITEMID de l'objet, suivie d'un terminateur.

 

CreateViewObject

Avant d'afficher le contenu d'un dossier, l'Explorateur Windows appelle cette méthode pour demander un pointeur vers une interface IShellView. Cette interface est utilisée par l'Explorateur Windows pour gérer l'affichage du dossier. Créez un objet de vue de dossier et renvoyez son interface IShellView.

La méthode IShellFolder::CreateViewObject est également appelée pour demander l'une des interfaces optionnelles, telles que IContextMenu, pour le dossier lui-même. Votre implémentation de cette méthode doit créer un objet qui expose l'interface requête et renvoie le pointeur d'interface. Si l'Explorateur Windows a besoin d'une interface optionnelle pour l'un des objets contenus dans le dossier, il appellera IShellFolder::GetUIObjectOf.

GetUIObjectOf

Si les méthodes IShellFolder permettent d'obtenir des informations de base sur le contenu d'un dossier, votre extension peut également fournir à l'Explorateur Windows divers types d'informations supplémentaires. Par exemple, vous pouvez spécifier des icônes pour le contenu d'un dossier ou le menu contextuel d'un objet. L'Explorateur Windows appelle la méthode IShellFolder::GetUIObjectOf pour tenter de récupérer des informations supplémentaires sur un objet contenu dans un dossier. L'Explorateur Windows spécifie l'objet pour lequel il souhaite obtenir des informations, ainsi que l'IID de l'interface concernée. L'objet dossier crée alors un objet qui expose l'interface demandée et renvoie le pointeur d'interface.

Si votre extension permet aux utilisateurs de transférer des objets par glisser-déposer ou à l'aide du presse-papiers, l'Explorateur Windows appellera IShellFolder::GetUIObjectOf pour demander une interface IDataObject ou IDropTarget. Pour plus d'informations, reportez-vous à la section Transfert d'objets de la commande par glisser-déposer et à l'aide du presse-papiers.

L'Explorateur Windows appelle IShellFolder::CreateViewObject lorsqu'il souhaite obtenir le même type d'informations sur le dossier lui-même.

BindToObject

L'Explorateur Windows appelle la méthode IShellFolder::BindToObject lorsqu'un utilisateur tente d'ouvrir l'un des sous-dossiers de votre extension. Si riid est défini comme IID_IShellFolder, vous devez créer et initialiser un objet dossier qui représente le sous-dossier et renvoyer l'interface IShellFolder de l'objet.

Remarque

À l'heure actuelle, l'Explorateur Windows n'appelle cette méthode que pour demander une interface IShellFolder. Toutefois, ne pensez pas que ce sera toujours le cas. Vous devez toujours vérifier la valeur de riid avant de poursuivre.

 

GetDisplayNameOf

L'Explorateur Windows appelle la méthode IShellFolder::GetDisplayNameOf pour convertir le PIDL de l'un des objets du dossier en un nom. Ce PIDL doit être relatif au dossier parent de l'objet. En d'autres termes, il doit contenir une structure SHITEMID unique et non NULL. Comme il existe plusieurs façons de nommer les objets, l'Explorateur Windows spécifie le type de nom en définissant un ou plusieurs indicateurs SHGDNF dans le paramètre uFlags. L'une des deux valeurs SHGDN_NORMAL ou SHGDN_INFOLDER est définie pour indiquer si le nom doit être relatif au dossier ou au bureau. L'une des trois autres valeurs, SHGDN_FOREDITING, SHGDN_FORADDRESSBAR ou SHGDN_FORPARSING, peut être définie pour indiquer à quoi servira le nom.

Vous devez renvoyer le nom sous la forme d'une structure STRRET. Si SHGDN_FOREDITING, SHGDN_FORADDRESSBAR et SHGDN_FORPARSING ne sont pas définies, le nom d'affichage de l'objet est renvoyé. Si l'indicateur SHGDN_FORPARSING est activé, l'Explorateur Windows demande un nom d'analyse. Les noms d'analyse sont transmis à IShellFolder::ParseDisplayName pour obtenir le PIDL d'un objet, même s'il peut être situé un ou plusieurs niveaux en dessous du dossier actuel dans la hiérarchie de l'espace noms. Par exemple, le nom d'analyse d'un objet de système de fichiers est son chemin d'accès. Vous pouvez transmettre le chemin d'accès complet de n'importe quel objet du système de fichiers à la méthode IShellFolder::ParseDisplayName du bureau, qui renverra le PIDL complet de l'objet.

Bien que les noms d'analyse soient des chaînes de texte, ils ne doivent pas nécessairement inclure le nom d'affichage. Vous devez attribuer des noms d'analyse en fonction de ce qui fonctionnera le plus efficacement lorsque IShellFolder::ParseDisplayName sera appelé. Par exemple, de nombreux dossiers virtuels de l'interpréteur de commandes ne font pas partie du système de fichiers et n'ont pas de chemin d'accès complet. Au lieu de cela, un GUID est attribué à chaque dossier et le nom d'analyse prend la forme ::{GUID}. Quel que soit le schéma que vous utilisez, il doit être capable d'effectuer des « allers-retours » de manière fiable. Par exemple, si un appelant transmet un nom d'analyse à IShellFolder::ParseDisplayName pour récupérer le PIDL d'un objet, puis transmet ce PIDL à IShellFolder::GetDisplayNameOf avec l'indicateur SHGDN_FORPARSING activé, l'appelant devrait retrouver le nom d'analyse d'origine.

GetAttributesOf

L'Explorateur Windows appelle la méthode IShellFolder::GetAttributesOf pour déterminer les attributs d'un ou de plusieurs éléments contenus dans un objet dossier. La valeur de cidl indique le nombre d'éléments dans la requête, et aPidl pointe vers une liste de leurs PIDL.

Étant donné que la vérification de certains attributs peut prendre beaucoup de temps, l'Explorateur Windows limite généralement la requête à un sous-ensemble d'indicateurs disponibles en définissant leurs valeurs dans rfgInOut. Votre méthode ne doit tester que les attributs dont les indicateurs sont définis dans rfgInOut. Laissez les indicateurs valides définis et effacez les autres. Si plusieurs éléments sont inclus dans la requête, définissez uniquement les indicateurs qui s'appliquent à tous les éléments.

Remarque

Les attributs doivent être correctement définis pour qu'un élément soit correctement affiché. Par exemple, si un élément est un dossier qui contient des sous-dossiers, vous devez définir l'indicateur SFGAO_HASSUBFOLDER. Sinon, l'Explorateur Windows n'affichera pas de + à côté de l'icône de l'élément dans l'arborescence.

 

ParseDisplayName

La méthode IShellFolder::ParseDisplayName est en quelque sorte l'image miroir de IShellFolder::GetDisplayNameOf. L'utilisation la plus courante de cette méthode consiste à convertir le nom d'analyse d'un objet en PIDL associé. Le nom d'analyse peut faire référence à tout objet situé en dessous du dossier dans la hiérarchie de l'espace de noms. Le PIDL renvoyé est relatif à l'objet dossier qui expose la méthode et n'est généralement pas entièrement qualifié. En d'autres termes, bien que le PIDL puisse contenir plusieurs structures SHITEMID, la première sera soit celle de l'objet lui-même, soit le premier sous-dossier du chemin menant du dossier à l'objet. L'appelant devra ajouter cette PIDL à la PIDL pleinement qualifiée du dossier pour obtenir une PIDL pleinement qualifiée pour l'objet.

IShellFolder::ParseDisplayName peut également être appelé pour requérir les attributs d'un objet. Comme la détermination de tous les attributs applicables peut prendre beaucoup de temps, l'appelant ne mettra en place que les indicateurs SFGAO_XXX qui représentent les informations qui l'intéressent. Vous devez déterminer lesquels de ces attributs sont vrais pour l'objet et effacer les indicateurs restants.

Interface IEnumIDList

Lorsque l'Explorateur Windows doit énumérer les objets contenus dans un dossier, il appelle IShellFolder::EnumObjects. L'objet dossier doit créer un objet d'énumération qui expose l'interface IEnumIDList et renvoyer ce pointeur d'interface. L'Explorateur Windows utilise alors IEnumIDList pour énumérer les PIDL de tous les objets contenus dans le dossier.

IEnumIDList est une interface d'énumération OLE standard et est implémentée de la manière habituelle. Rappelez-vous toutefois que les PIDL que vous renvoyez doivent être relatifs au dossier et ne contenir que la structure SHITEMID de l'objet et un terminateur.

Implémentation des interfaces optionnelles

Il existe un certain nombre d'interfaces Shell facultatives que les objets dossier de votre extension peuvent prendre en charge. Beaucoup d'entre elles, comme IExtractIcon, vous permettent de personnaliser divers aspects de la façon dont l'utilisateur voit votre extension. D'autres, comme IDataObject, permettent à votre extension de prendre en charge des fonctionnalités telles que le glisser-déposer.

Aucune des interfaces optionnelles n'est exposée directement par un objet dossier. Au lieu de cela, l'Explorateur Windows appelle l'une des deux méthodes IShellFolder pour demander une interface :

  • L'Explorateur Windows appelle la méthode IShellFolder::GetUIObjectOf d'un objet dossier pour requérir une interface pour l'un des objets contenus dans le dossier.
  • L'Explorateur Windows appelle la méthode IShellFolder::CreateViewObject d'un objet dossier pour demander une interface pour le dossier lui-même.

Pour fournir l'information, l'objet dossier crée un objet qui expose l'interface demandée et renvoie le pointeur d'interface. L'Explorateur Windows appelle alors cette interface pour récupérer les informations nécessaires. Cette section traite des interfaces optionnelles les plus couramment utilisées.

IExtractIcon

L'Explorateur Windows demande une interface IExtractIcon avant d'afficher le contenu d'un dossier. Cette interface permet à votre extension de spécifier des icônes personnalisées pour les objets contenus dans le dossier. Dans le cas contraire, les icônes standard des fichiers et des dossiers seront utilisées. Pour fournir une icône personnalisée, créez un objet d'extraction d'icône qui expose IExtractIcon et renvoie un pointeur vers cette interface. Pour plus d'informations, consultez la documentation de référence IExtractIcon ou la rubrique Création de gestionnaires d'icônes.

IContextMenu

Lorsqu'un utilisateur clique avec le bouton droit de la souris sur un objet, l'Explorateur Windows requiert une interface IContextMenu. Pour fournir des menus de raccourci pour vos objets, créez un objet gestionnaire de menu et renvoyez son interface IContextMenu.

Les procédures de création d'un objet gestionnaire de menu sont très similaires à celles utilisées pour créer une extension Shell gestionnaire de menu. Pour plus de détails, reportez-vous à la section Création de gestionnaires de menu contextuel ou à la référence IContextMenu, IContextMenu2 ou IContextMenu3.

IQueryInfo

L'Explorateur Windows appelle l'interface IQueryInfo pour récupérer une chaîne de texte infotip.

IDataObject et IDropTarget

Lorsque vos objets sont affichés par l'Explorateur Windows, un objet dossier n'a aucun moyen direct de savoir si un utilisateur tente de couper, copier ou faire glisser un objet. Au lieu de cela, l'Explorateur Windows requiert une interface IDataObject. Pour permettre le transfert de l'objet, créez un objet de données et renvoyez un pointeur vers son interface IDataObject.

De même, un utilisateur peut tenter de déposer un objet de données sur une représentation de l'Explorateur Windows de l'un de vos objets, tel qu'une icône ou un chemin d'accès à la barre d'adresse. L'Explorateur Windows demande alors une interface IDropTarget. Pour permettre à l'objet de données d'être déposé, créez un objet qui expose une interface IDropTarget et renvoyez le pointeur de l'interface.

La gestion du transfert de données est l'un des aspects les plus délicats de l'écriture d'extensions d'espace de noms. Pour en savoir plus, consultez la section Transfert d'objets interpréteurs de commandes par glisser-déposer et à l'aide du presse-papiers.

Utilisation de l'implémentation de la vue Dossier Shell par défaut

Les sources de données qui utilisent l'objet d'affichage du dossier Shell par défaut (DefView) doivent implémenter ces interfaces :

Optionnellement, elles peuvent également implémenter IPersistFolder3.