[MFC] 디렉토리 선택 가능한 대화상자(SHBrowseForFolder)


디렉토리만 선택해야하는 경우 아래와 같은 박스가 필요함. 아래 코드에서 약간은 수정하여 사용할 수 있습니다.
플래그 설정으로 디렉토리, 파일 선택을 할 수 있습니다. (파일도 가능함)


[Source Code]
        :
static int CALLBACK BrowseCallbakProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM pData)

{

switch(uMsg)

{

case BFFM_VALIDATEFAILED:

CString strText;

strText.Format("%s", reinterpret_cast<LPTSTR>(lParam));

AfxMessageBox(strText);

break;

}

return 0;

}

 

void CNet_ProgDlg::OnButton6() // 여기는 클레스, 함수 이름이 바꾸어야 합니다.

{

    // TODO: Add your control notification handler code here

   
    ITEMIDLIST *pildBrowse;

char pszPathname[MAX_PATH];

      

LPITEMIDLIST pidl = NULL;

BROWSEINFO bInfo;

ZeroMemory( &bInfo, sizeof(BROWSEINFO) );

      

SHPathToPidl( CSIDL_DESKTOP, &pidl ); // 루트 디렉토리 설정 부분.

bInfo.hwndOwner = GetSafeHwnd();

bInfo.pidlRoot = pidl;

bInfo.pszDisplayName = pszPathname;

bInfo.lpszTitle = "Please Select Directory....";

bInfo.lpfn = BrowseCallbakProc;              
    // 콜백함수가 필요없다면 NULL이나 지움. 위의 static int 함수 필요 없어짐

bInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_EDITBOX | BIF_VALIDATE ;
    // 디렉토리만 설정가능하도록 하였습니다... 플래그 설정은 맨 아래 참조하세요, 또는 MSDN

 

pildBrowse = ::SHBrowseForFolder(&bInfo);

      

if( pildBrowse != NULL )

{

SHGetPathFromIDList(pildBrowse, pszPathname);

        m_strDownFolder = (LPCTSTR)pszPathname; // 선택한 폴더 또는 파일… 이 부분을 목적에 맞게 수정.

        UpdateData(FALSE);                              

}

 

}

 

HRESULT CNet_ProgDlg::SHPathToPidl( LPCTSTR szPath, LPITEMIDLIST* ppidl )  // 여기는 클레스 이름 바꾸어야 함.

{

LPSHELLFOLDER pShellFolder = NULL;

OLECHAR wszPath[MAX_PATH] = {0};

ULONG nCharsParsed = 0;

      

HRESULT hr = SHGetDesktopFolder( &pShellFolder );

      

if( FAILED(hr) ) return FALSE;

      

MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, szPath, -1, wszPath, MAX_PATH );

hr = pShellFolder->ParseDisplayName( NULL, NULL, wszPath, &nCharsParsed, ppidl, NULL );

pShellFolder->Release();

      

return hr;

}

        : 

 

 

/*

// Browsing for directory.

#define BIF_RETURNONLYFSDIRS 0x0001 // For finding a folder to start document searching

#define BIF_DONTGOBELOWDOMAIN 0x0002 // For starting the Find Computer

#define BIF_STATUSTEXT 0x0004

#define BIF_RETURNFSANCESTORS 0x0008

#define BIF_EDITBOX 0x0010

#define BIF_VALIDATE 0x0020 // insist on valid result (or CANCEL)

 

#define BIF_BROWSEFORCOMPUTER 0x1000 // Browsing for Computers.

#define BIF_BROWSEFORPRINTER 0x2000 // Browsing for Printers

#define BIF_BROWSEINCLUDEFILES 0x4000 // Browsing for Everything

*/

-bInfo.ulFlags 플래그

 

BIF_BROWSEFORCOMPUTER : 네트워크의 컴퓨터만 선택가능

BIF_BROWSEFORPRINTER : 프린터만 선택가능

BIF_BROWSEINCLUDEFILES : 파일도 표시

BIF_DONTGOBELOWDOMAIN : 네트워크의 컴퓨터를 표시하지 않는다

BIF_EDITBOX : 에디트 박스를 표시한다

BIF_RETURNFSANCESTORS : 네트워크의 컴퓨터만 선택가능

BIF_RETURNONLYFSDIRS : 폴더만 선택가능

BIF_STATUSTEXT : 스테이터스 텍스트를 표시한다

BIF_VALIDATE : 부정 입력시에, BFFM_VALIDATEFAILED 이벤트

 

 

//Must be static funtion.
static int CALLBACK BrowseForFolder_CallbackProc(HWND m_hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
 if(uMsg == BFFM_INITIALIZED)
  SendMessage(m_hWnd, BFFM_SETSELECTION, (WPARAM)TRUE, (LPARAM)lpData);

 return 0;
}

위 함수는 꼭 static 함수여야 한다. 그리고 아래에서 함수포인터를 넣어준다.
아래 코드는 폴더 선택 다이얼로그를 띄워야 하는 곳에 넣어주면 되겠지.

 BROWSEINFO bi;
 ZeroMemory(&bi, sizeof(BROWSEINFO));
 bi.hwndOwner =  this->GetSafeHwnd();
 bi.pidlRoot = NULL;
 bi.pszDisplayName = NULL;
 bi.lpszTitle = NULL;
 bi.ulFlags = BIF_RETURNONLYFSDIRS;
 bi.lpfn = BrowseForFolder_CallbackProc;
 bi.lParam = (LPARAM)(LPCTSTR)m_strContentsDownloadFolder; //초기값 설정.

 LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
 TCHAR szPath[MAX_PATH] = {0,};  

 if( pidl )
 {
  SHGetPathFromIDList( pidl, szPath );
  m_strContentsDownloadFolder = szPath;
  GetDlgItem( IDC_DOWNLOAD_ADDRESS )->SetWindowText( m_strContentsDownloadFolder );
 }

위와 같이 하면 폴더를 선택할 수 있는 다이얼로그가 뜬다.

 

 

보통 많은 프로그램들을 보면 버튼 눌렀을때 폴더 선택할수 있게 다이얼로그를 띄워준다.

이것을 어케 하는지 알아본다.

간단하다.

 

   ITEMIDLIST *pidlBrowse;
   char pszPathname[1000];
   BROWSEINFO BrInfo;
   BrInfo.hwndOwner = GetSafeHwnd();
   BrInfo.pidlRoot = NULL;

  
   memset(&BrInfo, 0, sizeof(BrInfo));
   BrInfo.pszDisplayName = pszPathname;
   BrInfo.lpszTitle = "경로 선택";
   BrInfo.ulFlags = BIF_RETURNONLYFSDIRS;

   pidlBrowse = ::SHBrowseForFolder(&BrInfo);

   if( pidlBrowse != NULL)
   {
       ::SHGetPathFromIDList(pidlBrowse, pszPathname);
       m_strFileDownDir = pszPathname;  // 폴더 경로
   }

 

반환되는 폴더 경로는 pszPathname 에 저장된다.

 

+ Recent posts