PDA

Ver la Versión Completa : OnValidate y Foco


javiermorales
19-05-2003, 09:07:23
Buenos Días, tengo un problema con el foco de unos DBEdit, ya que cuando sales de un DBEdit, se activa el evento OnValidate del campo asociado y en este evento, se realiza la actualización de diversos campos (asociados a DBEdits de ese Form) y estos a su vez activan sus eventos OnValidate.

Al final, el campo que debe tener el foco, parece que lo tiene, ya que si haces una nueva tabulación pasa al siguiente campo en el orden correcto de tabulación. El problema está en que aunque parezca que tenga el foco si intentas escribir sobre él, se modifica, aunque al pasar al siguiente campo se pierden los cambios. Además no aparece como seleccionado.

Por favor, he intentado de todo (desactivando la actualización del formulario, con LockWindowUpdate, etc).

Realizando la traza todo funciona correctamente y el foco aparece correcto.

Estoy desesperado, alguien tiene alguna idea.

Gracias.

javiermorales
19-05-2003, 13:48:20
Cualquier sugerencia será bienvenida ya que he llegado a un callejón sin salida.

Un saludo.

Bacterion
19-05-2003, 15:58:16
Supongo que , al cambiar un campo de valor, quieres cambiar otros campos.

El OnValidate, se supone, es para que valides si el valor que vas a poner sigue las reglas que hayas definido para ese campo (que no sea 0, que no sea negativo, que rime con Pascual), y si no se cumplen, abortar (mensaje, silencioso, formateando el disco duro...). Mejor ponlo en el OnChange.

¿De todas formas, no podrías dar un ejemplo que reproduzca ese comportamiento (código?) para que veamos de que se trata?
A ver si es que lanzas un cambio sobre un campo que a su vez lanza otro cambio sobre el actual, etc...

Kafu
19-05-2003, 16:23:31
Estoy con Bacterion en cuanto a que tiene pinta de haber cruce de referencias entre varios componentes. De todas formas comentas que cuando lo traceas no tienes el problema. Evidentemente al coger el foco el depurador cuando vuelves a ver la pantalla windows ya ha gestionado el movimiento del foco, así que no te sirve ese traceo. Contando con dos monitores, uno para el depurado y otro con la aplicación sí verías el resultado real. Si no cuentas con ese segundo monitor yo escribiría a un fichero la información que quieras tracear, en tu caso iría rastreando el activecontrol, etc. Los showmessages tampoco te sirven porque te moverían el foco. En cuanto a poner las validaciones en el onchange no sé, es según la intención que tengas. Yo no suelo usar validaciones parciales y además ahí sí que hay riesgo de recursividad, si desde un onchange disparas otro. Pero claro depende de cómo esté programado.
Bueno un saludo,

javiermorales
20-05-2003, 08:15:42
Muchas gracias por contestar. En efecto lo que se busca es actualizar el valor de varios campos.
Ejemplo:

"Cantidad" "Precio" "Importe"

Cuando Actualizo "Cantidad", en el OnValidate, llamo a una función (CalculaPrecPAR) dentro del DataModule que realiza un cálculo en cascada de los datos que se ven afectados en la misma tabla del mismo formulario:

procedure TDM.CalculaPrecPAR();
begin
//Calcula PrecioCoste=(Precio*(%MA))*(%CI)
TaPTOPAR.FieldByName('PTOPAR_PREC2').ReadOnly := false;
TaPTOPAR.FieldValues['PTOPAR_PREC2'] := ((TaPTOPAR.FieldValues['PTOPAR_PREC'] *
(1+(TaPTOPAR.FieldValues['PTOPAR_MA']/100))) *
(1+(TaPTOPAR.FieldValues['PTOPAR_CI']/100)));
TaPTOPAR.FieldByName('PTOPAR_PREC2').ReadOnly := true;
//Calcula ImporteCoste=Cantidad x Precio2
TaPTOPAR.FieldByName('PTOPAR_IMP').ReadOnly := false;
TaPTOPAR.FieldValues['PTOPAR_IMP'] := TaPTOPAR.FieldValues['PTOPAR_CAN'] *
TaPTOPAR.FieldValues['PTOPAR_PREC2'];
TaPTOPAR.FieldByName('PTOPAR_IMP').ReadOnly := true;
//Calcula ImporteOferta=ImporteCoste x K
TaPTOPAR.FieldByName('PTOPAR_OFER').ReadOnly := false;
TaPTOPAR.FieldValues['PTOPAR_OFER'] := TaPTOPAR.FieldValues['PTOPAR_IMP'] *
TaPTOPAR.FieldValues['PTOPAR_K'];
TaPTOPAR.FieldByName('PTOPAR_OFER').ReadOnly := true;
//Calcula PrecioOferta=PrecioCoste x K
TaPTOPAR.FieldByName('PTOPAR_POFER').ReadOnly := false;
TaPTOPAR.FieldValues['PTOPAR_POFER'] := TaPTOPAR.FieldValues['PTOPAR_PREC2'] *
TaPTOPAR.FieldValues['PTOPAR_K'];
TaPTOPAR.FieldByName('PTOPAR_POFER').ReadOnly := true;
end;

Muchas Gracias.

marcoszorrilla
20-05-2003, 09:15:08
Yo para este tipo de casos, creo una "Procedure" que hace el trabajo y la llamo desde el OnChange de los campos susceptibles de producir cambios.

Teniendo cuidado de no incurrir en recursividad, por ejemplo en una línea de factura tanto se cambien las unidades como el precio se produce un cambio en el importe, en el OnChange de ambos campos llamo a un Procedimiento que hace el cálculo pertinente.

Un Saludo.

javiermorales
20-05-2003, 09:21:19
Gracias Marcos, una cuestión, el evento OnChange, ¿se dispara con cada modificación del importe, es decir con cada pulsación de un digito de la cifra?. En ese caso, ¿no serán demasiadas llamadas al procedimiento?.

¿Que tal te va a tí?. Gracias. Un saludo.

Bacterion
20-05-2003, 12:09:49
No, el evento OnChange se dispara cuando se cambia el valor del campo. Y como el TDBEdit (y demás componentes dbaware) solo mandan el cambio cuando sales de la celda (o edit) en la que estés editando, pues solo se te disparan una vez.

Por cierto, quizás esos cálculos puedas realizarlos en campos calculados y quitarte muchos problemas...

Otro problema que puedes tener puede venir de tus activaciones y desactivaciones del readonly. Si un campo es readonly, deja que lo sea (pobre). Casi te está indicando que debes usar Calculados.

javiermorales
20-05-2003, 12:14:58
Muchas Gracias Bacterión, probaré tus consejos.

Un abrazo.

javiermorales
21-05-2003, 08:10:16
Hola, os comento. Lo he probado en el evento OnChange y se dispará en 3 ocasiones:

1.- Cuando se carga el formulario
2.- Cuando pasas al estado dsEdit
3.- Cuando sales del campo

Como se disparaba varias veces, al final he optado por los campos calculados, como me indicaba Bacterión.

Con ellos no he tenido problemas, además como deseaba guardar dichos resultados en la BD, cuando se produce el evento OnPost hago que se guarden los campos calculados en sus correspondientes de la BD.

Muchas Gracias a todos, ahora funciona perfectamente.