Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Selección en TShellTreeView (https://www.clubdelphi.com/foros/showthread.php?t=86723)

radenf 23-09-2014 00:06:51

Selección en TShellTreeView
 
Hola amigos.

Utilizo un TShellTreeView de la paleta Samples, para acceder a las carpetas del disco duro.
Necesito que el evento onClick del ShellTreeView se ejecute únicamente si la carpeta seleccionada es la última de la ruta en el disco duro, es decir después del último backslash(\) y no al expandir los nodos o al hacer click sobre otra carpeta, que no sea la última.

Ejemplo

C:\Usuarios\Batman\Mis Imágenes\Cumpleaños de Robin <<< Sólo en esta Carpeta

Muchas gracias y saludos a todos

ecfisa 23-09-2014 08:31:43

Hola Iván.

No creo factible predeterminar el evento para que se dispare sólo ante determinada condición ajena a la pulsación del ratón. Sin embargo, sí es posible evaluar dentro del evento OnClick del TShellTreeView la condición que se te ocurra.

Dado que el componente TShellTreeView reconoce los archivos .ZIP y .CAB como carpetas no podemos usar las propiedades Folder y SubFolders de la carpeta seleccionada para hacer lo que buscas ya que al evaluar no mostraría como última a aquellas carpetas que contuvieran esos tipos de archivos.
Esto implica crear algo de código adicional, una pequeña función que nos diga si al menos existe una carpeta hija de la actual.

El código:
Código Delphi [-]
...
procedure TForm1.FormCreate(Sender: TObject);
begin
  with ShellTreeView1 do
    ObjectTypes := ObjectTypes + [otNonFolders];
end;

(* Devuelve True si la carpeta actual posee una subcarpeta *)
function HaveFolder(const Path: string): boolean;
var
  sr: TSearchRec;
begin
  Result:= False;
  if FindFirst(Path+'\*.*', faDirectory, sr) = 0 then
  begin
    repeat
      if (sr.Attr and faDirectory = faDirectory)and
         (sr.Name<>'.')and(sr.Name<>'..') then
        Result:= True;
    until (FindNext(sr) <> 0) or Result;
    FindClose(sr);
  end;
end;

(* Verifica si el click se hizo sobre la última carpeta *)
procedure TForm1.ShellTreeView1Click(Sender: TObject);
var
  pt: TPoint;
  ht: THitTests;
  pth: string;
  IsFolder: Boolean;
begin
  with TShellTreeView(Sender) do
  begin
    pt := ScreenToClient(Mouse.CursorPos); // coordenadas X~Y del click
    ht := GetHitTestInfoAt(pt.X, pt.Y);    // ¿ Donde fué ?
    if (htOnItem in ht) then               // ¿ Sobre un ítem ?
    begin
      pth:= SelectedFolder.PathName;       // Obtener ruta del ítem
      IsFolder:= FileGetAttr(pth) and faDirectory = faDirectory; //¿ Es carpeta ?
      if IsFolder and not HaveFolder(pth) then // ¿ Fué carpeta y no tiene subcarpetas ?
        ShowMessage('Última carpeta');  //Acciones a ejecutar cuando es última carpeta
    end;
  end;
end;

Saludos :)

radenf 23-09-2014 12:12:23

Muchas gracias por responder Daniel.

Probaré tu código y te comento.
Un abrazo

radenf 23-09-2014 23:41:18

Estimado Daniel:

El código realiza siempre la función de seleccionar la última carpeta. Le eliminé la opción de seleccionar los archivos, porque me interesa que sólo se puedan seleccionar carpetas. Sin embargo si por error o voluntariamente se selecciona por ejemplo mi PC, Panel de control u otra de las carpetas del sistema y después alguna carpeta de archivos, genera el siguiente error:


Debugger Exception Notification
---------------------------
Project ImageViewer.exe raised exception class EThread with message 'Cannot terminate an externally created thread'.


Imagino que Windows está ejecutando un Thread basado en el código, buscando la última carpeta del directorio seleccionado y no permite que se seleccione otra carpeta.
¿Es posible evitar este error?

Saludos

ecfisa 24-09-2014 02:40:52

Hola Iván.

He estado haciendo varias pruebas siguiendo las acciones que mencionas, también comentando el código del evento OnCreate, y no logro que se produzca ninguna excepción. Te adjunto el código de prueba para descartar cualquier posibilidad.

Tal vez sea debido a la versión de Delphi o Windows, en mi caso es Windows 7 32bits y Delphi 7, comentame si hace lo mismo con el código que te estoy adjuntando.

Saludos :)

radenf 24-09-2014 22:29:16

Estimado Daniel:

Gracias por responder.
El error era culpa mía porque tenía seleccionada la propiedad AutoRefresh:= True, al ponerla en False se corrigió el problema y funcionó perfecto.

Muchas gracias por todo
Saludos

ecfisa 24-09-2014 23:11:22

Hola Iván.

Me alegro ^\||/, pensé que el problema podría ser ocasionado por las diferentes versiones de Windows y en ese caso ya estaría pensando en cambiar de componente.

Saludos :)


La franja horaria es GMT +2. Ahora son las 07:23:28.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi