Condividi tramite


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 utilizzate 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 a una cartella anziché di una cartella. Per una descrizione completa di questo caso, vedere la sezione Osservazioni.

Osservazioni

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

È necessario inizializzare Component Object Model (COM) prima di chiamare SHBrowseForFolder. Se si inizializza COM utilizzando CoInitializeEx, è necessario impostare il flag COINIT_APARTMENTTHREADED nel relativo parametro dwCoInit. È anche possibile usare CoInitialize o OleInitialize, che usano sempre il threading apartment. Se è necessaria la funzionalità di trascinamento della selezione, è consigliabile OleInitialize perché inizializza il ole necessario e COM.

Nota Se COM viene inizializzato utilizzando CoInitializeEx con il flag COINIT_MULTITHREADED, SHBrowseForFolder ha esito negativo se l'applicazione chiamante utilizza il flag BIF_USENEWUI o BIF_NEWDIALOGSTYLE nella struttura BROWSEINFO.
 
È responsabilità dell'applicazione chiamante chiamare CoTaskMemFree 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 la funzionalità di trascinamento della selezione all'interno della finestra di dialogo, il riordinamento, l'eliminazione, i menu di scelta rapida, la 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 utilizzando lo stile più recente, impostare il flag di BIF_USENEWUI nel ulFlags membro della struttura BROWSEINFO .

Se si implementa una funzione di callback, specificata nel lpfn membro della struttura BROWSEINFO , si riceve un handle per la 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 di stile precedente è relativamente semplice. La modifica della finestra di dialogo stile più recente è molto più difficile e non consigliata. Non solo ha dimensioni e layout diversi rispetto allo stile precedente, ma le dimensioni e le posizioni dei relativi controlli cambiano ogni volta che viene ridimensionato dall'utente.

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

filtro personalizzato

A partire da Windows XP, SHBrowseForFolder supporta filtri personalizzati sul contenuto della finestra di dialogo. Per creare un filtro personalizzato, seguire questa procedura.
  1. Impostare il flag 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. Codificare la funzione di callback per ricevere i messaggi BFFM_INITIALIZED e BFFM_IUNKNOWN. Alla ricezione del messaggio di BFFM_IUNKNOWN, il parametro lParam della funzione di 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, passando un puntatore al IFolderFilter. metodi di IFolderFilter possono quindi essere usati per includere ed escludere elementi dall'albero.
  6. Dopo aver creato il filtro, l'interfaccia IFolderFilterSite non è più necessaria. Chiamare IFolderFilterSite::Release se non è più necessario usarlo.

gestire i tasti di scelta rapida

Nota Questa sezione si applica solo ai sistemi Windows 2000 e versioni 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 BIF_NOTRANSLATETARGETS non sia impostato nella struttura BROWSEINFO.
 
Se SHBrowseForFolder restituisce un PIDL a un collegamento, inviando tale 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 del preprocessore UNICODE. La combinazione dell'utilizzo dell'alias indipendente dalla codifica con il codice non indipendente dalla codifica può causare mancate corrispondenze che generano errori di compilazione o di runtime. Per altre informazioni, vedere convenzioni di per i prototipi di funzioni.

Fabbisogno

Requisito Valore
client minimo supportato Windows XP [solo app desktop]
server minimo supportato Windows 2000 Server [solo app desktop]
piattaforma di destinazione Finestre
intestazione shlobj_core.h (includere Shlobj.h, Shlobj_core.h)
libreria Shell32.lib
dll Shell32.dll (versione 4.0 o successiva)

Vedere anche

finestre di dialogo Apri e Salva con nome