Página 1 de 1

ExitLoop

Publicado: 23 Nov 2009, 19:07
por joaquin
¿Cómo puedo indicar a For-Next que salga del bucle con ExitLoop y se pueda cerrar la ventana? :smt017

Código: Seleccionar todo




#Include <Constants.au3>

#include <GUIConstantsEx.au3>

#include <StaticConstants.au3>

#include <WindowsConstants.au3>





$Form1 = GUICreate("Clock ", 450, 200, 192, 124);$WS_POPUPWINDOW)

GUISetBkColor(0x000000)





$font = "Comic Sans MS"



$Lh = GUICtrlCreateLabel (@HOUR, 190, 100, 15,15)

    GUICtrlSetColor(-1,0xE00000)

    GUICtrlSetFont(-1, 10, 400 , $font)

GUICtrlCreateLabel (":", 210, 100, 5,15)

    GUICtrlSetColor(-1,0xE00000)

    GUICtrlSetFont(-1, 10, 400 , $font)

$Lm = GUICtrlCreateLabel (@MIN, 220, 100,15,15)

    GUICtrlSetColor(-1,0xE00000)

    GUICtrlSetFont(-1, 10, 400 , $font)

GUICtrlCreateLabel (":", 240, 100, 5,15)

    GUICtrlSetColor(-1,0xE00000)

    GUICtrlSetFont(-1, 10, 400 , $font)

$Ls = GUICtrlCreateLabel (@SEC, 250, 100,15,20)

    GUICtrlSetColor(-1,0xE00000)

    GUICtrlSetFont(-1, 10, 400 , $font)





GUISetState(@SW_SHOW)





Do

  $nMsg = GUIGetMsg()



    $Sec = @SEC

    For $Sec = 01 to 59 Step 1

        Sleep (1000)

        GUICtrlSetData($Ls,@SEC)

        If $nMsg = $GUI_EVENT_CLOSE Then ExitLoop (2)

    Next



Until  $nMsg = $GUI_EVENT_CLOSE

 

Re: ExitLoop

Publicado: 23 Nov 2009, 20:07
por XPyro
Yo lo que hago es cambiar la variable para que ya no siga, ejemplo:

Código: Seleccionar todo

For $Sec = 01 to 59 Step 1

        Sleep (1000)

        GUICtrlSetData($Ls,@SEC)

        If $nMsg = $GUI_EVENT_CLOSE Then $Sec = 59

Next

Re: ExitLoop

Publicado: 23 Nov 2009, 21:29
por joaquin
Gracias por la sugerencia XPyro...
Cambio el valor de $Sec a diferentes valores que no esten en el rango del bucle For (01-59), y sigo sin poder cerrar la GUI.
Debe haber además, otro error...
Saludos

Re: ExitLoop

Publicado: 24 Nov 2009, 09:44
por Ximorro
El problema es que no estás tomando los mensajes dentro del bucle, por mucho que cierres, como GUIGetMsg() está fuera del For no lo ve.

Pero es más complicado, porque lo he probado y al estar el Sleep, resulta que hay que cerrar cuando no esté en Sleep, y eso es casi nunca.
Para arreglarlo lo que he hecho es lo siguiente:

Código: Seleccionar todo

For $Sec = 1 to 5900

    $nMsg = GUIGetMsg()

    GUICtrlSetData($Ls,@SEC)

    If $nMsg = $GUI_EVENT_CLOSE Then ExitLoop 2

    Sleep (10)

Next
Fíjate que es equivalente, pues los segundos no los tomas de $Sec, sino de @SEC (por cierto, la inicialización $Sec = @SEC es innecesaria, $Sec lo cambias luego en el bucle).
Lo que hago es 100 veces más el bucle, pero he acortado el Sleep 100 veces menos. De esta manera dura lo mismo, y también cambia cada segundo porque ese valor lo toma de @SEC.

Ahora lo podrás cerrar bien porque pasa muchas veces por GUIGetMsg(), con lo que es fácil que capture el evento. Lo que no me gusta mucho es que está continuamente escribiendo en la etiqueta, aunque sea el mismo valor (escribirá el valor 100 veces por segundo). Una mejora es cambiar la etiqueta sólo si el valor ha cambiado.

Hay otras opciones totalmente diferentes para hacer esto, aunque son más complicadas. Se trata de usar "timers" que interrumpan la ejecución cada segundo para actualizar la etiqueta. Se puede hacer con la librería Timers.au3 o con las funciones AdLib. Como digo esto ya es más complicadillo, pero para que sepas que existe...

Re: ExitLoop

Publicado: 24 Nov 2009, 09:55
por Ximorro
Por cierto, que no sabía que a ExitLoop le puedes poner un numerito para salir de varios bucles a la vez, siempre se aprenden cosas nuevas...

Re: ExitLoop

Publicado: 24 Nov 2009, 14:03
por joaquin
Gracias por la respuesta Ximorro...

Con $Sec = @SEC antes del For, pretendia que los valores 01-59 fueran los de @SEC, es decir, Si @SEC=11 que empezara el bucle con el valor 11, que es el tiempo real...No quiero que haga sólo un conteo, sino que lo haga a partir del valor de @SEC.

Con GUIGetMsg() dentro del For, cómo me indicas, Funciona!! :smt003
Lo del Sleep se me escapa el porqué, pero funciona como has indicado. (Si disminuyo el valor de Sleep, es cierto, que pasa menos tiempo pausado, pero si aumento de 59 a 5900, habrá muchos más tiempos de pausa, aunque sean más pequeños, por lo que parece que la probabilidad de capturar el evento tendría que ser la misma...no?) Bueno la cuestión es que funciona y puedo cerrar la ventana. He probado con 590 y Sleep (100), y no es lo mismo....cierra igual pero demora más, con lo cual a mayor valor en Sleep, más demora.
Para evitar que esté continuamente escribiendo la etiqueta (visualmente hace un parpadeo que no es estético) he optado por poner el GUICtrlSetData($Ls,@SEC) fuera del For y parece que todo funciona...

Código: Seleccionar todo




#Include <Constants.au3>

#include <GUIConstantsEx.au3>

#include <StaticConstants.au3>

#include <WindowsConstants.au3>





$Form1 = GUICreate("Clock ", 450, 200, 192, 124);$WS_POPUPWINDOW)

GUISetBkColor(0x000000)



$font = "Comic Sans MS"



$Lh = GUICtrlCreateLabel (@HOUR, 190, 100, 15,15)

    GUICtrlSetColor(-1,0xE00000)

    GUICtrlSetFont(-1, 10, 400 , $font)



GUICtrlCreateLabel (":", 210, 100, 5,15)

    GUICtrlSetColor(-1,0xE00000)

    GUICtrlSetFont(-1, 10, 400 , $font)



$Lm = GUICtrlCreateLabel (@MIN, 220, 100,15,15)

    GUICtrlSetColor(-1,0xE00000)

    GUICtrlSetFont(-1, 10, 400 , $font)



GUICtrlCreateLabel (":", 240, 100, 5,15)

    GUICtrlSetColor(-1,0xE00000)

    GUICtrlSetFont(-1, 10, 400 , $font)



$Ls = GUICtrlCreateLabel (@SEC, 250, 100,15,20)

    GUICtrlSetColor(-1,0xE00000)

    GUICtrlSetFont(-1, 10, 400 , $font)





GUISetState(@SW_SHOW)



Do

    If @MIN == 59 And @SEC == 59 Then

        Sleep (1000)

        GUICtrlSetData($Lh,@HOUR)

        GUICtrlSetData($Lm,@MIN)

    EndIf

    If  @SEC == 59 Then

        Sleep (1000)

        GUICtrlSetData($Lm,@MIN)

    EndIF



    For $i=1 to 10 Step 1

        $nMsg = GUIGetMsg()

        If $nMsg = $GUI_EVENT_CLOSE Then  ExitLoop (2)

    Next

    GUICtrlSetData($Ls,@SEC)



Until $nMsg = $GUI_EVENT_CLOSE

Exit



 

:smt017 Si comparo con la hora del PC, los segundos se corresponden, pero eso ¿es porque el conteo de For dura un segundo ¿no? y para este caso es eso lo que buscaba: que se actualizara la etiqueta cada segundo.
Vaya que es casualidad y aunque sirva para éste script, no serviría por ejemplo, para hacer un cronometro, no?

Re: ExitLoop

Publicado: 25 Nov 2009, 12:31
por Ximorro
A ver, es que creo que tienes una pequeña confusión, resulta que @SEC (junto con @MIN y @HOUR) dan la hora del sistema (también hay otros para la fecha).
Así que no tienes que hacer tu For empezando con los segundos actuales, al escribir con GUICtrlSetData($Ls,@SEC) ya pone los segundos del sistema y da lo mismo lo que valga $sec.
Con el For particionado de tal manera que espere un segundo, pues te cambiará la etiqueta cada segundo (según lo que valga @SEC, no $sec.
Ciertamente se puede hacer mejor sacando la escritura del For y haciendo que éste dure un segundo:
For $Sec = 1 to 100
$nMsg = GUIGetMsg()
If $nMsg = $GUI_EVENT_CLOSE Then ExitLoop 2
Sleep (10)
Next
GUICtrlSetData($Ls,@SEC)
La cuestión es que dure un segundo (10 milisegundos x 100 veces = 1000 milisegungos = 1 segundo). Cuando acaba ese tiempo actualiza la etiqueta porque como ha pasado aproximadamente un segundo @SEC ya habrá cambiado.
Sí es importante que el Sleep sea relativamente pequeño, porque así pasa más veces por GUIGetMsg(), es cuando ejecuta esa línea cuando mira si estás clicando en el aspa de cerrar (o en otros botones y tal). Si pulsas cuando no está ahí, por ejemplo porque está en el Sleep, pues no te hará caso.
Hombre se puede subir un poco, se puede probar con Sleep(20) haciendo el bucle 50 veces.

Respecto a ese código último que pones, no hace falta que mires tú si el segundo o el minuto llegan a 59 y pasan, como digo @SEC, @MIN y @HOUR cambian solitos con la hora del sistema. Lo del bucle For sería para no estar cambiando las etiquetas continuamente, pero no hace falta controlar la hora.

Re: ExitLoop

Publicado: 25 Nov 2009, 12:55
por Chefito
No va del todo sobre este tema, pero te dejo un pequeño ejemplo que hice hace tiempo donde muestra una de las posibles formas para hacer funcionar un reloj en AutoIt: http://www.emesn.com/autoitforum/viewto ... eloj#p3091

Ahí queda eso por si quieres echarle un vistacillo :smt002 .

Saludos.

Re: ExitLoop

Publicado: 26 Nov 2009, 09:01
por joaquin
Chefito...gracias por la sugerencia.

Ximorro...
Respecto a ese código último que pones, no hace falta que mires tú si el segundo o el minuto llegan a 59 y pasan, como digo @SEC, @MIN y @HOUR cambian solitos con la hora del sistema. Lo del bucle For sería para no estar cambiando las etiquetas continuamente, pero no hace falta controlar la hora.
Creo que las macros dan el valor que representan cada vez que son llamadas o actualizadas.Los IF no son para calcular el tiempo, sinó para indicar cuando quiero que actualize la etiqueta, es una cuestión más estética que funcional.
Si te fijaste, en el último código que postee, eliminé completamente el Sleep, con lo cual ya no dificulta la llamada al GuiGetMsg, y ahora la latencia de actualización de los segundos depende sólo de los valores que ponga en For. Es diferente si hago $i=01 to 10 Step 1, de $i=01 to 500 Step 1. En el último caso no mostrará los valores de @SEC de 1 en 1, porque demora más en hacer los 500 ciclos.
La idea de hacer $sec = @SEC era para no tener que calcular el intervalo en For, pero creo que eso no se puede hacer...
Espero haberme explicado mejor....
Creo que es mejor que postee el script entero, en el foro de programas, y seguimos desde ahí > Reloj Binario.au3
Thanks

Re: ExitLoop

Publicado: 26 Nov 2009, 09:33
por Ximorro
Ah, vale, no había cogido eso.
Vale es buena idea, aunque la etiqueta de los segundos sí la actualizas muchísimo. Yo sí pondría el Sleep en el For para que se espere por lo menos medio segundo antes de actualizarla. Con el Sleep pequeño como te dije, claro.

Lo de hacer el bucle 10 ó 500 veces no creas que se notará mucho. El For en sí será prácticamente instantáneo, si se nota algo será porque GuiGetMsg es algo bloqueante.

De todas maneras mírate el ejemplo de chefito. No te conté de primeras lo de los timers porque igual era demasiado avanzado así para verlo de repente, pero tomando como ejemplo su código igual lo haces fácil.
En realidad yo haría algo así con timers, puedes estar haciendo otras cosas y cada segundo ya se ocupa él de interrumpir lo que está haciendo para actualizar las etiquetas (ojo, no es multitarea, interrumpe lo que está haciendo, pero escribir unas etiquetas es rápido y no se notará)

taluec

Re: ExitLoop

Publicado: 27 Nov 2009, 23:16
por joaquin
...OK, tomo nota...
ya dejé posteado el Script completo en el Subforo de Scripts-Programas / Reloj Binario.