It has been my experience that 90 percent of programming occurs within the context of the form. Because the form is so central to Access, I am going to use this article to build and introduce the form class. In my last article, we saw how WithEvents allows us to encapsulate control event processing entirely outside the form’s class module. Instead of keeping event stubs and code scattered across form classes and library functions, using WithEvents moves all this code into the same location–the class that actually uses the events and functions. This makes maintenance much easier.
This article will take the next step and show how to encapsulate the form’s event processing in a class. Form event processing is the first time, but certainly not the last, where we will see a whole system of events working together to get something done.
As many of you know, I am an advocate of the framework concept. The word ‘framework’ means many different things to different people, but to me it means a system of code that forms the skeleton of an application. We take the framework, already built up and functioning, and then hang the pretty stuff and specific functionality on it to make one form look and act differently from the next.
One of my guidelines when building an application is that controls should look and act the same form to form and even application to application. Buttons to close the form should always look the same, perhaps always use the door symbol, and should always be located in a consistent location. Pick a spot, perhaps the upper left corner—I don’t care where—but put it there in every form. Don’t make the user hunt all over the screen to find the button to close the form.
If you use a system where you load the form with a set of records and allow the user to move through those records, you probably use some sort of record selector. That record selector, if it exists, should be located in the same place, be a consistent color, and work in a consistent manner. Don’t make the user search all over the form trying to figure out which control is the record selector.
Some people like to use the combo to display a list of choices for a given field. These choices usually come from a table, and we need a method of adding new data to these tables. If you are going to use a double click in the combo, do so everywhere, or at least pop up a message to tell the user why there is no double click available.
A consistent user interface is the key to learning to use the application. The framework is the key to a consistent user interface. In the following article, “A Form Class Demo,” I am going to show you how to search for and find controls that use a naming convention to tell the framework what they do.
I will build a command button to close the form. By naming the control cmdClose, I can have the form search itself for a control by that name and, if it exists, hook its click event and make it the close button. I will build a record selector control pair that again uses a naming convention. The form searches for the control and, if found, loads a class to make it work.
These are examples of how the framework makes it easy for the developer to set up a consistent user interface. You don’t have to worry about adding code to your forms to use a record selector. Just drop the control on your form and name it something consistent. The framework does the rest. You are no longer trying to remember what events this control uses to do its magic, or what function gets called from that event, and you’re not cluttering up your form’s class module with all the code to do this stuff.
Frameworks are fun to use and allow us to turbo charge Access’s Rapid Application Development environment. The form class is the center of the framework, at least for the portion that deals with forms.
For those interested, I did a little testing on the impacts of using classes, both in memory usage and time to open and close. I have included the form that I used for these tests in this article’s zip file in case you want to run the tests yourself.
I chose to test the timer class, simply because it contains the entire overhead of any other class—the variables and structures used to setup and tear down the class. It also uses the same method of instantiating and destroying itself as all the other classes. At the same time it has a very low additional overhead—variables and methods specific to the class. Furthermore, it doesn’t require that any controls be present to use it. These attributes make it a perfect base class to use as a test of what other classes might look like.
I built a form that opens 10,000 instances of the timer class. I timed how long the 10,000 instances take to open and displayed the time in a msgbox. I also timed how long it takes to destroy all the class instances and displayed that time in a msgbox.
I also opened the task manager and recorded how much memory was available as the form opened, and how much was available after the form opened. Thus the memory impact includes the memory required for the form itself.
The numbers were as follows:
· 4.453 seconds to open 10,000 instances. This means that each instance requires ~ .5 millisecond to instantiate. Since I bracketed the times to load with the timer code, this time excludes the form opening time.
· 7.766 seconds to destroy 10,000 instances, ~ .7 milliseconds per instance.
Memory usage was as follows:
· 109000 k before opening the form; 10500k after opening the form. This means that 10,000 instances of the timer class required 4 mb of memory, or 400 bytes per instance of the class. This memory total also includes the memory used for the form itself, however.
One caveat here: I chose the simplest class to test, which means that most classes will have some additional overhead for other code and variables to load and initialize.
From my perspective, this testing validates that classes have a minimal impact on both memory and load time. If I have a very complex form which requires 100 class instances, the additional time required to instantiate the class would be a mere 50 milliseconds and require an additional 40 kbytes of memory. For my purposes, this is very acceptable.
One other note: When I turned on debug printing of the form’s initialization, the class’s instantiation time jumped by 10 times. So do be careful to turn off the debug printing before distribution by using the constant at the top of each class module.
John
Colby©2001
May be distributed as long as the copyright remains.
John
Colby Bio