다음을 통해 공유


SHBrowseForFolderA 함수(shlobj_core.h)

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

통사론

PIDLIST_ABSOLUTE SHBrowseForFolderA(
  [in] LPBROWSEINFOA 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 사용하는 것이 좋습니다.

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

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

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

BIF_RETURNONLYFSDIRS 플래그가 BROWSEINFO 구조의 ulFlags 멤버에 설정된 경우 "\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구현에 대한 포인터가 포함됩니다. 해당 IUnknownQueryInterface 호출하여 IFolderFilterSite인스턴스에 대한 포인터를 가져옵니다.
  4. IFolderFilter구현하는 개체를 만듭니다.
  5. IFolderFilterSite::SetFilter호출하여 IFolderFilter대한 포인터를 전달합니다. IFolderFilter 메서드를 사용하여 트리에서 항목을 포함하고 제외할 수 있습니다.
  6. 필터가 만들어지면 IFolderFilterSite 인터페이스가 더 이상 필요하지 않습니다. 더 이상 사용하지 않는 경우 IFolderFilterSite::Release 호출합니다.

바로 가기를 다루는

참고 이 섹션은 Windows 2000 및 이전 시스템에만 적용됩니다. 기본적으로 windows XP 이상 시스템은 BIF_NOTRANSLATETARGETS 플래그가 BROWSEINFO 구조에서 설정되지 않는 한 바로 가기 자체가 아닌 바로 가기 대상의 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 이상)

참고 항목

대화 상자 열기 및 저장