En aquellos casos en los que nuestro programa requiera bajo nivel de programación usando la API directamente, podemos implementar una función similar usando sólo la API, en concreto SHBrowseForFolder.
Coloco un código simple en C y delphi:
En C:
cpp
#include <shlobj.h> // Asegurarse que Directory tiene espacio igual o mayor de MAX_PATH BOOL SelectDirectory(HWND hWnd, const PCHAR Caption, PCHAR Directory) { BROWSEINFO BrowseInfo; LPITEMIDLIST ItemIDList; LPMALLOC ShellMalloc; ZeroMemory(&BrowseInfo, sizeof(BrowseInfo)); if(SHGetMalloc(&ShellMalloc) == S_OK && ShellMalloc){ BrowseInfo.hwndOwner = hWnd; BrowseInfo.pidlRoot = 0; BrowseInfo.pszDisplayName = Directory; BrowseInfo.lpszTitle = Caption; BrowseInfo.ulFlags = BIF_RETURNONLYFSDIRS; ItemIDList = SHBrowseForFolder(&BrowseInfo); if(ItemIDList){ SHGetPathFromIDList(ItemIDList, Directory); ShellMalloc->Free(ItemIDList); } } return ItemIDList!=0; }
Ejemplo en C:
cpp
char Carpeta[MAX_PATH]; SelectDirectory(Handle, "Seleccione la carpeta destino", Carpeta);
Y ahora en delphi:
delphi
uses ShlObj, ActiveX; function SelectDirectory(Wnd: HWND; const Caption: string; var Directory: String): boolean; var BrowseInfo: TBrowseInfo; ItemIDList: PItemIDList; ShellMalloc: IMalloc; Buffer: array [0..MAX_PATH] of CHAR; begin ZeroMemory(@BrowseInfo, sizeof(BrowseInfo)); if(SHGetMalloc(ShellMalloc) = S_OK) and (ShellMalloc <> nil) then begin BrowseInfo.hwndOwner:= Wnd; BrowseInfo.pidlRoot:= 0; BrowseInfo.pszDisplayName:= Buffer; BrowseInfo.lpszTitle:= PCHAR(Caption); BrowseInfo.ulFlags:= BIF_RETURNONLYFSDIRS; ItemIDList:= SHBrowseForFolder(BrowseInfo); if(ItemIDList <> nil) then begin SHGetPathFromIDList(ItemIDList, Buffer); ShellMalloc.Free(ItemIDList); Directory:= Buffer; end; end; Result:= ItemIDList <> nil; end;
Ejemplo en delphi:
delphi
var Carpeta: string; begin SelectDirectory(Handle, 'Seleccione Carpeta', Carpeta); Label1.Caption:= Carpeta; end;
Espero que os sea de utilidad.
Saludos.