Implementando as interfaces básicas de objeto de pasta
O procedimento para implementar uma extensão de namespace é semelhante ao de qualquer outro objeto COM (Component Object Model) em processo. Todas as extensões devem dar suporte a três interfaces primárias que fornecem ao Windows Explorer as informações básicas necessárias para exibir as pastas da extensão no modo de exibição de árvore. No entanto, para fazer uso total dos recursos do Windows Explorer, sua extensão também deve expor uma ou mais interfaces opcionais que dão suporte a recursos mais sofisticados, como menus de atalho ou arrastar e soltar, e fornecer uma exibição de pasta.
Este documento discute como implementar as interfaces primárias e opcionais que o Windows Explorer chama para obter informações sobre o conteúdo de sua extensão. Para obter uma discussão sobre como implementar um modo de exibição de pasta e como personalizar o Windows Explorer, consulte Implementando um modo de exibição de pasta.
- Implementação e registro básicos
- Manipulando PIDLs
- Implementando as interfaces primárias
- Implementando as interfaces opcionais
- Trabalhando com a implementação de exibição de pasta do Shell padrão
Implementação e registro básicos
Como um servidor COM em processo, sua DLL deve expor várias funções e interfaces padrão:
Essas funções e interfaces são implementadas da mesma forma que para a maioria dos outros objetos COM. Para obter detalhes, confira a Documentação do COM.
Registrar uma extensão
Assim como acontece com todos os objetos COM, você deve criar um GUID CLSID (identificador de classe) para sua extensão. Registre o objeto criando uma subchave de HKEY_CLASSES_ROOT\CLSID nomeada para o CLSID da sua extensão. A DLL deve ser registrada como um servidor em processo e deve especificar o modelo de threading de apartamento. Você pode personalizar o comportamento da pasta raiz de uma extensão adicionando uma variedade de subchaves e valores à chave CLSID da extensão.
Vários desses valores se aplicam somente a extensões com pontos de junção virtuais. Esses valores não se aplicam a extensões cujos pontos de junção são pastas do sistema de arquivos. Para obter mais informações, consulte Especificando o local de uma extensão de namespace. Para modificar o comportamento de uma extensão com um ponto de junção virtual, adicione um ou mais dos seguintes valores à chave CLSID da extensão:
- WantsFORPARSING. O nome de análise de uma extensão com um ponto de junção virtual normalmente terá o formato ::{GUID}. Extensões desse tipo normalmente contêm itens virtuais. No entanto, algumas extensões, como Meus Documentos, correspondem a pastas do sistema de arquivos, embora tenham pontos de junção virtuais. Se sua extensão representar objetos do sistema de arquivos dessa maneira, você poderá definir o valor WantsFORPARSING. O Windows Explorer solicitará o nome de análise da pasta raiz chamando o método IShellFolder::GetDisplayNameOf do objeto da pasta com uFlags definido como SHGDN_FORPARSING e pidl definido como um único ponteiro vazio para uma PIDL (lista de identificadores de item). Um PIDL vazio contém apenas um terminador. Seu método deve retornar o nome de análise ::{GUID} da pasta raiz.
- HideFolderVerbs. Os verbos registrados em HKEY_CLASSES_ROOT\Folder normalmente estão associados a todas as extensões. Eles aparecem no menu de atalho da extensão e podem ser invocados pelo ShellExecute. Para impedir que qualquer um desses verbos seja associado à sua extensão, defina o valor HideFolderVerbs.
- HideAsDelete. Se um usuário tentar excluir sua extensão, o Windows Explorer ocultará a extensão.
- HideAsDeletePerUser. Esse valor tem o mesmo efeito que HideAsDelete, mas por usuário. A extensão está oculta apenas para os usuários que tentaram excluí-la. A extensão é visível para todos os outros usuários.
- QueryForOverlay. Defina esse valor para indicar que o ícone da pasta raiz pode ter uma sobreposição de ícone. O objeto de pasta deve dar suporte à interface IShellIconOverlay. Antes que o Windows Explorer exiba o ícone da pasta raiz, ele solicitará um ícone de sobreposição chamando um dos dois métodos IShellIconOverlay com pidlItem definido como um PIDL vazio.
Os valores e subchaves restantes se aplicam a todas as extensões:
- Para especificar o nome de exibição da pasta de ponto de junção da extensão, defina o valor padrão da subchave CLSID da extensão como uma cadeia de caracteres apropriada.
- Quando o cursor passa sobre uma pasta, normalmente é exibida uma dica de informação que descreve o conteúdo da pasta. Para fornecer uma dica de informações para a pasta raiz da extensão, crie um valor REG_SZ de Dica de Informação para a chave CLSID da extensão e defina-o como uma cadeia de caracteres apropriada.
- Para especificar um ícone personalizado para a pasta raiz da extensão, crie uma subchave da subchave CLSID da extensão chamada DefaultIcon. Defina o valor padrão de DefaultIcon como um valor REG_SZ que contém o nome do arquivo que contém o ícone, seguido por uma vírgula, seguido por um sinal de menos, seguido pelo índice do ícone nesse arquivo.
- Por padrão, o menu de atalho da pasta raiz da extensão conterá os itens definidos em HKEY_CLASSES_ROOT\Folder. Os itens Excluir, Renomear e Propriedades serão adicionados se você tiver definido os sinalizadores de SFGAO_XXX apropriados. Você pode adicionar outros itens ao menu de atalho da pasta raiz ou substituir itens existentes, da mesma forma que faria com um tipo de arquivo. Crie uma subchave Shell na chave CLSID da extensão e defina comandos conforme discutido em Estendendo menus de atalho.
- Se você precisar de uma maneira mais flexível de lidar com o menu de atalho da pasta raiz, poderá implementar um manipulador de menu de atalho. Para registrar o manipulador de menu de atalho, crie uma chave ShellEx na chave CLSID da extensão. Registre o CLSID do manipulador como faria para um manipulador de extensão de shell convencional.
- Para adicionar uma página à folha de propriedades Propriedades da pasta raiz, dê à pasta o atributo SFGAO_HASPROPSHEET e implemente um manipulador de folha de propriedades. Para registrar o manipulador de folha de propriedades, crie uma chave ShellEx na chave CLSID da extensão. Registre o CLSID do manipulador como faria para um manipulador de extensão de shell convencional.
- Para especificar os atributos da pasta raiz, adicione uma subchave ShellFolder à subchave CLSID da extensão. Crie um valor de Atributos e defina-o como a combinação apropriada de sinalizadores SFGAO_XXX.
A tabela a seguir lista alguns atributos comumente usados para pastas raiz.
Sinalizador | Valor | Descrição |
---|---|---|
SFGAO_FOLDER | 0x20000000 | A pasta raiz da extensão contém um ou mais itens. |
SFGAO_HASSUBFOLDER | 0x80000000 | A pasta raiz da extensão contém um ou mais subpastas. O Windows Explorer colocará um sinal de mais ( + ) ao lado do ícone da pasta. |
SFGAO_CANDELETE | 0x00000020 | A pasta raiz da extensão pode ser excluída pelo usuário. O menu de atalho da pasta terá um item Excluir. Esse sinalizador deve ser definido para pontos de junção colocados em uma das pastas virtuais. |
SFGAO_CANRENAME | 0x00000010 | A pasta raiz da extensão pode ser renomeada pelo usuário. O menu de atalho da pasta terá um item Renomear. |
SFGAO_HASPROPSHEET | 0x00000040 | A pasta raiz da extensão tem uma folha de propriedades Propriedades. O menu de atalho da pasta terá um item Propriedades. Para fornecer a folha de propriedades, você deve implementar um manipulador de folha de propriedades. Registre o manipulador na chave CLSID da extensão, conforme discutido anteriormente. |
O exemplo a seguir mostra a entrada do Registro CLSID para uma extensão com um nome de exibição de MyExtension. A extensão tem um ícone personalizado contido na DLL da extensão com um índice de 1. Os atributos SFGAO_FOLDER, SFGAO_HASSUBFOLDER e SFGAO_CANDELETE são definidos.
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
Manipulando PIDLs
Cada item no namespace do Shell deve ter um PIDL exclusivo. O Windows Explorer atribui um PIDL à sua pasta raiz e passa o valor para sua extensão durante a inicialização. Sua extensão é responsável por atribuir um PIDL construído corretamente a cada um de seus objetos e fornecer esses PIDLs ao Windows Explorer mediante solicitação. Quando o Shell usa um PIDL para identificar um dos objetos da extensão, sua extensão deve ser capaz de interpretar o PIDL e identificar o objeto específico. Sua extensão também deve atribuir um nome de exibição e um nome de análise a cada objeto. Como os PIDLs são usados por praticamente todas as interfaces de pasta, as extensões geralmente implementam um único gerenciador de PIDL para lidar com todas essas tarefas.
O termo PIDL é a abreviação de uma estrutura ITEMIDLIST ou um ponteiro para essa estrutura, dependendo do contexto. Conforme declarado, uma estrutura ITEMIDLIST tem um único membro, uma estrutura SHITEMID . A estrutura ITEMIDLIST de um objeto é na verdade um array compactado de duas ou mais estruturas SHITEMID. A ordem dessas estruturas define um caminho através do namespace, da mesma forma que c:\MyDirectory\MyFile define um caminho através do sistema de arquivos. Normalmente, o PIDL de um objeto consistirá em uma série de estruturas SHITEMID que correspondem às pastas que definem o caminho do namespace, seguidas pela estrutura SHITEMID do objeto, seguida por um terminador.
O terminador é uma estrutura SHITEMID, com o membro cb definido como NULL. O terminador é necessário porque o número de estruturas SHITEMID no PIDL de um objeto depende do local do objeto no namespace do Shell e do ponto de partida do caminho. Além disso, o tamanho das várias estruturas SHITEMID pode variar. Ao receber um PIDL, você não tem uma maneira simples de determinar seu tamanho ou mesmo o número total de estruturas SHITEMID. Em vez disso, você deve "percorrer" a matriz compactada, estrutura por estrutura, até chegar ao terminador.
Para criar um PIDL, seu aplicativo precisa:
- Crie uma estrutura SHITEMID para cada um de seus objetos.
- Monte as estruturas SHITEMID relevantes em um PIDL.
Criando uma estrutura SHITEMID
A estrutura SHITEMID de um objeto identifica exclusivamente o objeto dentro de sua pasta. Na verdade, um tipo de PIDL usado por muitos dos métodos IShellFolder consiste apenas na estrutura SHITEMID do objeto, seguida por um terminador. A definição de uma estrutura SHITEMID é:
typedef struct _SHITEMID {
USHORT cb;
BYTE abID[1];
} SHITEMID, * LPSHITEMID;
O membro abID é o identificador do objeto. Como o comprimento de abID não é definido e pode variar, o membro cb é definido como o tamanho da estrutura SHITEMID, em bytes.
Como nem o comprimento nem o conteúdo do abID são padronizados, você pode usar qualquer esquema que desejar para atribuir valores de abID aos seus objetos. O único requisito é que você não pode ter dois objetos na mesma pasta com valores idênticos. No entanto, por motivos de desempenho, sua estrutura SHITEMID deve ser alinhada a DWORD. Em outras palavras, você deve construir seus valores abID de forma que cb seja um múltiplo integral de 4.
Normalmente, o abID aponta para uma estrutura definida pela extensão. Além da ID do objeto, essa estrutura geralmente é usada para armazenar uma variedade de informações relacionadas, como o tipo ou os atributos do objeto. Os objetos de pasta da extensão podem extrair rapidamente as informações do PIDL em vez de ter que consultá-las.
Observação
Um dos aspectos mais importantes do projeto de uma estrutura de dados para um PIDL é tornar a estrutura persistente e transportável. No contexto de PIDLs, o significado desses termos é:
- Persistente. O sistema frequentemente coloca PIDLs em vários tipos de armazenamento de longo prazo, como arquivos de atalho. Ele pode recuperar esses PIDLs do armazenamento posteriormente, possivelmente após a reinicialização do sistema. Um PIDL que foi recuperado do armazenamento ainda deve ser válido e significativo para sua extensão. Esse requisito significa, por exemplo, que você não deve usar ponteiros ou identificadores em sua estrutura PIDL. Os PIDLs que contêm esse tipo de dados normalmente não terão sentido quando o sistema os recuperar posteriormente do armazenamento.
- Transportável. Um PIDL deve permanecer significativo quando transportado de um computador para outro. Por exemplo, um PIDL pode ser gravado em um arquivo de atalho, copiado para um disquete e transportado para outro computador. Esse PIDL ainda deve ser significativo para sua extensão em execução no segundo computador. Por exemplo, para garantir que seus PIDLs sejam transportáveis, use caracteres ANSI ou Unicode explicitamente. Evite tipos de dados como TCHAR ou LPTSTR. Se você usar esses tipos de dados, um PIDL criado em um computador que executa uma versão Unicode de sua extensão não poderá ser lido por uma versão ANSI dessa extensão em execução em um computador diferente.
A declaração a seguir mostra um exemplo simples de estrutura de dados.
typedef struct tagMYPIDLDATA {
USHORT cb;
DWORD dwType;
WCHAR wszDisplayName[40];
} MYPIDLDATA, *LPMYPIDLDATA;
O membro cb é definido como o tamanho da estrutura MYPIDLDATA. Esse membro torna MYPIDLDATA uma estrutura SHITEMID válida, por si só. O restante dos membros é equivalente ao membro abID de uma estrutura SHITEMID e contém dados privados. O membro dwType é um valor definido pela extensão que indica o tipo de objeto. Para este exemplo, dwType é definido como TRUE para pastas e FALSE caso contrário. Esse membro permite, por exemplo, determinar rapidamente se o objeto é uma pasta ou não. O membro wszDisplayName contém o nome de exibição do objeto. Como você não atribuiria o mesmo nome de exibição a dois objetos diferentes na mesma pasta, o nome de exibição também serve como a ID do objeto. Neste exemplo, wszDisplayName é definido como 40 caracteres para garantir que a estrutura SHITEMID seja alinhada a DWORD. Para limitar o tamanho de seus PIDLs, você pode usar uma matriz de caracteres de comprimento variável e ajustar o valor de cb de acordo. Preencha a cadeia de caracteres de exibição com caracteres '\0' suficientes para manter o alinhamento DWORD da estrutura. Outros membros que podem ser úteis para colocar na estrutura incluem o tamanho do objeto, os atributos ou o nome da análise.
Construir um PIDL
Depois de definir estruturas SHITEMID para seus objetos, você pode usá-las para construir um PIDL. Os PIDLs podem ser construídos para uma variedade de propósitos, mas a maioria das tarefas usa um dos dois tipos de PIDL. O mais simples, um PIDL de nível único, identifica o objeto em relação à sua pasta pai. Esse tipo de PIDL é usado por muitos dos métodos IShellFolder . Um PIDL de nível único contém a estrutura SHITEMID do objeto, seguida por um terminador. Um PIDL totalmente qualificado define um caminho através da hierarquia de namespace da área de trabalho para o objeto. Esse tipo de PIDL começa na área de trabalho e contém uma estrutura SHITEMID para cada pasta no caminho, seguida pelo objeto e pelo terminador. Um PIDL totalmente qualificado identifica exclusivamente o objeto em todo o namespace do Shell.
A maneira mais simples de construir um PIDL é trabalhar diretamente com a própria estrutura ITEMIDLIST. Crie uma estrutura ITEMIDLIST, mas aloque memória suficiente para manter todas as estruturas SHITEMID. O endereço dessa estrutura apontará para a estrutura SHITEMID inicial. Defina valores para os membros dessa estrutura inicial e, em seguida, acrescente quantas estruturas SHITEMID adicionais forem necessárias, na ordem apropriada. O procedimento a seguir descreve como criar um PIDL de nível único. Ele contém duas estruturas SHITEMID — uma estrutura MYPIDLDATA seguida por um terminador:
- Use a função CoTaskMemAlloc para alocar memória para o PIDL. Aloque memória suficiente para seus dados privados mais um USHORT (dois bytes) para o terminador. Converta o resultado em LPMYPIDLDATA.
- Defina o membro cb da primeira estrutura MYPIDLDATA para o tamanho dessa estrutura. Para este exemplo, você definiria cb como sizeof(MYPIDLDATA). Se você quiser usar uma estrutura de comprimento variável, terá que calcular o valor de cb.
- Atribua valores apropriados aos membros de dados privados.
- Calcule o endereço da próxima estrutura SHITEMID. Converta o endereço da estrutura MYPIDLDATA atual em LPBYTE e adicione esse valor ao valor de cb determinado na etapa 3.
- Nesse caso, a próxima estrutura SHITEMID é o terminador. Defina o membro cb da estrutura como zero.
Para PIDLs mais longos, aloque memória suficiente e repita as etapas 3 a 5 para cada estrutura SHITEMID adicional.
A função de exemplo a seguir usa o tipo e o nome de exibição de um objeto e retorna o PIDL de nível único do objeto. A função pressupõe que o nome de exibição, incluindo seu caractere nulo de terminação, não exceda o número de caracteres declarados para a estrutura MYPIDLDATA. Se essa suposição estiver errada, a função StringCbCopyW truncará o nome de exibição. A variável g_pMalloc é um ponteiro IMalloc criado em outro lugar e armazenado em uma variável 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;
Um PIDL totalmente qualificado deve ter estruturas SHITEMID para cada objeto, desde a área de trabalho até o objeto. Sua extensão recebe um PIDL totalmente qualificado para sua pasta raiz quando o Shell chama IPersistFolder::Initialize. Para construir um PIDL totalmente qualificado para um objeto, pegue o PIDL que o Shell atribuiu à sua pasta raiz e acrescente as estruturas SHITEMID necessárias para levá-lo da pasta raiz para o objeto.
Interpretando PIDLs
Quando o Shell ou um aplicativo chama uma das interfaces da extensão para solicitar informações sobre um objeto, ele geralmente identifica o objeto por um PIDL. Alguns métodos, como IShellFolder::GetUIObjectOf, usam PIDLs que são relativos à pasta pai e são simples de interpretar. No entanto, sua extensão provavelmente também receberá PIDLs totalmente qualificados. O gerenciador PIDL deve determinar a qual dos objetos o PIDL está se referindo.
O que complica a tarefa de associar um objeto a um PIDL totalmente qualificado é que uma ou mais das estruturas SHITEMID no PIDL podem pertencer a objetos que estão fora de sua extensão no namespace do Shell. Você não tem como interpretar o significado do membro abID dessas estruturas. O que sua extensão deve fazer é "percorrer" a lista de estruturas SHITEMID, até chegar à estrutura que corresponde à sua pasta raiz. A partir de então, você saberá como interpretar as informações nas estruturas SHITEMID.
Para percorrer o PIDL, pegue o primeiro valor cb e adicione-o ao endereço do PIDL para avançar o ponteiro para o início da próxima estrutura SHITEMID. Em seguida, ele apontará para o membro cb dessa estrutura, que você pode usar para avançar o ponteiro para o início da próxima estrutura SHITEMID e assim por diante. Cada vez que você avançar o ponteiro, examine a estrutura SHITEMID para determinar se você atingiu a raiz do namespace da extensão.
Implementando as interfaces primárias
Assim como acontece com todos os objetos COM, a implementação de uma extensão é em grande parte uma questão de implementar uma coleção de interfaces. Esta seção discute as três interfaces principais que devem ser implementadas por todas as extensões. Eles são usados para inicialização e para fornecer ao Windows Explorer informações básicas sobre o conteúdo da extensão. Essas interfaces, além de uma exibição de pasta, são tudo o que é necessário para uma extensão funcional. No entanto, para explorar totalmente os recursos do Windows Explorer, a maioria das extensões também implementa uma ou mais das interfaces opcionais.
IPersistFolder Interface
A interface IPersistFolder é chamada para inicializar um novo objeto de pasta. O método IPersistFolder::Initialize atribui um PIDL totalmente qualificado ao novo objeto. Armazene este PIDL para uso posterior. Por exemplo, um objeto de pasta deve usar esse PIDL para construir PIDLs totalmente qualificados para os filhos do objeto. O criador do objeto de pasta também pode chamar IPersist::GetClassID para solicitar o CLSID do objeto.
Normalmente, um objeto de pasta é criado e inicializado pelo método IShellFolder::BindToObject de sua pasta pai. No entanto, quando um usuário navega em sua extensão, o Windows Explorer cria e inicializa o objeto de pasta raiz da extensão. O PIDL que o objeto de pasta raiz recebe por meio de IPersistFolder::Initialize contém o caminho da área de trabalho para a pasta raiz que você precisará para construir PIDLs totalmente qualificados para sua extensão.
Interface IShellFolder
O Shell trata uma extensão como uma coleção hierarquicamente ordenada de objetos de pasta. A interface IShellFolder é o núcleo de qualquer implementação de extensão. Ele representa um objeto de pasta e fornece ao Windows Explorer muitas das informações necessárias para exibir o conteúdo da pasta.
IShellFolder normalmente é a única interface de pasta diferente de IPersistFolder que é exposta diretamente por um objeto de pasta. Embora o Windows Explorer use uma variedade de interfaces necessárias e opcionais para obter informações sobre o conteúdo da pasta, ele obtém ponteiros para essas interfaces por meio de IShellFolder.
O Windows Explorer obtém o CLSID da pasta raiz da extensão de várias maneiras. Para obter detalhes, consulte Especificando o local de uma extensão de namespace ou Exibindo uma exibição independente de uma extensão de namespace. Em seguida, o Windows Explorer usa esse CLSID para criar e inicializar uma instância da pasta raiz e consultar uma interface IShellFolder . Sua extensão cria um objeto de pasta para representar a pasta raiz e retorna a interface IShellFolder do objeto. Grande parte do restante da interação entre sua extensão e o Windows Explorer ocorre por meio de IShellFolder. O Windows Explorer chama IShellFolder para:
- Solicite um objeto que possa enumerar o conteúdo da pasta raiz.
- Obtenha vários tipos de informações sobre o conteúdo da pasta raiz.
- Solicite um objeto que exponha uma das interfaces opcionais. Essas interfaces podem ser consultadas para obter informações adicionais, como ícones ou menus de atalho.
- Solicite um objeto de pasta que represente uma subpasta da pasta raiz.
Quando um usuário abre uma subpasta da pasta raiz, Windows Explorer chama IShellFolder::BindToObject. Sua extensão cria e inicializa um novo objeto de pasta para representar a subpasta e retorna sua interface IShellFolder . Em seguida, o Windows Explorer chama essa interface para vários tipos de informações e assim por diante até que o usuário decida navegar em outro lugar no namespace do Shell ou fechar o Windows Explorer.
O restante desta seção discute brevemente os métodos IShellFolder mais importantes e como implementá-los.
EnumObjects
Antes de exibir o conteúdo de uma pasta no modo de exibição de árvore, Windows Explorer deve primeiro determinar o que a pasta contém chamando o método IShellFolder::EnumObjects . Esse método cria um objeto de enumeração OLE padrão que expõe uma interface IEnumIDList e retorna esse ponteiro de interface. A interface IEnumIDList permite que o Windows Explorer obtenha os PIDLs de todos os objetos contidos na pasta. Esses PIDLs são usados para obter informações sobre os objetos contidos na pasta. Para obter mais detalhes, consulte Interface IEnumIDList.
Observação
O método IEnumIDList::Next só deve retornar PIDLs relativos à pasta pai. O PIDL deve conter apenas a estrutura SHITEMID do objeto, seguida por um terminador.
CreateViewObject
Antes que o conteúdo de uma pasta seja exibido, Windows Explorer chama esse método para solicitar um ponteiro para uma interface IShellView. Essa interface é usada pelo Windows Explorer para gerenciar a exibição de pasta. Crie um objeto de exibição de pasta e retorne sua interface IShellView.
O método IShellFolder::CreateViewObject também é chamado para solicitar uma das interfaces opcionais, como IContextMenu, para a própria pasta. Sua implementação desse método deve criar um objeto que expõe a interface solicitada e retorna o ponteiro da interface. Se o Windows Explorer precisar de uma interface opcional para um dos objetos contidos na pasta, ele chamará IShellFolder::GetUIObjectOf.
GetUIObjectOf
Embora as informações básicas sobre o conteúdo de uma pasta estejam disponíveis por meio dos métodos IShellFolder, sua extensão também pode fornecer ao Windows Explorer vários tipos de informações adicionais. Por exemplo, você pode especificar ícones para o conteúdo de uma pasta ou menu de atalho de um objeto. O Windows Explorer chama o método IShellFolder::GetUIObjectOf para tentar recuperar informações adicionais sobre um objeto contido em uma pasta. O Windows Explorer especifica para qual objeto ele deseja as informações e a IID da interface relevante. Em seguida, o objeto de pasta cria um objeto que expõe a interface solicitada e retorna o ponteiro da interface.
Se sua extensão permitir que os usuários transfiram objetos com arrastar e soltar ou a área de transferência, Windows Explorer chamará IShellFolder::GetUIObjectOf para solicitar uma interface IDataObject ou IDropTarget. Para obter detalhes, consulte Transferindo objetos de shell com arrastar e soltar e a área de transferência.
O Windows Explorer chama IShellFolder::CreateViewObject quando deseja o mesmo tipo de informação sobre a própria pasta.
BindToObject
O Windows Explorer chama o método IShellFolder::BindToObject quando um usuário tenta abrir uma das subpastas da sua extensão. Se riid estiver definido como IID_IShellFolder, você deverá criar e inicializar um objeto de pasta que represente a subpasta e retorne a interface IShellFolder do objeto.
Observação
No momento, o Windows Explorer chama esse método apenas para solicitar uma interface IShellFolder. No entanto, não assuma que esse sempre será o caso. Você deve sempre verificar o valor de riid antes de prosseguir.
GetDisplayNameOf
O Windows Explorer chama o método IShellFolder::GetDisplayNameOf para converter o PIDL de um dos objetos da pasta em um nome. Esse PIDL deve ser relativo à pasta pai do objeto. Em outras palavras, ele deve conter uma única estrutura SHITEMIDnão NULL. Como há mais de uma maneira possível de nomear objetos, o Windows Explorer especifica o tipo de nome definindo um ou mais sinalizadores SHGDNF no parâmetro uFlags. Um dos dois valores, SHGDN_NORMAL ou SHGDN_INFOLDER, será definido para especificar se o nome deve ser relativo à pasta ou à área de trabalho. Um dos outros três valores, SHGDN_FOREDITING, SHGDN_FORADDRESSBAR ou SHGDN_FORPARSING, pode ser definido para especificar para que o nome será usado.
Você deve retornar o nome na forma de uma estrutura STRRET. Se SHGDN_FOREDITING, SHGDN_FORADDRESSBAR e SHGDN_FORPARSING não estiverem definidos, retorne o nome de exibição do objeto. Se o sinalizador SHGDN_FORPARSING estiver definido, o Windows Explorer está solicitando um nome de análise. Os nomes de análise são passados para IShellFolder::ParseDisplayName para obter o PIDL de um objeto, mesmo que ele esteja localizado um ou mais níveis abaixo da pasta atual na hierarquia de namespace. Por exemplo, o nome de análise de um objeto do sistema de arquivos é seu caminho. Você pode passar o caminho totalmente qualificado de qualquer objeto no sistema de arquivos para o método IShellFolder::ParseDisplayName da área de trabalho e ele retornará o PIDL totalmente qualificado do objeto.
Embora os nomes de análise sejam cadeias de caracteres de texto, eles não precisam necessariamente incluir o nome de exibição. Você deve atribuir nomes de análise com base no que funcionará com mais eficiência quando IShellFolder::ParseDisplayName for chamado. Por exemplo, muitas das pastas virtuais do Shell não fazem parte do sistema de arquivos e não têm um caminho totalmente qualificado. Em vez disso, cada pasta recebe um GUID e o nome de análise assume o formato ::{GUID}. Independentemente do esquema que você usa, ele deve ser capaz de "ida e volta" de forma confiável. Por exemplo, se um chamador passar um nome de análise para IShellFolder::ParseDisplayName para recuperar o PIDL de um objeto e, em seguida, passar esse PIDL para IShellFolder::GetDisplayNameOf com o sinalizador SHGDN_FORPARSING definido, o chamador deverá recuperar o nome de análise original.
GetAttributesOf
Windows Explorer chama o método IShellFolder::GetAttributesOf para determinar os atributos de um ou mais itens contidos por um objeto de pasta. O valor de cidl fornece o número de itens na consulta e aPidl aponta para uma lista de seus PIDLs.
Como o teste de alguns atributos pode ser demorado, o Windows Explorer normalmente restringe a consulta a um subconjunto dos sinalizadores disponíveis definindo seus valores em rfgInOut. Seu método deve testar apenas os atributos cujos sinalizadores são definidos em rfgInOut. Deixe os sinalizadores válidos definidos e limpe o restante. Se mais de um item for incluído na consulta, defina apenas os sinalizadores que se aplicam a todos os itens.
Observação
Os atributos devem ser definidos corretamente para que um item seja exibido corretamente. Por exemplo, se um item for uma pasta que contém subpastas, você deverá definir o sinalizador SFGAO_HASSUBFOLDER. Caso contrário, o Windows Explorer não exibirá um + ao lado do ícone do item no modo de exibição de árvore.
ParseDisplayName
O método IShellFolder::ParseDisplayName é, em certo sentido, uma imagem espelhada de IShellFolder::GetDisplayNameOf. O uso mais comum desse método é converter o nome de análise de um objeto no PIDL associado. O nome da análise pode se referir a qualquer objeto que esteja abaixo da pasta na hierarquia do namespace. O PIDL retornado é relativo ao objeto de pasta que expõe o método e geralmente não é totalmente qualificado. Em outras palavras, embora o PIDL possa conter várias estruturas SHITEMID , a primeira será a do próprio objeto ou a primeira subpasta no caminho da pasta para o objeto. O chamador terá que acrescentar esse PIDL ao PIDL totalmente qualificado da pasta para obter um PIDL totalmente qualificado para o objeto.
IShellFolder::ParseDisplayName também pode ser chamado para solicitar os atributos de um objeto. Como determinar todos os atributos aplicáveis pode ser demorado, o chamador definirá apenas os sinalizadores SFGAO_XXX que representam informações nas quais o chamador está interessado. Você deve determinar quais desses atributos são verdadeiros para o objeto e limpar os sinalizadores restantes.
IEnumIDList Interface
Quando o Windows Explorer precisa enumerar os objetos contidos em uma pasta, ele chama IShellFolder::EnumObjects. O objeto de pasta deve criar um objeto de enumeração que expõe a interface IEnumIDList e retornar esse ponteiro de interface. O Windows Explorer normalmente usará IEnumIDList para enumerar os PIDLs de todos os objetos contidos na pasta.
IEnumIDList é uma interface de enumeração OLE padrão e é implementada da maneira usual. Lembre-se, no entanto, de que os PIDLs retornados devem ser relativos à pasta e conter apenas a estrutura SHITEMID do objeto e um terminador.
Implementando as interfaces opcionais
Há várias interfaces opcionais do Shell que os objetos de pasta da sua extensão podem dar suporte. Muitos deles, como IExtractIcon, permitem que você personalize vários aspectos da maneira como o usuário exibe sua extensão. Outros, como IDataObject, permitem que sua extensão dê suporte a recursos como arrastar e soltar.
Nenhuma das interfaces opcionais é exposta diretamente por um objeto de pasta. Em vez disso, o Windows Explorer chama um dos dois métodos IShellFolder para solicitar uma interface:
- O Windows Explorer chama o IShellFolder::GetUIObjectOf de um objeto de pasta para solicitar uma interface para um dos objetos contidos na pasta.
- O Windows Explorer chama o IShellFolder::CreateViewObject de um objeto de pasta para solicitar uma interface para a própria pasta.
Para fornecer as informações, o objeto de pasta cria um objeto que expõe a interface solicitada e retorna o ponteiro da interface. Em seguida, o Windows Explorer chama essa interface para recuperar as informações necessárias. Esta seção discute as interfaces opcionais mais usadas.
IExtractIcon
O Windows Explorer solicita uma interface IExtractIcon antes de exibir o conteúdo de uma pasta. A interface permite que sua extensão especifique ícones personalizados para os objetos contidos na pasta. Caso contrário, os ícones padrão de arquivos e pastas serão usados. Para fornecer um ícone personalizado, crie um objeto de extração de ícone que exponha IExtractIcon e retorne um ponteiro para essa interface. Para obter mais informações, consulte a documentação de referência do IExtractIcon ou Criando manipuladores de ícones.
IContextMenu
Quando um usuário clica com o botão direito do mouse em um objeto, o Windows Explorer solicita uma interface IContextMenu. Para fornecer menus de atalho para seus objetos, crie um objeto manipulador de menu e retorne sua interface IContextMenu .
Os procedimentos para criar um objeto manipulador de menu são muito semelhantes aos usados para criar uma extensão Shell do manipulador de menu. Para obter detalhes, consulte Criando manipuladores de menu de contexto ou a referência IContextMenu, IContextMenu2 ou IContextMenu3.
IQueryInfo
Windows Explorer chama a interface IQueryInfo para recuperar uma cadeia de caracteres de texto de dica de informação.
IDataObject e IDropTarget
Quando seus objetos são exibidos pelo Windows Explorer, um objeto de pasta não tem uma maneira direta de saber quando um usuário está tentando recortar, copiar ou arrastar um objeto. Em vez disso, o Windows Explorer solicita uma interface IDataObject. Para permitir que o objeto seja transferido, crie um objeto de dados e retorne um ponteiro para sua interface IDataObject.
Da mesma forma, um usuário pode tentar soltar um objeto de dados em uma representação do Windows Explorer de um de seus objetos, como um ícone ou caminho da barra de endereços. Em seguida, o Windows Explorer solicita uma interface IDropTarget. Para permitir que o objeto de dados seja descartado, crie um objeto que exponha uma interface IDropTarget e retorne o ponteiro da interface.
Lidar com a transferência de dados é um dos aspectos mais complicados da gravação de extensões de namespace. Para obter uma discussão detalhada, consulte Transferindo objetos de shell com arrastar e soltar e a área de transferência.
Trabalhando com a implementação de exibição de pasta do Shell padrão
As fontes de dados que usam o objeto de exibição de pasta padrão do Shell (DefView) devem implementar estas interfaces:
Opcionalmente, eles também podem implementar IPersistFolder3.