Controlar la tecla ESC en un ciclo while de formulario

732 views
Skip to first unread message

carlosmupe

unread,
May 15, 2015, 9:08:02 AM5/15/15
to publice...@googlegroups.com
Estimados, tengo un formulario con un proceso bastante largo en un ciclo while, el cual me gustaria poder interrumpir si presiona la tecla ESC, me pregunte via messagebox si desea cancelar si responde que si, que cancele (salga del ciclo while), sin embargo he intentado utilizar ON KEY LABEL ESC thisform.cancelar() pero me marca un error de sintaxis, alguna sugerencia??

saludos y gracias por los comentarios.

Rick C. Hodgin

unread,
May 15, 2015, 9:15:47 AM5/15/15
to publice...@googlegroups.com, carlo...@gmail.com
ON KEY LABEL 'ESC' DO cancelar

PUBLIC glCancel
*glCancel = .F.

DO WHILE ...
    *DOEVENTS    && Pueden ser necesarios DOEVENTS aquí
    IF glCancel
        EXIT
    ENDIF
    * ... su código normal
ENDDO

FUNCTION cancelar
glCancel = .T.
ENDFUNC

Saludos cordiales,
Rick C. Hodgin

carlosmupe

unread,
May 15, 2015, 9:18:56 AM5/15/15
to publice...@googlegroups.com, rick.c...@gmail.com, carlo...@gmail.com
Gracias por la pronta respuesta Rick lo pruebo y te comento.

carlosmupe

unread,
May 15, 2015, 9:33:08 AM5/15/15
to publice...@googlegroups.com, carlo...@gmail.com, rick.c...@gmail.com
Estimado, funciona siempre y cuando no este dentro del ciclo while :(, cuando estoy en el ciclo while aparece la ventana de FOX que indica si quiero suspender, cancelar, etc.. Y no el messagebox, quizas me falte definir en el formulario alguna propiedad de este para que omita este cuadro de dialogo y asuma el procedimiento cancelar??

Rick C. Hodgin

unread,
May 15, 2015, 10:00:00 AM5/15/15
to publice...@googlegroups.com, carlo...@gmail.com, rick.c...@gmail.com
SET ESCAPE OFF

ON KEY LABEL 'ESC' DO cancelar

...


Saludos cordiales,
Rick C. Hodgin

Arnaldo Toledano

unread,
May 15, 2015, 10:19:20 AM5/15/15
to publice...@googlegroups.com, arnaldo....@gmail.com
Yo lo aria asi.

Sale = .T.
Do WHile condicion and Sale
    variable = inkey()
    If variable = 27
       todo lo que quieras.
       sale = .F. o .T.  lo que quieras
    endif
   codigo.......

endif


El 15/05/2015 a las 11:00 a.m., Rick C. Hodgin escibió:
--
Arnaldo Toledano Tesys Informática Córdoba Argentina

carlosmupe

unread,
May 15, 2015, 10:25:35 AM5/15/15
to publice...@googlegroups.com, rick.c...@gmail.com, carlo...@gmail.com
estimado, no me funciona la tecla esc queda inabilitada en el ciclo while ya que no me muestra el messagebox, adjunto el codigo que estoy utilizando:

main.prg
*------->
public m.CancelaWhile
m.CancelaWhile=.f.
set escape off
ON KEY LABEL 'ESC' DO CANCELAR
do form formulario
READ events
ON KEY LABEL 'ESC'
CLEAR all
SET ESCAPE ON

PROCEDURE CANCELAR
*---------------->
LOCAL resp
resp=MESSAGEBOX("¿Desea Cancelar el Proceso?",4+32+256,"Aviso")
IF (resp==6)
    m.CancelaWhile=.t.
ENDIF


formulario.scx
*------------------>
DO WHILE !FEOF(nfile)
   *muchos eventos
   IF (m.CancelaWhile)
       EXIT
   ENDIF
ENDDO

Victor Espina

unread,
May 15, 2015, 10:33:54 AM5/15/15
to publice...@googlegroups.com, arnaldo....@gmail.com, arnaldo....@gmail.com
Ni este metodo ni el propuesto por Rick funcionaran sin incluid un DOEVENTS() dentro del DOWHILE.  La razon de esto es que VFP no procesa la lista de eventos pendientes en la cola de Windows mientras esta ejecutando codigo.  Por lo tanto, el evento windows generado al pulsar ESC estara en cola pero no sera procesado hasta el siguiente WAIT STATE.  Justamente lo que hace el DOEVENTS es forzar a VFP a hacer una pausa para procesar los eventos pendientes en la cola de Windows.  Lamentablemente esto trae como consecuencia que el ciclo DO WHILE tome mucho mas tiempo del que tomaria sin el uso de DOEVENTS.

Saludos

Victor

carlosmupe

unread,
May 15, 2015, 10:38:18 AM5/15/15
to publice...@googlegroups.com, vesp...@gmail.com, arnaldo....@gmail.com
ok estimado, muchas gracias por la aclaración, buscare otro modo de corregir este problema, sin castigar el desempeño de la aplicación.

Victor Espina

unread,
May 15, 2015, 12:11:31 PM5/15/15
to publice...@googlegroups.com, carlo...@gmail.com, vesp...@gmail.com, arnaldo....@gmail.com
Tesys tuvo la amabilidad de senalarme que el uso de INKEY() dentro de un DO WHILE permite de forma efectiva cancelar un proceso al pulsar una tecla como ESC, lo cual pude confirmar en mis pruebas. Efectivamente el uso de INKEY permite procesar la cola de eventos (de teclado al menos) e introduce un retardo en la ejecucion del ciclo, pero este retardo es tan bajo que es perfectamente despreciable.  Adicionalmente comprobe que efectivamente DOEVENTS() introduce un retardo importante en la ejecucion de un ciclo... pero SOLO en VFP6... en VFP9 parece haber cambiado esto y ahora es mucho menor el retardo introducido por el uso de DOEVENTS.

Victor Espina

carlosmupe

unread,
May 15, 2015, 2:10:46 PM5/15/15
to publice...@googlegroups.com, vesp...@gmail.com, carlo...@gmail.com, vesp...@gmail.com
ok, gracias a todos por su ayuda, implementare esta ultima solución.

saludos

ZeRoberto

unread,
May 15, 2015, 3:21:38 PM5/15/15
to publicesvfoxpro
Pero usar INKEY() o WAIT retardaría un poco el bucle.

Saludos

Victor Espina

unread,
May 15, 2015, 4:32:59 PM5/15/15
to publice...@googlegroups.com, zero...@gmail.com
Eso mismo pensaba yo del INKEY, pero a insistencia de Tesys yo mismo probe su tecnica en un loop DO WHILE de 5.000.000 de iteraciones.  El loop completo sin INKEY tardo 2.7s, mientras que con el INKEY tardo 5.2s y, en cualquier momento de esos 5.2s al pulsar ESC se cancelaba el proceso (por que INKEY devolvia 27).

Porcentualmente es un recargo importante, del 100%, pero en la practica estamos hablando de poco mas de 2s de retardo en un loop de 5.000.000 de iteraciones... por lo que en loops mas reales, de apenas unas decenas o cientos de iteraciones, este retardo seria completamente despreciable.

Saludos

Victor

ZeRoberto

unread,
May 15, 2015, 4:37:20 PM5/15/15
to publicesvfoxpro
Y a eso si el DO WHILE tiene mas condiciones dentro, me imagino que demorara mas

Rick C. Hodgin

unread,
May 16, 2015, 3:17:30 PM5/16/15
to publice...@googlegroups.com, carlo...@gmail.com
http://www.libsf.org/software/misc/keytrap.prg
DO keytrap.prg
* Presione algunas teclas, a continuación, pulse la tecla Escape

* Ejemplos de uso después de refactorización para su aplicación::
oKeyTrap = CREATEOBJECT("myKeyTrap")
DO WHILE .T.
    IF oKeyTrap.cancelar
        CLEAR TYPEAHEAD
        EXIT
    ENDIF

    * Codigo
ENDDO
oKeyTrap.release

Saludos cordiales,
Rick C. Hodgin


On Friday, May 15, 2015 at 9:08:02 AM UTC-4, carlosmupe wrote:

ZeRoberto

unread,
May 16, 2015, 5:31:52 PM5/16/15
to publicesvfoxpro
Not work , I press ESC but don't stop

Rick C. Hodgin

unread,
May 16, 2015, 5:56:21 PM5/16/15
to publice...@googlegroups.com, zero...@gmail.com
I have changed basic use since I first posted.  If you see the comment inside keytrap.prg you will see the current form.  It is here also:

He cambiado
el uso básico desde que publiqué. Si ves el comentario dentro keytrap.prg verá la forma actual. Es aquí
también:

oKeyTrap = CREATEOBJECT("myKeyTrap")
oKeyTrap.bind

DO WHILE .T.
    IF oKeyTrap.cancelar
        CLEAR TYPEAHEAD
        EXIT
    ENDIF

    * Codigo
ENDDO
oKeyTrap.unbind

Saludos cordiales,
Rick C. Hodgin

Reply all
Reply to author
Forward
0 new messages