Ir al contenido


Foto

Mover Archivos y carpetas sin colgar el Form


  • Por favor identifícate para responder
12 respuestas en este tema

#1 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 04 abril 2012 - 02:18

Buenas chicos, una consultita haber si alguien me puede ayudar, resulta que
estoy tratando de mover archivos de un lugar a otro y utilizo la siguiente función:



delphi
  1. Uses
  2.   windows, shellapi....;
  3.  
  4. var
  5.   fuente, destino: String;
  6.  
  7.  
  8. function MoveDir(const fromDir, toDir: string): Boolean;
  9. var
  10.   fos: TSHFileOpStruct;
  11.  
  12. begin
  13.   //application.ProcessMessages;  // para que no se cuelgue
  14.   ZeroMemory(@fos, SizeOf(fos));
  15.   with fos do
  16.  
  17.   begin
  18.  
  19.     wFunc  := FO_MOVE;
  20.     fFlags := FOF_FILESONLY or FOF_SILENT or FOF_NOCONFIRMATION;
  21.     pFrom  := PChar(fromDir + #0);
  22.     pTo    := PChar(toDir)
  23.   end;
  24.   Result := (0 = ShFileOperation(fos));
  25. end;




Y su llamada:



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.   destino:= 'D:\textos';
  4.   fuente:=  'D:\*.txt';
  5.  
  6.   movedir(fuente, destino);
  7. end;



Hasta aquí todo bien, el único inconveniente es que cuando realiza la operación de mover
pone el form como colgado y me gustaría que lo dejará activo, he tratado de subsanarlo con "application.ProcessMessages;"
pero no resulta ponga en donde lo ponga......

Porfavor una manito ... :)
  • 0

#2 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 04 abril 2012 - 02:28

Otra alternativa es crear un hilo de proceso aparte para esta acción.



Saludos!
  • 0

#3 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 05 abril 2012 - 01:23

Gracias por su respuesta.... pero no habrá otra manera..... como modificando esta función que les puse.....
  • 0

#4 German

German

    Member

  • Miembros
  • PipPip
  • 40 mensajes

Escrito 05 abril 2012 - 03:51

En la paleta System tienes el componente TAsyncProcess, que permite ejecutar procesos externos de forma asincronica. Quizas puedas usarlo para llamar a un aplicativo externo como el comando MOVE, que se encargue de mover los archivos, en vez de usar la API de WINDOWS. Esto si no quieres lidiar con THREADS y problemas de sincronizacion y exclusion mutua.
Para mi lo mejor seria usar THREADS.

Saludos.
  • 0

#5 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 09 abril 2012 - 11:45

Gracias por sus consejos .... pero viendo la función que les mostré como podrìa ser su implementación en un THREADS..... :undecided:  ????
  • 0

#6 fredycc

fredycc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 874 mensajes
  • LocationOaxaca, México

Escrito 09 abril 2012 - 11:59

Hola, puedes guiarte con unos ejemplos que viene incluidos un la carpeta de Lazarus:

C:\lazarus\examples\multithreading


O bien, esta wiki te puede apoyar: http://wiki.freepasc...cation_Tutorial

Saludos.
  • 0

#7 rretamar

rretamar

    Member

  • Miembros
  • PipPip
  • 23 mensajes

Escrito 11 abril 2012 - 05:30

La idea, como RAD multiplataforma que es, sería usar funciones navitas (y exclusivas) de la API del sistema operativo lo menos posible.
  • 0

#8 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 13 abril 2012 - 02:26

Si bien es cierto lo que apunta rretamar, y esa debería ser la filosofía trabajando con Lazarus, se puede estar de acuerdo con el planteamiento de monchito_elroro si su aplicación va a estar enfocada sólo a Windows.

Para aclarar un poquito el tema pongo una sencilla modificación del código de monchito_elroro usando un Thread para Windows usando la API:



delphi
  1. type
  2. PSHFileOpStruct = ^TSHFileOpStruct;
  3.  
  4.  
  5. procedure MoveDir(const fromDir, toDir: string);
  6. var
  7.   fos: TSHFileOpStruct;
  8.   ID : Cardinal;
  9. begin
  10.   ZeroMemory(@fos, SizeOf(TSHFileOpStruct));
  11.   with fos do
  12.   begin
  13.     wFunc  := FO_MOVE;
  14.     fFlags := FOF_FILESONLY or FOF_SILENT or FOF_NOCONFIRMATION;
  15.     pFrom  := PChar(fromDir + #0);
  16.     pTo    := PChar(toDir)
  17.   end;
  18.   CreateThread(nil, 0, @ShFileOperation, @fos, 0, ID);
  19. end;                                                       




Saludos.
  • 0

#9 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 14 abril 2012 - 07:46

Gracias amigo escafranda se agradece...... justo iba a publicar una alternativa que encontre, se las pongo de todas maneras:



delphi
  1. procedure TForm1.Button4Click(Sender: TObject);
  2. var
  3. Origen, Destino, aPath : String;
  4. sr: TSearchRec;
  5. begin
  6.  
  7.   aPath := 'd:\';
  8.  
  9.   if FindFirst(aPath + '*.txt', faAnyFile, sr) = 0 Then
  10.  
  11.     repeat
  12.     application.ProcessMessages;  // para que no se cuelgue
  13.  
  14.       Origen := aPath+sr.Name;
  15.       Destino := 'd:\textos\'+sr.Name;
  16.       MoveFile(PChar(Origen), PChar(Destino));
  17.       until FindNext(sr) <> 0;
  18.       SysUtils.FindClose(sr);
  19.  
  20.       begin
  21.         ShowMessage('Listo...!!!');
  22.       end;
  23.  
  24. End;




Este còdigo no se cuelga mucho, se las dejo y probarè la ayuda de escafranda...

de ahì les cuento...... :)
  • 0

#10 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 17 abril 2012 - 11:11

Para ahondar en el tema de los Threads a bajo nivel, he preparado un pequeño tutorial que resuelve la cuestión de este tema usando una función que crea un hilo cada vez que se llama. He preferido hacer este pequeño tutorial para permitirme explicar de forma detallada la filosofía aplicada que puede ser extendida a la solución de otros problemas.

Aquí dejo el enlace.


Saludos.
  • 0

#11 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 17 abril 2012 - 01:57

Buenas amigos, he probado el código que puso escafranda.... pero me sale un error conocido al
aplicarlo, este error dice:
"El proyecto project1.exe ha lanzado una excepción de la clase 'External: SIGSEGV'."


Guiandome del ejemplo lo pongo así




delphi
  1. Uses
  2. windows, shellapi, . . . . ;
  3.  
  4. type
  5.   PSHFileOpStruct = ^TSHFileOpStruct;
  6.  
  7.   { TForm1 }
  8.  
  9.   TForm1 = class(TForm)
  10.     Button1: TButton;
  11.     procedure Button1Click(Sender: TObject);
  12.     procedure FormCreate(Sender: TObject);
  13.   private
  14.     { private declarations }
  15.   public
  16.     { public declarations }
  17.   end;
  18.  
  19. var
  20.   Form1: TForm1;
  21.   origen, destino: String;
  22.  
  23. implementation
  24.  
  25. {$R *.lfm}
  26.  
  27. { TForm1 }
  28.  
  29. procedure MoveDir(const fromDir, toDir: string);
  30. var
  31.   fos: TSHFileOpStruct;
  32.   ID : Cardinal;
  33. begin
  34.   ZeroMemory(@fos, SizeOf(TSHFileOpStruct));
  35.   with fos do
  36.   begin
  37.     wFunc  := FO_MOVE;
  38.     fFlags := FOF_FILESONLY or FOF_SILENT or FOF_NOCONFIRMATION;
  39.     pFrom  := PChar(fromDir + #0);
  40.     pTo    := PChar(toDir)
  41.   end;
  42.   CreateThread(nil, 0, @ShFileOperation, @fos, 0, ID);
  43. end;
  44.  
  45. procedure TForm1.Button1Click(Sender: TObject);
  46. begin
  47.   origen:='D:\*.txt';
  48.   MoveDir(origen, destino);
  49. end;
  50.  
  51. procedure TForm1.FormCreate(Sender: TObject);
  52. begin
  53.   destino:='D:\textos';
  54. end;
  55.  
  56. end.



Que estaré haciendo mal.......
  • 0

#12 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 17 abril 2012 - 02:10

El ejemplo que puse es un boceto no operativo tal cual.

Si quieres que funcione mínimamente debes hacer global la variable  fos: TSHFileOpStruct;. Pero no debes ejecutar la función antes de que termine el Thread pues el nuevo Thread creado entrará en conflicto con el previo.

Si te fijas, en el mensaje anterior dejé un enlace a un tutorial donde expongo la solución con múltiples Threads a tu problema, precisamente basado en el boceto que puse y que no puedes hacer funcionar.

Te dejo el enlace (de nuevo).


Saludos.
  • 0

#13 monchito_elroro

monchito_elroro

    Advanced Member

  • Miembros
  • PipPipPip
  • 259 mensajes

Escrito 18 abril 2012 - 01:24

Entonces le darè un vistazo y de  ahí les cuento ...  :)
  • 0




IP.Board spam blocked by CleanTalk.