次の方法で共有


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することをお勧めします。

注意 COINIT_MULTITHREADED フラグを使用して com が CoInitializeEx を使用して初期化されている場合、呼び出し元のアプリケーションが BROWSEINFO 構造体で BIF_USENEWUI または BIF_NEWDIALOGSTYLE フラグを使用している場合、SHBrowseForFolder は失敗します。
 
呼び出し元アプリケーションは、CoTaskMemFree 呼び出して、不要になったときに SHBrowseForFolder 返される IDList を解放する必要があります。

ダイアログ ボックスには 2 つのスタイルがあります。 古いスタイルは既定で表示され、サイズ変更できません。 新しいスタイルには、ダイアログ ボックス内のドラッグ アンド ドロップ機能、並べ替え、削除、ショートカット メニュー、新しいフォルダーを作成する機能、その他のショートカット メニュー コマンドなど、さまざまな追加機能が用意されています。 最初は、古いダイアログ ボックスよりも大きくなりますが、ユーザーはサイズを変更できます。 新しいスタイルを使用してダイアログ ボックスを指定するには、BROWSEINFO 構造体の ulFlags メンバーに BIF_USENEWUI フラグを設定します。

BROWSEINFO 構造体の lpfn メンバーで指定されたコールバック関数を実装すると、ダイアログ ボックスへのハンドルが表示されます。 このウィンドウ ハンドルの 1 つの用途は、ダイアログ ボックスのレイアウトまたは内容を変更することです。 サイズ変更できないため、古いスタイルのダイアログ ボックスの変更は比較的簡単です。 新しいスタイル ダイアログ ボックスの変更ははるかに困難であり、推奨されません。 古いスタイルとはサイズとレイアウトが異なるだけでなく、ユーザーがサイズを変更するたびに、そのサイズとコントロールの位置が変わります。

BROWSEINFO 構造体の ulFlags メンバーでBIF_RETURNONLYFSDIRS フラグが設定されている場合、"\server" 項目、および "\server\share" およびディレクトリ項目に対して OK ボタンは有効なままになります。 ただし、ユーザーが "\server" 項目を選択した場合、SHBrowseForFolder 返された PIDL を SHGetPathFromIDList 渡すと失敗します。

カスタム フィルター処理の

Windows XP の時点で、SHBrowseForFolder では、ダイアログ ボックスの内容に対するカスタム フィルター処理がサポートされています。 カスタム フィルターを作成するには、次の手順に従います。
  1. lpbi パラメーターが指す BROWSEINFO 構造体の ulFlags メンバーに、BIF_NEWDIALOGSTYLE フラグを設定します。
  2. 同じ BROWSEINFO 構造体の lpfn メンバーにコールバック関数を指定します。
  3. BFFM_INITIALIZEDとBFFM_IUNKNOWNメッセージを受信するようにコールバック関数をコーディングします。 BFFM_IUNKNOWN メッセージを受信すると、コールバック関数の lParam パラメーターには、ダイアログ ボックスの IUnknownの実装へのポインター 含まれます。 IUnknown QueryInterface を呼び出して、IFolderFilterSiteのインスタンスへのポインター 取得します。
  4. IFolderFilter実装するオブジェクトを作成します。
  5. IFolderFilterSite::SetFilter呼び出し、IFolderFilterへのポインターを渡します。 IFolderFilter メソッドを使用して、ツリーに項目を含めるか、ツリーから除外することができます。
  6. フィルターが作成されると、IFolderFilterSite インターフェイスは不要になります。 IFolderFilterSite::Release 呼び出します (これ以上使用しない場合)。

ショートカットを扱う

このセクションは、Windows 2000 以前のシステムにのみ適用されます。 既定では、BIF_NOTRANSLATETARGETS フラグが BROWSEINFO 構造体に設定されていない限り、Windows XP 以降のシステムはショートカット自体ではなくショートカットのターゲットの PIDL を返します。
 
SHBrowseForFolder
がショートカットに PIDL を返す場合、その PIDL を SHGetPathFromIDList に送信、ターゲットのパスではなく、ショートカット自体のパスが返されます。 ショートカットのターゲットへのパスは、この例に示すように、IShellLink インターフェイスを使用して取得できます。
#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 以降)

関連項目

ダイアログ ボックスを開いて保存