Partager via


SHBrowseForFolderA, fonction (shlobj_core.h)

Affiche une boîte de dialogue qui permet à l’utilisateur de sélectionner un dossier Shell.

Syntaxe

PIDLIST_ABSOLUTE SHBrowseForFolderA(
  [in] LPBROWSEINFOA lpbi
);

Paramètres

[in] lpbi

Type : LPBROWSEINFO

Pointeur vers une structure BROWSEINFO qui contient des informations utilisées pour afficher la boîte de dialogue.

Valeur de retour

Type : PIDLIST_ABSOLUTE

Retourne un code PIDL qui spécifie l’emplacement du dossier sélectionné par rapport à la racine de l’espace de noms. Si l’utilisateur choisit le bouton Annuler dans la boîte de dialogue, la valeur de retour est NULL.

Il est possible que le code PIDL retourné soit celui d’un raccourci de dossier plutôt que d’un dossier. Pour une discussion complète de ce cas, consultez la section Remarques.

Remarques

Pour Windows Vista ou version ultérieure, il est recommandé d’utiliser IFileDialog avec l’option FOS_PICKFOLDERS plutôt que la fonction SHBrowseForFolder. Cette opération utilise la boîte de dialogue Ouvrir des fichiers en mode Choisir des dossiers et est l’implémentation préférée.

Vous devez initialiser com (Component Object Model) avant d’appeler SHBrowseForFolder. Si vous initialisez COM à l’aide de CoInitializeEx, vous devez définir l’indicateur COINIT_APARTMENTTHREADED dans son paramètre dwCoInit. Vous pouvez également utiliser CoInitialize ou OleInitialize, qui utilisent toujours le thread d’appartement. Si vous avez besoin de fonctionnalités de glisser-déplacer, OleInitialize est recommandé, car il initialise l’OLE requis ainsi que COM.

Remarque Si COM est initialisé à l’aide de CoInitializeEx avec l’indicateur COINIT_MULTITHREADED, SHBrowseForFolder échoue si l’application appelante utilise l’indicateur BIF_USENEWUI ou BIF_NEWDIALOGSTYLE dans la structure BROWSEINFO.
 
Il incombe à l’application appelante d’appeler CoTaskMemFree de libérer l’IDList retourné par SHBrowseForFolder lorsqu’il n’est plus nécessaire.

Il existe deux styles de boîte de dialogue disponibles. L’ancien style est affiché par défaut et n’est pas redimensionnable. Le style plus récent fournit plusieurs fonctionnalités supplémentaires, notamment la fonctionnalité glisser-déplacer dans la boîte de dialogue, la réorganisation, la suppression, les menus contextuels, la possibilité de créer de nouveaux dossiers et d’autres commandes de menu contextuel. Initialement, il est supérieur à l’ancienne boîte de dialogue, mais l’utilisateur peut le redimensionner. Pour spécifier une boîte de dialogue à l’aide du style plus récent, définissez l’indicateur de BIF_USENEWUI dans l'ulFlags membre de la structure BROWSEINFO .

Si vous implémentez une fonction de rappel, spécifiée dans le membre lpfn de la structure BROWSEINFO, vous recevez un handle dans la boîte de dialogue. L’une des utilisations de ce handle de fenêtre consiste à modifier la disposition ou le contenu de la boîte de dialogue. Étant donné qu’il n’est pas redimensionnable, la modification de l’ancienne boîte de dialogue de style est relativement simple. La modification de la boîte de dialogue de style plus récente est beaucoup plus difficile et n’est pas recommandée. Non seulement il a une taille et une disposition différentes que l’ancien style, mais ses dimensions et les positions de ses contrôles changent chaque fois qu’il est redimensionné par l’utilisateur.

Si l’indicateur BIF_RETURNONLYFSDIRS est défini dans le ulFlags membre de la structure BROWSEINFO, le bouton OK reste activé pour les éléments « \server », ainsi que « \server\share » et les éléments de répertoire. Toutefois, si l’utilisateur sélectionne un élément « \server », le passage du code PIDL retourné par SHBrowseForFolder à SHGetPathFromIDList échoue.

filtrage personnalisé

À compter de Windows XP, SHBrowseForFolder prend en charge le filtrage personnalisé sur le contenu de la boîte de dialogue. Pour créer un filtre personnalisé, procédez comme suit.
  1. Définissez l’indicateur BIF_NEWDIALOGSTYLE dans le membre ulFlags de la structure BROWSEINFO pointée par le paramètre lpbi .
  2. Spécifiez une fonction de rappel dans le membre lpfn de cette même structure BROWSEINFO.
  3. Codez la fonction de rappel pour recevoir les messages BFFM_INITIALIZED et BFFM_IUNKNOWN. À la réception du message BFFM_IUNKNOWN, le paramètre de la fonction de rappel lParam contient un pointeur vers l’implémentation de IUnknownde boîte de dialogue. Appelez QueryInterface sur ce IUnknown pour obtenir un pointeur vers une instance de IFolderFilterSite.
  4. Créez un objet qui implémente IFolderFilter.
  5. Appelez IFolderFilterSite ::SetFilter, en lui transmettant un pointeur vers votre IFolderFilter. méthodes IFolderFilter peuvent ensuite être utilisées pour inclure et exclure des éléments de l’arborescence.
  6. Une fois le filtre créé, l’interface IFolderFilterSite n’est plus nécessaire. Appelez IFolderFilterSite ::Release si vous n’avez pas d’autre utilisation pour celle-ci.

traiter les raccourcis

Remarque Cette section s’applique uniquement aux systèmes Windows 2000 et versions antérieures. Par défaut, les systèmes Windows XP et versions ultérieures retournent le code PIDL de la cible d’un raccourci plutôt que le raccourci lui-même, tant que l’indicateur de BIF_NOTRANSLATETARGETS n’est pas défini dans la structure BROWSEINFO.
 
Si SHBrowseForFolder renvoie un code PIDL à un raccourci, en envoyant ce code PIDL à SHGetPathFromIDList retourne le chemin du raccourci lui-même plutôt que le chemin d’accès de sa cible. Le chemin d’accès à la cible du raccourci peut être obtenu à l’aide de l’interface IShellLink , comme illustré dans cet exemple.
#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;
}

Note

L’en-tête shlobj_core.h définit SHBrowseForFolder comme alias qui sélectionne automatiquement la version ANSI ou Unicode de cette fonction en fonction de la définition de la constante de préprocesseur UNICODE. Le mélange de l’utilisation de l’alias neutre en encodage avec du code qui n’est pas neutre en encodage peut entraîner des incompatibilités qui entraînent des erreurs de compilation ou d’exécution. Pour plus d’informations, consultez Conventions pour les prototypes de fonction.

Exigences

Exigence Valeur
client minimum pris en charge Windows XP [applications de bureau uniquement]
serveur minimum pris en charge Windows 2000 Server [applications de bureau uniquement]
plateforme cible Windows
d’en-tête shlobj_core.h (include Shlobj.h, Shlobj_core.h)
bibliothèque Shell32.lib
DLL Shell32.dll (version 4.0 ou ultérieure)

Voir aussi

Ouvrir et enregistrer sous forme de boîtes de dialogue