Share via


Implementación de las interfaces de objeto de carpeta básica

El procedimiento para implementar una extensión de espacio de nombres es similar al de cualquier otro objeto del modelo de objetos componentes (COM) en proceso. Todas las extensiones deben admitir tres interfaces principales que proporcionan al Explorador de Windows la información básica necesaria para mostrar las carpetas de la extensión en la vista de árbol. Sin embargo, para hacer uso completo de las funcionalidades del Explorador de Windows, la extensión también debe exponer una o varias interfaces opcionales que admitan características más sofisticadas, como menús contextuales o arrastrar y colocar, y proporcionar una vista de carpeta.

En este documento se describe cómo implementar las interfaces principales y opcionales que el Explorador de Windows llama para obtener información sobre el contenido de la extensión. Para obtener información sobre cómo implementar una vista de carpeta y cómo personalizar el Explorador de Windows, consulte Implementación de una vista de carpetas.

Implementación y registro básicos

Como servidor COM en proceso, el archivo DLL debe exponer varias funciones e interfaces estándar:

Estas funciones e interfaces se implementan de la misma manera que para la mayoría de los demás objetos COM. Para obtener más información, consulte la documentación de COM.

Registro de una extensión

Al igual que con todos los objetos COM, debe crear un GUID de identificador de clase (CLSID) para la extensión. Registre el objeto creando una subclave de HKEY_CLASSES_ROOT\CLSID denominado para el CLSID de la extensión. El archivo DLL debe registrarse como un servidor en proceso y debe especificar el modelo de subprocesos de apartamento. Puede personalizar el comportamiento de la carpeta raíz de una extensión agregando una variedad de subclaves y valores a la clave CLSID de la extensión.

Varios de estos valores solo se aplican a extensiones con puntos de unión virtual. Estos valores no se aplican a las extensiones cuyos puntos de unión son carpetas del sistema de archivos. Para obtener más información, consulte Especificación de la ubicación de una extensión de espacio de nombres. Para modificar el comportamiento de una extensión con un punto de unión virtual, agregue uno o varios de los siguientes valores a la clave CLSID de la extensión:

  • QuiereFORPARSING. El nombre de análisis de una extensión con un punto de unión virtual normalmente tendrá el formato ::{GUID}. Normalmente, las extensiones de este tipo contienen elementos virtuales. Sin embargo, algunas extensiones, como Mis documentos, corresponden realmente a carpetas del sistema de archivos, aunque tengan puntos de unión virtual. Si la extensión representa objetos del sistema de archivos de esta manera, puede establecer el valor WantsFORPARSING. A continuación, el Explorador de Windows solicitará el nombre de análisis de la carpeta raíz llamando al método IShellFolder::GetDisplayNameOf del objeto de carpeta con uFlags establecido en SHGDN_FORPARSING y pidl establecido en un único puntero vacío a una lista de identificadores de elemento (PIDL). Un PIDL vacío contiene solo un terminador. A continuación, el método debe devolver el nombre de análisis ::{GUID} de la carpeta raíz.
  • HideFolderVerbs. Los verbos registrados en HKEY_CLASSES_ROOT\Carpeta normalmente están asociados a todas las extensiones. Aparecen en el menú contextual de la extensión y se pueden invocar mediante ShellExecute. Para evitar que cualquiera de estos verbos esté asociado a la extensión, establezca el valor HideFolderVerbs.
  • HideAsDelete. Si un usuario intenta eliminar la extensión, el Explorador de Windows ocultará en su lugar la extensión.
  • HideAsDeletePerUser. Este valor tiene el mismo efecto que HideAsDelete, pero por usuario. La extensión solo está oculta para aquellos usuarios que han intentado eliminarla. La extensión es visible para todos los demás usuarios.
  • QueryForOverlay. Establezca este valor para indicar que el icono de la carpeta raíz puede tener una superposición de icono. El objeto folder debe admitir la interfaz IShellIconOverlay . Antes de que el Explorador de Windows muestre el icono de la carpeta raíz, solicitará un icono de superposición llamando a uno de los dos métodos IShellIconOverlay con pidlItem establecido en un PIDL vacío.

Los valores y subclaves restantes se aplican a todas las extensiones:

  • Para especificar el nombre para mostrar de la carpeta de punto de unión de la extensión, establezca el valor predeterminado de la subclave CLSID de la extensión en una cadena adecuada.
  • Cuando el cursor mantiene el puntero sobre una carpeta, normalmente se muestra una información sobre información que describe el contenido de la carpeta. Para proporcionar una información sobre información sobre la carpeta raíz de la extensión, cree un valor de infoTip REG_SZ para la clave CLSID de la extensión y establézcalo en una cadena adecuada.
  • Para especificar un icono personalizado para la carpeta raíz de la extensión, cree una subclave de la subclave CLSID de la extensión denominada DefaultIcon. Establezca el valor predeterminado de DefaultIcon en un valor de REG_SZ que contiene el nombre del archivo que contiene el icono, seguido de una coma, seguido de un signo menos, seguido del índice del icono en ese archivo.
  • De forma predeterminada, el menú contextual de la carpeta raíz de la extensión contendrá los elementos definidos en HKEY_CLASSES_ROOT\Folder. Los elementos Eliminar, Cambiar nombre y Propiedades se agregan si ha establecido las marcas de SFGAO_XXX adecuadas. Puede agregar otros elementos al menú contextual de la carpeta raíz o invalidar los elementos existentes, lo mismo que lo haría para un tipo de archivo. Cree una subclave shell en la clave CLSID de la extensión y defina comandos como se describe en Extensión de menús contextuales.
  • Si necesita una manera más flexible de controlar el menú contextual de la carpeta raíz, puede implementar un controlador de menú contextual. Para registrar el controlador de menú contextual, cree una clave ShellEx en la clave CLSID de la extensión. Registre el CLSID del controlador como lo haría para un controlador de extensión de shell convencional.
  • Para agregar una página a la hoja de propiedades Propiedades de la carpeta raíz, asigne a la carpeta el atributo SFGAO_HASPROPSHEET e implemente un controlador de hoja de propiedades. Para registrar el controlador de hoja de propiedades, cree una clave ShellEx en la clave CLSID de la extensión. Registre el CLSID del controlador como lo haría para un controlador de extensión de shell convencional.
  • Para especificar los atributos de la carpeta raíz, agregue una subclave ShellFolder a la subclave CLSID de la extensión. Cree un valor Attributes y establézcalo en la combinación adecuada de marcas de SFGAO_XXX .

En la tabla siguiente se enumeran algunos atributos usados habitualmente para las carpetas raíz.

Marca Value Descripción
SFGAO_FOLDER 0x20000000 La carpeta raíz de la extensión contiene uno o varios elementos.
SFGAO_HASSUBFOLDER 0x80000000 La carpeta raíz de la extensión contiene una o varias subcarpetas. El Explorador de Windows colocará un signo más ( + ) junto al icono de carpeta.
SFGAO_CANDELETE 0x00000020 El usuario puede eliminar la carpeta raíz de la extensión. El menú contextual de la carpeta tendrá un elemento Eliminar . Esta marca debe establecerse para los puntos de unión que se colocan en una de las carpetas virtuales.
SFGAO_CANRENAME 0x00000010 El usuario puede cambiar el nombre de la carpeta raíz de la extensión. El menú contextual de la carpeta tendrá un elemento Cambiar nombre .
SFGAO_HASPROPSHEET 0x00000040 La carpeta raíz de la extensión tiene una hoja de propiedades Properties . El menú contextual de la carpeta tendrá un elemento Propiedades . Para proporcionar la hoja de propiedades, debe implementar un controlador de hoja de propiedades. Registre el controlador en la clave CLSID de la extensión, como se explicó anteriormente.

 

En el ejemplo siguiente se muestra la entrada del Registro CLSID para una extensión con un nombre para mostrar de MyExtension. La extensión tiene un icono personalizado incluido en el archivo DLL de la extensión con un índice de 1. Se establecen los atributos SFGAO_FOLDER, SFGAO_HASSUBFOLDER y SFGAO_CANDELETE .

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

Control de PIDLs

Cada elemento del espacio de nombres de Shell debe tener un PIDL único. El Explorador de Windows asigna un PIDL a la carpeta raíz y pasa el valor a la extensión durante la inicialización. Después, la extensión es responsable de asignar un PIDL construido correctamente a cada uno de sus objetos y proporcionar esos PIN al Explorador de Windows a petición. Cuando el Shell usa un PIDL para identificar uno de los objetos de la extensión, la extensión debe ser capaz de interpretar el PIDL e identificar el objeto determinado. La extensión también debe asignar un nombre para mostrar y un nombre de análisis a cada objeto. Dado que las PIDL se usan prácticamente en todas las interfaces de carpetas, las extensiones suelen implementar un único administrador de PIDL para controlar todas estas tareas.

El término PIDL es corto para una estructura ITEMIDLIST o un puntero a dicha estructura, dependiendo del contexto. Como se declara, una estructura ITEMIDLIST tiene un único miembro, una estructura SHITEMID . La estructura ITEMIDLIST de un objeto es realmente una matriz empaquetada de dos o más estructuras SHITEMID . El orden de estas estructuras define una ruta de acceso a través del espacio de nombres, de la misma manera que c:\MyDirectory\MyFile define una ruta de acceso a través del sistema de archivos. Normalmente, el PIDL de un objeto constará de una serie de estructuras SHITEMID que corresponden a las carpetas que definen la ruta de acceso del espacio de nombres, seguida de la estructura SHITEMID del objeto, seguida de un terminador.

El terminador es una estructura SHITEMID , con el miembro cb establecido en NULL. El terminador es necesario porque el número de estructuras SHITEMID en el PIDL de un objeto depende de la ubicación del objeto en el espacio de nombres shell y del punto de partida de la ruta de acceso. Además, el tamaño de las distintas estructuras SHITEMID puede variar. Cuando recibe un PIDL, no tiene ninguna manera sencilla de determinar su tamaño o incluso el número total de estructuras SHITEMID . En su lugar, debe "caminar" la matriz empaquetada, estructura por estructura, hasta llegar al terminador.

Para crear un PIDL, la aplicación debe:

  1. Cree una estructura SHITEMID para cada uno de sus objetos.
  2. Ensamblar las estructuras SHITEMID pertinentes en un PIDL.

Crear una estructura SHITEMID

La estructura SHITEMID de un objeto identifica de forma única el objeto dentro de su carpeta. De hecho, un tipo de PIDL usado por muchos de los métodos IShellFolder consta simplemente de la estructura SHITEMID del objeto, seguida de un terminador. La definición de una estructura SHITEMID es:

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

El miembro abID es el identificador del objeto. Dado que la longitud de abID no está definida y puede variar, el miembro cb se establece en el tamaño de la estructura SHITEMID , en bytes.

Dado que ni la longitud ni el contenido de abID están estandarizados, puede usar cualquier esquema que desee asignar valores abID a los objetos. El único requisito es que no puede tener dos objetos en la misma carpeta con valores idénticos. Sin embargo, por motivos de rendimiento, la estructura SHITEMID debe estar alineada con DWORD. En otras palabras, debe construir los valores abID de forma que cb sea un múltiplo entero de 4.

Normalmente, abID apunta a una estructura definida por la extensión. Además del identificador del objeto, esta estructura se usa a menudo para contener una variedad de información relacionada, como el tipo o los atributos del objeto. Los objetos de carpeta de la extensión pueden extraer rápidamente la información del PIDL en lugar de tener que consultarla.

Nota

Uno de los aspectos más importantes de diseño de una estructura de datos para un PIDL es hacer que la estructura sea persistente y transportable. En el contexto de las PIDL, el significado de estos términos es:

  • Conservable. El sistema coloca los PIDL con frecuencia en varios tipos de almacenamiento a largo plazo, como archivos de acceso directo. A continuación, puede recuperar estas PIDL del almacenamiento más adelante, posiblemente después de reiniciar el sistema. Un PIDL que se ha recuperado del almacenamiento debe seguir siendo válido y significativo para la extensión. Este requisito significa, por ejemplo, que no debe usar punteros ni identificadores en la estructura PIDL. Los PIDL que contienen este tipo de datos normalmente no tendrán sentido cuando el sistema los recupere más adelante del almacenamiento.
  • Transportable. Un PIDL debe permanecer significativo cuando se transporta de un equipo a otro. Por ejemplo, un PIDL se puede escribir en un archivo de acceso directo, copiarse en un disco de disquete y transportarse a otro equipo. Ese PIDL debe seguir siendo significativo para la extensión que se ejecuta en el segundo equipo. Por ejemplo, para asegurarse de que las PIDL son transportables, use caracteres ANSI o Unicode explícitamente. Evite tipos de datos como TCHAR o LPTSTR. Si usa esos tipos de datos, un PIDL creado en un equipo que ejecute una versión Unicode de la extensión no será legible por una versión ANSI de esa extensión que se ejecuta en otro equipo.

 

En la declaración siguiente se muestra un ejemplo sencillo de una estructura de datos.

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

El miembro cb se establece en el tamaño de la estructura MYPIDLDATA . Este miembro convierte MYPIDLDATA en una estructura SHITEMID válida, en y de sí misma. El resto de los miembros son equivalentes al miembro abID de una estructura SHITEMID y contienen datos privados. El miembro dwType es un valor definido por la extensión que indica el tipo de objeto. En este ejemplo, dwType se establece en TRUE para las carpetas y FALSE de lo contrario. Este miembro permite, por ejemplo, determinar rápidamente si el objeto es una carpeta o no. El miembro wszDisplayName contiene el nombre para mostrar del objeto. Puesto que no asignaría el mismo nombre para mostrar a dos objetos diferentes en la misma carpeta, el nombre para mostrar también actúa como identificador de objeto. En este ejemplo, wszDisplayName se establece en 40 caracteres para garantizar que la estructura SHITEMID esté alineada con DWORD. Para limitar el tamaño de las PIDL, en su lugar puede usar una matriz de caracteres de longitud variable y ajustar el valor de cb en consecuencia. Rellenar la cadena de presentación con suficientes caracteres '\0' para mantener la alineación DWORD de la estructura. Otros miembros que podrían ser útiles para colocar en la estructura incluyen el tamaño, los atributos o el nombre de análisis del objeto.

Construcción de un PIDL

Una vez que haya definido estructuras SHITEMID para los objetos, puede usarlas para construir un PIDL. Los PIDL se pueden construir para diversos propósitos, pero la mayoría de las tareas usan uno de dos tipos de PIDL. El PIDL de nivel único más sencillo identifica el objeto relativo a su carpeta primaria. Muchos de los métodos IShellFolder usan este tipo de PIDL. Un PIDL de nivel único contiene la estructura SHITEMID del objeto, seguida de un terminador. Un PIDL completo define una ruta de acceso a través de la jerarquía de espacios de nombres del escritorio al objeto . Este tipo de PIDL se inicia en el escritorio y contiene una estructura SHITEMID para cada carpeta de la ruta de acceso, seguida del objeto y el terminador. Un PIDL completo identifica de forma única el objeto dentro de todo el espacio de nombres de Shell.

La manera más sencilla de construir un PIDL es trabajar directamente con la propia estructura ITEMIDLIST . Cree una estructura ITEMIDLIST , pero asigne suficiente memoria para contener todas las estructuras SHITEMID . La dirección de esta estructura apuntará a la estructura SHITEMID inicial. Defina valores para los miembros de esta estructura inicial y, a continuación, anexe tantas estructuras SHITEMID adicionales como necesite, en el orden adecuado. En el procedimiento siguiente se describe cómo crear un PIDL de nivel único. Contiene dos estructuras SHITEMID : una estructura MYPIDLDATA seguida de un terminador:

  1. Use la función CoTaskMemAlloc para asignar memoria para el PIDL. Asigne suficiente memoria para los datos privados más un USHORT (dos bytes) para el terminador. Convierta el resultado en LPMYPIDLDATA.
  2. Establezca el miembro cb de la primera estructura MYPIDLDATA en el tamaño de esa estructura. En este ejemplo, establecería cb en sizeof(MYPIDLDATA). Si desea usar una estructura de longitud variable, tendrá que calcular el valor de cb.
  3. Asigne los valores adecuados a los miembros de datos privados.
  4. Calcule la dirección de la siguiente estructura SHITEMID . Convierta la dirección de la estructura MYPIDLDATA actual en LPBYTE y agregue ese valor al valor de cb determinado en el paso 3.
  5. En este caso, la siguiente estructura SHITEMID es el terminador. Establezca el miembro cb de la estructura en cero.

Para los PIDL más largos, asigne memoria suficiente y repita los pasos 3 a 5 para cada estructura SHITEMID adicional.

La siguiente función de ejemplo toma el tipo y el nombre para mostrar de un objeto y devuelve el PIDL de un solo nivel. La función supone que el nombre para mostrar, incluido su carácter nulo de terminación, no supera el número de caracteres declarados para la estructura MYPIDLDATA . Si esa suposición resulta errónea, la función StringCbCopyW truncará el nombre para mostrar. La variable g_pMalloc es un puntero IMalloc creado en otro lugar y almacenado en una variable global.

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 completo debe tener estructuras SHITEMID para cada objeto del escritorio al objeto. La extensión recibe un PIDL completo para la carpeta raíz cuando shell llama a IPersistFolder::Initialize. Para construir un PIDL completo para un objeto, tome el PIDL que el Shell ha asignado a la carpeta raíz y anexe las estructuras SHITEMID necesarias para llevarle de la carpeta raíz al objeto.

Interpretación de LOS PIDL

Cuando el Shell o una aplicación llaman a una de las interfaces de la extensión para solicitar información sobre un objeto, normalmente identificará el objeto por un PIDL. Algunos métodos, como IShellFolder::GetUIObjectOf, usan PIN relativos a la carpeta primaria y son sencillos de interpretar. Sin embargo, la extensión probablemente también recibirá PIN completos. Después, el administrador de PIDL debe determinar a qué objetos hace referencia PIDL.

Lo que complica la tarea de asociar un objeto con un PIDL completo es que una o varias de las estructuras SHITEMID iniciales del PIDL pueden pertenecer a objetos que se encuentran fuera de la extensión en el espacio de nombres shell. No tiene forma de interpretar el significado del miembro abID de esas estructuras. Lo que debe hacer la extensión es "caminar" la lista de estructuras SHITEMID , hasta que llegue a la estructura que corresponde a la carpeta raíz. A partir de entonces, sabrá cómo interpretar la información en las estructuras SHITEMID .

Para recorrer el PIDL, tome el primer valor cb y agréguelo a la dirección del PIDL para avanzar el puntero al inicio de la siguiente estructura SHITEMID . A continuación, apuntará al miembro cb de esa estructura, que puede usar para avanzar el puntero al inicio de la siguiente estructura SHITEMID , etc. Cada vez que avance el puntero, examine la estructura SHITEMID para determinar si ha llegado a la raíz del espacio de nombres de la extensión.

Implementación de las interfaces principales

Al igual que con todos los objetos COM, la implementación de una extensión es en gran medida una cuestión de implementación de una colección de interfaces. En esta sección se describen las tres interfaces principales que deben implementar todas las extensiones. Se usan para la inicialización y para proporcionar al Explorador de Windows información básica sobre el contenido de la extensión. Estas interfaces, además de una vista de carpeta, son todas necesarias para una extensión funcional. Sin embargo, para aprovechar completamente las características del Explorador de Windows, la mayoría de las extensiones también implementan una o varias de las interfaces opcionales.

Interfaz IPersistFolder

Se llama a la interfaz IPersistFolder para inicializar un nuevo objeto de carpeta. El método IPersistFolder::Initialize asigna un PIDL completo al nuevo objeto. Almacene este PIDL para su uso posterior. Por ejemplo, un objeto de carpeta debe usar este PIDL para construir PIN completos para los elementos secundarios del objeto. El creador del objeto de carpeta también puede llamar a IPersist::GetClassID para solicitar el CLSID del objeto.

Normalmente, se crea e inicializa un objeto de carpeta mediante el método IShellFolder::BindToObject de su carpeta primaria. Sin embargo, cuando un usuario examina la extensión, el Explorador de Windows crea e inicializa el objeto de carpeta raíz de la extensión. El PIDL que recibe el objeto de carpeta raíz a través de IPersistFolder::Initialize contiene la ruta de acceso del escritorio a la carpeta raíz que necesitará para construir LOS PIDLs completos para la extensión.

Interfaz IShellFolder

Shell trata una extensión como una colección ordenada jerárquicamente de objetos de carpeta. La interfaz IShellFolder es el núcleo de cualquier implementación de extensión. Representa un objeto de carpeta y proporciona al Explorador de Windows gran parte de la información necesaria para mostrar el contenido de la carpeta.

IShellFolder suele ser la única interfaz de carpeta distinta de IPersistFolder que expone directamente un objeto folder. Aunque el Explorador de Windows usa una variedad de interfaces obligatorias y opcionales para obtener información sobre el contenido de la carpeta, obtiene punteros a esas interfaces a través de IShellFolder.

El Explorador de Windows obtiene el CLSID de la carpeta raíz de la extensión de varias maneras. Para obtener más información, vea Especificar la ubicación de una extensión de espacio de nombres o mostrar una vista Self-Contained de una extensión de espacio de nombres. A continuación, el Explorador de Windows usa ese CLSID para crear e inicializar una instancia de la carpeta raíz y consultar una interfaz IShellFolder . La extensión crea un objeto de carpeta para representar la carpeta raíz y devuelve la interfaz IShellFolder del objeto. Gran parte de la interacción entre la extensión y el Explorador de Windows se realiza a través de IShellFolder. El Explorador de Windows llama a IShellFolder para:

  • Solicite un objeto que pueda enumerar el contenido de la carpeta raíz.
  • Obtenga varios tipos de información sobre el contenido de la carpeta raíz.
  • Solicite un objeto que exponga una de las interfaces opcionales. Esas interfaces se pueden consultar para obtener información adicional, como iconos o menús contextuales.
  • Solicite un objeto de carpeta que represente una subcarpeta de la carpeta raíz.

Cuando un usuario abre una subcarpeta de la carpeta raíz, el Explorador de Windows llama a IShellFolder::BindToObject. La extensión crea e inicializa un nuevo objeto de carpeta para representar la subcarpeta y devuelve su interfaz IShellFolder . A continuación, el Explorador de Windows llama a esta interfaz para varios tipos de información, etc. hasta que el usuario decida navegar por otro lugar del espacio de nombres de Shell o cerrar el Explorador de Windows.

En el resto de esta sección se describen brevemente los métodos más importantes de IShellFolder y cómo implementarlos.

EnumObjects

Antes de mostrar el contenido de una carpeta en la vista de árbol, el Explorador de Windows debe determinar primero qué contiene la carpeta mediante una llamada al método IShellFolder::EnumObjects . Este método crea un objeto de enumeración OLE estándar que expone una interfaz IEnumIDList y devuelve ese puntero de interfaz. La interfaz IEnumIDList permite al Explorador de Windows obtener los PIN de todos los objetos contenidos en la carpeta. A continuación, estos PIN se usan para obtener información sobre los objetos contenidos en la carpeta . Para obtener más información, consulte IEnumIDList Interface.

Nota

El método IEnumIDList::Next solo debe devolver los PIN relativos a la carpeta primaria. El PIDL debe contener solo la estructura SHITEMID del objeto, seguida de un terminador.

 

CreateViewObject

Antes de que se muestre el contenido de una carpeta, el Explorador de Windows llama a este método para solicitar un puntero a una interfaz IShellView . El Explorador de Windows usa esta interfaz para administrar la vista de carpetas. Cree un objeto de vista de carpeta y devuelva su interfaz IShellView .

También se llama al método IShellFolder::CreateViewObject para solicitar una de las interfaces opcionales, como IContextMenu, para la propia carpeta. La implementación de este método debe crear un objeto que exponga la interfaz solicitada y devuelva el puntero de interfaz. Si el Explorador de Windows necesita una interfaz opcional para uno de los objetos contenidos en la carpeta, llamará a IShellFolder::GetUIObjectOf.

GetUIObjectOf

Aunque la información básica sobre el contenido de una carpeta está disponible a través de los métodos IShellFolder , la extensión también puede proporcionar al Explorador de Windows varios tipos de información adicional. Por ejemplo, puede especificar iconos para el contenido de una carpeta o el menú contextual de un objeto. El Explorador de Windows llama al método IShellFolder::GetUIObjectOf para intentar recuperar información adicional sobre un objeto contenido en una carpeta. El Explorador de Windows especifica el objeto para el que desea obtener la información y el IID de la interfaz pertinente. A continuación, el objeto folder crea un objeto que expone la interfaz solicitada y devuelve el puntero de interfaz.

Si la extensión permite a los usuarios transferir objetos con arrastrar y colocar o el Portapapeles, el Explorador de Windows llamará a IShellFolder::GetUIObjectOf para solicitar una interfaz IDataObject o IDropTarget . Para obtener más información, consulte Transferencia de objetos de Shell con arrastrar y colocar y el Portapapeles.

El Explorador de Windows llama a IShellFolder::CreateViewObject cuando desea el mismo tipo de información sobre la propia carpeta.

BindToObject

El Explorador de Windows llama al método IShellFolder::BindToObject cuando un usuario intenta abrir una de las subcarpetas de la extensión. Si riid se establece en IID_IShellFolder, debe crear e inicializar un objeto de carpeta que represente la subcarpeta y devuelva la interfaz IShellFolder del objeto.

Nota

En la actualidad, el Explorador de Windows llama a este método solo para solicitar una interfaz IShellFolder . Sin embargo, no suponga que esto siempre será el caso. Siempre debe comprobar el valor de riid antes de continuar.

 

GetDisplayNameOf

El Explorador de Windows llama al método IShellFolder::GetDisplayNameOf para convertir el PIDL de uno de los objetos de la carpeta en un nombre. Ese PIDL debe ser relativo a la carpeta primaria del objeto. En otras palabras, debe contener una única estructura SHITEMID que no sea NULL. Dado que hay más de una manera posible de asignar nombres a objetos, el Explorador de Windows especifica el tipo de nombre estableciendo una o varias marcas SHGDNF en el parámetro uFlags . Uno de los dos valores, SHGDN_NORMAL o SHGDN_INFOLDER, se establecerá para especificar si el nombre debe ser relativo a la carpeta o al escritorio. Uno de los otros tres valores, SHGDN_FOREDITING, SHGDN_FORADDRESSBAR o SHGDN_FORPARSING, se puede establecer para especificar para qué se usará el nombre.

Debe devolver el nombre en forma de estructura STRRET . Si SHGDN_FOREDITING, SHGDN_FORADDRESSBAR y SHGDN_FORPARSING no se establecen, devuelva el nombre para mostrar del objeto. Si se establece la marca SHGDN_FORPARSING , el Explorador de Windows solicita un nombre de análisis. Los nombres de análisis se pasan a IShellFolder::P arseDisplayName para obtener el PIDL de un objeto, aunque se encuentre uno o varios niveles por debajo de la carpeta actual en la jerarquía del espacio de nombres. Por ejemplo, el nombre de análisis de un objeto de sistema de archivos es su ruta de acceso. Puede pasar la ruta de acceso completa de cualquier objeto del sistema de archivos al método IShellFolder::P arseDisplayName del escritorio y devolverá el PIDL completo del objeto.

Aunque el análisis de nombres son cadenas de texto, no tienen que incluir necesariamente el nombre para mostrar. Debe asignar nombres de análisis en función de lo que funcionará de forma más eficaz cuando se llame a IShellFolder::P arseDisplayName . Por ejemplo, muchas de las carpetas virtuales del Shell no forman parte del sistema de archivos y no tienen una ruta de acceso completa. En su lugar, a cada carpeta se le asigna un GUID y el nombre del análisis adopta la forma ::{GUID}. Independientemente del esquema que use, debería ser capaz de "ida y vuelta". Por ejemplo, si un llamador pasa un nombre de análisis a IShellFolder::P arseDisplayName para recuperar el PIDL de un objeto y, a continuación, pasa ese PIDL a IShellFolder::GetDisplayNameOf con la marca SHGDN_FORPARSING establecida, el autor de la llamada debe recuperar el nombre de análisis original.

GetAttributesOf

El Explorador de Windows llama al método IShellFolder::GetAttributesOf para determinar los atributos de uno o varios elementos contenidos en un objeto folder. El valor de cidl proporciona el número de elementos de la consulta y aPidl apunta a una lista de sus PIN.

Dado que las pruebas de algunos atributos pueden llevar mucho tiempo, el Explorador de Windows normalmente restringe la consulta a un subconjunto de las marcas disponibles estableciendo sus valores en rfgInOut. El método debe probar solo los atributos cuyos marcadores se establecen en rfgInOut. Deje las marcas válidas establecidas y desactive el resto. Si se incluye más de un elemento en la consulta, establezca solo las marcas que se aplican a todos los elementos.

Nota

Los atributos deben establecerse correctamente para que se muestre correctamente un elemento. Por ejemplo, si un elemento es una carpeta que contiene subcarpetas, debe establecer la marca SFGAO_HASSUBFOLDER . De lo contrario, el Explorador de Windows no mostrará un signo + junto al icono del elemento en la vista de árbol.

 

ParseDisplayName

El método IShellFolder::P arseDisplayName tiene algún sentido una imagen reflejada de IShellFolder::GetDisplayNameOf. El uso más común de este método es convertir el nombre de análisis de un objeto en el PIDL asociado. El nombre de análisis puede hacer referencia a cualquier objeto que se encuentra debajo de la carpeta de la jerarquía de espacios de nombres. El PIDL devuelto es relativo al objeto de carpeta que expone el método y normalmente no está completo. En otras palabras, aunque el PIDL puede contener varias estructuras SHITEMID , la primera será la del propio objeto o la primera subcarpeta de la ruta de acceso de la carpeta al objeto . El autor de la llamada tendrá que anexar este PIDL a la PIDL completa de la carpeta para obtener un PIDL completo para el objeto.

También se puede llamar a IShellFolder::P arseDisplayName para solicitar los atributos de un objeto. Dado que la determinación de todos los atributos aplicables puede llevar mucho tiempo, el autor de la llamada establecerá solo las marcas de SFGAO_XXX que representan información en la que está interesado el autor de la llamada. Debe determinar cuál de esos atributos es true para el objeto y borrar las marcas restantes.

IEnumIDList (interfaz)

Cuando el Explorador de Windows necesita enumerar los objetos contenidos en una carpeta, llama a IShellFolder::EnumObjects. El objeto folder debe crear un objeto de enumeración que exponga la interfaz IEnumIDList y devuelva ese puntero de interfaz. Después, el Explorador de Windows usará IEnumIDList para enumerar los PIN de todos los objetos contenidos en la carpeta.

IEnumIDList es una interfaz de enumeración OLE estándar y se implementa de la manera habitual. No obstante, recuerde que los PIDL que se devuelven deben ser relativos a la carpeta y contener solo la estructura SHITEMID del objeto y un terminador.

Implementación de las interfaces opcionales

Hay una serie de interfaces de Shell opcionales que pueden admitir los objetos de carpeta de la extensión. Muchos de ellos, como IExtractIcon, permiten personalizar varios aspectos de la forma en que el usuario ve la extensión. Otros, como IDataObject, permiten que la extensión admita características como arrastrar y colocar.

Ningún objeto de carpeta expone directamente ninguna de las interfaces opcionales. En su lugar, el Explorador de Windows llama a uno de los dos métodos IShellFolder para solicitar una interfaz:

  • El Explorador de Windows llama a IShellFolder::GetUIObjectOf de un objeto de carpeta para solicitar una interfaz para uno de los objetos contenidos en la carpeta.
  • El Explorador de Windows llama a IShellFolder::CreateViewObject de un objeto de carpeta para solicitar una interfaz para la propia carpeta.

Para proporcionar la información, el objeto folder crea un objeto que expone la interfaz solicitada y devuelve el puntero de interfaz. A continuación, el Explorador de Windows llama a esa interfaz para recuperar la información necesaria. En esta sección se describen las interfaces opcionales más usadas.

IExtractIcon

El Explorador de Windows solicita una interfaz IExtractIcon antes de mostrar el contenido de una carpeta. La interfaz permite a la extensión especificar iconos personalizados para los objetos contenidos en la carpeta. De lo contrario, se usarán los iconos estándar de archivo y carpeta. Para proporcionar un icono personalizado, cree un objeto de extracción de iconos que exponga IExtractIcon y devuelva un puntero a esa interfaz. Para obtener más información, consulte la documentación de referencia de IExtractIcon o Creating Icon Handlers.

IContextMenu

Cuando un usuario hace clic con el botón derecho en un objeto, el Explorador de Windows solicita una interfaz IContextMenu . Para proporcionar menús contextuales para los objetos, cree un objeto de controlador de menús y devuelva su interfaz IContextMenu .

Los procedimientos para crear un objeto de controlador de menús son muy similares a los que se usan para crear una extensión shell del controlador de menús. Para obtener más información, vea Crear controladores de menú contextual o la referencia IContextMenu, IContextMenu2 o IContextMenu3 .

IQueryInfo

El Explorador de Windows llama a la interfaz IQueryInfo para recuperar una cadena de texto de información.

IDataObject e IDropTarget

Cuando el Explorador de Windows muestra los objetos, un objeto de carpeta no tiene ninguna manera directa de saber cuándo un usuario intenta cortar, copiar o arrastrar un objeto. En su lugar, el Explorador de Windows solicita una interfaz IDataObject . Para permitir que el objeto se transfiera, cree un objeto de datos y devuelva un puntero a su interfaz IDataObject .

Del mismo modo, un usuario podría intentar quitar un objeto de datos en una representación del Explorador de Windows de uno de los objetos, como un icono o una ruta de acceso de la barra de direcciones. A continuación, el Explorador de Windows solicita una interfaz IDropTarget . Para permitir que se quite el objeto de datos, cree un objeto que exponga una interfaz IDropTarget y devuelva el puntero de interfaz.

Controlar la transferencia de datos es uno de los aspectos más complicados de escribir extensiones de espacio de nombres. Para obtener una explicación detallada, consulte Transferencia de objetos de Shell con arrastrar y colocar y el Portapapeles.

Trabajar con la implementación predeterminada de la vista carpeta de Shell

Los orígenes de datos que usan el objeto de vista de carpeta de Shell predeterminado (DefView) deben implementar estas interfaces:

Opcionalmente, también pueden implementar IPersistFolder3.