Funzione SHBrowseForFolderA (shlobj_core.h)

Visualizza una finestra di dialogo che consente all'utente di selezionare una cartella shell.

Sintassi

PIDLIST_ABSOLUTE SHBrowseForFolderA(
  [in] LPBROWSEINFOA lpbi
);

Parametri

[in] lpbi

Tipo: LPBROWSEINFO

Puntatore a una struttura BROWSEINFO che contiene informazioni usate per visualizzare la finestra di dialogo.

Valore restituito

Tipo: PIDLIST_ABSOLUTE

Restituisce un PIDL che specifica il percorso della cartella selezionata rispetto alla radice dello spazio dei nomi. Se l'utente sceglie il pulsante Annulla nella finestra di dialogo, il valore restituito è NULL.

È possibile che il PIDL restituito sia quello di un collegamento di cartella anziché di una cartella. Per una discussione completa di questo caso, vedere la sezione Osservazioni.

Commenti

Per Windows Vista o versioni successive, è consigliabile usare IFileDialog con l'opzione FOS_PICKFOLDERS anziché la funzione SHBrowseForFolder. In questo modo viene usata la finestra di dialogo Apri file in modalità cartelle di selezione ed è l'implementazione preferita.

È necessario inizializzare Il modello a oggetti componente (COM) prima di chiamare SHBrowseForFolder. Se si inizializza COM usando CoInitializeEx, è necessario impostare il flag di COINIT_APARTMENTTHREADED nel relativo parametro dwCoInit . È anche possibile usare CoInitialize o OleInitialize, che usano sempre il threading di appartamento. Se è necessaria la funzionalità di trascinamento della selezione, OleInitialize è consigliato perché inizializza l'OLE obbligatorio e COM.

Nota Se COM viene inizializzato usando CoInitializeEx con il flag COINIT_MULTITHREADED, SHBrowseForFolder ha esito negativo se l'applicazione chiamante usa il flag BIF_USENEWUI o BIF_NEWDIALOGSTYLE nella struttura BROWSEINFO .
 
È responsabilità dell'applicazione chiamante chiamare CoTaskMemFree per liberare l'IDList restituito da SHBrowseForFolder quando non è più necessario.

Sono disponibili due stili di finestra di dialogo. Lo stile precedente viene visualizzato per impostazione predefinita e non è ridimensionabile. Lo stile più recente offre numerose funzionalità aggiuntive, tra cui funzionalità di trascinamento della selezione all'interno della finestra di dialogo, riordinazione, eliminazione, menu di scelta rapida, possibilità di creare nuove cartelle e altri comandi di menu di scelta rapida. Inizialmente, è più grande della finestra di dialogo precedente, ma l'utente può ridimensionarlo. Per specificare una finestra di dialogo usando lo stile più recente, impostare il flag di BIF_USENEWUI nel membro ulFlags della struttura BROWSEINFO .

Se si implementa una funzione di callback, specificata nel membro lpfn della struttura BROWSEINFO , viene visualizzato un handle nella finestra di dialogo. Un uso di questo handle di finestra consiste nel modificare il layout o il contenuto della finestra di dialogo. Poiché non è ridimensionabile, la modifica della finestra di dialogo stile precedente è relativamente semplice. La modifica della finestra di dialogo stile più recente è molto più difficile e non consigliata. Non solo ha una dimensione e un layout diversi rispetto allo stile precedente, ma le dimensioni e le posizioni dei controlli cambiano ogni volta che viene ridimensionata dall'utente.

Se il flag BIF_RETURNONLYFSDIRS è impostato nel membro ulFlags della struttura BROWSEINFO , il pulsante OK rimane abilitato per gli elementi "\server", nonché per gli elementi della directory "\server\share". Tuttavia, se l'utente seleziona un elemento "\server", passando il PIDL restituito da SHBrowseForFolder a SHGetPathFromIDList ha esito negativo.

Filtro personalizzato

A partire da Windows XP , SHBrowseForFolder supporta il filtro personalizzato sul contenuto della finestra di dialogo. Per creare un filtro personalizzato, seguire questa procedura.
  1. Impostare il flag di BIF_NEWDIALOGSTYLE nel membro ulFlags della struttura BROWSEINFO a cui punta il parametro lpbi .
  2. Specificare una funzione di callback nel membro lpfn della stessa struttura BROWSEINFO .
  3. Codice della funzione di callback per ricevere i messaggi di BFFM_INITIALIZED e BFFM_IUNKNOWN. Al momento della ricezione del messaggio BFFM_IUNKNOWN, il parametro lParam della funzione callback contiene un puntatore all'implementazione della finestra di dialogo di IUnknown. Chiamare QueryInterface in tale IUnknown per ottenere un puntatore a un'istanza di IFolderFilterSite.
  4. Creare un oggetto che implementa IFolderFilter.
  5. Chiamare IFolderFilterSite::SetFilter, passandolo a un puntatore al filtro IFolderFilter. I metodi IFolderFilter possono quindi essere usati per includere ed escludere elementi dall'albero.
  6. Una volta creato il filtro, l'interfaccia IFolderFilterSite non è più necessaria. Chiamare IFolderFilterSite::Release se non è più possibile usarlo.

Gestione dei collegamenti

Nota Questa sezione si applica solo ai sistemi Windows 2000 e precedenti. Per impostazione predefinita, i sistemi Windows XP e versioni successive restituiscono il PIDL della destinazione di un collegamento anziché il collegamento stesso, purché il flag di BIF_NOTRANSLATETARGETS non sia impostato nella struttura BROWSEINFO .
 
Se SHBrowseForFolder restituisce un PIDL a un collegamento, inviando piDL a SHGetPathFromIDList restituisce il percorso del collegamento stesso anziché il percorso della destinazione. Il percorso della destinazione del collegamento può essere ottenuto usando l'interfaccia IShellLink , come illustrato in questo esempio.
#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;
}

Nota

L'intestazione shlobj_core.h definisce SHBrowseForFolder come alias che seleziona automaticamente la versione ANSI o Unicode di questa funzione in base alla definizione della costante preprocessore UNICODE. La combinazione dell'utilizzo dell'alias di codifica neutrale con il codice che non è neutrale dalla codifica può causare errori di corrispondenza che causano errori di compilazione o runtime. Per altre informazioni, vedere Convenzioni per i prototipi di funzione.

Requisiti

Requisito Valore
Client minimo supportato Windows XP [solo app desktop]
Server minimo supportato Windows 2000 Server [solo app desktop]
Piattaforma di destinazione Windows
Intestazione shlobj_core.h (includere Shlobj.h, Shlobj_core.h)
Libreria Shell32.lib
DLL Shell32.dll (versione 4.0 o successiva)

Vedi anche

Aprire e salvare le finestre di dialogo