[WinAPI] Cum selectez un folder?

Folosire Windows API in programe C/C++ (forum moderat)
Post Reply
User avatar
Marius Bancila
Fondator
Fondator
Posts: 2344
Joined: 11 Jul 2007, 11:45
Judet: Timiş
Location: Timisoara
Contact:

[WinAPI] Cum selectez un folder?

Post by Marius Bancila » 18 Jul 2007, 17:11

Intrebare: Cum pot selecta un folder? Ce trebuie sa apelez pentru a obtine acea fereastra care imi permite selectarea unui folder?

Raspuns: Trebuie folosita functia de Windows Shell SHBrowseForFolder. Codul de mai jos reprezinta un wrapper peste aceasta:

Code: Select all

int CALLBACK BrowseCallbackProc(HWND hWnd, 
         UINT uMsg, 
         LPARAM lParam, 
         LPARAM pData )
{
   LPCTSTR pszRootDir = (LPCTSTR)pData;
   switch(uMsg)
   {
   case BFFM_INITIALIZED:
      { 
         SendMessage(hWnd,BFFM_SETSELECTION,TRUE,(LPARAM)pszRootDir);
         break;
      }
   case BFFM_SELCHANGED:
      {
         LPTSTR pszSelDir = new TCHAR[_MAX_PATH];
         if( SHGetPathFromIDList((LPITEMIDLIST)lParam, pszSelDir)) 
         {
            SendMessage(hWnd,BFFM_SETSTATUSTEXT,0,(LPARAM)pszSelDir);
         }
         delete[] pszSelDir;
      }
   default:
      break;
   }
   return 0;
}

BOOL BrowseForFolder(HWND hWnd, LPCTSTR lpszTitle, LPTSTR& lpszDirectory)
{
	LPMALLOC lpMalloc;

	LPITEMIDLIST   pidl;
	HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidl);
	if(FAILED(hr))
		return FALSE;

	if (::SHGetMalloc(&lpMalloc) != NOERROR)
		return FALSE;

	TCHAR szDisplayName[MAX_PATH] = {0};

	// seteaza parametrii pentru apel
	BROWSEINFO info;
	if(::IsWindow(hWnd))
		info.hwndOwner   = hWnd;
	else
		info.hwndOwner   = NULL;
	info.pidlRoot      = pidl;
	info.pszDisplayName = szDisplayName;
	info.lpszTitle      = lpszTitle;
	info.ulFlags      = BIF_DONTGOBELOWDOMAIN|BIF_STATUSTEXT;
	info.lpfn         = BrowseCallbackProc;
	info.lParam         = (LPARAM)lpszDirectory;
	info.iImage         = 0;

	LPITEMIDLIST lpItemIDList;

	// selecteaza folder-ul
	if ((lpItemIDList = SHBrowseForFolder(&info)) != NULL)
	{
		// foloseste informatia returnata pentru a obtine calea absoluta a directorului
		if (SHGetPathFromIDList(lpItemIDList, lpszDirectory))
		{
			if (lpszDirectory[0] == _T('\0'))
			{
				AfxMessageBox(_T("Selectarea directorului a esuat!"),MB_ICONSTOP|MB_OK);
				return FALSE;
			}
		}
		else
		{
			AfxMessageBox(_T("Selectarea directorului a esuat!"),MB_ICONSTOP|MB_OK);
		}

		lpMalloc->Free(lpItemIDList);
		lpMalloc->Release();       
	}

	return TRUE;
}
Pentru a folosi functia de mai sus:

Code: Select all

// defineste un buffer pentru calea directorului
TCHAR path[MAX_PATH+1] = {0};
// apeleaza functia
BrowseForFolder(NULL, _T("Selecteaza director"), path);
Daca folositi MFC si CString aveti grija sa apelati functia GetBuffer():

Code: Select all

// declara un string
CString str;
// obtine un pointer la buffer-ul intern al obiectului CString
LPSTR buf = str.GetBuffer(MAX_PATH);
// apeleaza functia
BOOL bRet = BrowseForFolder(NULL, _T("Selecteaza director"), buf);
// elibereaza buffer-ul string-ului
str.ReleaseBuffer();


Marius Bancila
Fondator Codexpert, Microsoft MVP VC++
Site personal | Blog

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[WinAPI] Cum selectez un folder? (2)

Post by Ovidiu Cucu » 26 Aug 2009, 23:41

Intrebare: Ce trebuie sa fac pentru ca sa apara butonul "Make New Folder" in dialogul creat cu SHBrowseForFolder?
Make New Folder.gif
Make New Folder.gif (23.67 KiB) Viewed 3236 times
Raspuns: Se adauga flag-ul BIF_NEWDIALOGSTYLE in structura BROWSEINFO.

Exemplu:

Code: Select all

BOOL BrowseForFolder(HWND hWnd, LPCTSTR pszTitle, LPTSTR pszDir)
{
   _ASSERT((hWnd == NULL) || ::IsWindow(hWnd));
   BOOL bRet = FALSE;

   BROWSEINFO browseInfo = {0};
   browseInfo.hwndOwner = hWnd;
   browseInfo.lpszTitle = pszTitle;
   browseInfo.ulFlags   = BIF_NEWDIALOGSTYLE; // enable "Make New Folder" button

   LPITEMIDLIST lpItemIDList = ::SHBrowseForFolder(&browseInfo);
   if(NULL != lpItemIDList)
   {
      bRet = SHGetPathFromIDList(lpItemIDList, pszDir);
   }
   return bRet;
}
Note
  • BIF_NEWDIALOGSTYLE adauga si alte proprietati: redimensionare, drag and drop, context menu si shortcut-uri cu comenzile din explorer;
  • daca BIF_NEWDIALOGSTYLE este setat atunci BIF_STATUSTEXT este ignorat.

<< Back to Windows API Index

Post Reply