SHBrowseForFolderW 関数 (shlobj_core.h)
ユーザーがシェル フォルダーを選択できるようにするダイアログ ボックスを表示します。
構文
PIDLIST_ABSOLUTE SHBrowseForFolderW(
[in] LPBROWSEINFOW lpbi
);
パラメーター
[in] lpbi
型: LPBROWSEINFO
ダイアログ ボックスの表示に使用される情報を含む BROWSEINFO 構造体へのポインター。
戻り値
種類: PIDLIST_ABSOLUTE
名前空間のルートを基準にして、選択したフォルダーの場所を指定する PIDL を返します。 ユーザーがダイアログ ボックスで [キャンセル ] ボタンを選択した場合、戻り値は NULL になります。
PIDL が返されるのは、フォルダーではなくフォルダー ショートカットの場合です。 このケースの詳細については、「解説」セクションを参照してください。
注釈
Windows Vista 以降では、SHBrowseForFolder 関数ではなく、FOS_PICKFOLDERS オプションで IFileDialog を使用することをお勧めします。 これは、選択フォルダー モードで [ファイルを開く] ダイアログを使用し、推奨される実装です。
SHBrowseForFolder を呼び出す前に、コンポーネント オブジェクト モデル (COM) を初期化する必要があります。 CoInitializeEx を使用して COM を初期化する場合は、dwCoInit パラメーターに COINIT_APARTMENTTHREADED フラグを設定する必要があります。 また、常にアパートメント スレッド処理を使用する CoInitialize または OleInitialize を使用することもできます。 ドラッグ アンド ドロップ機能が必要な場合は、必要な OLE と COM を初期化するため、 OleInitialize をお勧めします。
ダイアログ ボックスには 2 つのスタイルがあります。 古いスタイルは既定で表示され、サイズ変更できません。 新しいスタイルには、ダイアログ ボックス内のドラッグ アンド ドロップ機能、並べ替え、削除、ショートカット メニュー、新しいフォルダーの作成機能、その他のショートカット メニュー コマンドなど、多くの追加機能が用意されています。 最初は、古いダイアログ ボックスよりも大きくなりますが、ユーザーはサイズを変更できます。 新しいスタイルを使用してダイアログ ボックスを指定するには、BROWSEINFO 構造体の ulFlags メンバーでBIF_USENEWUI フラグを設定します。
BROWSEINFO 構造体の lpfn メンバーで指定されたコールバック関数を実装すると、ダイアログ ボックスへのハンドルが表示されます。 このウィンドウ ハンドルの 1 つの用途は、ダイアログ ボックスのレイアウトまたは内容を変更することです。 サイズ変更できないため、古いスタイルのダイアログ ボックスの変更は比較的簡単です。 新しいスタイル ダイアログ ボックスの変更ははるかに困難であり、推奨されません。 古いスタイルとはサイズやレイアウトが異なるだけでなく、ユーザーがサイズを変更するたびに、そのサイズとコントロールの位置が変わります。
BROWSEINFO 構造体の ulFlags メンバーでBIF_RETURNONLYFSDIRS フラグが設定されている場合、"\server" 項目と "\server\share" およびディレクトリ項目に対して [OK] ボタンは有効なままになります。 ただし、ユーザーが "\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 プリプロセッサ定数の定義に基づいて、この関数の ANSI または Unicode バージョンを自動的に選択するエイリアスとして SHBrowseForFolder を定義します。 encoding-neutral エイリアスの使用を encoding-neutral ではないコードと混在すると、コンパイル エラーまたはランタイム エラーが発生する不一致が発生する可能性があります。 詳細については、「 関数プロトタイプの規則」を参照してください。
要件
要件 | 値 |
---|---|
サポートされている最小のクライアント | Windows XP (デスクトップ アプリのみ) |
サポートされている最小のサーバー | Windows 2000 Server [デスクトップ アプリのみ] |
対象プラットフォーム | Windows |
ヘッダー | shlobj_core.h (Shlobj.h、Shlobj_core.h を含む) |
Library | Shell32.lib |
[DLL] | Shell32.dll (バージョン 4.0 以降) |