Hola!!
* El When es cuando un objeto recibe el foco si pasa la validación entonces se ejecuta el GoFocus, No te recomiendo usar el When para negar el focus a un objeto ya que visualmente no es una buena practica.
* El InteractiveChange se ejecuta por cada cambio que realices en los datos del objeto, por ejemplo cada tecla que presiones para cambiar el contenido o cada que seleccionas una opción del listado del ComboBox
* El Valid se ejecuta cuando confirmas los cambios ya sea con Enter, al Seleccionar un opción del listado del combobox, o al perder el foco porque diste click en otro objeto, usaste tab, etc.
* Una vez que se pasa la validación dentro del Valid entonces se ejecuta el LostFocus, por lo tanto si retornas un Cero en el Valid el LostFocus no se ejecuta.
--------------------------------
Para validar tu ComboBox o cualquier otro objeto en VFP todo va depender de la necesidad, pero sabiendo como funciona el orden de ejecución de los objetos es mas fácil saber como resolver esa necesidad.
Que problema tiene el VALID, porque si tiene un detalle y es que se ejecuta si o si, y a veces necesitamos que no lo haga, pero el simple hecho de que un objeto reciba el foco y salga de él entonces el valid se va a ejecutar y es ese el detalle que muchos no saben como resolver y por eso realizan la validación dentro del LostFocus
La forma que realizo no se si es la adecuada pero no he encontrado una propiedad que pueda decirme si dentro de un objeto cuando recibe el focus algo cambio, para que de esta forma decirle al Valid, hey no ha cambiado nada así que no valides nada, pero no la he encontrado, por lo que realizo una forma manual ese proceso.
Hay muchas formas, la forma rápida para explicarte es que crees una propiedad en el formulario, le pones por ejemplo el siguiente nombre y la inicias en Falso:
validarCambios = .f.
Luego esta propiedad la vas a utilizar dentro del InteractiveChange de cualquier objeto que quieras validar si hubo cambios o no.
thisform.validarCambios = .t.
Y por ultimo dentro del Valid de cualquier objeto vas a preguntar por el valor de esta propiedad, si hubo cambios la regresas a False inmediatamente porque ya se va a realizar la validación y luego escribes tu código.
IF thisform.validarCambios = .t.
thisform.validarCambios = .f.
* Aquí tu código que quieras validar y retornar 0 (Cero) para que no pierda el focus, retornar .t. para que salga o retornar el nombre del objeto a enviar el focus, etc.
ENDIF
Esta es la forma rápida, la que uso es por medio de clases, donde cada objeto de mi clase sea un TextBox, ComboBox, etc ya tiene creada una propiedad validarCambios = .f. y en el interactiveChange ya tiene el this.validarCambios = .t. incluso el Valid ya tiene la condición pero a demás a cada objeto le agregue un método mValid() donde pongo mi código, es decir en la clase Valid de cada objeto tengo un código como este:
IF thisform.validarCambios = .t.
thisform.validarCambios = .f.
_valid = this.mValid()
...
...
ENDIF
Desde luego hay mas código en el Valid() que uso, por ejemplo para saber si debe perder el focus, si debe enviar a un objeto el focus, o continuar.
Espero que te haya explicado el tema del Valid() y se entienda el motivo porque el que la mayoría no lo usa que es porque siempre se va a ejecutar con entrar y salir de un objeto y el desconocimiento del orden de ejecución de sus los métodos, y apliques cualquier técnica que encuentres que permita saber si realmente se realizaron cambios o no dentro del objeto para que de esta forma puedas evitar que se ejecute el código a validar cuando no es necesario.
Y otra cosa importante dentro del valid no esta permitido el SetFocus y por esa razón también muchos o la mayoría usa el LostFocus, porque no saben que para enviar el focus a un objeto desde el Valid se usa RETURN ya sea con un numero o con el nombre del objeto: Ejemplo:
* Mover hacia atrás como si presionaras shift+tab
Return -1
* Mover hacia delante como si presionaras tab
Return 1
* Mover 3 objetos hacia delante como si presionaras tres veces tab
Return 3
* La que siempre uso indicar el objeto a enviar el focus
Return (thisform.objetoNombre)
Nota: Cualquier corrección será bienvenida!!! y si tienen una mejor forma de realizar la validación seria mucho mejor que la compartieran.
saludos
Antonio Meza