Welcome To The Home Of The Visual FoxPro Experts  
home. signup. forum. archives. search. google. articles. downloads. faq. members. weblogs. file info. rss. print.
CONDITIONAL BY-PASSING OF THE FIELD LEVEL VALID EVENT IN VISUAL FOXPRO VERSIONS 8.0 AND 9.0

General Overview
One question that has come up several time in the Foxite forum of late, is when you set field level validation events, the flip side to this is asked how in the heck do you conditionally by-pass this event in cases where you really want to. A good example of this is where you have a field input on a form that you really want to validate at the field level. You decide in your application that you want field level validation and want the input resolved at the point of inputting to this field. You have already looked at combo box drop downs, grid pick list, and various other validation options.


Many times in the Forum, others will advise you to validate the required field when you click the Save command button and perform all the validation routines here, but this is not really what you really want. You want field level validation at the time of input to the field in question. “End of story, give me a work-a-round!”.

So you add the field level validation in the valid event of the field in question and ensure that this field gets the focus when a new record is added to 100% ensure that an entry is entered to match your validation event. You also want to ensure if the user by mistake during editing a record and deletes the entry, you have the code logic in place to validate at this field level entity and force the user to input an acceptable
value.
All of this is fine and well until a user by mistake clicks the Add command button and the focus is moved to the validate field as per your planned setfocus default. Now knowing the Add command button was clicked in error, you want a graceful ability to exit the form without the validation event firing. Or you could be sitting in Add mode with the focus like you had designed at the validated field that is blank, and you want to call a secondary form to do some other process, like a lookup function into another table that is maintained in another form.
So you are now into a catch-22 scenario. You want to maintain your field level validation for sure, and do not want to validate in the Save command button, yet you want a way to exit the form, or call a secondary form. What are you to do?

VFP version 8.0 and 9.0 Solution
This simple trick to this dilemma and the key is the “mousemove” and the “mouseleave” events that you can place in a command button. “Mousemove” fires when you move your mouse over a control and “mouseleave” fires when your mouse moves out of the control. So this mechanism will provide a true on/off switching capability in your form to change the value of a memory variable based upon a specific command button, or group of command buttons. If the mouse is sitting over say an Exit command button, you can flip a memory variable to .F., and if not over the Exit command button (leaving the Exit command button with the mouse), you can flip the memory variable to .T. Are you starting to get the drift here?

So let’s say you have a field level valid event like the code below:

IF EMPTY(This.Value)
  * --- User action required.
  messval=messagebox("You must enter in a value for the Product ID !",0+16,"Input Required")
  RETURN .F.
ENDIF

The above code will fire each and every time this input location has the focus and if left blank and you cannot move out of this field unless you enter in a value, but this is not want you want. What you really want is conditional firing of this event so if the user clicks the Exit command button the validation event will not fire. Now let’s look at a modification to this valid event code:


IF EMPTY(This.Value) .AND. plValidFire = .T.
  * --- User action required.
  messval=messagebox("You must enter in a value for the Product ID !",0+16,"Input Required")
  RETURN .F.
ENDIF

Now you can see this valid event will only fire if the memory variable plVaidFire = .T. So all we need to do is use the “mousemove” event in a command button to switch the value of this memory variable to .F., so code like above will not fire. Below will stop the valid event from firing in the “mousemove” event of a command button:

plValidFire = .F.

This will ensure that when we move the mouse over an exit command button and click it, the valid event will not fire. Now we have a very nice way for the user to click Exit, Revert, or call a secondary form without the hassles of the valid event firing.

Likewise, when the user moves the mouse off of this command button (or other command buttons), the “mouseleave” event can flip the memory variable back to:

plValidFire = .T.

and the valid event will now fire again.

Ok, what about this memory variable “plValidFire”. Although I try not to use global memory variables in my application as a general rule this is a case where I do. I need the memory variable “plValidFire” globally useable within the instance of this form. So I do add this memory variable as a public memory variable in the load event of the form. Below is the code in the load event:

* --- Form global settings.
SET DELETED ON
SET SAFETY OFF
SET DATE ANSI
SET CENTURY ON
* --- Public memory variable to turn on/off the validation firing event
* --- associated with the txtProductid input box.
* --- NOTE: This is a global memory variable declared in this form’s load
* ---    event. This global memory variable is only used in this form’s
* ---    instance and is released in this form’s destroy event.
PUBLIC plValidFire
plValidfire = .T.

Now to clean up, this code is to add the release of this memory variable in the destroy event in this form:

RELEASE plValidFire 

Summary
I have included a very simple VFP 9.0 project that you can load up and look through to try this out and see how it works, however this code should work as well under VFP 8.0. I am not 100% sure if the “mouseleave” exists in VFP 7.0, but am pretty sure it does not exist in 7.0, or earlier versions of Visual FoxPro. It has been so long that I worked in VFP 7.0, I am not sure and no longer have a copy of this version on my development computer to verify this fact. This project is in a zipped file called VFPValidCondition.zip . Just unzip this file and load up the project and run the “frmvalidfire” form. You can look through this example and apply the basics to your applications.

Keep in mind, I have added all the code in the command buttons, and did this so you do not have to have to weed through my custom command button classes. In a real world application, I do not have all the enabling and disabling of command buttons in the click event of my command buttons. The scope of this article is not to show you how to sub-class command buttons, but to understand the basics of conditional valid event control, so I have exposed the code directly in the click events, and all code in the method events of the two forms in the example.
Some may say that I should not have used a public memory variable for my on/off switch for the valid event. I do think that although one must try to limit the use of global memory variables, there are times when they can be used. On this topic, if I have to call a form and can use the with parameter I will. See the Visual FoxPro help on the DO FORM below.

DO FORM FormName | ? [NAME VarName [LINKED]] [WITH cParameterList] [TO VarName] [NOREAD] [NOSHOW]

I think the main thing I look at with any programmer, if the programmer declares a global memory variable for a specific task and ensures he/she cleans up after the memory variable is used, this is OK in my books. As you know, using global memory variables that you could forget about and over-write in error can result in a lot of wasted debugging time. So if you must use global memory variables; limit them, write down the memory variables, used in source documentation to declare their names, their purpose and identify when they are created where they are released. You will find I am a real stickler for in source documentation and comments. I am talking about in source documentation like below:

* --- Public memory variable to turn on/off the validation firing event
* --- associated with the txtProductid input box.
* --- NOTE: This is a global memory variable declared in this forms load
* ---    event. This global memory variable is only used in this form’s
* ---    instance and is released in this form’s destroy event.
PUBLIC plValidFire
plValidfire = .T.

I hope you find this article and project example helpful to you in future Visual FoxPro design concepts. Like I mentioned at the beginning of this article, lots of Foxite threads exist on this topic and how to by-pass field level validation events.
It has been a while since I submitted an article. Sorry for this folks, but damn I have been swamped with workload – overload in my current systems analyst position for many months now. I am sure those out there in systems analyst roles know what I am talking about – lol.
I apologize for my lack of frequenting the forum, but hope to visit more in the future.

ABOUT THE AUTHOR: PETE SASS

Pete Sass Pete has worked in the computer world since the late 70's. He loves the outdoors and lives in a small town called Marathon, in the north of Canada.

FEEDBACK

Khurram Tahir @ 4/28/2007 1:42:44 PM
Good logic , what is your opnion on that if create a EXIT command button with cancel property set to .T. and in the valid event of any text box put the following condition

IF Lastkey() == 27
RETURN .T.
Endif

tushar @ 7/11/2008 6:37:19 PM
Instead of using plValidFire as a public variable, you could add a property callled plValidFire and use that instead. So there would be no need for a public variable.

P Blue @ 10/7/2009 9:56:27 AM
MouseMove and MouseLeave method works fine in my form. Lastkey() = 27 does not work in a Valid Event as it only erases what has been typed in the current field.



Your Name: 
Your Feedback: 

Spam Protection:
Enter the code shown: