Jeff Webb, Mike McKelvy, Ronald Martinsen, Taylor Maxwell, Michael Regelski September 1995 Special Edition Using Visual Basic 4 - Chapter 18 1-56529-998-1 Computer Programming computer programming Visual Basic OLE database applications ODBC VB VBA API This book is an all-in-one reference that provides extensive coverage of every topic and technique for creating optimized and customized applications with Visual Basic.

Chapter 18

Creating Objects


Packaging your modules as objects with properties and methods is a natural way to expand Visual Basic's capabilities. You can create objects for use within a single project, or make those objects available to other applications through OLE Automation.

In this chapter, you learn how to do the following:


To create OLE Automation objects, you first must have Visual Basic Professional or Enterprise Edition. Although you can create objects with the Standard Edition, you can use those objects only within the current project.

Overview of Objects

With Visual Basic, you can create your own objects that have properties and methods. Each object is contained in a module, the name of which identifies the object. Visual Basic now has three types of modules: code modules, form modules, and class modules.

Code modules now support object-style syntax. For example, the following line calls the Average function in Module1:

x = Module1.Average(98, 22, 45, 67, 876)

MODULE1.BAS defines the Average function as a procedure, as follows:

' MODULE1.BAS
' Average method, returns the average of a series of numbers.
' Note the use of the ParamArray argument -- this procedure takes
' any number of arguments.
Function Average(ParamArray x())
' Using each element in the array x()...
For Each vCount In x
' Add the value to a running total.
temp = temp + vCount
Next vCount
' Return the average.
Average = temp / (UBound(x) + 1)
End Function

Module1.Average's syntax looks just like that of an object reference, with one significant difference: instances. Code modules have one static instance that the application creates on startup. Form and class modules can have multiple instances with separate storage for each.

You can use objects within a single project, or across projects as OLE Automation objects. You use different types of modules to define different types of objects, as shown in table 18.1.

Table 18.1 Module Types and Their Uses

Module Type Default Name Use
Code module Modulen Defines procedures, variables, and constants for use within the current project. Code modules don't usually have a visual interface.
Form module Formn Defines a visible object for use within the current project.
Class module Classn Defines an object for use by the current application or other applications and projects. Class modules enable other applications to control the current application as an OLE Automation object.

Objects that you define in code modules and form modules are called internal objects, because you use them within the project in which you defined them. Objects that you define in class modules are called OLE Automation objects, because they are available to other projects and applications through OLE Automation.

Creating and Using OLE Automation Objects

Class modules are perhaps the most interesting type of module for creating objects, because they are available to other projects and applications through OLE Automation. Class modules enable you to create compiled libraries of code that you can use in the current project or other applications. Class modules have two properties not found in code and form modules:

You set the Instancing and Public properties in the class module's Properties window, as shown in figure 18.1.

Fig. 18.1

Use the class module's Instancing and Public properties to make an object available to other applications.

Creating Your First OLE Automation Object

To create an OLE Automation object, follow these steps:

  1. Create a new project.
  2. Choose Insert, Class Module. Visual Basic adds a new class module to your project.
  3. Create a simple method by adding the following lines of code to the class module:

    Sub AddText(Text)
    Form1.Print Text
    End Sub

  4. Right-click on the class module window and choose Properties. You should change the Instantiating property to Creatable SingleUser and the Public property to True.
  5. Choose Tools, Options. In the Project tab of the Options dialog box, set Startmode to be OLE Server.
  6. Choose File, Make EXE File. Visual Basic compiles the project.
  7. From Windows, run the .EXE file that you just created. Running the file outside of Visual Basic registers the application with your system registration database to make it available to other applications.

Using the Object from Another Application

To use the OLE Automation object that you created in the preceding section, follow these steps:

  1. Create a new project in Visual Basic.
  2. Add a text box and a command button to Form1.
  3. Add the following lines of code to the command button's Click event procedure:

    Private Sub Command1_Click()
    Dim x As Object
    Set x = CreateObject("Project1.Class1")
    x.AddText Text1
    End Sub

  4. Press F5 to run the project in Visual Basic.


If your OLE Automation object doesn't recognize methods and properties that you've just defined, check to ensure that you are running the right version of the object. When debugging, you can easily load the .EXE version accidentally rather than the new version that Visual Basic hasn't yet compiled. To avoid this, be sure to use GetObject in your container application and start the OLE Automation application in the other instance of Visual Basic before calling the object from the container application.

When you click the Command1 button on Form1, the CreateObject function starts the OLE Automation object application, PROJECT1.EXE, and returns a reference to the Class1 object. The AddText method then places the text in the Text1 text box on the OLE Automation object's form, as shown in figure 18.2.

Fig. 18.2

Running the simple OLE Automation object from another application.

Finding the String That Works with CreateObject and GetObject

To identify OLE Automation objects to other applications, you use a string called a programmatic identifier or ProgID. The CreateObject and GetObject functions use this string to query the system registration database to find the application.

For OLE Automation objects, the programmatic identifier consists of the name that you enter in the Project Options dialog box's Project Name text box and the name of the class module that defines the object. Figure 18.3 shows this relationship.

Fig. 18.3

The string that you use with CreateObject and GetObject consists of the project name and the class module name.

Visual Basic registers programmatic identifiers for all class modules that have their Instancing property set to Creatable Single Use or Creatable MultiUse. Therefore, a project with more than one creatable class has multiple entries in the registration database.

Visual Basic doesn't register applications permanently until you run the application outside of the programming environment. When you run the application within Visual Basic, it creates a registration entry in a temporary area that Visual Basic controls. Figure 18.4 shows the difference between permanent and temporary entries in the system registration database.

Fig. 18.4

Visual Basic adds a temporary registration entry when you debug an OLE Automation object. After you build the .EXE file and run the application, the entry becomes permanent.

Creating and Using Internal Objects

Objects defined in forms, procedures, and code modules are available only within the current project. Using a method from an internal object isn't any different from using a procedure defined in the module. The following code lines show alternative syntax for calling the Average() procedure in Module1:

' Object syntax: call Average as method.
MsgBox Module1.Average(12, 3, 4, 54)
' Old-style syntax: call Average as function.
MsgBox Average(12, 3, 4, 54)

Both object and old-style syntax display the same result. However, using object syntax gives you a few advantages over the old syntax:

Code Modules versus Form Modules

Code modules aren't truly objects. However, objects defined in a form module are full-blown objects. Thus you can use form modules, but not code modules, in any statement or function that takes an object reference. Examples of such statements and functions include the following:

Another major difference is that forms have a built-in visual interface (the form) and modules don't. Use form modules for objects that have an appearance or that you need to use as objects with the preceding statements. Use code modules to perform general support tasks, such as mathematical operations.

Code and Form Modules versus Class Modules

Class modules provide the external interface that a project exposes to other applications. Code and form modules define the properties and methods used internally in the project. Without the class modules to act as the connection point, different programs could not communicate.

Naming Objects

You identify objects by their module name. By default, Visual Basic names modules based on their module type�Form1, Module1, Module2, Class1, and so on. Instead of relying on these default names, you should carefully choose descriptive names for your objects, just as you would for the procedures, variables, and other symbols in your project.

The object names that you choose should be as obvious as possible. For instance, an application that provides one OLE Automation object might name the object "Application." A project that uses many internal objects might have its own object-naming convention, using such prefixes as mod, frm, and cls to identify the type of object. Although naming objects is a subjective process, there are a few OLE conventions to follow. Chapter 20, "Designing Object Libraries," discusses OLE naming guidelines for objects.

To change the name of a module, follow these steps:

  1. In the project window (fig. 18.5), double-click on the module that you want to rename. For form modules, Visual Basic displays the form. For code and class modules, Visual Basic displays the module's code windows.

Fig. 18.5

Select the module to rename in the project window.

  1. Press F4. Visual Basic displays the module's Properties window as shown in figure 18.6.

Fig. 18.6

Use the Properties window to rename a module.

  1. Type the new module name in the Name property box.

Creating Methods and Properties

As mentioned previously, you can use module names when calling procedures in Visual Basic. For example, the following code line displays the result of the Average() function in Module1:

MsgBox Module1.Average(1, 12, 31, 44, 15)

This line is syntactically identical to the Pmt method in the Visual Basic for Applications (VBA) object library:

MsgBox VBA.Pmt(.07 / 12, 360, -70000, 0, True)

In fact, a module's Sub and Function procedures are equivalent to an object's methods. Like Function procedures, methods that return values enclose their arguments in parentheses, as in the preceding example. Like Sub procedures, methods that don't return values omit the parentheses. The following two lines demonstrate methods that don't return values:

Module1.Swap arg1, arg2
Form1.Move 1, 1, 90, 90

You use special Property procedures to create properties for an object. Table 18.2 describes the different types of procedures that you use when creating objects.

Table 18.2 Types of Procedures That Objects Use

Procedure TypeUse
Sub Defines methods that don't return a value
Function Defines methods that return a value
Property Get Returns a property's value
Property Let Assigns a property's value
Property Set Sets the property to a reference to an object

Creating Read/Write Properties

Properties can have one or all three types of property procedures. Usually, properties have both a Property Get and Property Let procedure. Listing 18.1 shows a pair of property procedures that define the NumLock property:

Listing 18.1 Two Property Procedures That Define the NumLock Property

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Module Keyboard
' File: 18LIST01.TXT
' Declare Windows API calls used to get and set keyboard states.
Declare Sub GetKeyboardState Lib "USER32" (lpKeyState As Any)
Declare Sub SetKeyboardState Lib "USER32" (lpKeyState As Any)
' The index for the NumLock key in the 256-byte lpKeyState array.
Const VK_NUMLOCK = vbKeyNumLock
' Returns the state of the NumLock key: True = on, False = Off
Property Get NumLock() As Boolean
' Create an array to hold key states
' (256 bytes = 128 integers)
Dim lpbKeyState(128) As Integer
' Get key state settings.
GetKeyboardState lpbKeyState(0)
' Check the VK_NUMLOCK element of the array.
If (lpbKeyState(VK_NUMLOCK / 2)) Then
NumLock = True
Else
NumLock = False
End If
End Property
' Changes the state of the NumLock key: True = on, False = off
Property Let NumLock(bState As Boolean)
' Create an array to hold key states
' (256 bytes = 128 integers)
Dim lpbKeyState(128) As Integer
' Get key state settings.
GetKeyboardState lpbKeyState(0)
' If the current state is the same as the bState,
' then no change needed.
If lpbKeyState(VK_NUMLOCK / 2) And bState Then Exit Property
' Otherwise, set the correct value in the array.
If bState Then
lpbKeyState(VK_NUMLOCK / 2) = 1
Else
lpbKeyState(VK_NUMLOCK / 2) = 0
End If
' Set the keyboard state.
SetKeyboardState lpbKeyState(0)
End Property

You use a property procedure the same way that you use object properties. The following code lines display the Num Lock key state and then turn on the Num Lock key:

Sub UseNumLock()
' Get property
MsgBox Keyboard.NumLock
' Set property.
Keyboard.NumLock = True
End Sub

Creating a Read-Only or Write-Only Property

To create a read-only property, create Property Get procedure for the property and omit the Property Let procedure. The following code shows a read-only SystemDirectory property that returns the Windows system directory:

' Environmental Windows functions
Declare Function GetSystemDirectory Lib "KERNEL" (ByVal _
lpBuffer As String, ByVal nSize As Integer) As Integer
Property Get SystemDirectory() As String
Dim lpBuffer As String * 256
iLen = GetSystemDirectory(lpBuffer, 256)
If iLen Then
SystemDirectory = Mid$(lpBuffer, 1, iLen)
Else
SystemDirectory = ""
End If
End Property

You can read the new SystemDirectory property, but you cannot set it. The following assignment statement causes a "Procedure type mismatch" error:

Sub TestSystemDirectory()
' Display SystemDirectory
MsgBox SystemDirectory
' Set SystemDirectory (causes procedure type mismatch error)
SystemDirectory = "c:\win\system"
End Sub

"Procedure type mismatch" is not a trappable error; that is, you cannot handle such an error in code. To be a little kinder to your application's users, define a Property Let procedure that triggers an error, as in the following example:

Property Let SystemDirectory(s As String)
' Error 383 is the same error that VB displays
' when you try to set a read-only property.
Err.Raise 383
End Property

You can trigger any error value with the Error statement. Error 383 is the error code that Excel returns when you try to assign a value to one of its read-only properties.

To create a write-only property, define a Property Let procedure and omit (or return an error for) the Property Get procedure. Write-only properties are far less common than read/write and read-only properties.

Creating Object Properties

Properties that contain objects have Property Get and Property Set procedures. As you might expect, working with objects is more complicated than setting or returning simple values. Listing 18.2 shows procedures that demonstrate four common operations:

Listing 18.2 Creating Object Properties

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Document form module.
' File: 18LIST02.TXT
' This is the code for a form named "Document" containing an
' OLE container control named oleWord.
'
' Internal variable for WordBasic object.
Private mobjBasic As Object
Function Create(x1, y1, x2, y2) As Object
' Add a Word object to an OLE container object on a form.
With Me.oleWord
' Create the embedded object
.CreateEmbed "", "Word.Document"
' Set the position and size.
.top = x1
.left = y1
.Width = x1 - x2
.Height = y2 - y1
' Set the Basic property of the Word object
Set Document.SetBasic = _
oleWord.OLEObjects(.Index) _
.Object.Application.WordBasic
' Return the object that was created
' (same behavior as Excel's Add methods)
Set Create = oleWord.OLEObjects(.Index)
End With
End Function
Private Property Set SetBasic(obj As Object)
' Check if this is a WordBasic object.
If TypeName(obj) = "wordbasic" Then
Set mobjBasic = obj
Else
Err.Raise 1005
End If
End Property
Property Get Basic() As Object
' If there is an object in mobjBasic.
If IsEmpty(mobjBasic) = False Then
' Return the WordBasic object.
Set Basic = mobjBasic
Else
' No current object, trigger
' "Unable to get property" error (same as Excel uses).
Err.Raise 1006
End If
End Property
' Optional, let users assign an object to the object variable.
Property Let Basic(obj As Object)
' Delegates to SetBasic().
Set SetBasic = obj
End Property

The TestObject() procedure demonstrates how to use the Property Get Basic procedure:

Sub TestObject()
Basic.Activate
' Create an embedded document.
With Document.Create(1, 1, 100, 100)
.Activate
' Get the Basic property and call Word's Insert method.
.Basic.Insert "Some text"
End With
End Sub

The AssignObject() procedure demonstrates how to use the Property Let Basic procedure to set an object reference with assignment rather than using the Set statement:

Sub AssignObject()
' Set an object reference using property assignment.
Basic = Me.oleWord.Object.Application.WordBasic
End Sub

You might not want to let users create object references by using assignment. You simply determine which is clearer: allowing assignment, requiring the Set statement, or prohibiting the setting of references altogether.

Adding OLE Automation Objects to Existing Projects

One of the fastest ways to get up and running with OLE Automation is to add a class module to an existing application. To do so, follow these steps:

  1. Change to Public the declarations of selected event procedures in an application.
  2. Create a set of methods and properties in a class module that call the newly Public event procedures.
  3. Change the Project Property settings to generate an OLE server.
  4. Compile the application and run the .EXE file to register the application in the system registration database.

The following sections describe each of these steps in greater detail, using the VB Terminal (VBTERM.VBP) sample application included on the Visual Basic distribution disks.

Making Form Event Procedures Public

To make the VB Terminal sample application an OLE Automation object that you can use from other applications, you must change event procedures declarations in VBTERM.FRM from Private to Public. This change enables you to call the event procedures from the class module that provides the OLE Automation object that other applications use.

To change the VB Terminal event procedure declarations to Public, follow these steps:

  1. Load the project VBTERM.VBP in Visual Basic.
  2. In the project window, select the form file VBTERM.FRM and click the View Code button.
  3. Change each of the Private declarations to Public, as follows:

    Public Sub MDial_Click()
    Public Sub MHangup_Click()

    For now, you need only change these declarations. The other event procedures can remain Private.

  4. Save the project.

You use these Public event procedures in the next section.

Calling Form Events from a Class Module

After making it possible to call the crucial event procedures from outside a form, you can create a class module to repackage those procedures as methods. To create a class module for VB Terminal, follow these steps:

  1. Choose Insert, Class Module. Visual Basic displays a new class module and adds it to the project.
  2. Press F4. Visual Basic displays the Properties window for the class module.
  3. Change the instancing to Creatable SingleUse, the Name property to Application, and the Public property to True, as shown in figure 18.7.

Fig. 18.7

Change the Name and Public properties of the new class.

  1. Select the code window for the class module and enter the following lines:

    ' Dial method -- same as clicking the Dial Phone Number
    ' menu item in the user interface.
    Sub Dial()
    Form1.MDial_Click
    End Sub
    ' Hangup method--same as clicking the Hangup Phone menu
    ' item in the user interface.
    Sub HangUp()
    Form1.MHangup_Click
    End Sub

  2. Save the project.


If you have Visual Basic Professional Edition but get an error message when you try to create a Public class module, your installation might be corrupt. Try reinstalling the Visual Basic development environment.

Running and Using the New OLE Automation Object

After making event procedures Public and creating a class module to call those event procedures, you can run and test VB Terminal as an OLE Automation object. To run VB Terminal as an OLE Automation object, follow these steps:

  1. Choose Tools, Options. Visual Basic displays the Options dialog box. Choose the Project tab as shown in figure 18.8.

Fig. 18.8

The Project tab of the Options dialog box enables you to change the project name and select the StartMode.

  1. In the Project Options dialog box, change the entry in the Project Name text box to VBTerminal and select the OLE Server option button in the StartMode group. The project name identifies the application through OLE Automation. The StartMode tells Visual Basic to watch for OLE Automation requests from another instance of Visual Basic. Click OK to close the Options dialog box.
  2. Save the project.
  3. Run the project.
  4. Start another instance of Visual Basic. You need to have two instances of Visual Basic running at the same time so that you can step through code in both the OLE Automation object application and the container application that uses the object.
  5. In the new instance of Visual Basic, write some code to test the VB Terminal OLE Automation object. The following code is a sample of a simple test:

    ' Declare a module-level variable for the OLE Automation
    ' object being tested.
    Dim objVBTerm As Object
    Private Sub Command1_Click()
    ' Get a reference to the VB Terminal application
    Set objVBTerm = GetObject("", "VBTerminal.Application")
    ' Call the Dial method.
    objVBTerm.Dial
    End Sub

  6. Run the test code. You might want to step through the test procedure and use the Immediate window to test the other methods.

When you are satisfied with the VB Terminal OLE Automation object, you can build it as an .EXE file and test it outside of the Visual Basic environment.

To build and test the VB Terminal application as an .EXE file, follow these steps:

  1. Stop the test application and the VB Terminal application in both instances of Visual Basic.
  2. In the instance of Visual Basic that contains VB Terminal, choose File, Make EXE File. Visual Basic displays the Make EXE File dialog box (see fig. 18.9).

Fig. 18.9

Building an OLE Automation .EXE file is the same as for any other project.

  1. Click OK to compile the project into an .EXE file.
  2. In the Windows File Manager, run the .EXE file that you just created. You must run the application to register it with the system registration database.
  3. Close the VB Terminal application.
  4. Change the test code that you used previously so that it ensures that the VB Terminal application is registered. The following code runs VB Terminal from the .EXE file:

    ' Declare a module-level variable for the OLE Automation
    ' object being tested.
    Dim objVBTerm As Object
    Private Sub Command1_Click()
    ' Start the VB Terminal application
    ' and get a reference.
    Set objVBTerm = CreateObject("VBTerm.Application")
    ' Call the Dial method.
    objVBTerm.Dial
    End Sub

  5. Run the test code. The CreateObject method starts the VB Terminal application if it is not already running. This differs from the previous example, which used GetObject to get the VB Terminal application running in another instance of Visual Basic.

Running the .EXE file reregisters the application in the system registration database. This reregistration maintains the registration entry even if the user moves or renames the file. In some cases, you must rerun the application outside of Visual Basic to get CreateObject to work after changes to the OLE Automation object.

Refining the OLE Automation Object

The methods defined so far for VB Terminal are quite simple: they merely repackage existing event procedures without adding any more logic. The limitation of defining such simple methods is that the interface is not as programmable as you might want it to be. For instance, the Dial method displays an input box to get the phone number, whereas a more useful technique is to enable Dial to accept a phone number argument.

The next few sections refine the VB Terminal OLE Automation object by adding or modifying the following features:

With these additional or modified features, VB Terminal becomes quite useful to other applications.

Adding a Phone Number Argument to the Dial Method

The Dial method calls the MDial_Click event procedure in VBTERM.FRM, which displays an input box. This call isn't necessary if Dial has a phone number argument. To add a phone number argument to Dial, you must modify the VBTERM.FRM and APPLICAT.CLS files.

The first change is to split the MDial_Click event procedure into two procedures, as shown in listing 18.3.

Listing 18.3 Splitting the MDial Click Event Procedure

' 18LIST03.TXT
Public Sub MDial_Click()
On Local Error Resume Next
Static Num$
' Get a number from the user.
Num$ = InputBox$("Enter Phone Number:", "Dial Number", Num$)
If Num$ = "" Then Exit Sub
' Call new DialNumber procedure.
DialNumber Num$
' Move to new DialNumber procedure. -- comment out here.
' Open the port if it isn't already open.
'If Not MSComm1.PortOpen Then
' MOpen_Click
' If Err Then Exit Sub
'End If
' Dial the number.
'MSComm1.Output = "ATDT" + Num$ + Chr$(13) + Chr$(10)
End Sub
' New procedure bypasses user input for Dial method.
Public Sub DialNumber(Num$)
On Local Error Resume Next
' Open the port if it isn't already open.
If Not MSComm1.PortOpen Then
MOpen_Click
If Err.Number <> 0 Then Exit Sub
End If
' Dial the number.
MSComm1.Output = "ATDT" + Num$ + Chr$(13) + Chr$(10)
End Sub

Next, change the Dial method in APPLICAT.CLS to take an optional argument. If the user omits the argument, call MDial_Click as before; if the user includes the argument, call the new DialNumber procedure. The following code lines show the new Dial method:

Sub Dial(Optional PhoneNumber As Variant)
If IsMissing(PhoneNumber) Then
Form1.MDial_Click
Else
Form1.DialNumber Cstr(PhoneNumber)
End If
End Sub

Adding a PortOpen Property

Knowing whether the comm port is open is important to any application that wants to send a command string directly to VB Terminal. The port's status is also useful if other applications can open or close the port. To provide these features, you should add a read/write PortOpen property to the VB Terminal OLE Automation object.


Deciding whether to provide an item as a property or as a method is often difficult. Usually, properties represent the state of an object and methods represent an action that the object takes.

The following PortOpen property enables other applications to get and set the PortOpen property for the MSComm control on the VB Terminal form:

' PortOpen property
' Read/Write, Boolean
' True if Comm port is open.
' False if Comm port is closed.
Property Get PortOpen() As Boolean
PortOpen = Form1.MSComm1.PortOpen
End Property
Property Let PortOpen(bSetting As Boolean)
Form1.MSComm1.PortOpen = bSetting
End Property

Adding a SendLine Method

Another useful feature to provide is a way to send command strings directly to the VB Terminal application. This feature enables another application to configure the modem by using standard modem commands and to send strings for logging on to services, exchanging data, and so on.

The SendLine method sends a string of characters to the comm port. If the VB Terminal Echo flag is on, the characters echo in the Terminal window; otherwise, the window does not display the characters. The following code is the SendLine method:

' SendLine method.
' Sends a command string to the VB Terminal window.
Sub SendLine(strText As String)
If Form1.MSComm1.PortOpen Then
' Send the line to the comm port.
Form1.MSComm1.Output = strText & Chr$(13)
' If Echo is on, send the string to the
' text box on the VB Terminal form.
If Echo Then
Form1.Term.Text = Form1.Term.Text _
& strText & Chr(13)
End If
End If
End Sub

Adding TrapText and Text Properties

If you want to send commands to VB Terminal, you probably also want it to return information. For these purposes, you must define two related properties: TrapText and Text.

Normally, when VB Terminal receives data from the comm port, that data triggers the OnComm event procedure in VBTERM.FRM. This procedure retrieves the data and clears the buffer. To retrieve this data from another application, you must delay the OnComm event by increasing the threshold value that triggers the event. As listing 18.4 shows, if you set the TrapText property to True, you increase the MSComm control's threshold value to its maximum setting. This setting enables you to retrieve the data in the buffer from another application by using the Text property, which is described next.

Listing 18.4 The TrapText Property

' TrapText property
' Read/write
' True turns on trapping -- Text property
' returns the text from the comm port.
' False turns off trapping -- data received
' from the comm port is passed through to the
' Terminal window via the OnComm event.
Property Let TrapText(bSetting As Boolean)
' If True, set to the current buffer size.
If bSetting Then
Form1.MSComm1.RThreshold = Form1.MSComm1.InBufferSize
Else
Form1.MSComm1.RThreshold = 0
End If
End Property
Property Get TrapText() As Boolean
If Form1.MSComm1.RThreshold <> 0 Then
TrapText = True
Else
TrapText = False
End If
End Property

The Text property (listing 18.5) returns the text that was in the comm port's input buffer. It also echos the received text in the VB Terminal window if Echo is on.

Listing 18.5 The Text Property

' Text property
' Read only.
' Returns the text waiting in the comm port
' input buffer. Display the text in the VB
' Terminal window if Echo is on.
Property Get Text() As String
' Set InputLen to 0 so all data is retrieved.
Form1.MSComm1.InputLen = 0
' Get the data.
Text = Form1.MSComm1.Input
' If Echo is on, display the data in the
' Terminal window.
Form1.Term.Text = Form1.Term.Text _
& Text
End Property

Extending Form Properties

Property procedures provide a good way to extend form display attributes. For instance, you can display a Help window on top of all other windows by choosing Help, Always On Top. To display the window this way with a Visual Basic form, you must call the Windows API function SetWindowPos. This technique isn't elegant, because SetWindowPos takes seven arguments, most of which the function doesn't even use when setting the window to display always on top of all others. A more natural (or BASIC-like) technique is to repackage the SetWindowPos function in an OnTop property.

Listing 18.6 shows the declarations and property procedures that you use to create the OnTop property. When you set the form's OnTop property to True, the form appears on top of all other windows. When set to False, the form displays as it normally does.

Listing 18.6 Setting the OnTop Property

' 16-bit Win API declaration and constants used by OnTop property.
Private Declare Sub SetWindowPos Lib "User" _
(ByVal hWnd As Integer, _
ByVal hWndInsertAfter As Integer, _
ByVal X As Integer, ByVal Y As Integer, _
ByVal cx As Integer, ByVal cy As Integer, _
ByVal wFlags As Integer)
' 32-bit Win API declaration and constants used by OnTop property.
Private Declare Function SetWindowPos Lib "user32" _
(ByVal hwnd As Long, _
ByVal hWndInsertAfter As Long, _
ByVal x As Long, _
ByVal y As Long, _
ByVal cx As Long, _
ByVal cy As Long, _
ByVal wFlags As Long) As Long
Const SWP_NOACTIVATE = &h10
Const SWP_SHOWWINDOW = &h40
Const SWP_NOSIZE = &h1
Const SWP_NOMOVE = &h2
Const HWND_TOPMOST = -1
Const HWND_NOTOPMOST = -2
' Flag used by OnTop property to track window state.
Dim mbOnTop As Boolean
' Assigns the OnTop property.
Property Let OnTop(bSetting As Boolean)
' If True, Form is displayed as always on top.
If bSetting Then
SetWindowPos Me.hWnd, _
HWND_TOPMOST, _
0, 0, 0, 0, _
SWP_NOSIZE Or SWP_NOMOVE _
Or SWP_NOACTIVATE Or SWP_SHOWWINDOW
' Set flag to keep track of window state.
mbOnTop = True
' If False, Form is displayed normally.
Else
SetWindowPos Me.hWnd, _
HWND_NOTOPMOST, _
0, 0, 0, 0, _
SWP_NOSIZE Or SWP_NOMOVE _
Or SWP_NOACTIVATE
' Set flag to keep track of window state.
mbOnTop = False
End If
End Property
' Returns True if the form is displayed as always on top,
' otherwise returns false.
Property Get OnTop() As Boolean
' Return the value of the flag set by Property Let.
OnTop = mbOnTop
End Property

You need only one version of the declare for the SetWindowPos API. Choose the one that you need based on whether you are writing a 16- or 32-bit application.

To see the OnTop property at work, add the preceding code to a form, then set the form's property in code. The following Click event procedure demonstrates turning OnTop on and off:

Private Sub Command1_Click()
Form1.OnTop = Not Form1.OnTop
End Sub

Documenting Objects, Properties, and Methods

You can document your objects, properties, and methods at two levels:

Figure 18.10 shows how to use the Object Browser to display Help for your object, properties, and methods.

Fig. 18.10

The Object Browser.

To document the object's properties and methods in a project, follow these steps:

  1. Choose Tools, Options, and select the Project tab. Visual Basic displays the Project page of the Options dialog box (fig. 18.11).

Fig. 18.11

To find Help for a project's objects, properties, and methods, you can use the Object Browser to search for the file name in the Help File text box of the Project page of the Options dialog box.

  1. Enter the name of the project's Help file in the Help File text box. The same Help file that lists items related to your project's user interface also lists more technical items, such such as programming with objects, properties, and methods.
  2. Choose View, Object Browser. Visual Basic displays the Object Browser dialog box.
  3. Select the item that you want to document and then choose the Options button. Visual Basic displays the Member Options dialog box (see fig. 18.12).

Fig. 18.12

Enter the description and Help context ID in the Member Options dialog box.

  1. In the Description text box, enter the description to display in the Object Browser. In the Help Context ID text box, enter the Help context ID number.
  2. Repeat steps 4 and 5 for each item that you want to document.


To document a class or module, click on the class or module name in the Object Browser in step 4. This deselects the properties and methods in the class or module.

Help for a project's objects, properties, and methods resides in the same Help file as for the rest of the project. When designing your Help file, you should be careful not to confuse users by including highly technical programming topics in the same table of contents used by people seeking Help on your application's user interface.

Restricted Names

You cannot redefine any existing form properties or methods. Therefore, you cannot create Property procedures that use the same name as any form property, and you cannot create any Sub or Function procedures that use the same name as any form method.

This prevents you from changing a form's built-in behavior. For instance, preventing a form's window state from changing in code is sometimes useful. The following Property procedure prevents other procedures from changing a form's window state:

' Intercept calls to the form's WindowState property.
Property Let WindowState(Value)
' Do nothing
End Property

Visual Basic enables you to add this procedure to a form, but when you try to run the project, it causes the error message "Member already exists on this form." The following names are restricted within a form module:

Similarly, Visual Basic reserves about 100 names for its own use. If you try to use these names as identifiers in any module, you get an error with the form "Expected: description", where description is some text describing the keyword's usual use. The following are the names that Visual Basic restricts within any module:

From Here...

In this chapter, you learned about creating objects and the many different facets of using them. You learned about their properties and how to create and use OLE objects from other processes.

To learn more about related topics, see Chapter 19, "Creating Object Collections," which discusses in more detail how to create collections of objects. Collections can be very useful and time saving from a programming point of view.


© 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.