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.
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.
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.
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.
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.
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.
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! |
Control | Property | Setting |
Form | Name | frmTeleBook |
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.
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.
Control | Property | Setting |
Form | Name | frmTbMaster |
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.
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.
Control | Property | Setting |
Form | Name | frmTBLog |
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.
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.
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.
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.