The LostFocus of Validation
This column appeared in the December 1998 edition of
EXE, and covered the new Validate keyword
This month Im having a look at a new feature that has
been provided in Visual Basic 6, namely the new Validate event and the
associated CausesValidation property. Im then providing a review of the
Graphics Server product from Bits Per Second, a powerful and flexible
alternative to the Microsoft Chart control that ships with Visual Basic.
Problems with validation routines
Up until now there have been three ways of validating user
input in a Visual Basic form. First, all validation can be performed at the end
of the information gathering, such as when the user presses OK or
Apply. The first field that fails the validation, if there is one,
is then made the focus target and perhaps a message box will be displayed. This
approach is actually fine as long as you dont mind the fact that the
validation around each individual field will not take place while the
users attention is placed directly upon it. The second approach is to
place code directly into either the KeyPress or Change events which only allows
for limited validation because you cant be sure at this stage whether the
user has completed the entire field input. It is unfriendly to throw up a
validation message in this instance because the user might well have mistyped a
character and could be intending to hit the backspace and retype it a
message box at this stage will be unwelcome. Therefore the only useful work
that can be done here is to filter out invalid characters. The third way is to
write the code into the LostFocus event, but this can lead to all sorts of
problems. Consider the following code extracts for two text boxes where we are
validating against empty fields (and both fields are in fact empty):
Private Sub Text1_GotFocus()
Debug.Print "Text1.GotFocus"
End Sub
Private Sub Text1_LostFocus()
Debug.Print "Text1.LostFocus"
If Text1.Text = "" Then
Text1.SetFocus
End If
End Sub
Private Sub Text2_GotFocus()
Debug.Print "Text2.GotFocus"
End Sub
Private Sub Text2_LostFocus()
Debug.Print "Text2.LostFocus"
If Text2.Text = "" Then
Text2.SetFocus
End If
End Sub
This code highlights a difficulty with event ordering in
Visual Basic. If you run the above code when both Text1 and Text2 are empty and
you press the tab button on the keyboard to move on to Text2 then you will
almost certainly end up in a loop. The immediate window will display a
continuous run of something along the lines of
I should point out at this stage that this sequence of events
is only an approximation of the true order of processing. In reality Windows
does not guarantee the order in which messages are processed. When I was
performing my own tests for this article (under Windows NT 4) there was nothing
else of note taking place on the machine. However different load conditions,
different versions of Windows, or even the fact that a butterfly just flapped
its wings in the South American jungle could slightly alter the dynamics of
this message queuing. Having emaphasised this point, the likely order of
processing can be demonstrated by removing the If..EndIf block of code from the
Text2_LostFocus routine. A tab action from the Text1 control (again, empty)
will probably just show the following four messages:
Understanding the nature of the ordering that takes place here
can be very useful in resolving the type of looping problems that I described
above.
The new Validate event
As a means of helping the developer to overcome the problems
described above, the Visual Basic team has introduced the Validate event. This
event is designed to run before the control loses focus, thereby preventing the
need to place a SetFocus call into our code. The syntax for the event is
defined as
Private Sub object_Validate(KeepFocus As Boolean)
The KeepFocus argument (called Cancel in the actual code
declaration) is the means by which you can prevent the focus from being lost.
If the validation fails then set this value to True and the focus wont go
anywhere. A simple piece of code to demonstrate this use could be:
Private Sub Text1_Validate(Cancel As Boolean)
If Text1.Text = "" Then
Debug.Print "Text1 validation failed"
Cancel = True
End If
End Sub
The firing of the Validate event is governed by a property
called CausesValidation. This property, however, is relevant on the other
controls on the form, specifically on the control that the user attempts to
shift focus to. If the CausesValidation property on the second control is set
to True then the Validate event on the first control will fire; on the other
hand if the property is set to false then the event wont fire. This
property is get/let and is defined as
Object.CausesValidation [ = boolean ]
To use this combination properly all data controls would
probably have the CausesValidation property set to True (the default value). As
the user tabs from one field to the next the contents of the current field can
be properly validated before the actual focus changes. However any other
controls, such as a Help command button, should have the CausesValidation
property set to False. This will allow the requested course of action to take
place without the interference of the validation failure code.
This concept requires just one further discipline on the part
of the programmer to really come together well. The actual validation code
should not reside within each Validate event itself, but rather a call to a
separate validation function would be more efficient. This is because the new
approach does not guarantee that all controls will have been subject to its
respective validation routine if the user entered a value, pressed Help,
and then pressed OK the Validate routine will not have fired. Therefore it will
be sensible to design a means of also calling the various validation routines
from the OK button before the data is committed to ensure that everything is
correct.
Graphics Server review
Arguably one of the few "core" third party products
within the Visual Basic world, its a refreshing fact that Graphics Server
is actually written by a UK company, Bits Per Second, rather than an American
one. The product offers a wider and more flexible range of graph types than the
Microsoft Chart control that is supplied as standard with Visual Basic. For
example, I was recently writing a front-end tool that displays the status of a
set of SQL Server databases. It was my intention to offer a Properties option
via a right mouse click that would show a 3D pie chart showing the amount of
device space used and remaining. The standard chart control only offers 2D
charts and so the result looked rather flat, especially when compared with a
Drive Properties dialog when using the Windows Explorer. Using Graphics Server
would, of course, have been one solution to this problem.
The current edition, version 5, offers direct support for
quite a few languages so a fair few redistributable component types are
provided. As well as the OCX control that most Visual Basic programmers would
expect there is a DLL version, a C++ class, a Delphi VCL, and a FoxPro FLL. All
of these components come in 16 and 32-bit form (there is a 16-bit VBX version
too). There is also support for both client and server side Internet
applications. All of these come as part of the one product, so there is no need
to buy a separate version of the product for each development language. For
each of these languages there are plenty of sample projects that illustrate
coding for different graph types.
To use the control within the IDE after the developers kit has
been installed, check the "Pinnacle-BPS Extended Graph" entry in the
Project, Components dialog. Once the new control is added to the toolbox it can
be dragged onto a form as normal. A custom properties dialog for the control
displays numerous tabs that highlight the many aspects of functionality that
the product offers. The control is data aware and can be bound to the standard
Data Control. Once a connection is made the resulting chart will be able to
automatically update itself if the underlying data changes. There is also a
large library of functions that can be called to create, show, and manipulate
graphs programmatically.
In addition to the graph types supported by the Microsoft
Chart control, Graphics Server offers 3D pie charts, surface graphs (see Figure
1 for an example), time-series graphs, scatter graphs, open-high-low-close
("Wall Street") graphs, bubble graphs, and...Well, you get the idea.
To illustrate the positioning of the product within the development community,
the American Visual Basic Programmers Journal readership has consistently voted
Graphics Server as the best graphing tool for the past seven years.
Do I have any criticisms? Well yes, a couple of minor ones,
but both of these are being fixed in the next release. First, the printed
documentation, although comprehensive, is a little untidy in that you are
provided with two version 4 manuals, two version 4.5 addendum manuals, and a
version 5 addendum. On this matter I have been informed that the next release
will contain a proper "version 6" set of manuals. My second point is
that whenever your application makes use of the graphics server engine a
Graphics Server button appears on the Windows taskbar. Clicking the button does
not bring up a window of any kind and is therefore, I would argue, an incorrect
design feature as it is closer to being a service than an application. Bits Per
Second apparently accept this point because the next version will instead
display an icon in the system tray area of the taskbar, which is the correct
location for a service that wishes to show its presence.
As I mentioned there will soon be a version
6 which, at the time of writing, is due for release around January.
Features include full compatibility with Visual Studio 6, and
enhancements to the documentation, help files, samples, and the
installation routine. Also, there will be improvements to the
graphing engine itself in the form of increased data precision,
improved printing, user-defined colour palettes, and improved
GIF and JPG image handling. Further details on the product can
be found at http://www.contemporary.co.uk
It is available from most UK software resellers, priced at £245
+ VAT. My thanks to Contemporary Software for the review copy.
