Seleccionar una carpeta
agosto 28, 2007 en Artículos, Entrada Diario, Velneo
En una de las entradas anteriores, justamente en los comentarios de “Primeros pasos tras el curso…”, AROJAS comentaba:
Buenos Días, dime tendrias alguna DLL hecha que sirva para llamar el cuadro de diálogo Buscar y Seleccionar Carpeta de Windows, como para que funcione en VELNEO, desde ya gracias
Veamos a ver que podemos hacer… ummmm
En este caso concreto, no tiene mucho sentido desde la perspectiva de Delphi tener esta función dentro de una librería. Sin embargo, desde la perspectiva de Velneo la cosa cambia y posiblemente sí que nos interese incluirla, ya que al necesitar inicializar estructuras para invocar la función, puesto que recibe como parámetro un puntero a la estructura TBrowseInfo, no lo vamos a poder hacer desde Velneo. Solución: Abrimos nuestro editor de Delphi (otros compañeros sustituiran este entorno por otro cualquiera que nos permita generar la libreria) y no queda más que escribir unas lineas de código.
Vamos a necesitar la función del API de Windows, SHBrowseForFolder que se encuentra ya declarada en el modulo ShlObj.pas de Delphi, lo que nos ahorra tiempo y problemas. De no ser así, deberiamos declararla y traducir los tipos originales de C que necesita la función a los de nuestro entorno.
Básicamente, lo que hacemos es inicializar la estructura TBrowseInfo con los valores adecuados y una vez hecho esto, entregamos un puntero al registro como parámetro de entrada de la función ShBrowseForFolder. La respuesta de la función es similar a otras funciones de la Shell del mismo ámbito. Nos devuelve un puntero a una estructura (PItemIdList). Finalmente, liberamos mediante la interfaz IMalloc la asignación de memoria que hizo el sistema en su respuesta, según reza la documentación técnica.
Descargar el codigo fuente y el mapa para testear la función
Lo que ya dejo un poco a gusto de vosotros es modificar los parámetros de entrada de la función MostrarCuadroCarpetas para que muestre determinadas opciones, o por el contrario no las muestre. Podriamos querer que se visualizase un botón para permitirnos crear una nueva carpeta, mostrar solo los directorios del sistema, mostrar solo los equipos o solo las impresoras. Existen bastantes posibilidades y parece razonable que no nos sean necesarias siempre por lo que he preferido no complicar innecesariamente este pequeño ejemplo. En todo caso, una gran parte de ellas van a depender del valor que tome el campo ulFlags y convendría conocer los distintos valores de las constantes que pueden ser usadas.
BIF_RETURNONLYFSDIRS = $0001;
BIF_DONTGOBELOWDOMAIN = $0002;
BIF_STATUSTEXT = $0004;
BIF_RETURNFSANCESTORS = $0008;
BIF_EDITBOX = $0010;
BIF_VALIDATE = $0020;
BIF_NEWDIALOGSTYLE = $0040;
BIF_USENEWUI = BIF_NEWDIALOGSTYLE or BIF_EDITBOX;
BIF_BROWSEINCLUDEURLS = $0080;
BIF_UAHINT = $100;
BIF_NONEWFOLDERBUTTON = $200;
BIF_NOTRANSLATETARGETS = $400;
BIF_BROWSEFORCOMPUTER = $1000;
BIF_BROWSEFORPRINTER = $2000;
BIF_BROWSEINCLUDEFILES = $4000;
BIF_SHAREABLE = $8000;
Si quisieramos por ejemplo que además de las carpetas nos mostrara los archivos para poder seleccionar cualquiera de ellos, bastaría hacer la asignación:
ulFlags:= BIF_STATUSTEXT or BIF_BROWSEINCLUDEFILES;
Así de fácil.
function MostrarCuadroCarpetas(ACaption: PChar; ACallBack: Boolean): PChar; stdcall;
var
fres: Array[0..MAX_PATH] of Char;
fName: Array[0..MAX_PATH] of Char;
IDList: PItemIDList;
BrowseInfo: TBrowseInfo;
Malloc: IMalloc;
begin
//rellenamos la estructura con los datos deseados
with BrowseInfo do begin
hwndOwner:= 0; //en nuestro caso no existe handle y
//se mostrara de forma no modal
pidlRoot:= nil; //no existe origen predefinido
pszDisplayName:= fName; //Nombre de la carpeta
lpszTitle:= ACaption; //Titulo de la ventana
//se podria parametrizar desde Velneo para mostrar opciones distintas
//en este caso solo hemos seleccionado la posibilidad de mostrar el
//texto a traves del mensaje en la función callback
{
Ver la unidad ShlObj para obtener una lista de todas las constantes
disponibles.
}
ulFlags:= BIF_STATUSTEXT;
//si no queremos ejecutar el callback para modificar la ventana de exploracion
if ACallBack then
lpfn:= @BrowseCallBackProc
else lpfn:= nil;
lParam:= 0;
end;
//Invocamos la funcion del API SHBrowseForFolder pasando como parámetro la
//estructura que hemos inicializado
IDList:= SHBrowseForFolder(BrowseInfo);
//Obtenemos la ruta
ShGetPathFromIDList(IDList, @fres);
//segun la documentación de windows sería necesario liberar la memoria
//que windows reserva para la estructura IDList. Nosotros seguimos la
//mecanica aconsejada y hacemos uso de la interfaz IMalloc para ello.
//El metodo Free libera la memoria asignada
//Previamente comprobamos que podemos obtener un handle a la interfaz
//para hacer uso de las funciones.
if Succeeded(SHGetMalloc(Malloc)) then begin
Malloc.Free(IDList);
end;
Result:= fres;
end;
{$R *.res}
exports
BrowseCallBackProc,
MostrarCuadroCarpetas;
begin
end.






http://www.danysoft.com/
http://www.embarcadero.com
Delphi Access
Muy buen ejemplo!!!
Y muchas gracias.
Saludos,
Fran Varona