Função SHBrowseForFolderA (shlobj_core.h)
Exibe uma caixa de diálogo que permite que o usuário selecione uma pasta shell.
Sintaxe
PIDLIST_ABSOLUTE SHBrowseForFolderA(
[in] LPBROWSEINFOA lpbi
);
Parâmetros
[in] lpbi
Tipo: LPBROWSEINFO
Um ponteiro para uma estrutura BROWSEINFO que contém informações usadas para exibir a caixa de diálogo.
Retornar valor
Tipo: PIDLIST_ABSOLUTE
Retorna um PIDL que especifica o local da pasta selecionada em relação à raiz do namespace. Se o usuário escolher o botão Cancelar na caixa de diálogo, o valor retornado será NULL.
É possível que o PIDL retornado seja o de um atalho de pasta em vez de uma pasta. Para obter uma discussão completa sobre esse caso, consulte a seção Comentários.
Comentários
Para o Windows Vista ou posterior, é recomendável que você use IFileDialog com a opção FOS_PICKFOLDERS em vez da função SHBrowseForFolder. Isso usa a caixa de diálogo Abrir Arquivos no modo escolher pastas e é a implementação preferencial.
Você deve inicializar o COM (Component Object Model) antes de chamar SHBrowseForFolder. Se você inicializar COM usando CoInitializeEx, deverá definir o sinalizador COINIT_APARTMENTTHREADED em seu parâmetro dwCoInit . Você também pode usar CoInitialize ou OleInitialize, que sempre usam threading de apartment. Se você precisar de funcionalidade de arrastar e soltar, o OleInitialize será recomendado porque inicializa o OLE necessário, bem como o COM.
Há dois estilos de caixa de diálogo disponíveis. O estilo mais antigo é exibido por padrão e não é redimensionável. O estilo mais recente fornece uma série de recursos adicionais, incluindo a funcionalidade de arrastar e soltar dentro da caixa de diálogo, reordenação, exclusão, menus de atalho, a capacidade de criar novas pastas e outros comandos de menu de atalho. Inicialmente, ele é maior que a caixa de diálogo mais antiga, mas o usuário pode redimensioná-lo. Para especificar uma caixa de diálogo usando o estilo mais recente, defina o sinalizador BIF_USENEWUI no membro ulFlags da estrutura BROWSEINFO .
Se você implementar uma função de retorno de chamada, especificada no membro lpfn da estrutura BROWSEINFO , receberá um identificador para a caixa de diálogo. Um uso desse identificador de janela é modificar o layout ou o conteúdo da caixa de diálogo. Como não é redimensionável, modificar a caixa de diálogo de estilo mais antigo é relativamente simples. Modificar a caixa de diálogo de estilo mais recente é muito mais difícil e não é recomendável. Ele não só tem um tamanho e layout diferentes do estilo antigo, mas suas dimensões e as posições de seus controles mudam sempre que são redimensionadas pelo usuário.
Se o sinalizador BIF_RETURNONLYFSDIRS estiver definido no membro ulFlags da estrutura BROWSEINFO , o botão OK permanecerá habilitado para itens "\server", bem como "\server\share" e itens de diretório. No entanto, se o usuário selecionar um item "\server", a passagem do PIDL retornado por SHBrowseForFolder para SHGetPathFromIDList falhará.
Filtragem personalizada
A partir do Windows XP, SHBrowseForFolder dá suporte à filtragem personalizada no conteúdo da caixa de diálogo. Para criar um filtro personalizado, siga estas etapas.- Defina o sinalizador BIF_NEWDIALOGSTYLE no membro ulFlags da estrutura BROWSEINFO apontada pelo parâmetro lpbi .
- Especifique uma função de retorno de chamada no membro lpfn dessa mesma estrutura BROWSEINFO .
- Codifique a função de retorno de chamada para receber as mensagens de BFFM_INITIALIZED e BFFM_IUNKNOWN. Ao receber a mensagem BFFM_IUNKNOWN, o parâmetro lParam da função de retorno de chamada contém um ponteiro para a implementação de IUnknown da caixa de diálogo. Chame QueryInterface nesse IUnknown para obter um ponteiro para uma instância de IFolderFilterSite.
- Crie um objeto que implemente IFolderFilter.
- Chame IFolderFilterSite::SetFilter, passando para ele um ponteiro para o IFolderFilter. Os métodos IFolderFilter podem ser usados para incluir e excluir itens da árvore.
- Depois que o filtro é criado, a interface IFolderFilterSite não é mais necessária. Chame IFolderFilterSite::Release se você não tiver mais uso para ele.
Lidando com atalhos
#include
// Macros for interface casts
#ifdef __cplusplus
#define IID_PPV_ARG(IType, ppType) IID_##IType, reinterpret_cast(static_cast(ppType))
#else
#define IID_PPV_ARG(IType, ppType) &IID_##IType, (void**)(ppType)
#endif
// Retrieves the UIObject interface for the specified full PIDL
STDAPI SHGetUIObjectFromFullPIDL(LPCITEMIDLIST pidl, HWND hwnd, REFIID riid, void **ppv)
{
LPCITEMIDLIST pidlChild;
IShellFolder* psf;
*ppv = NULL;
HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlChild);
if (SUCCEEDED(hr))
{
hr = psf->GetUIObjectOf(hwnd, 1, &pidlChild, riid, NULL, ppv);
psf->Release();
}
return hr;
}
#define ILSkip(pidl, cb) ((LPITEMIDLIST)(((BYTE*)(pidl))+cb))
#define ILNext(pidl) ILSkip(pidl, (pidl)->mkid.cb)
HRESULT SHILClone(LPCITEMIDLIST pidl, LPITEMIDLIST *ppidl)
{
DWORD cbTotal = 0;
if (pidl)
{
LPCITEMIDLIST pidl_temp = pidl;
cbTotal += sizeof (pidl_temp->mkid.cb);
while (pidl_temp->mkid.cb)
{
cbTotal += pidl_temp->mkid.cb;
pidl_temp += ILNext (pidl_temp);
}
}
*ppidl = (LPITEMIDLIST)CoTaskMemAlloc(cbTotal);
if (*ppidl)
CopyMemory(*ppidl, pidl, cbTotal);
return *ppidl ? S_OK: E_OUTOFMEMORY;
}
// Get the target PIDL for a folder PIDL. This also deals with cases of a folder
// shortcut or an alias to a real folder.
STDAPI SHGetTargetFolderIDList(LPCITEMIDLIST pidlFolder, LPITEMIDLIST *ppidl)
{
IShellLink *psl;
*ppidl = NULL;
HRESULT hr = SHGetUIObjectFromFullPIDL(pidlFolder, NULL, IID_PPV_ARG(IShellLink, &psl));
if (SUCCEEDED(hr))
{
hr = psl->GetIDList(ppidl);
psl->Release();
}
// It's not a folder shortcut so get the PIDL normally.
if (FAILED(hr))
hr = SHILClone(pidlFolder, ppidl);
return hr;
}
// Get the target folder for a folder PIDL. This deals with cases where a folder
// is an alias to a real folder, folder shortcuts, the My Documents folder, and
// other items of that nature.
STDAPI SHGetTargetFolderPath(LPCITEMIDLIST pidlFolder, LPWSTR pszPath, UINT cchPath)
{
LPITEMIDLIST pidlTarget;
*pszPath = 0;
HRESULT hr = SHGetTargetFolderIDList(pidlFolder, &pidlTarget);
if (SUCCEEDED(hr))
{
SHGetPathFromIDListW(pidlTarget, pszPath); // Make sure it is a path
CoTaskMemFree(pidlTarget);
}
return *pszPath ? S_OK : E_FAIL;
}
// Retrieves the UIObject interface for the specified full PIDLstatic
HRESULT SHGetUIObjectFromFullPIDL(LPCITEMIDLIST pidl, HWND hwnd, REFIID riid, void **ppv)
{
LPCITEMIDLIST pidlChild;
IShellFolder* psf;
*ppv = NULL;
HRESULT hr = SHBindToParent(pidl, IID_IShellFolder, (LPVOID*)&psf, &pidlChild);
if (SUCCEEDED(hr))
{
hr = psf->GetUIObjectOf(hwnd, 1, &pidlChild, riid, NULL, ppv);
psf->Release();
}
return hr;
}
static HRESULT SHILClone(LPCITEMIDLIST pidl, LPITEMIDLIST *ppidl)
{
DWORD cbTotal = 0;
if (pidl)
{
LPCITEMIDLIST pidl_temp = pidl;
cbTotal += pidl_temp->mkid.cb;
while (pidl_temp->mkid.cb)
{
cbTotal += pidl_temp->mkid.cb;
pidl_temp = ILNext(pidl_temp);
}
}
*ppidl = (LPITEMIDLIST)CoTaskMemAlloc(cbTotal);
if (*ppidl)
CopyMemory(*ppidl, pidl, cbTotal);
return *ppidl ? S_OK: E_OUTOFMEMORY;
}
// Get the target PIDL for a folder PIDL. This also deals with cases of a folder
// shortcut or an alias to a real folder.
static HRESULT SHGetTargetFolderIDList(LPCITEMIDLIST pidlFolder, LPITEMIDLIST *ppidl)
{
IShellLink *psl;
*ppidl = NULL;
HRESULT hr = SHGetUIObjectFromFullPIDL(pidlFolder, NULL, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hr))
{
hr = psl->GetIDList(ppidl);
psl->Release();
}
// It's not a folder shortcut so get the PIDL normally.
if (FAILED(hr))
hr = SHILClone(pidlFolder, ppidl);
return hr;
}
// Get the target folder for a folder PIDL. This deals with cases where a folder
// is an alias to a real folder, folder shortcuts, the My Documents folder,
// and so on.
STDAPI SHGetTargetFolderPath(LPCITEMIDLIST pidlFolder, LPWSTR pszPath, UINT cchPath)
{
LPITEMIDLIST pidlTarget;
*pszPath = 0;
HRESULT hr = SHGetTargetFolderIDList(pidlFolder, &pidlTarget);
if (SUCCEEDED(hr))
{
SHGetPathFromIDListW(pidlTarget, pszPath);
// Make sure it is a path
CoTaskMemFree(pidlTarget);
}
return *pszPath ? S_OK : E_FAIL;
}
Observação
O cabeçalho shlobj_core.h define SHBrowseForFolder como um alias que seleciona automaticamente a versão ANSI ou Unicode dessa função com base na definição da constante de pré-processador UNICODE. Misturar o uso do alias neutro de codificação com código que não seja neutro em codificação pode levar a incompatibilidades que resultam em erros de compilação ou de runtime. Para obter mais informações, consulte Convenções para protótipos de função.
Requisitos
Requisito | Valor |
---|---|
Cliente mínimo com suporte | Windows XP [somente aplicativos da área de trabalho] |
Servidor mínimo com suporte | Windows 2000 Server [somente aplicativos da área de trabalho] |
Plataforma de Destino | Windows |
Cabeçalho | shlobj_core.h (inclua Shlobj.h, Shlobj_core.h) |
Biblioteca | Shell32.lib |
DLL | Shell32.dll (versão 4.0 ou posterior) |