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