Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Ayuda: Necesito refrescar la aplicación MIENTRAS se copian archivos muy grandes (https://www.clubdelphi.com/foros/showthread.php?t=55194)

Black_Ocean 10-04-2008 03:33:49

Ayuda: Necesito refrescar la aplicación MIENTRAS se copian archivos muy grandes
 
Hola estimados colegas de ClubDelphi,

Necesito que me echen una pequeña ayuda,

Pasa que las funciones CopyFile y SHFileOperation solo me refrescan el formulario después de haber terminado el copiado de un archivo, es decir:

Código Delphi [-]
  CopyFile(PChar('C:\Ejemplo_fuente.exe'), PChar('C:\Ejemplo_destino.exe'), False);
  Application.ProcessMessages;

Esta función es muy pobre y no sirve, puesto que MIENTRAS el copiado está en progreso, el formulario igual es inaccesible e innoperable (por ejemplo, con archivos muy grandes que toman más tiempo en copiarse).

En el caso con SHFileOperation, se refresca la UI de la API de Windows (el diálogo que se muestra cuando el flag es especificado), pero yo no quiero mostrar un diálogo de copiado de esa API, sino que un formulario que yo mismo hice para mostrar el progreso (esto es el progreso en bytes), pero, el problema es que MIENTRAS se está copiando un archivo grande (por ejemplo, de 300 MB). La aplicación queda congelada y el usuario no puede mover el formulario. Sólo cuando termina de copiar se refresca por la especificación de Application.ProcessMessages en la siguiente línea, pero cuando comienza a copiar otro archivo grande, nuevamente hay que esperar a que termine el copiado para que el formulario reaccione.

¿Cómo se puede solucionar este problema en forma eficiente, sin componentes, etc?

Saludos y de antemano gracias amigos como siempre.

egostar 10-04-2008 03:41:16

Hola amigo

Lo que pasa es que el ProcessMessage esta sin efecto ya que eso se usa para rutinas de loop, yo creo que se podria hacer algo como leer por bloques y copiarlos al otro archivo y en ese loop si tendría efecto el ProcessMessage.

Salud OS

Black_Ocean 10-04-2008 03:51:36

Cita:

Empezado por egostar (Mensaje 278837)
Hola amigo

Lo que pasa es que el ProcessMessage esta sin efecto ya que eso se usa para rutinas de loop, yo creo que se podria hacer algo como leer por bloques y copiarlos al otro archivo y en ese loop si tendría efecto el ProcessMessage.

Salud OS

Gracias por tu respuesta,

Si me pudieras explicar y enseñar un poco aquello que me dices te lo agradecería bastante.

De antemano, gracias.

egostar 10-04-2008 03:55:47

Bueno en la ayuda de delphi viene este ejemplo

Código Delphi [-]
var
  FromF, ToF: file;
  NumRead, NumWritten: Integer;
  Buf: array[1..2048] of Char;
begin
  if OpenDialog1.Execute then                               { Display Open dialog box }
  begin
    AssignFile(FromF, OpenDialog1.FileName);
    Reset(FromF, 1);  { Record size = 1 }
    if SaveDialog1.Execute then                              { Display Save dialog box}
    begin
      AssignFile(ToF, SaveDialog1.FileName);  { Open output file }

      Rewrite(ToF, 1);  { Record size = 1 }
      Canvas.TextOut(10, 10, 'Copying ' + IntToStr(FileSize(FromF))
        + ' bytes...');
      repeat
        BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
        BlockWrite(ToF, Buf, NumRead, NumWritten);
        Application.ProcessMessages; //Aquí lo pondría yo :)
      until (NumRead = 0) or (NumWritten <> NumRead);
        CloseFile(FromF);
        CloseFile(ToF);
    end;
  end;
end;

Lo que no se es como se comportaria en tiempo de copiado, es cosa de que lo pruebes.

Salud OS

jachguate 10-04-2008 07:06:10

La solución mas natural, me parece, es el uso de CopyFileEx, que permite introducir una función CallBack, que será llamada constantemente de vuelta por la rutina de copia a través de la que el proceso que llama (tu aplicación) es notificada del avance de la copia.

Entonces, podrías actualizar la interfaz de usuario para reportar el progreso de la copia.

Por otro lado, si lo que querés es que la aplicación siga utilizándose mientras la copia se realiza, podes lanzarla en otro hilo.

Hasta luego.

;)

Khronos 10-04-2008 15:52:59

Yo creo que se puede solucionar mucho mejor con un thread.

Código Delphi [-]
type
   TCopyThread = class (TThread)
       protected
        procedure execute; override;
   end;
 
var
Copiar: TCopyThread;
 
implementation
 
procedure TCopyThread.execute;
begin
Copiar.FreeOnTerminate:=true;
 
CopyFile(PChar('C:\Ejemplo_fuente.exe'), PChar('C:\Ejemplo_destino.exe'), False);
end;
Añades esto en tu formulario. Para ejecutarlo:

Código Delphi [-]
begin
Copiar:= TCopyThread.create(true);
Copiar.execute;
end;

Salu2 espero que te sirva.

cHackAll 10-04-2008 16:33:33

Código Delphi [-]
function Thread(hWnd: Cardinal): Cardinal; stdcall;
begin
 CopyFile('C:\Ejemplo_fuente.exe', 'C:\Ejemplo_destino.exe', False);
 SendMessage(hWnd, WM_USER, 0, 0);
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
 CreateThread(nil, 0, @Thread, Pointer(Handle), 0, PDWORD(0)^);
end;

Tu aplicación recivirá el mensaje WM_USER cuando la copia finalice (ejemplo).

Quien dá mas?? :p

Saludos

Black_Ocean 10-04-2008 21:07:51

Gracias a todos por su ayuda. Probaré los métodos que me han señalado.

Saludos y como siempre muy amables :)


La franja horaria es GMT +2. Ahora son las 23:44:30.

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