SHBrowseForFolderA 函式 (shlobj_core.h)
顯示可讓用戶選取 Shell 資料夾的對話框。
語法
PIDLIST_ABSOLUTE SHBrowseForFolderA(
[in] LPBROWSEINFOA lpbi
);
參數
[in] lpbi
類型: LPBROWSEINFO
BROWSEINFO 結構的指標,其中包含用來顯示對話框的資訊。
傳回值
類型: PIDLIST_ABSOLUTE
會傳回 PIDL,指定相對於命名空間根目錄的選取資料夾位置。 如果使用者在對話框中選擇 [ 取消] 按鈕,則傳回值為 NULL。
傳回的 PIDL 可能是資料夾快捷方式而非資料夾。 如需此案例的完整討論,請參閱一節。
備註
針對 Windows Vista 或更新版本,建議您搭配使用 IFileDialog 搭配 FOS_PICKFOLDERS 選項,而不是 SHBrowseForFolder 函式。 這會在挑選資料夾模式中使用 [開啟檔案] 對話框,而且是慣用的實作。
呼叫 SHBrowseForFolder之前,您必須先初始化元件物件模型 (COM) 。 如果您使用 CoInitializeEx 初始化 COM,則必須在其 dwCoInit 參數中設定COINIT_APARTMENTTHREADED旗標。 您也可以使用 CoInitialize 或 OleInitialize,一律使用 Apartment 線程。 如果您需要拖放功能,建議使用 OleInitialize ,因為它會初始化必要的 OLE 和 COM。
有兩種可用的對話框樣式。 默認會顯示較舊的樣式,而且無法重設大小。 較新的樣式提供一些額外的功能,包括對話框內的拖放功能、重新排序、刪除、快捷功能表、建立新資料夾的能力,以及其他快捷方式功能表命令。 一開始,它大於較舊的對話框,但使用者可以調整其大小。 若要使用較新的樣式指定對話框,請在 BROWSEINFO 結構的 ulFlags 成員中設定BIF_USENEWUI旗標。
如果您實作在 BROWSEINFO 結構的 lpfn 成員中指定的回呼函式,您會收到對話框的句柄。 此視窗句柄的其中一個用法是修改對話框的配置或內容。 因為無法重設大小,所以修改較舊的樣式對話框相當簡單。 修改較新的樣式對話框會比較困難,不建議這麼做。 它不僅具有與舊樣式不同的大小和版面配置,也會在每次使用者重設大小時變更其控件的維度和位置。
如果BIF_RETURNONLYFSDIRS旗標是在 BROWSEINFO 結構的 ulFlags 成員中設定,則 [確定] 按鈕仍會針對 “\server” 專案啟用,以及 “\server\share” 和目錄專案。 不過,如果用戶選取 「\server」 專案,將 SHBrowseForFolder 傳回的 PIDL 傳遞至 SHGetPathFromIDList 失敗。
自訂篩選
從 Windows XP 起, SHBrowseForFolder 支援對話框內容的自定義篩選。 若要建立自定義篩選,請遵循下列步驟。- 在 lpbi 參數所指向之 BROWSEINFO 結構的 ulFlags 成員中設定BIF_NEWDIALOGSTYLE旗標。
- 在相同 BROWSEINFO 結構的 lpfn 成員中指定回呼函式。
- 撰寫回呼函式的程式碼,以接收BFFM_INITIALIZED和BFFM_IUNKNOWN訊息。 在收到BFFM_IUNKNOWN訊息時,回呼函式的 lParam 參數包含對話框的 IUnknown 實作指標。 在該 IUnknown 上呼叫 QueryInterface,以取得 IFolderFilterSite 實例的指標。
- 建立實作 IFolderFilter 的物件。
- 呼叫 IFolderFilterSite::SetFilter,並傳遞至 IFolderFilter 的指標。 接著可以使用 IFolderFilter 方法來包含和排除樹狀結構中的專案。
- 建立篩選之後,就不再需要 IFolderFilterSite 介面。 如果您尚未進一步使用它,請呼叫 IFolderFilterSite::Release 。
處理快捷方式
#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;
}
注意
shlobj_core.h 標頭會根據 UNICODE 預處理器常數的定義,將 SHBrowseForFolder 定義為別名,自動選取此函式的 ANSI 或 Unicode 版本。 混合使用編碼中性別名與非編碼中性的程序代碼,可能會導致編譯或運行時間錯誤不符。 如需詳細資訊,請參閱 函式原型的慣例。
規格需求
需求 | 值 |
---|---|
最低支援的用戶端 | Windows XP [僅限傳統型應用程式] |
最低支援的伺服器 | Windows 2000 Server [僅限傳統型應用程式] |
目標平台 | Windows |
標頭 | shlobj_core.h (包含 Shlobj.h、Shlobj_core.h) |
程式庫 | Shell32.lib |
Dll | Shell32.dll (4.0 版或更新版本) |