다음을 통해 공유


SHBrowseForFolderW 함수(shlobj_core.h)

사용자가 Shell 폴더를 선택할 수 있는 대화 상자를 표시합니다.

구문

PIDLIST_ABSOLUTE SHBrowseForFolderW(
  [in] LPBROWSEINFOW lpbi
);

매개 변수

[in] lpbi

형식: LPBROWSEINFO

대화 상자를 표시하는 데 사용되는 정보를 포함하는 BROWSEINFO 구조체에 대한 포인터입니다.

반환 값

형식: PIDLIST_ABSOLUTE

네임스페이스의 루트를 기준으로 선택한 폴더의 위치를 지정하는 PIDL을 반환합니다. 사용자가 대화 상자에서 취소 단추를 선택하면 반환 값은 NULL입니다.

반환된 PIDL은 폴더가 아닌 바로 가기 폴더의 PIDL일 수 있습니다. 이 사례에 대한 자세한 내용은 설명 섹션을 참조하세요.

설명

Windows Vista 이상의 경우 SHBrowseForFolder 함수 대신 FOS_PICKFOLDERS 옵션과 함께 IFileDialog 를 사용하는 것이 좋습니다. 선택 폴더 모드에서 파일 열기 대화 상자를 사용하며 기본 설정 구현입니다.

SHBrowseForFolder를 호출하기 전에 COM(구성 요소 개체 모델)을 초기화해야 합니다. CoInitializeEx를 사용하여 COM을 초기화하는 경우 dwCoInit 매개 변수에서 COINIT_APARTMENTTHREADED 플래그를 설정해야 합니다. 항상 아파트 스레딩을 사용하는 CoInitialize 또는 OleInitialize를 사용할 수도 있습니다. 끌어서 놓기 기능이 필요한 경우 필요한 OLE와 COM을 초기화하므로 OleInitialize 를 사용하는 것이 좋습니다.

참고 COINIT_MULTITHREADED 플래그와 함께 CoInitializeEx를 사용하여 COM을 초기화하면 호출 애플리케이션이 BROWSEINFO 구조에서 BIF_USENEWUI 또는 BIF_NEWDIALOGSTYLE 플래그를 사용하는 경우 SHBrowseForFolder가 실패합니다.
 
더 이상 필요하지 않을 때 SHBrowseForFolder에서 반환된 IDList를 해제하기 위해 CoTaskMemFree를 호출하는 것은 호출 애플리케이션의 책임입니다.

사용할 수 있는 대화 상자의 두 가지 스타일이 있습니다. 이전 스타일은 기본적으로 표시되며 크기 조정이 불가능합니다. 최신 스타일은 대화 상자 내의 끌어서 놓기 기능, 순서 변경, 삭제, 바로 가기 메뉴, 새 폴더를 만드는 기능 및 기타 바로 가기 메뉴 명령을 비롯한 다양한 추가 기능을 제공합니다. 처음에는 이전 대화 상자보다 크지만 사용자는 크기를 조정할 수 있습니다. 최신 스타일을 사용하여 대화 상자를 지정하려면 BROWSEINFO 구조체의 ulFlags 멤버에서 BIF_USENEWUI 플래그를 설정합니다.

BROWSEINFO 구조체의 lpfn 멤버에 지정된 콜백 함수를 구현하는 경우 대화 상자에 대한 핸들을 받게 됩니다. 이 창 핸들의 한 가지 용도는 대화 상자의 레이아웃 또는 내용을 수정하는 것입니다. 크기 조정이 불가능하므로 이전 스타일 대화 상자를 수정하는 것은 비교적 간단합니다. 최신 스타일 대화 상자를 수정하는 것은 훨씬 더 어렵고 권장되지 않습니다. 이전 스타일과는 크기 및 레이아웃이 다를 뿐만 아니라 사용자가 크기를 조정할 때마다 해당 차원과 컨트롤의 위치가 변경됩니다.

BROWSEINFO 구조체의 ulFlags 멤버에 BIF_RETURNONLYFSDIRS 플래그가 설정된 경우 "\server" 항목과 "\server\share" 및 디렉터리 항목에 대해 확인 단추가 계속 활성화되어 있습니다. 그러나 사용자가 "\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의 instance 대한 포인터를 가져옵니다.
  4. IFolderFilter를 구현하는 개체를 만듭니다.
  5. IFolderFilterSite::SetFilter를 호출하여 IFolderFilter에 대한 포인터를 전달합니다. 그런 다음, IFolderFilter 메서드를 사용하여 트리에서 항목을 포함 및 제외할 수 있습니다.
  6. 필터가 만들어지면 IFolderFilterSite 인터페이스가 더 이상 필요하지 않습니다. 더 이상 사용하지 않는 경우 IFolderFilterSite::Release 를 호출합니다.

바로 가기 처리

참고 이 섹션은 Windows 2000 및 이전 시스템에만 적용됩니다. 기본적으로 WINDOWS XP 이상 시스템은 BROWSEINFO 구조에서 BIF_NOTRANSLATETARGETS 플래그가 설정되지 않는 한 바로 가기 자체가 아닌 바로 가기 대상의 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 또는 유니코드 버전을 자동으로 선택하는 별칭으로 SHBrowseForFolder를 정의합니다. 인코딩 중립 별칭을 인코딩 중립이 아닌 코드와 혼합하면 컴파일 또는 런타임 오류가 발생하는 불일치가 발생할 수 있습니다. 자세한 내용은 함수 프로토타입에 대한 규칙을 참조하세요.

요구 사항

요구 사항
지원되는 최소 클라이언트 Windows XP [데스크톱 앱만 해당]
지원되는 최소 서버 Windows 2000 Server[데스크톱 앱만]
대상 플랫폼 Windows
헤더 shlobj_core.h(Shlobj.h, Shlobj_core.h 포함)
라이브러리 Shell32.lib
DLL Shell32.dll(버전 4.0 이상)

추가 정보

대화 상자 열기 및 다른 이름으로 저장