Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 06-08-2003
dmariscal dmariscal is offline
Miembro
 
Registrado: may 2003
Ubicación: jalisco
Posts: 12
Poder: 0
dmariscal Va por buen camino
detener un bucle con un boton cancelar...

hola amigos, al momento de oprimir un boton se inicia un bucle, y quiero tener un boton (cancelar) que me cancele o detenga el bucle, mi problema es que al momento de hacer el bucle el deplhi esta en ese proceso (obvio) y no me pela nada, no me permite apretar ningun boton, sabes como hacer para que me deje apretar el boton de cancelar aun cuando esta realizando un bucle??

gracias por la atencion !!
Responder Con Cita
  #2  
Antiguo 06-08-2003
nachoasensio nachoasensio is offline
Miembro
 
Registrado: may 2003
Ubicación: Málaga
Posts: 61
Poder: 21
nachoasensio Va por buen camino
Hola:

Para que el bucle se pare y atienda los mensajes de windows, puedes hacer en su interior:

Application.ProcessMessages;

Ahora bien, si tu bucle se repite muchas veces y el proceso que se realiza en su interior es muy rápido, esta llamada te lo va a enlentecer mucho. En ese caso es mejor que hagas algo como:

Cont := 0;
Pulsada:= False;

while not (Pulsada) do
begin

// Aquí iría tu proceso
.
.
.

// Sólo se llama a ProcessMessages una vez de cada 100
// iteraciones
if (cont mod 100) = 0 then
begin
Application.ProcessMessages;
end;

INC(cont);
end;





El código del botón Cancelar sería, simplemente,

Pulsada := True;


donde "Pulsada" sería una variable global.

Un saludo.
Responder Con Cita
  #3  
Antiguo 06-08-2003
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 27
jachguate Va por buen camino
Cool

Solo quiero agregar que cuando llamas a application.processMessages dentro de un bucle, debes tener cuidado con un par de cosas, principalmente deshabilitando controles, pues tu aplicación seguirá respondiendo a todos los mensajes que reciba.
  • Si tenes un usuario "travieso", que presiona diez veces el botón "Procesar", vas a tener en la pila diez procesos corriendo, uno detras de otro, y esto podria provocar problemas serios. Digamos, si es un proceso que aumenta los precios en un 10%, al final vas a tener los precios aumentados en un 159.37%!!!. Además, podrias tener problemas de concurrencia.
  • Si hay controles para parametrizar alguna acción del proceso (como checkboxes, etc) el usuario podria cambar su valor a mitad del proceso, por ejemplo.
  • Otro problema es que el usuario podria cerrar la ventana a medio proceso.

Por lo tanto lo recomendable es deshabilitar todos los controles antes de iniciar el proceso (excepto el botón cancelar) y controlar si se permitirá cerrar la ventana al usuario.

En código, podria ser algo como:

Código:
Type
  TForm1 = Class(TForm)
  ..
  Private
     FEnProceso : Boolean;
     FCancelado : Boolean;
  ..
  
Implementation

Procedure TForm1.bProcesarClick(Sender : TObject);

Var
  i : Longint;

Begin
  FEnProceso := True;
  FCancelado := False;
  try
    InicializarProceso;
    DeshabilitarControles;
    For i := 1 to 2147483647 do
    Begin
       RealizarIteracionDelProceso;
       Application.ProcessMessages;
       if FCancelado Then
           Break; // paramos el proceso
    End;
    if Not FCancelado Then
       ProcesoTerminadoConExito;
    else
       RealizarAccionesParaCancelar;
  finally
    FEnProceso := False;
    HabilitarControles;
  end;
End;

Procedure TForm1.CloseQuery(sender : TObject; var CanClose : Boolean);

Begin
  // evitamos que el usuario cierre la forma mientras se está ejecutando el proceso
  CanClose := not FEnProceso;
End;

Procedure TForm1.bCancelarClick(Sender : TObject);

Begin
  FCancelado := ConfirmaQueQuieraCancelarElProceso;
End;
Espero que la idea te sea de ayuda.

Hasta luego.

__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #4  
Antiguo 06-08-2003
dmariscal dmariscal is offline
Miembro
 
Registrado: may 2003
Ubicación: jalisco
Posts: 12
Poder: 0
dmariscal Va por buen camino
muchas gracias por las respuestas!!
voy a probarlos!
Responder Con Cita
  #5  
Antiguo 13-07-2004
Patxi Patxi is offline
Miembro
 
Registrado: nov 2003
Posts: 12
Poder: 0
Patxi Va por buen camino
Hola,
oye jachguate, con respecto al ejemplo que has enviado, en

Procedure TForm1.CloseQuery(sender : TObject; var CanClose : Boolean);

Begin
// evitamos que el usuario cierre la forma mientras se está ejecutando el proceso
CanClose := not FEnProceso;
End;


si al pulsar el botón de Salir, FEnProceso no es True, no pasa nada, pero si quiséramos esperar a que FEnProceso sea True y cerrar la aplicación sin tener que pulsar de nuevo, cómo se haría?
Gracias.
Responder Con Cita
  #6  
Antiguo 13-07-2004
Avatar de jachguate
jachguate jachguate is offline
Miembro
 
Registrado: may 2003
Ubicación: Guatemala
Posts: 6.254
Poder: 27
jachguate Va por buen camino
Vamos.. un poco de ingenio al asunto... plantea una solución que se te ocurra y si no te funciona yo te echo un cable. Pero hacertelo todo, me resisto. Te has avocado a la persona equivocada
__________________
Juan Antonio Castillo Hernández (jachguate)
Guía de Estilo | Etiqueta CODE | Búsca antes de preguntar | blog de jachguate
Responder Con Cita
  #7  
Antiguo 13-07-2004
Patxi Patxi is offline
Miembro
 
Registrado: nov 2003
Posts: 12
Poder: 0
Patxi Va por buen camino
Perdona, pero no se trata exactamente de eso, simplemente he utilizado tu respuesta para simplificar. El problema es, siguiendo utilizando parte de tu ejemplo:

Type
TForm1 = Class(TForm)
..
Private
FEnProceso : Boolean;
FCancelado : Boolean;
..

Implementation

Procedure TForm1.bProcesarClick(Sender : TObject);

Var
i : Longint;

Begin
FEnProceso := True;
FCancelado := False;
try
InicializarProceso;
DeshabilitarControles;
For i := 1 to 2147483647 do
Begin
RealizarIteracionDelProceso;
Application.ProcessMessages;
if FCancelado Then
Break; // paramos el proceso
End;
if Not FCancelado Then
ProcesoTerminadoConExito;
else
RealizarAccionesParaCancelar;
finally
FEnProceso := False;
HabilitarControles;
end;
End;

Olvidándonos de los botones de Cancelar y Cerrar y poniendo otro:

TForm1.ClickButton1(Sender: TObject);
begin
.... (CA) Parte del Codigo ...
while FEnProceso do Application.ProcessMessages; ??
begin
.... (CB) Resto del Codigo ...
end;
end;

La pregunta es cómo esperar a que FEnProceso sea False para seguir el código CB es decir que haya terminado el bProcesarClick.


E imaginación le he echado toda la que tengo.

Por cierto, cómo se hace para encerrar el código en una cajita en estos mensajes?

Saludos.
Responder Con Cita
  #8  
Antiguo 13-07-2004
Avatar de Nuria
Nuria Nuria is offline
Miembro
 
Registrado: may 2003
Posts: 531
Poder: 21
Nuria Va por buen camino
Cita:
Empezado por Patxi
Por cierto, cómo se hace para encerrar el código en una cajita en estos mensajes?
[ delphi ]
.....
Código
....
[ /delphi ]

Sin espacios en blanco entre los corchetes...más información sobre etiquetas .

Saludos!
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro


La franja horaria es GMT +2. Ahora son las 01:18:50.


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
Copyright 1996-2007 Club Delphi