Chapter 29

Writing TAPI-Assisted Applications


CONTENTS


Now that you have a good idea of how the TAPI system is designed, it's time to start writing some TAPI programs! This chapter covers the simplest form of TAPI-the outbound voice-phone call. When you complete this chapter you'll know how to add phone-dialing capabilities to Excel spreadsheets (or any other VBA-compatible system) and you'll build a complete Visual Basic 4.0 online phone book that can store names and numbers, place calls, and log your call history into an Access database for tracking and reporting purposes.

The Assisted Telephony API Calls

Before jumping into the coding routines for Assisted TAPI, it is a good idea to review and test out the two API calls that you'll use throughout the chapter. The two functions you need to work with in order to complete Assisted TAPI calls are:

The TAPI system uses the tapiGetLocationInfo to determine the current country/area code settings when attempting to dial a phone number passed in the tapiRequestMakeCall function. For example, if the code supplied in the call request includes an area code, TAPI will check to see if it matches the current area code. If the two codes match, TAPI will not dial the area code since it is understood that it is not needed to successfully place a call. This means that you can store complete area code information with all your phone numbers in your address book. Just like you, TAPI is smart enough to skip the area code when it's appropriate.

Tip
Although TAPI's ability to strip out area codes is handy, it can cause minor problems. In several areas of the world, phone companies allow local calls across area codes-especially in locations where both parties live close to one another along the "dividing line." In these cases, TAPI will notice the area code difference and attempt to place the call using the area code. This usually results in error tones from the phone exchange. If you are in an area where this occurs, you'll need to leave out area codes from the affected address entries.

tapiGetLocationInfo is a read-only function. You cannot use it to set the current country or area code. However, you can use this function to return the country/area code string to be used as a default in building new entries in an online address book. You'll see how this works later in the chapter.

Testing the Assisted TAPI Functions

For now, let's put together a short project that illustrates the two Assisted TAPI functions you'll use throughout the chapter. You'll need a modem connected to your pc and a telephone handset connected to the same line as the modem. Figure 29.1 shows how the equipment should be connected for all Assisted TAPI calls.

Figure 29.1 : Modem, pc, and phone connections for Assisted TAPI

To test the Assisted TAPI functions, start a new Visual Basic 4.0 project and place buttons on the form. Set the caption of Command1 to Get Info and the caption of Command2 to Place Call. Next add a code module to the project (select Insert | Module from the main menu) and add the code shown in Listing 29.1 to the declaration section of the module.


Listing 29.1. Declaring the TAPI functions.
Option Explicit

'
' declare assisted tapi functions
'
#If Win32 Then
    Declare Function tapiRequestMakeCall Lib "TAPI32.DLL" (ByVal lpszDestAddress As
ÂString, ByVal lpszAppName As String, ByVal lpszCalledParty As String, ByVal ÂlpszComment As String) As Long
    Declare Function tapiGetLocationInfo Lib "TAPI32.DLL" (ByVal lpszCountryCode As ÂString, ByVal lpszCityCode As String) As Long
#Else
    Declare Function tapiRequestMakeCall Lib "TAPI.DLL" (ByVal lpszDestAddress As ÂString, ByVal lpszAppName As String, ByVal lpszCalledParty As String, ByVal ÂlpszComment As String) As Long
    Declare Function tapiGetLocationInfo Lib "TAPI.DLL" (ByVal lpszCountryCode As ÂString, ByVal lpszCityCode As String) As Long
#End If

These are the two Assisted TAPI functions in their 16-bit and 32-bit form. If you are only working in one environment, you can remove the extra code. But, if you plan to use this application code in more than one environment, leave the two sets of declares in the file.

Now you need to add code behind the two buttons. Listing 29.2 shows the code for the
Command1 (Get Info) button. Add this code to the Command1_Click event.


Listing 29.2. Adding code for the Get Info button.
Private Sub Command1_Click()
    '
    Dim lTapi As Long
    Dim cCountry As String * 1
    Dim cCity As String * 3
    '
    lTapi = tapiGetLocationInfo(cCountry, cCity)
    MsgBox Mid(cCountry, 1, 1) + "-(" + Mid(cCity, 1, 3) + ")", 0, "Location Info"
    '
End Sub

Pressing this button causes Visual Basic to display a message box showing the current country and city code (area code) stored in the TELEPHON.INI file/registry.Notice the variable declaration sets string sizes for the cCountry and cCity variables. This is needed in order to make sure the tapiGetLocationInfo function returns clean data. You also need to make sure you trim the returned variables. TAPI will return these two variables as zero-terminated strings (the last character is a zero-Chr(0)). Zero characters are unprintable in Visual Basic and can produce unexpected results. It's always a good idea to clean your string upon return from API calls.

The code in Listing 29.3 shows how to place a call using the tapiRequestMakeCall function. Add this code to the Command2_Click event.


Listing 29.3. Adding code for the Place Call button.
Private Sub Command2_Click()
    '
    Dim cAddress As String
    Dim lTapi As Long
    '
    cAddress = InputBox("Enter Phone Number to Call:", "Place Call")
    cAddress = Trim(cAddress)
    '
    If Len(cAddress) <> 0 Then
        lTapi = tapiRequestMakeCall(cAddress, "", "", "")
        If lTapi <> 0 Then
            MsgBox "Error placing call!", vbCritical, "TAPI Error Code [" + ÂCStr(lTapi) + "]"
        End If
    End If
    '
End Sub

Only the first parameter (the phone number) is required for the tapiRequestMakeCall function. The other parameters are optional (dialing application, called party, and comment). You'll use those variables in the Visual Basic 4.0 project at the end of the chapter.

Save the form as TAPI01.FRM, the module as TAPI01.BAS, and the project as TAPI01.VBP. Now run the project. When you click on the Get_Info button, you'll see your country and city code. When you click on the Place_Call button, you'll be asked to enter a phone number to dial. Visual Basic will hand the number to the TAPI DLL, which will call the default dialer application (DIALER.EXE) which will then process the call. You'll hear the phone dialing and see the dialog asking you to pick up the phone and begin speaking.

Those are the basics of Assisted TAPI calls. Now you can use this knowledge to add dialing capabilities to an Excel spreadsheet.

Creating the QikDial Application Using Excel 95

It's really quite easy to add outbound dialing to any Excel spreadsheet. Since you only need one API call (tapiRequestMakeCall), you have very little code to deal with. All you need is a single declare statement to cover the API call and one subroutine to handle the details of gathering the phone number from the user and calling the API function.

For this chapter, you'll create a very simple phone book using Excel. The example here will allow users to create a two-column table within a worksheet that contains a name in one column and a phone number in the next column. Users can highlight a name and then press an on-screen command button that will then place the call for them.

Note
The example illustrated here was done using Excel 95, but the same general idea can be handled in Excel 5.0.

Start Excel and/or open a new workbook. Since you'll be doing a bit of coding, be sure that the Visual Basic toolbar and the Forms toolbar are visible. If not, select View | Toolbars and then place a check mark next to Visual Basic and Forms. Figure 29.2 shows you what your Excel spreadsheet should look like.

The first thing you need to do is add the TAPI function declaration. To do this you must first add a code module to the project. Select Insert | Macro | Module from the main menu or click on the Insert Module icon in the Visual Basic toolbar. Once the module has been added to the project, rename the tab to VBA Code. Now insert the code in Listing 29.4.

Figure 29.2 : Adding the Visual Basic and forms tools to Excel


Listing 29.4. Adding the API declare to an Excel module.
'
' declare assisted-tapi function
'
Declare Function tapiRequestMakeCall Lib "TAPI32.DLL" (ByVal lpszDestAddress As String, ByVal lpszAppName As String, ByVal lpszCalledParty As String, ByVal lpszComment As String) As Long

Warning
This example uses the 32-bit version of the API call. This code will not run under 16-bit Windows environments (Window 3.11 or Windows for Workgroups). If you are using Excel in a 16-bit environment, modify the declare statement to reference TAPI.DLL rather than TAPI32.DLL.

Now you need to add a small subroutine that will determine the cell selected by the user, locate the associated phone number and then place the call using the TAPI function declared in Listing 29.4. Listing 29.5 shows the code needed for this routine. Place this code in the same module that contains the API declare.


Listing 29.5. Adding the subroutine that makes the call.
'
' call number in active cell
'
Sub CallBtn()
    Dim x As Long ' for return
    Dim cPhone As String
    Dim cName As String
    '
    cName = ActiveCell
    cPhone = ActiveCell.Offset(0, 1)
    '
    x = tapiRequestMakeCall(cPhone, "", cName, "")
    '
End Sub

You'll notice that this routine passes empty strings for the second and fourth parameters of the API call. These are optional parameters and are not needed for our example. You'll use these extra parameters in the Visual Basic 4.0 example later in this chapter. Now all you need to do is lay out the worksheet page to contain the name/phone number pairs. Figure 29.3 shows one way to lay out the form.

Figure 29.3 : Laying out the QikDial worksheet

Notice that this worksheet contains a command button. Use the Create Button icon from the Forms toolbar to add the button to the worksheet. When you are prompted to enter the macro associated with this button, be sure to enter the name of the subroutine shown in Listing 29.5 (CallBtn). It doesn't matter where you place things on the form. Just be sure to arrange the Name and Phone columns next to each other. The CallBtn subroutine will only work if the two columns are arranged side-by-side in the proper order. This example also has some friendly instructions to help the first-time user.

Save the file as QikDial.xls and then highlight a name and press the Call button. You should hear the modem in your pc dialing the number and see a dialog box on your screen that looks like the one in Figure 29.4.

Figure 29.4 : Testing the QikDial spreadsheet

You now have a short set of code that can be added to any VBA-compatible program, including Microsoft Project and Microsoft Access. In the next section, you'll create a complete application in Visual Basic 4.0 that performs basically the same function.

Writing the TeleBook Application Using Visual Basic 4.0

TeleBook is a sample telephone dialing application that can be used to place voice calls using the modem attached to the pc. Once the phone number has been dialed, a dialog box will appear telling the user to pick up the handset and start talking. The user can then click on another button to hang up the call upon completion.

This project has three forms, one class module, and one basic code module. The main form contains a list box showing the list of all the people in the phone book and a set of pushbuttons that mimic the keys on a standard single-line phone. A set of command buttons appears at the bottom of the form to allow users to add, edit, delete, find, and dial numbers selected from the phone list. Figure 29.5 shows how the form will look when it is completed.

Figure 29.5 : Laying out the TeleBook main form

The second form in the project is the phone list entry form. This form appears when the user selects the add or edit buttons on the main form. This is where the user can add or edit TeleBook entries (see Figure 29.6).

Figure 29.6 : Laying out the phone list entry form

The last form shows a log of all calls placed using the TeleBook application. TeleBook saves all call data in a Microsoft Access database for later use. The call history data can be shared with other programs that are capable of reading Microsoft Access files, including Excel, Microsoft Query, and several reporting tools. Figure 29.7 shows the Call Log form.

Figure 29.7 : Laying out the Call Log form.

Before laying out the forms, you first need to create the basic code module that contains the TAPI declare statement and the support routines. You also need a class module to encapsulate the API call into an easy-to-use method that allows four property settings.

Creating the TeleBook Class Module

Start a new VB4 project and insert a new module. Add the code shown in Listing 29.6. This is the only Telephony API you need for the TeleBook application.


Listing 29.6. Adding the Telephony API call.
Option Explicit


'
' declare tapi-assist API
'
#If Win16 Then
    Declare Function tapiRequestMakeCall Lib "TAPI.DLL" (ByVal lpszDestAddress As ÂString, ByVal lpszAppName As String, ByVal lpszCalledParty As String, ByVal ÂlpszComment As String) As Long
#Else
    Declare Function tapiRequestMakeCall Lib "TAPI32.DLL" (ByVal lpszDestAddress As ÂString, ByVal lpszAppName As String, ByVal lpszCalledParty As String, ByVal ÂlpszComment As String) As Long
#End If

Notice that the code in Listing 29.3 uses the #If...#Else...#End If compiler directive. This is done to create a code piece that will compile properly for both 16-bit and 32-bit environments.

Before continuing, save this module as TBOOK0.BAS and save the project as TELEBOOK.VBP.

Now that the API declare is done, you are ready to build a class module that will encapsulate the API. By writing a class module as a "wrapper" for the API, you'll make your program easier to read and much easier to update in the future-especially if the syntax of the API declare changes in the future.

Insert a class module into your VB project, set its Name property to clsPhoneCall, and add the code shown in listing 29.7.


Listing 29.7. Coding the clsPhoneCall class module.
Option Explicit

Dim cDestAddress As String
Dim cAppName As String
Dim cCalledParty As String
Dim cComment As String

The code in Listing 29.7 declares four variables used within the class module to keep track of the property values set using the Property Get and Property Let routines. Next you need to add these routines.

Warning
Be sure to use the Insert | Property menu option from the Visual Basic main menu. If you simply type Property Get and Property Let in the module, it will not work properly.

Listing 29.8 shows all four sets of Property Get/Property Let statement pairs. Use this listing to build your class module.


Listing 29.8. Coding the clsPhoneCall property routines.
Public Property Get DestAddress()
    DestAddress = cDestAddress
End Property

Public Property Let DestAddress(vNewValue)
    cDestAddress = vNewValue
End Property

Public Property Get AppName()
    AppName = cAppName
End Property

Public Property Let AppName(vNewValue)
    cAppName = vNewValue
End Property

Public Property Get CalledParty()
    CalledParty = cCalledParty
End Property

Public Property Let CalledParty(vNewValue)
    cCalledParty = vNewValue
End Property

Public Property Get Comment()
    Comment = cComment
End Property

Public Property Let Comment(vNewValue)
    cComment = vNewValue
End Property

The last routine you need to add to the class module is a function called RequestMakeCall. Since this function is built within a Visual Basic class module, it will act as a VB method. You'll call this method in the main program (see Listing 29.9).


Listing 29.9. Adding the RequestMakeCall function to the class module.
Public Function RequestMakeCall() As Long
    RequestMakeCall = tapiRequestMakeCall(cDestAddress, cAppName, cCalledParty, cComment)
End Function

The function in Listing 29.9 calls the API declared in the TBOOK0.BAS module by using the four parameters set with the Property Get/Property Let routines defined in the clsPhoneCall class.

Coding the TeleBook Main Form

Now it's time to build the onscreen forms for the TeleBook application. Use the information in Table 29.1 and Figure 29.5 to build the main form.

There are a few things to be aware of as you build this form. It contains two command button arrays-cmdKey(0-11) and cmdBtn(0-5). You can save typing by adding the first button and then using Edit | Copy, Edit | Paste from the Visual Basic main menu.

Also, be sure to place the Frame control on the form before you place any of the controls that appear within the frame. When you place controls in the frame, you must click the control from the toolbox and then draw the control within the frame.

Finally, be sure to set the Data1.DatabaseName property to point to the TELEBOOK.MDB database that ships with the CD-ROM. It can be found in the chAP29 directory.

Note
If you want to run the project, but don't want to do all the typing, you can find the source code in the chAP29 directory. Simply load this project (make sure the data control is set properly) and run it!

Table 29.1. Building the TeleBook main form.
ControlProperty Setting
Form NamefrmTeleBook
 Caption TeleBook Control
 Height 4515
 Left 1155
 MaxButton 0 - False
 Top 1155
 Width 5370
CommandButton Name cmdBtn
 Caption &Add
 Font Arial, 10pt
 Height 315
 Index 0
 Left 120
 Top 3660
 Width 750
CommandButton Name cmdBtn
 Caption &Edit
 Font Arial, 10pt
 Height 315
 Index 1
 Left 960
 Top 3660
 Width 750
CommandButton Name cmdBtn
 Caption &Delete
 Font Arial, 10pt
 Height 315
 Index 2
 Left 1800
 Top 3660
 Width 750
CommandButton Name cmdBtn
 Caption &Call
 Font Arial, 10pt
 Height 315
 Index 3
 Left 2640
 Top 3660
 Width 750
CommandButton Name cmdBtn
 Caption &Log
 Font Arial, 10pt
 Height 315
 Index 4
 Left 3480
 Top 3660
 Width 750
CommandButton Name cmdBtn
 Caption E&xit
 Font Arial, 10pt
 Height 315
 Index 4
 Left 4320
 Top 3660
 Width 750
DataBound List Name DBList1
 Height 3180
 Left 120
 Top 360
 Width 2955
 Font Arial, 10pt
 ListField Name
 BoundColumn Name
 DataSource Data1
Data Control Name Data1
 DatabaseName telebook.mdb
 RecordSource MasterList
 Visible False
Label Control Name Label1
 Caption Phone List
 Font Arial, 10pt
 Height 255
 Left 120
 Top 120
 Width 2955
Frame Control Name Frame1
 Caption Dialer
 Font Arial, 10pt
 Height 3555
 Left 3180
 Top 0
 Width 1935
TextBox Control Name txtDial
 Alignment 1 - Right Justify
 Font Arial, 10pt
 Height 375
 Left 120
 Top 300
 Width 1635
CommandButton Name cmdKey
 Caption 1
 Font MS Sans Serif, 10pt Bold
 Height 450
 Index 0
 Left 120
 Top 840
 Width 450
CommandButton Name cmdKey
 Font MS Sans Serif, 10pt Bold
 Caption 2
 Height 450
 Index 1
 Left 720
 Top 840
 Width 450
CommandButton Name cmdKey
 Font MS Sans Serif, 10pt Bold
 Caption 3
 Height 450
 Index 2
 Left 1320
 Top 840
 Width 450
CommandButton Name cmdKey
 Caption 4
 Font MS Sans Serif, 10pt Bold
 Height 450
 Index 3
 Left 120
 Top 1380
 Width 450
CommandButton Name cmdKey
 Font MS Sans Serif, 10pt Bold
 Caption 5
 Height 450
 Index 1
 Left 720
 Top 1380
 Width 450
CommandButton Name cmdKey
 Font MS Sans Serif, 10pt Bold
 Caption 6
 Height 450
 Index 5
 Left 1320
 Top 1380
 Width 450
CommandButton Name cmdKey
 Caption 7
 Font MS Sans Serif, 10pt Bold
 Height 450
 Index 6
 Left 120
 Top 1920
 Width 450
CommandButton Name cmdKey
 Font MS Sans Serif, 10pt Bold
 Caption 8
 Height 450
 Index 7
 Left 720
 Top 1920
 Width 450
CommandButton Name cmdKey
 Font MS Sans Serif, 10pt Bold
 Caption 9
 Height 450
 Index 8
 Left 1320
 Top 1920
 Width 450
CommandButton Name cmdKey
 Caption *
 Font MS Sans Serif, 10pt Bold
 Height 450
 Index 9
 Left 120
 Top 2460
 Width 450
CommandButton Name cmdKey
 Font MS Sans Serif, 10pt Bold
 Caption 0
 Height 450
 Index 10
 Left 720
 Top 2460
 Width 450
CommandButton Name cmdKey
 Font MS Sans Serif, 10pt Bold
 Caption #
 Height 450
 Index 11
 Left 1320
 Top 2460
 Width 450
CommandButton Name cmdDial
 Caption Direct Dial
 Font Arial, 10pt Bold
 Height 450
 Left 120
 Top 3000
 Width 1635

Now that the form controls have been placed, there are six form events that need to be coded and two form-level variables that must be declared. Open the code window of the form and add the code in Listing 29.10 in the general declaration area.


Listing 29.10. Declaring the form-level variables for frmTeleBook.
Option Explicit

'
' form level vars
'
Dim nWidth As Integer
Dim nHeight As Integer

Next add the code for the Form_Load event of the form (see Listing 29.11). If you are not saving the code in the same directory that contains the TELEBOOK.MDB database, you need to modify the line that sets the Data1.DatabaseName property to point to the directory that contains the database.


Listing 29.11. Coding the Form_Load event.
Private Sub Form_Load()
    nWidth = Me.Width
    nHeight = Me.Height
    Data1.DatabaseName = App.Path + "\telebook.mdb"
    Data1.RecordSource = "MasterList"
    frmTBLog.Data1.DatabaseName = App.Path + "\telebook.mdb"
    frmTBLog.Data1.RecordSource = "PhoneLog"
End Sub

The first two lines of code in Listing 29.11 store the form's initial width and height. This will be used in the resize event to override users who attempt to resize the form. This could be done by setting the form's BorderStyle property to something other than 2 (Sizable). However, other styles do not allow the minimize button to appear. Because we want to allow users to minimize the TeleBook (to keep it handy!), we'll use this workaround to prevent users from resizing the form.

Listing 29.12 shows the code for the Form_Resize event that uses the variables we are talking about. Add this code to the main form.


Listing 29.12. Adding the Form_Resize event code.
Private Sub Form_Resize()
    '
    ' override resizing
    '
    If Me.WindowState <> vbMinimized Then
        Me.Width = nWidth
        Me.Height = nHeight
        '
        Me.Left = (Screen.Width - Me.Width) / 2
        Me.Top = (Screen.Height - Me.Height) / 2
        '
    End If
    '
End Sub

The main code for the TeleBook form is contained in the cmdBtn_Click event. This is where all the command button clicks are handled. Listing 29.13 shows the code needed to handle the Add, Edit, Delete, Call, Log, and Exit buttons for the form.

Note
This routine contains calls to four support routines (ClearRec, SaveRec, LoadRec, and CallRec). You'll build these routines as the last step in the project. If you attempt to run the program before you build these routines, you'll get an error message.


Listing 29.13. Coding the cmdBtn_Click event.
Private Sub cmdBtn_Click(Index As Integer)
    '
    ' handle button selection
    '
    Dim cName As String
    Dim nAns As Integer
    Dim lReturn As Boolean
    '
    Select Case Index
        Case Is = 0 ' add
            ClearRec ' clear input form
            frmTbMaster.Show vbModal
            If frmTbMaster.SaveFlag = True Then
                SaveRec frmTbMaster.txtFields(0), "ADD"
            End If
        Case Is = 1 ' edit
            cName = DBList1.BoundText
            If Len(Trim(cName)) = 0 Then
                MsgBox "Select a Name to Edit", vbExclamation, "Edit Error"
            Else
                If LoadRec(cName) Then
                    frmTbMaster.Show vbModal
                    If frmTbMaster.SaveFlag = True Then
                        SaveRec cName, "EDIT"
                    End If
                End If
            End If
        Case Is = 2 ' delete
            cName = DBList1.BoundText
            If Len(Trim(cName)) = 0 Then
                MsgBox "Select a Name to Delete", vbExclamation, "Delete Error"
            Else
                nAns = MsgBox("Remove [" + cName + "] from TeleBook?", vbYesNo + ÂvbInformation, "Delete Entry")
                If nAns = vbYes Then
                    Data1.Recordset.FindFirst "Name='" + cName + "'"
                    If Data1.Recordset.NoMatch = False Then
                        Data1.Recordset.Delete
                    End If
                End If
            End If
        Case Is = 3 ' call
            cName = DBList1.BoundText
            If Len(Trim(cName)) = 0 Then
                MsgBox "Select a Name to Call", vbExclamation, "Call Error"
            Else
                Data1.Recordset.FindFirst "Name='" + cName + "'"
                If Data1.Recordset.NoMatch = False Then
                    ' update master list
                    Data1.Recordset.Edit
                    Data1.Recordset.Fields("LastCalled") = Now
                    Data1.Recordset.Update
                    ' update phone log
                    frmTBLog.Data1.Recordset.AddNew
                    frmTBLog.Data1.Recordset.Fields("CalledParty") = ÂData1.Recordset.Fields("Name")
                    frmTBLog.Data1.Recordset.Fields("NumberDialed") = ÂData1.Recordset.Fields("Phone")
                    frmTBLog.Data1.Recordset.Fields("DateCalled") = Now
                    frmTBLog.Data1.Recordset.Update
                    ' now place call
                    CallRec
                End If
            End If
        Case Is = 4 ' show call log
            frmTBLog.Show vbModal
        Case Is = 5 ' exit
            Unload frmTbMaster
            Unload Me
            End
    End Select
    '
    Me.Data1.Refresh
    DBList1.Refresh
    '
End Sub

The code needed to handle the phone keypad buttons is much simpler than the code shown in Listing 29.13. Add the code shown in Listing 29.14 to the cmdKey_Click event.


Listing 29.14. Coding the cmdKey_Click event.
Private Sub cmdKey_Click(Index As Integer)
    '
    ' handle phone key presses
    '
    txtDial = Trim(txtDial) + Mid("123456789*0#", Index + 1, 1)
    '
End Sub

The code in Listing 29.14 takes the Index property of the cmdKey button and uses that as a pointer into a string that contains all the associated digits.

Another short code routine is the one in the DBList1_DblClick event. This code simply mimics the pressing of the Edit button whenever the user double-clicks a name in the phone list. Add the code shown in Listing 29.15.


Listing 29.15. Coding the DBList1_DblClick event.
Private Sub DBList1_DblClick()
    '
    cmdBtn_Click 1 ' send "Edit message"
    '
End Sub

The last bit of code for this form is the one that actually makes the phone call (finally!). Listing 29.16 shows the code needed for the cmdDial_Click event. This event reads the phone number entered into the txtDial control from the direct keypad and passes that to the properties of the new clsPhoneCall object. Once the properties are set, the RequestMakeCall method is invoked on the clsPhoneCall object.


Listing 29.16. Coding the cmdDial_Click event.
Private Sub cmdDial_Click()
    '
    ' handle direct dial from keypad
    '
    Dim lTapi As Long
    Dim TBCall As New ClsPhoneCall
    Dim cPhone As String
    '
    cPhone = Trim(txtDial.Text)
    If Len(cPhone) = 0 Then
        MsgBox "Enter a Number to Dial", vbExclamation, "Direct Dial Error"
    Else
        TBCall.DestAddress = cPhone
        TBCall.CalledParty = "Direct Dial"
        TBCall.AppName = "dialer.exe"
        '
        lTapi = TBCall.RequestMakeCall
    End If
    '
End Sub

That completes the code for the frmTeleBook form. Save the form as TBOOK1.FRM and save the project. You'll receive errors if you run the project now since there are four support routines called in the cmdBtn_Click event that will be defined in the following section.

Coding the TeleBook Phone Entry Form

The phone book entry form is used to add or edit phone entries. It contains two large control arrays-txtFields(0-8) and lblLabels(0-8). These controls contain the data field contents and the data field names, respectively. Along with the Save and Cancel buttons, there is an additional invisible label control used as a flag value read from the main form. Use the information in Table 29.2 and Figure 29.6 to build the data table entry form.

Table 29.2. Controls for the frmTbMaster data entry form.
ControlProperty Setting
Form NamefrmTbMaster
 BorderStyle 3 - Fixed Dialog
 Caption TeleBook Entry
 Font Arial, 10pt
 Height 5925
 Left 1785
 Top 1140
 Width 4590
CommandButton Name cmdBtn
 Caption &Cancel
 Height 350
 Index 1
 Left 3180
 Top 5040
 Width 1200
CommandButton Name cmdBtn
 Caption &Save
 Height 350
 Index 0
 Left 1860
 Top 5040
 Width 1200
Label Control Name lblLabels
 Caption Name:
 Height 255
 Index 0
 Left 120
 Top 120
 Width 1200
Label Control Name lblLabels
 Caption Address:
 Height 600
 Index 1
 Left 120
 Top 540
 Width 1200
Label Control Name lblLabels
 Caption City:
 Height 255
 Index 2
 Left 120
 Top 1200
 Width 1200
Label Control Name lblLabels
 Caption StateProv:
 Height 255
 Index 3
 Left 120
 Top 1620
 Width 1200
Label Control Name lblLabels
 Caption PostalCode:
 Height 255
 Index 4
 Left 120
 Top 2040
 Width 1200
Label Control Name lblLabels
 Caption Country:
 Height 255
 Index 5
 Left 120
 Top 2505
 Width 1200
Label Control Name lblLabels
 Caption Phone:
 Height 255
 Index 6
 Left 120
 Top 2940
 Width 1200
Label Control Name lblLabels
 Caption Notes:
 Height 1110
 Index 7
 Left 120
 Top 3405
 Width 1200
Label Control Name lblLabels
 Caption Last Called:
 Height 255
 Index 8
 Left 120
 Top 4560
 Width 1200
Text Box Name txtFields
 Height 360
 Index 0
 Left 1380
 Top 105
 Width 3000
Text Box Name txtFields
 Height 600
 Index 1
 Left 1380
 MultiLine -1 (True)
 ScrollBars 2 (Vertical)
 Top 540
 Width 3000
Text Box Name txtFields
 Height 360
 Index 2
 Left 1380
 Top 1200
 Width 3000
Text Box Name txtFields
 Height 360
 Index 3
 Left 1380
 Top 1620
 Width 3000
Text Box Name txtFields
 Height 360
 Index 4
 Left 1380
 Top 2040
 Width 3000
Text Box Name txtFields
 Height 360
 Index 5
 Left 1380
 Top 2475
 Width 3000
Text Box Name txtFields
 Height 360
 Index 6
 Left 1380
 Top 2925
 Width 3000
Text Box Name txtFields
 Height 1140
 Index 7
 Left 1380
 MultiLine -1 (True)
 ScrollBars 2 (Vertical)
 Top 3360
 Width 3000
Text Box Name txtFields
 Height 360
 Index 8
 Left 1380
 Top 4560
 Width 3000
Label Control Name SaveFlag
 Visible 0 (False)

Once you complete the form design, save the form as TBOOK2.FRM.

Only two events need some code. Listing 29.17 shows the code needed for both the Form_Load event and the cmdBtn_Click event of the frmTbMaster form.


Listing 29.17. Adding the code for the frmTbMaster form.
Private Sub cmdBtn_Click(Index As Integer)
    '
    ' handle button select
    '
    If Index = 0 Then
        SaveFlag = True
    Else
        SaveFlag = False
    End If
    '
    Me.Hide
    '
End Sub


Private Sub Form_Load()
    '
    Me.Left = (Screen.Width - Me.Width) / 2
    Me.Top = (Screen.Height - Me.Height) / 2
    '
End Sub

After entering the code from Listing 29.17, save the form as TBOOK2.FRM and save the project before continuing.

Coding the Phone Log Form for TeleBook

The last form in the project is the Phone Log. This form shows a list of all the calls made using the TeleBook application. Use the data in Table 29.3 and Figure 29.7 to build the form.

Table 29.3. Controls for the frmTBLog form.
ControlProperty Setting
Form NamefrmTBLog
 BorderStyle 3 - Fixed Dialog
 Caption TeleBook Phone Log
 Height 4545
 Left 1065
 Top 1485
 Width 7650
CommandButton Name Command1
 Caption &Clear
 Height 300
 Index 0
 Left 4860
 Top 3720
 Width 1200
CommandButton Name Command1
 Caption &Return
 Height 300
 Index 1
 Left 4860
 Top 3720
 Width 1200
DBGrid Name DBGrid1
 Height 3435
 Left 120
 Top 120
 Width 7275
Data Control Name Data1
 Connect Access
 DatabaseName \CDG\chAP29\TELEBOOK.MDB
 RecordSource PhoneLog

Note
Be sure to change the DatabaseName property of the Data1 control to point to the directory on your workstation that holds the TELEBOOK.MDB file that was installed from the CD-ROM that ships with this book.

There are only two code routines needed for the frmTBLog form. The first just centers the form at load time. Add the code in Listing 29.18 to the Form_Load event.


Listing 29.18. Adding the code to the Form_Load event.
Private Sub Form_Load()
    '
    Me.Left = (Screen.Width - Me.Width) / 2
    Me.Top = (Screen.Height - Me.Height) / 2
    '
End Sub

Finally, add the code in Listing 29.19 behind the Command1_Click event of the two-button control array.


Listing 29.19. Adding code to the click event of the button array.
Private Sub Command1_Click(Index As Integer)
    '
    ' handle button press
    '
    Dim nCount As Integer
    Dim nLoop As Integer
    '
    Select Case Index
        Case Is = 0 ' clear log
            MousePointer = vbHourglass
            nCount = Data1.Recordset.RecordCount
            For nLoop = 1 To nCount
                Data1.Recordset.MoveFirst
                Data1.Recordset.Delete
            Next nLoop
            MousePointer = vbDefault
        Case Is = 1 ' exit form
            Unload Me
    End Select
    '
End Sub

The first case (Case Is = 0) handles the process of deleting all existing records in the log table. The second case exits the form.

Coding the Support Routines for the TeleBook Application

There are four support routines needed to complete the TeleBook project. Three of these routines deal with reading and writing phone book data records. The fourth routine uses the clsPhoneCall object to place a call.

Open the TBOOK0.BAS module and insert a new subroutine called ClearRec. This routine will be used to clear the data entry fields before adding a new record. Add the code in Listing 29.20.


Listing 29.20. Coding the ClearRec support routine.
Public Sub ClearRec()
    '
    ' clear input form
    '
    Dim nFlds As Integer
    Dim X As Integer
    '
    nFlds = frmTeleBook.Data1.Recordset.Fields.Count
    For X = 0 To nFlds - 1
        frmTbMaster.txtFields(X) = ""
    Next X
    '
End Sub

Next, add the routine needed to read an existing record from the database into the input form. Insert a new function called LoadRec and add the code in Listing 29.21. Be sure to modify the function declaration line to include the string parameter and the As Boolean return declaration.


Listing 29.21. Coding the LoadRec support function.
Public Function LoadRec(cTBName As String) As Boolean
    '
    ' load record data from
    ' frmTelebook to frmTbMaster
    '
    Dim nFlds As Integer
    Dim X As Integer
    Dim lReturn As Boolean
    '
    frmTeleBook.Data1.Recordset.FindFirst "Name='" + cTBName + "'"
    If frmTeleBook.Data1.Recordset.NoMatch = False Then
        nFlds = frmTeleBook.Data1.Recordset.Fields.Count
        For X = 0 To nFlds - 1
            frmTbMaster.txtFields(X) = frmTeleBook.Data1.Recordset.Fields(X)
        Next X
        lReturn = True
    Else
        lReturn = False
    End If
    '
    LoadRec = lReturn
    '
End Function

The next routine needed is the one that writes the updated input data back to the data table. Insert the SaveRec subroutine and add the code shown in Listing 29.22. Be sure to add the two parameters to the declaration line.


Listing 29.22. Coding the SaveRec support routine.
Public Sub SaveRec(cTBName As String, cAction As String)
    '
    ' move data from frmTBMaster
    ' to frmTeleBook.data1
    '
    Dim nFlds As Integer
    Dim X As Integer
    '
    cAction = UCase(cAction)
    If cAction = "ADD" Then
        frmTeleBook.Data1.Recordset.AddNew
    Else
        frmTeleBook.Data1.Recordset.FindFirst "Name='" + cTBName + "'"
        If frmTeleBook.Data1.Recordset.NoMatch = False Then
            frmTeleBook.Data1.Recordset.Edit
        Else
            frmTeleBook.Data1.Recordset.AddNew
        End If
    End If
    '
    nFlds = frmTeleBook.Data1.Recordset.Fields.Count
    For X = 0 To nFlds - 1
        frmTeleBook.Data1.Recordset.Fields(X) = frmTbMaster.txtFields(X)
    Next X
    '
    frmTeleBook.Data1.Recordset.Update
    '
End Sub

The final routine of the project is used to place a call from the command button array on the main form. Insert a new subroutine called CallRec and add the code shown in Listing 29.23.


Listing 29.23. Coding the CallRec support routine.
Public Sub CallRec()
    '
    ' call the book entry
    '
    Dim lTapi As Long                   ' return value
    Dim TBCall As New ClsPhoneCall      ' declare new object
    '
    TBCall.DestAddress = frmTeleBook.Data1.Recordset.Fields("Phone")
    TBCall.CalledParty = frmTeleBook.Data1.Recordset.Fields("Name")
    TBCall.AppName = "Dialer.exe"       ' set service provider
    '
    lTapi = TBCall.RequestMakeCall      ' make the call
End Sub

After entering this routine, save the TBOOK0.BAS module and save the project. Run the project to check for errors and correct any problems before you create a compiled version of the TeleBook application.

Running the TeleBook TAPI Application

You are now ready to run the TeleBook application. When you first start the application, you'll see an empty phone list and the phone keypad. You can dial a number by clicking on the keypad, then click the Direct Dial button. Once you click the dialing button, you'll see the Windows DIALER.EXE program start and show you the number you are dialing along with the name of the person you are calling (see Figure 29.8).

Figure 29.8 : The TeleBook application in action

You can also click on the Add button at the bottom of the form to bring up the phone book entry form. When you fill out the form and click the Save button, you'll return to the main form and see the new phone book entry in the phone list. You can dial a name displayed on the phone list by highlighting the name (click once) and then clicking on the Call button.

The same code you used to build this form can be used to add dialing capabilities to all your VB applications.

Summary

In this chapter you learned how to use the Assisted TAPI function (tapiRequestMakeCall) to build outbound voice phone solutions in both Excel and Visual Basic 4.0.

A key point to remember is that the tapiRequestMakeCall function provides Windows applications with access to outbound dialing only.

You now have tools that allow you to add phone dialing to any VBA-compatible application. And you have a complete online phone book that will log all your calls into a Microsoft JET database that can be read, analyzed, and reported by other Windows programs.

This chapter covered the most rudimentary TAPI functions. In the next chapter, you'll learn how to write programs that use the API functions that belong to the Basic TAPI set.