Saturday, December 26, 2009

Type function

The TypeName function

The TypeName function returns the name of an object’s class in the form of a string. This means that you can find the type of an object in a more concise form, as follows:
Print "P1 is of type " & TypeName(P1)
In many situations, testing an object’s type using the TypeName function is preferable to using the TypeOf...Is statement because it doesn’t require that the object class be present in the current application or in the References dialog box.
ByVal and ByRef keywords
The fact the object variables are just pointers can puzzle many a programmer when object variables are passed to a procedure as ByVal arguments. The familiar rule—a procedure can alter a ByVal value without affecting the original value seen by the caller—is obviously void when the value is just a pointer. In this case, you’re simply creating a copy of the pointer, not of the instance data area. Both the original and the new object reference are pointing to the same area, so the called procedure can freely read and modify all the properties of the object. If you want to prevent any modifications of the original object, you must pass the procedure a copy of the object. To do so, you must create a new object yourself, duplicate all the properties’ values, and pass that new object instead. Visual Basic doesn’t offer a shortcut for this.
That said, you need to understand that there’s a subtle difference when you declare an object parameter using ByRef or ByVal, as this code snippet demonstrates:
Sub Reset(pers As CPerson) ‘ ByRef can be omitted.
Set pers = Nothing ‘ This actually sets the original
End Sub ‘ variable to Nothing.

Sub Reset2(ByVal pers As CPerson)
Set pers = Nothing ‘ This code doesn’t do anything.
End Sub
When you pass an object using ByVal, its internal reference counter is temporarily incremented and is decremented when the procedure exits. This doesn’t happen if you pass the object by reference. For this reason, the ByRef keyword is slightly faster when used with objects.
The Class_Terminate Event
Visual Basic fires the Class_Terminate event one instant before releasing the data instance block and terminating the object’s life. You usually write code for this event when you need to undo things that you did at initialization time or during the life of the instance. Typically in this event procedure, you close any open files and release Windows resources obtained through direct API calls. If you want to make the object’s properties persist in a database for a future session, this is where you usually do it. All in all, however, you’ll rarely write code for this event or at least you’ll need it less frequently than code for the Class_Initialize event. For example, the CPerson class module doesn’t actually require code in its Class_Terminate event procedure.
On the other hand, the mere fact that you can write some executable code and be sure that it will be executed when an object is destroyed opens up a world of possibilities that couldn’t be exploited using any other, non-OOP technique. To show you what I mean, I’ve prepared three sample classes that are almost completely based on this simple concept. It’s a great occasion to show how you can streamline several common programmer tasks using the power that objects give you.
Caution Visual Basic calls the Class_Terminate event procedure only when the object is released in an orderly manner—that is, when all references pointing to it are set to Nothing or go out of scope, or when the application comes to an end. This includes the case when the application ends because of a fatal error. The only case when Visual Basic does not invoke the Class_Terminate event is when you abruptly stop a program using the End command from the Run menu or the End button on the toolbar. This immediately stops all activity in your code, which means that no Class_Terminate event will ever be invoked. If you inserted critical code in the Terminate events—for example, code that releases Windows resources allocated via APIs—you’ll experience problems. Sometimes these are big problems, including system crashes. By the same token, never terminate a program using an End statement in code: This has exactly the same effect, but it’s going to create problems even after you compile the application and run it outside the environment.

Example 1: managing the mouse cursor
Programmers commonly change the shape of the mouse cursor, typically to an hourglass, to inform the user that some lengthy operation is going on. Of course, you also have to restore the cursor before exiting the current procedure; otherwise, the hourglass stays visible and the user never realizes that the wait is over. As simple as this task is, I’ve found that a good number of commercial applications fail to restore the original shape under certain circumstances. This is a clear symptom that the procedure has exited unexpectedly and therefore missed its opportunity to restore the original shape. How can classes and objects help you avoid the same error? Just have a look at this simple CMouse class module:
‘ The CMouse class – complete source code
Dim m_OldPointer As Variant

‘ Enforce a new mouse pointer.
Sub SetPointer(Optional NewPointer As MousePointerConstants = vbHourglass)
‘ Store the original pointer only once.
If IsEmpty(m_OldPointer) Then m_OldPointer = Screen.MousePointer
Screen.MousePointer = NewPointer
End Sub

‘ Restore the original pointer when the object goes out of scope.
Private Sub Class_Terminate()
‘ Only if SetPointer had been actually called
If Not IsEmpty(m_OldPointer) Then Screen.MousePointer = m_OldPointer
End Sub
Not bad, eh? Just eight lines of code (not counting comments) to solve a recurring bug once and for all! See how easy it is to use the class in a real program:
Sub ALengthyProcedure()
Dim m As New CMouse
m.SetPointer vbHourglass ‘ Or any other pointer shape
‘ ... slow code here ... (omitted)
End Sub
The trick works because as soon as the variable goes out of scope, the object is destroyed and Visual Basic fires its Class_Terminate event. The interesting point is that this sequence also occurs if the procedure is exited because of an error; even in that case, Visual Basic releases all the variables that are local to the procedure in an orderly fashion.


• Sequential files can handle both text data and variable values. Sequential access is best when dealing with files that have lines with mixed information of different lengths. I use them to transfer data between applications.

We first look at writing values of variables to sequential files. The first step is to Open a file to write information to. The syntax for opening a sequential file for output is:
Open SeqFileName For Output As #N
where SeqFileName is the name of the file to open and N is an integer file number. The filename must be a complete path to the file.
• When done writing to the file, Close it using:
Close N
Once a file is closed, it is saved on the disk under the path and filename used to open the file.
• Information is written to a sequential file one line at a time. Each line of output requires a separate Basic statement.
• There are two ways to write variables to a sequential file. The first uses the Write statement:
Write #N, [variable list]
where the variable list has variable names delimited by commas. (If the variable list is omitted, a blank line is printed to the file.) This statement will write one line of information to the file, that line containing the variables specified in the variable list. The variables will be delimited by commas and any string variables will be enclosed in quotes. This is a good format for exporting files to other applications like Excel.
Example
Dim A As Integer, B As String, C As Single, D As Integer
.
.
Open TestOut For Output As #1
Write #1, A, B, C
Write #1, D
Close 1
After this code runs, the file TestOut will have two lines. The first will have the variables A, B, and C, delimited by commas, with B (a string variable) in quotes. The second line will simply have the value of the variable D.
• The second way to write variables to a sequential file is with the Print statement:

No comments:

Post a Comment