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 Stammverzeichnis des Namespace angibt. Wenn der Benutzer im Dialogfeld die Schaltfläche Abbrechen auswählt, ist der Rückgabewert NULL.

Es ist möglich, dass die zurückgegebene PIDL die einer Ordnerverknüpfung und nicht eines Ordners ist. Eine vollständige Erläuterung dieses Falls finden Sie im Abschnitt Hinweise.

Hinweise

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 OleInitialize verwenden, die immer Apartmentthreading verwenden. Wenn Sie Drag-and-Drop-Funktionen benötigen, wird OleInitialize empfohlen, da es sowohl den erforderlichen 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 Arten von Dialogfelder zur Verfügung. Die ältere Formatvorlage wird standardmäßig angezeigt und kann nicht geändert werden. Der neuere Stil bietet eine Reihe zusätzlicher Features, einschließlich Drag-and-Drop-Funktionen innerhalb des Dialogfelds, Neuanordnung, Löschen, Kontextmenüs, die Möglichkeit zum Erstellen neuer Ordner und andere Kontextmenübefehle. Anfangs ist es größer als das ältere Dialogfeld, aber der Benutzer kann seine Größe ändern. Um ein Dialogfeld mithilfe des neueren Stils anzugeben, legen Sie das flag BIF_USENEWUI im ulFlags-Element der BROWSEINFO-Struktur fest.

Wenn Sie eine Rückruffunktion implementieren, die im lpfn-Element der BROWSEINFO-Struktur angegeben ist, erhalten Sie ein Handle für das Dialogfeld. Eine Verwendung dieses Fensterhandles 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 die ältere Formatvorlage relativ einfach. Das Ändern des Neueren Stildialogfelds ist viel schwieriger und wird nicht empfohlen. Es hat nicht nur eine andere Größe und ein anderes Layout als der alte Stil, sondern auch seine Abmessungen und die Positionen seiner Steuerelemente ändern sich bei jeder Größenänderung durch den Benutzer.

Wenn das flag BIF_RETURNONLYFSDIRS im ulFlags-Element der BROWSEINFO-Struktur festgelegt ist, bleibt die Schaltfläche OK für "\server"-Elemente sowie "\server\share" und Verzeichniselemente aktiviert. Wenn der Benutzer jedoch ein Element "\server" auswählt, schlägt das Übergeben der von SHBrowseForFolder zurückgegebenen PIDL an SHGetPathFromIDList 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-Element der BROWSEINFO-Struktur fest, auf die der lpbi-Parameter verweist.
  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. Beim Empfang der BFFM_IUNKNOWN Meldung 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 instance von IFolderFilterSite abzurufen.
  4. Erstellen Sie ein -Objekt, das IFolderFilter implementiert.
  5. Rufen Sie IFolderFilterSite::SetFilter auf, und übergeben Sie einen Zeiger auf Ihren IFolderFilter. IFolderFilter-Methoden können dann verwendet werden, um Elemente aus der Struktur einzu- und auszuschließen.
  6. Nachdem der Filter erstellt wurde, wird die IFolderFilterSite-Schnittstelle nicht mehr benötigt. Rufen Sie IFolderFilterSite::Release auf, wenn Sie keine weitere Verwendung dafür haben.

Umgang mit Tastenkombinationen

Hinweis Dieser Abschnitt gilt nur für Windows 2000- und frühere Systeme. Standardmäßig geben Windows XP und höhere Systeme die PIDL des Ziels einer Verknüpfung anstelle der Verknüpfung selbst zurück, solange das flag BIF_NOTRANSLATETARGETS nicht in der BROWSEINFO-Struktur festgelegt ist.
 
Wenn SHBrowseForFolder eine PIDL an eine Verknüpfung zurückgibt, gibt das Senden dieser PIDL an SHGetPathFromIDList den Pfad der Verknüpfung selbst und nicht den Pfad des Ziels zurück. 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;
}

Hinweis

Der shlobj_core.h-Header 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
Unterstützte Mindestversion (Client) Windows XP [nur Desktop-Apps]
Unterstützte Mindestversion (Server) Windows 2000 Server [nur Desktop-Apps]
Zielplattform Windows
Kopfzeile shlobj_core.h (einschließlich Shlobj.h, Shlobj_core.h)
Bibliothek Shell32.lib
DLL Shell32.dll (Version 4.0 oder höher)

Weitere Informationen

Dialogfelder "Öffnen" und "Speichern unter"