Conflicto entre evento ON CHANGE y ON ENTER de TEXTBOX

HMG en Español

Moderator: Rathinagiri

Post Reply
citro
Posts: 52
Joined: Wed Dec 22, 2010 3:45 pm

Conflicto entre evento ON CHANGE y ON ENTER de TEXTBOX

Post by citro » Wed Oct 26, 2011 2:43 am

Tengo un Textbox en el que se ingresan una serie de 6 números separados por el punto y coma, cada uno de esos números se evaluan con una función (Controlserie() ), para determinar que esten dentro de un rango de 0 a 45.
Si alguno de esos números está fuera de rango aparece un MSGINFO() indicando que el número está fuera del rango especificado, esta evaluación se hace en el evento ON ENTER del TEXTBOX.
Dentro del mismo TextBox hay un evento ON CHANGE que basicamente lo que hace es fijarse si se completó el Textbox, salta al próximo control, en Clipper no había este problema porque cuando se completaba el get lo hacía automáticamente. El problema surge justamente en este evento porque antes de pasar al próximo control debe evaluar que los números ingresados esten dentro del rango anterior, y si no es así despliega el MSGINFO() y al presionar la tecla ENTER para cerrar la ventana de ese MSGINFO() activa el evento ON ENTER del TEXTBOX, por lo cual la ventana del MSGINFO() aparece 2 veces. Un ejemplo:

en el TEXTBOX ingreso 01;02;03;04;05;46

el 46 es un número que esta fuera de rango por lo que activa el MSGINFO():

El número 46
esta fuera del rango especificado

OK

Este MSGINFO aparece 2 veces. Bueno la idea es que este MSGINFO aparezca una sola vez. Abajo describo el TEXTBOX

DEFINE TEXTBOX TxtSerJug
ROW 100
COL 120
WIDTH 120
VALUE serisali->seriejuga
TOOLTIP 'Serie jugada'
INPUTMASK "99;99;99;99;99;99"
ON ENTER {|| if( Empty( strtran( Frm_JueAlta.TxtSerJug.value,";" ) ) .or.;
!Controlserie( Frm_JueAlta.TxtSerJug.value,cTipo ) .or. ;
!NumeroExis( Frm_JueAlta.TxtSerJug.value,Frm_JueAlta.dtpfecha.value ),;
Frm_JueAlta.TxtSerJug.setfocus,Nil ) }

ON CHANGE {|| if( !Empty( right(Frm_JueAlta.TxtSerJug.value,1 ) ) .and. ;
Controlserie( Frm_JueAlta.TxtSerJug.value,cTipo ),Frm_JueAlta.TxtLt.setfocus,Nil ) }
END TEXTBOX
Antonio
Sistemas
Resipol

User avatar
Rathinagiri
Posts: 5250
Joined: Tue Jul 29, 2008 6:30 pm
DBs Used: MariaDB, SQLite, SQLCipher and MySQL
Location: Sivakasi, India
Has thanked: 167 times
Been thanked: 165 times
Contact:

Post by Rathinagiri » Wed Oct 26, 2011 4:10 am

Actually you are calling the controlserie() function twice. That's why MsgInfo is also called twice.

You try to use it either in onchange or in onenter. IMHO, 'onchange' is enough.
East or West HMG is the Best.
South or North HMG is worth.
...the possibilities are endless.

User avatar
l3whmg
Posts: 694
Joined: Mon Feb 23, 2009 8:46 pm
Location: Italy
Contact:

Post by l3whmg » Wed Oct 26, 2011 12:11 pm

Hi Citro.
Remember that ONCHANGE is fired on every (and everywhere) character is changed.
This "can be" a problem if you need to check more then one character somewhere within your functions.

Cheers
Luigi from Italy
www.L3W.it

citro
Posts: 52
Joined: Wed Dec 22, 2010 3:45 pm

Post by citro » Mon Oct 31, 2011 5:27 pm

Finalmente solucioné el problema usando 1 flag y el paso de unos parámetros lógicos, así:

ON GOTFOCUS lFlag:=.f.

ON ENTER {|| if( Empty( strtran( Frm_JueAlta.TxtSerJug.value,";" ) ) .or.;
!Controlserie( Frm_JueAlta.TxtSerJug.value,cTipo,,.f.,.t.,thiswindow.name,this.name ) .or. ;
!NumeroExis( Frm_JueAlta.TxtSerJug.value,Frm_JueAlta.dtpfecha.value ),;
Frm_JueAlta.TxtSerJug.setfocus,Nil ) }

ON CHANGE {|| if( !Empty( right(Frm_JueAlta.TxtSerJug.value,1 ) ) .and.;
Controlserie( Frm_JueAlta.TxtSerJug.value,cTipo,,.t.,.f.,thiswindow.name,this.name,@lFlag ),;
Frm_JueAlta.TxtLt.setfocus,if( !Empty( right(Frm_JueAlta.TxtSerJug.value,1 ) ),;
Frm_JueAlta.TxtSerjug.setfocus,Nil ) ) }

En la función ControlSerie(...)

Function ControlSerie( cSerie,cTipo,lJugado,lChange,lEnter,cFrmName,cTxtName,lFlag )

...
...
if lEnter .or. ( lChange .and. !lFlag )
Mensaje()
lRetorno:=.f.

if lChange .and. !lFlag
lFlag:=.t.
end if

if lChange
lEnter:=.t.
end if
end if

Si se activa el evento ON CHANGE, entonces lFlag pasa a ser verdadero con lo cual no se vuelve a activar nuevamente en el mismo evento, si lo hace si uno activa ON ENTER, y al pasar al otro control en el ON GOTFOCUS del próximo TEXTBOX inicio lFlag nuevamente a .F., de esta manera el Mensaje se muestra una sola vez por control, en el caso de que se tenga que mostrar.

translate

Finally solved the problem by using a flag and the passage of logical parameters, as follows:

ON GOTFOCUS lFlag:=.f.

ON ENTER {|| if( Empty( strtran( Frm_JueAlta.TxtSerJug.value,";" ) ) .or.;
!Controlserie( Frm_JueAlta.TxtSerJug.value,cTipo,,.f.,.t.,thiswindow.name,this.name ) .or. ;
!NumeroExis( Frm_JueAlta.TxtSerJug.value,Frm_JueAlta.dtpfecha.value ),;
Frm_JueAlta.TxtSerJug.setfocus,Nil ) }

ON CHANGE {|| if( !Empty( right(Frm_JueAlta.TxtSerJug.value,1 ) ) .and.;
Controlserie( Frm_JueAlta.TxtSerJug.value,cTipo,,.t.,.f.,thiswindow.name,this.name,@lFlag ),;
Frm_JueAlta.TxtLt.setfocus,if( !Empty( right(Frm_JueAlta.TxtSerJug.value,1 ) ),;
Frm_JueAlta.TxtSerjug.setfocus,Nil ) ) }

In function ControlSerie(...)

Function ControlSerie( cSerie,cTipo,lJugado,lChange,lEnter,cFrmName,cTxtName,lFlag )

...
...
if lEnter .or. ( lChange .and. !lFlag )
Mensaje()
lRetorno:=.f.

if lChange .and. !lFlag
lFlag:=.t.
end if

if lChange
lEnter:=.t.
end if
end if

If ON CHANGE event fires, then it becomes true lFlag thus not re-activate at the same event again, if you do if you activate ON ENTER, and move to another control on the GotFocus of the next ON TEXTBOX lFlag start again. F., so the message is displayed once for control, in case you need to show.
Antonio
Sistemas
Resipol

Post Reply