Freigeben über


SHBrowseForFolderA-Funktion (shlobj_core.h)

Zeigt ein Dialogfeld an, in dem der Benutzer einen Shellordner auswählen kann.

Syntax

PIDLIST_ABSOLUTE SHBrowseForFolderA(
  [in] LPBROWSEINFOA lpbi
);

Parameter

[in] lpbi

Typ: LPBROWSEINFO

Ein Zeiger auf eine BROWSEINFO- Struktur, die Informationen enthält, die zum Anzeigen des Dialogfelds verwendet werden.

Rückgabewert

Typ: PIDLIST_ABSOLUTE

Gibt eine PIDL zurück, die den Speicherort des ausgewählten Ordners relativ zum Stamm des Namespaces angibt. Wenn der Benutzer die Schaltfläche Abbrechen im Dialogfeld auswäht, ist der Rückgabewert NULL-.

Es ist möglich, dass die zurückgegebene PIDL eine Ordnerverknüpfung anstelle eines Ordners ist. Eine vollständige Erläuterung dieses Falls finden Sie im Abschnitt "Anmerkungen".

Bemerkungen

Für Windows Vista oder höher wird empfohlen, IFileDialog mit der Option FOS_PICKFOLDERS anstelle der SHBrowseForFolder-Funktion zu verwenden. Dies verwendet das Dialogfeld "Dateien öffnen" im Ordnerauswahlmodus und ist die bevorzugte Implementierung.

Sie müssen das Component Object Model (COM) initialisieren, bevor Sie SHBrowseForFolder-aufrufen. Wenn Sie COM mit CoInitializeEx-initialisieren, müssen Sie das COINIT_APARTMENTTHREADED Flag im dwCoInit-Parameter festlegen. Sie können auch CoInitialize oder OleInitializeverwenden, die immer Apartmentthreading verwenden. Wenn Sie Drag-and-Drop-Funktionen benötigen, wird OleInitialize- empfohlen, da sie sowohl das erforderliche OLE als auch COM initialisiert.

Hinweis Wenn COM mit CoInitializeEx- mit dem COINIT_MULTITHREADED-Flag initialisiert wird, schlägt SHBrowseForFolder fehl, wenn die aufrufende Anwendung das BIF_USENEWUI- oder BIF_NEWDIALOGSTYLE-Flag in der BROWSEINFO- Struktur verwendet.
 
Es liegt in der Verantwortung der aufrufenden Anwendung, CoTaskMemFree aufzurufen, um die von SHBrowseForFolder zurückgegebene IDList freizugeben, wenn sie nicht mehr benötigt wird.

Es stehen zwei Formatvorlagen des Dialogfelds zur Verfügung. Die ältere Formatvorlage wird standardmäßig angezeigt und kann nicht geändert werden. Die neuere Formatvorlage bietet eine Reihe zusätzlicher Features, einschließlich der Drag-and-Drop-Funktion innerhalb des Dialogfelds, neu anordnen, löschen, Kontextmenüs, die Möglichkeit zum Erstellen neuer Ordner und andere Kontextmenübefehle. Anfangs ist sie größer als das ältere Dialogfeld, aber der Benutzer kann die Größe ändern. Um ein Dialogfeld mit der neueren Formatvorlage anzugeben, legen Sie das BIF_USENEWUI Flag im ulFlags Member der BROWSEINFO--Struktur fest.

Wenn Sie eine Rückruffunktion implementieren, die im lpfn Member der BROWSEINFO Struktur angegeben ist, erhalten Sie ein Handle für das Dialogfeld. Eine Verwendung dieses Fensterziehpunkts besteht darin, das Layout oder den Inhalt des Dialogfelds zu ändern. Da die Größe nicht geändert werden kann, ist das Ändern des Dialogfelds für ältere Formatvorlagen relativ einfach. Das Ändern des Dialogfelds für neuere Formatvorlagen ist viel schwieriger und wird nicht empfohlen. Es hat nicht nur eine andere Größe und ein anderes Layout als die alte Formatvorlage, sondern seine Abmessungen und die Positionen der Steuerelemente ändern sich jedes Mal, wenn die Größe des Benutzers geändert wird.

Wenn das BIF_RETURNONLYFSDIRS Flag im ulFlags Mitglied der BROWSEINFO Struktur festgelegt ist, bleibt die Schaltfläche OK für Elemente "\server" sowie "\server\share" und Verzeichniselemente aktiviert. Wenn der Benutzer jedoch ein "\server"-Element auswählt, schlägt die von SHBrowseForFolder zurückgegebene PIDL an SHGetPathFromID List fehl.

benutzerdefinierte Filterung

Ab Windows XP unterstützt SHBrowseForFolder- benutzerdefinierte Filterung für den Inhalt des Dialogfelds. Führen Sie die folgenden Schritte aus, um einen benutzerdefinierten Filter zu erstellen.
  1. Legen Sie das BIF_NEWDIALOGSTYLE Flag im ulFlags Member der BROWSEINFO- Struktur fest, auf die vom lpbi-Parameter verwiesen wird.
  2. Geben Sie eine Rückruffunktion im lpfn Member derselben BROWSEINFO- Struktur an.
  3. Codieren Sie die Rückruffunktion, um die BFFM_INITIALIZED und BFFM_IUNKNOWN Nachrichten zu empfangen. Nach Erhalt der BFFM_IUNKNOWN Nachricht enthält der lParam--Parameter der Rückruffunktion einen Zeiger auf die Implementierung von IUnknown-im Dialogfeld. Rufen Sie QueryInterface- für diese IUnknown- auf, um einen Zeiger auf eine Instanz von IFolderFilterSiteabzurufen.
  4. Erstellen Sie ein Objekt, das IFolderFilter-implementiert.
  5. Rufen Sie IFolderFilterSite::SetFilterauf, und übergeben Sie an den IFolderFilter-. IFolderFilter- Methoden können dann verwendet werden, um Elemente aus der Struktur einzuschließen und auszuschließen.
  6. Nachdem der Filter erstellt wurde, ist die IFolderFilterSite- Schnittstelle nicht mehr erforderlich. Rufen Sie IFolderFilterSite::Release auf, wenn Sie keine weitere Verwendung dafür haben.

Umgang mit Verknüpfungen

Hinweis Dieser Abschnitt gilt nur für Windows 2000- und frühere Systeme. Standardmäßig geben Windows XP und spätere Systeme die PIDL eines Verknüpfungsziels anstelle der Verknüpfung selbst zurück, solange das BIF_NOTRANSLATETARGETS Flag nicht in der BROWSEINFO- Struktur festgelegt ist.
 
Wenn SHBrowseForFolder- eine PIDL an eine Verknüpfung zurückgibt, wird diese PIDL an SHGetPathFromIDList gesendet, den Pfad der Verknüpfung selbst und nicht den Pfad des Ziels zurückgibt. Der Pfad zum Ziel der Verknüpfung kann mithilfe der IShellLink Schnittstelle abgerufen werden, wie in diesem Beispiel gezeigt.
#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;
}

Anmerkung

Der header shlobj_core.h definiert SHBrowseForFolder als Alias, der die ANSI- oder Unicode-Version dieser Funktion basierend auf der Definition der UNICODE-Präprozessorkonstante automatisch auswählt. Das Mischen der Verwendung des codierungsneutralen Alias mit Code, der nicht codierungsneutral ist, kann zu Nichtübereinstimmungen führen, die zu Kompilierungs- oder Laufzeitfehlern führen. Weitere Informationen finden Sie unter Konventionen für Funktionsprototypen.

Anforderungen

Anforderung Wert
mindestens unterstützte Client- Windows XP [nur Desktop-Apps]
mindestens unterstützte Server- Windows 2000 Server [nur Desktop-Apps]
Zielplattform- Fenster
Header- shlobj_core.h (einschließlich Shlobj.h, Shlobj_core.h)
Library Shell32.lib
DLL- Shell32.dll (Version 4.0 oder höher)

Siehe auch

Dialogfelder öffnen und speichern unter