In this chapter, you'll learn how to use a special custom control, the TAPILine control, to gain access to TAPI services from within your Visual Basic 4.0 programs. You'll also learn about the TAPILine control's properties and methods, and how to use a series of accompanying DLL calls that allow you to pass data structures between your Visual Basic program and the TAPI32.DLL.
After a review of the control itself, you'll build a demonstration project in Visual Basic 4.0 that will use the methods, properties, and DLL calls you learned about in the first part of the chapter. In the process you'll learn how to access all the major operations of Basic Telephony from within your Visual Basic programs.
When you complete this chapter, you'll know how to use the new control and how to add Basic Telephony services to your Visual Basic applications.
Accessing all but the simplest TAPI services requires the use of a notification callback (also known as a sink). Because Visual Basic is not capable of passing a callback address to TAPI, there is a special TAPI control included with this book, called TAPILINE.OCX, which allows the TAPI.DLL to notify your Visual Basic program whenever a critical event happens during a TAPI operation. This is done through an OCX event called TAPICallBack.
There is also a handful of properties that can be set or read. These allow you to get information from the TAPI services about the application ID, the line devices, and the identifying number of the call that is currently in progress at your workstation.
TAPILINE.OCX has a wealth of methods. In fact, TAPILINE.OCX includes every single method for TAPI line devices. You can use these methods to invoke dialog boxes, call TAPI functions, and get and read critical TAPI settings and return values.
The TAPILINE development kit also includes a DLL file that is used to pass data structures between your Visual Basic program and the TAPI system. This DLL file is needed because Visual Basic cannot use API calls to pass structured data directly. Rather than create routines that handle long byte arrays, you'll use DLL helper functions to read and write data structures used by the TAPI system.
Before you can use the TAPILINE
control in your projects, you must add several files to your WINDOWS\SYSTEM
folder. Table 26.1 shows the files you must add:
File Name | Description |
TAPILINE.OCX | This is the actual OLE control that appears in your Visual Basic tool box. |
TAPILINE.LIC | A short license file to verify you have a legal copy of TAPILINE. |
TAPILINE.OCA | An additional control file used by Visual Basic. |
TAPILINE.TLB | A type library file. You can use this to access TAPILINE services without loading the control on the form. |
PSTAPIDLL32.DLL | The DLL that holds supporting routines for passing structured data between Visual Basic and TAPI. |
MCf40.DLL | The DLL that provides support for Microsoft Foundation Class services. |
MSVCRT40.DLL | The DLL that supports Microsoft Visual C++. |
You can find these files in the TAPISYS and RUNTIMEC folders on the CD-ROM that ships with this book.
Warning |
It is possible that you have the last two files already in your WINDOWS\SYSTEM directory. If you already have them, do not copy them from the CD-ROM to your system. |
After you copy the files to the WINDOWS\SYSTEM directory, you can start up Visual Basic 4.0 and add the TAPILINE control to your tool box. To do this, select Tools | Custom Controls... from the main menu. A dialog box will appear showing all the controls that Visual Basic knows about. You should see one called "TAPILINE OLE Custom Control Module" (see Figure 26.1).
Figure 26.1 : Loading the TAPILINE custom control
Once you locate the control, click it to turn the check mark on and then press OK to close the dialog box.
Tip |
If you do not see the TAPILINE.OCX listed when you open the Tools | Custom Controls... dialog box, select Browse... and load the control from the WINDOWS\SYSTEM folder. Then you can select it from the list and close the dialog box. |
After loading the TAPILINE control into your toolbox, you'll be able to double-click the control to load it onto a Visual Basic form. You'll notice that you cannot resize the control once it is on your form. You will also notice that it disappears when you run your Visual Basic program. This is normal behavior for the TAPILINE control (see Figure 26.2).
Figure26.2 : Placing the TAPILINE control on a Visual Basic form
The one event recognized by the TAPILINE.OCX control is the TapiCallBack event. This event fires each time the TAPI system sends out a message. The TapiCallBack event receives a device ID, the message ID and program instance, and three additional parameters. It is up to the Visual Basic program to respond to the messages appropriately. Listing 26.1 shows how the event declaration appears within Visual Basic.
Listing 26.1. The TapiCallBack event declaration.
Private Sub Tapiline1_TapiCallBack(ByVal hDevice As Long, ByVal dwMessage As Long, ÂByVal dwInstance As Long, ByVal dwParam1 As Long, ByVal dwParam2 As Long, ByVal ÂdwParam3 As Long)
End Sub
The TAPI system can generate 14 different messages that will be passed to the TapiCallBack event. Listing 26.2 shows the message names along with their unique values. These are the values that Visual Basic must check for in the TapiCallBack event.
Listing 26.2. The TAPI event messages.
'
' Line callback messages
'
Global Const LINE_ADDRESSSTATE = 0&
Global Const LINE_CALLINFO = 1&
Global Const LINE_CALLSTATE = 2&
Global Const LINE_CLOSE = 3&
Global Const LINE_DEVSPECIFIC = 4&
Global Const LINE_DEVSPECIFICFEATURE = 5&
Global Const LINE_GATHERDIGITS = 6&
Global Const LINE_GENERATE = 7&
Global Const LINE_LINEDEVSTATE = 8&
Global Const LINE_MONITORDIGITS = 9&
Global Const LINE_MONITORMEDIA = 10&
Global Const LINE_MONITORTONE = 11&
Global Const LINE_REPLY = 12&
Global Const LINE_REQUEST = 13&
Note |
Chapter 23, "TAPI Architecture," describes the TAPILINE messages, their parameters, and their use. |
The TAPILINE.OCX has 12 unique,
TAPI-related properties. TAPILINE
uses these properties to keep track of important handles, ID values,
and other settings. You can read or write these values using standard
Visual Basic code or manipulate them at design time through the
Properties window of Visual Basic. Table 26.2 shows the 12 TAPI-related
properties along with short descriptions.
Property | Description |
AddressID | This is a value from 0 to the maximum number of addresses available on a line device. Use this value to identify multiple addresses for the same line (multiple-line phones only). |
APIVersion | This is the value of the TAPI API version currently in use. This is set by TAPI. |
CompletionID | This is a unique value set by TAPI to identify a call that is in progress. Used in multiline systems that allow call camp and other advanced features. |
GatheredDigits | This is a string of digits pressed by the user. This is the results of the lineGatherDigits function. |
HandleToCall | This is the unique handle of the current call. |
HandleToConfCall | This is the unique handle of a conference call in progress. |
HandleToConsultCall | This is the unique handle of a call transfer that is in progress. This is used by several Supplemental TAPI functions. |
LineApp | This is the unique ID of this session between Visual Basic and TAPI. |
LineHandle | This is the unique ID of the line that has been opened for use. |
NumberOfRings | This is the maximum number of rings to allow for an outbound call. |
NumDevices | This is the total number of devices TAPI recognizes on the workstation. |
PermanentProviderID | This is the unique ID of the TAPI service provider that is being used to complete the TAPI service request. |
Priority | This is the priority value used to complete the last TAPI service request. |
Most of these values are set at run-time by TAPI. You can read them to get status information about the state of a TAPI service request. As you will see in the example project built later in this chapter, there are a few properties here which you can manipulate safely during run-time. However, most should be treated as read-only properties.
The TAPILINE.OCX has numerous methods that can be used to make TAPI service requests. In fact, all of the TAPI line functions have been recreated as methods for the TAPILINE.OCX control. Instead of listing all the methods here, you can use the TAPILINE.HLP file that ships with the TAPILINE.OCX control. This file contains detailed information on each of the methods. To use the help file as a reference, click the TAPILINE.HLP file and then press the Help Topics button to bring up the search dialog box. You can browse the search list or type in search strings to locate the desired function. Figure 26.3 shows you how the help file looks when it is first loaded.
Figure 26.3 : Loading the TAPILINE help file
Tip |
You can also refer to Chapter 23, "TAPI Architecture," to get a complete list of all TAPILINE functions, including short descriptions. |
The TAPI system makes extensive use of data structures. In fact, several of the structures are variable in length. These are difficult to pass between Visual Basic and Windows DLLs or OCX controls. In order to simplify the process, the TAPILINE control comes with a helper DLL called PSTAPIDLL32. This DLL contains 17 functions that are used to pass data structures. Listing 26.3 shows a sample of the API declarations used to link these helper functions to your Visual Basic programs.
Listing 26.3. Declaring the DLL helper functions for TAPILINE.
Declare Sub LineMonitorToneFunc Lib "pstapidll32" (ByVal nMode As Long, structdata ÂAs LINEMONITORTONE)
Declare Sub LineTranslateOutputFunc Lib "pstapidll32" (ByVal nMode As Long, Âstructdata As LINETRANSLATEOUTPUT, ByVal ExtraData As String)
Each call has at least two parameters and several of them have three. The first parameter (nMode) is used to indicate whether you are attempting to read (1) or write (0) TAPI data. The second parameter is a pre-defined data structure that contains the TAPI-related information. You will have other Type...End Type statements in your Visual Basic program that match these data structures.
Some of the DLL calls have a third parameter called sExtraData. This parameter contains string information that will be used to augment the structured data sent in the same call. This is how the TAPILINE control passes variable-length structures between Visual Basic and the TAPI system.
You'll see all 17 of the helper DLL calls in the next section of the chapter when you build the TAPILine Test application.
The TAPILINE Test project will show you how to build TAPI applications using Visual Basic 4.0. You'll see how to use the TAPILINE control and the PSTAPIDLL32 dynamic link library to perform TAPI service requests. You'll see how these two added resources (along with a bit of Visual Basic code) can give you extensive access to the TAPI services built into every Win95 and WinNT machine.
Before you can begin running TAPI applications from Visual Basic, you need a few support modules that contain DLL declarations, structured data types, global constants, and several internal help routines to decipher the messages returned by TAPI.
Once you have the DLL declarations, the line constants and structures, and the helper functions, you are ready to lay out the TAPILINE Test form and place code behind several buttons to see how TAPI services work from within Visual Basic programs.
Creating the support code of declarations, data structures, and
constants is a big (and tedious) job. Instead of asking you to
type all the code yourself, a set of support modules is included
on the CD-ROM that accompanies this book. You can find the code
support routines in the TAPILINE\VBTAPI
folder on the CD-ROM. Table 26.3 lists the Visual Basic support
modules along with short descriptions of their uses.
Module Name | Description |
TAPILINE.BAS | All the DLL declarations, line constants, and line data structures needed for creating TAPI applications that use line devices. |
TAPIPHON.BAS | All the constants and data structures needed to handle phone devices. |
TAPICALL.BAS | A set of helper functions that handle TAPI callback messages and other routines |
Note |
The TAPILINE.OCX can only handle line devices. The TAPIPHON.BAS module is included to help you if you wish to develop additional OCX or DLL code to support phone device programming from Visual Basic. It is possible that TAPILINE will support phone device programming in the future. |
Copy the modules listed in Table 26.3 onto your own hard disk and use them whenever you use the TAPILINE.OCX file. The next section of the chapter reviews the modules listed to help you understand what is in them and to give you a good idea of how they work.
The first code in the TAPILINE.BAS module is the set of DLL declarations needed to call the TAPILINE helper functions for passing structured data. Listing 26.4 shows the code that handles the DLL declarations.
Listing 26.4. PSTAPIDLL32 DLL declarations.
'
' DLL declares for TAPILine control
'
Declare Sub LineCallParamsFunc Lib "pstapidll32" (ByVal nMode As Long, structdata ÂAs LINECALLPARAMS, ByVal ExtraData As String)
Declare Sub LineForwardListFunc Lib "pstapidll32" (ByVal nMode As Long, structdata ÂAs LINEFORWARDLIST, ByVal ExtraData As String)
Declare Sub LineGenerateToneFunc Lib "pstapidll32" (ByVal nMode As Long, structdata ÂAs LINEGENERATETONE_TYPE, ByVal ExtraData As String)
Declare Sub LineAddressCapsFunc Lib "pstapidll32" (ByVal nMode As Long, structdata ÂAs LINEADDRESSCAPS, ByVal ExtraData As String)
Declare Sub LineCallInfoFunc Lib "pstapidll32" (ByVal nMode As Long, structdata As ÂLINECALLINFO, ByVal ExtraData As String)
Declare Sub LineCallStatusFunc Lib "pstapidll32" (ByVal nMode As Long, structdata ÂAs LINECALLSTATUS, ByVal ExtraData As String)
Declare Sub LineCallListFunc Lib "pstapidll32" (ByVal nMode As Long, structdata As ÂLINECALLLIST, ByVal ExtraData As String)
Declare Sub LineDevCapsFunc Lib "pstapidll32" (ByVal nMode As Long, structdata As ÂLINEDEVCAPS, ByVal ExtraData As String)
Declare Sub VarStringFunc Lib "pstapidll32" (ByVal nMode As Long, structdata As ÂVARSTRING, ByVal ExtraData As String)
Declare Sub LineDevStatusFunc Lib "pstapidll32" (ByVal nMode As Long, structdata As ÂLINEDEVSTATUS, ByVal ExtraData As String)
Declare Sub LineTranslateCapsFunc Lib "pstapidll32" (ByVal nMode As Long, Âstructdata As LINETRANSLATECAPS, ByVal ExtraData As String)
Declare Sub LineMonitorToneFunc Lib "pstapidll32" (ByVal nMode As Long, structdata ÂAs LINEMONITORTONE)
Declare Sub LineExtensionIDFunc Lib "pstapidll32" (ByVal nMode As Long, structdata ÂAs LINEEXTENSIONID)
Declare Sub LineDialParmsFunc Lib "pstapidll32" (ByVal nMode As Long, structdata As ÂLINEDIALPARAMS)
Declare Sub LineMediaControlDigitFunc Lib "pstapidll32" (ByVal nMode As Long, Âstructdata As LINEMEDIACONTROLDIGIT)
Declare Sub LineTranslateOutputFunc Lib "pstapidll32" (ByVal nMode As Long, Âstructdata As LINETRANSLATEOUTPUT, ByVal ExtraData As String)
Declare Sub LineAddressStatusFunc Lib "pstapidll32" (ByVal nMode As Long, Âstructdata As LINEADDRESSSTATUS, ByVal ExtraData As String)
'
' constants for read/write of params
'
Global Const TAPI_WRITE = 0
Global Const TAPI_READ = 1
You'll notice that the global constants for TAPI_WRITE and TAPI_READ appear at the end of the DLL declarations. These are used for the nMode parameter of the DLL calls.
After the DLL declares, you'll see a list of TAPI error message values that could be returned. Listing 26.5 shows the error values that appear in the TAPILINE.BAS module.
Listing 26.5. The TAPI error message values.
'
' ************************************************
' general TAPI constants
' ************************************************
'
Global Const TAPI_REPLY = &H400& + 99&
Global Const TAPIERR_CONNECTED = 0&
Global Const TAPIERR_DROPPED = -1&
Global Const TAPIERR_NOREQUESTRECIPIENT = -2&
Global Const TAPIERR_REQUESTQUEUEFULL = -3&
Global Const TAPIERR_INVALDESTADDRESS = -4&
Global Const TAPIERR_INVALWINDOWHANDLE = -5&
Global Const TAPIERR_INVALDEVICECLASS = -6&
Global Const TAPIERR_INVALDEVICEID = -7&
Global Const TAPIERR_DEVICECLASSUNAVAIL = -8&
Global Const TAPIERR_DEVICEIDUNAVAIL = -9&
Global Const TAPIERR_DEVICEINUSE = -10&
Global Const TAPIERR_DESTBUSY = -11&
Global Const TAPIERR_DESTNOANSWER = -12&
Global Const TAPIERR_DESTUNAVAIL = -13&
Global Const TAPIERR_UNKNOWNWINHANDLE = -14&
Global Const TAPIERR_UNKNOWNREQUESTID = -15&
Global Const TAPIERR_REQUESTFAILED = -16&
Global Const TAPIERR_REQUESTCAncELLED = -17&
Global Const TAPIERR_INVALPOINTER = -18&
Global Const TAPIMAXDESTADDRESSSIZE = 80&
Global Const TAPIMAXAPPNAMESIZE = 40&
Global Const TAPIMAXCALLEDPARTYSIZE = 40&
Global Const TAPIMAXCOMMENTSIZE = 80&
Global Const TAPIMAXDEVICECLASSSIZE = 40&
Global Const TAPIMAXDEVICEIDSIZE = 40&
Next, there is the list of callback message values. These will be used to check the MessageID values returned in the TapiCallBack event of the TAPILINE control. Listing 26.6 shows the list of 14 possible messages.
Listing 26.6. The TAPICallBack message Ids.
'
' Line callback messages
'
Global Const LINE_ADDRESSSTATE = 0&
Global Const LINE_CALLINFO = 1&
Global Const LINE_CALLSTATE = 2&
Global Const LINE_CLOSE = 3&
Global Const LINE_DEVSPECIFIC = 4&
Global Const LINE_DEVSPECIFICFEATURE = 5&
Global Const LINE_GATHERDIGITS = 6&
Global Const LINE_GENERATE = 7&
Global Const LINE_LINEDEVSTATE = 8&
Global Const LINE_MONITORDIGITS = 9&
Global Const LINE_MONITORMEDIA = 10&
Global Const LINE_MONITORTONE = 11&
Global Const LINE_REPLY = 12&
Global Const LINE_REQUEST = 13&
There are numerous constants and declarations needed to support all the TAPI line device functions. There are too many to include here, but one is shown in Listing 26.7 to give you an example.
Listing 26.7. An example line constant and type declaration.
Global Const LINEADDRCAPFLAGS_FWDNUMRINGS = &H1&
Global Const LINEADDRCAPFLAGS_PICKUPGROUPID = &H2&
Global Const LINEADDRCAPFLAGS_SECURE = &H4&
Global Const LINEADDRCAPFLAGS_BLOCKIDDEFAULT = &H8&
Global Const LINEADDRCAPFLAGS_BLOCKIDOVERRIDE = &H10&
Global Const LINEADDRCAPFLAGS_DIALED = &H20&
Global Const LINEADDRCAPFLAGS_ORIGOFFHOOK = &H40&
Global Const LINEADDRCAPFLAGS_DESTOFFHOOK = &H80&
Global Const LINEADDRCAPFLAGS_FWDCONSULT = &H100&
Global Const LINEADDRCAPFLAGS_SETUpcONFNULL = &H200&
Global Const LINEADDRCAPFLAGS_AUTORECONNECT = &H400&
Global Const LINEADDRCAPFLAGS_COMPLETIONID = &H800&
Global Const LINEADDRCAPFLAGS_TRANSFERHELD = &H1000&
Global Const LINEADDRCAPFLAGS_TRANSFERMAKE = &H2000&
Global Const LINEADDRCAPFLAGS_CONFEREncEHELD = &H4000&
Global Const LINEADDRCAPFLAGS_CONFEREncEMAKE = &H8000&
Global Const LINEADDRCAPFLAGS_PARTIALDIAL = &H10000
Global Const LINEADDRCAPFLAGS_FWDSTATUSVALID = &H20000
Global Const LINEADDRCAPFLAGS_FWDINTEXTADDR = &H40000
Global Const LINEADDRCAPFLAGS_FWDBUSYNAADDR = &H80000
Global Const LINEADDRCAPFLAGS_AccEPTTOALERT = &H100000
Global Const LINEADDRCAPFLAGS_CONFDROP = &H200000
Global Const LINEADDRCAPFLAGS_PICKUpcALLWAIT = &H400000
Type LINEADDRESSCAPS
dwTotalSize As Long
dwNeededSize As Long
dwUsedSize As Long
dwLineDeviceID As Long
dwAddressSize As Long
dwAddressOffset As Long
dwDevSpecificSize As Long
dwDevSpecificOffset As Long
dwAddressSharing As Long
dwAddressStates As Long
dwCallInfoStates As Long
dwCallerIDFlags As Long
dwCalledIDFlags As Long
dwConnectedIDFlags As Long
dwRedirectionIDFlags As Long
dwRedirectingIDFlags As Long
dwCallStates As Long
dwDialToneModes As Long
dwBusyModes As Long
dwSpecialInfo As Long
dwDisconnectModes As Long
dwMaxNumActiveCalls As Long
dwMaxNumOnHoldCalls As Long
dwMaxNumOnHoldPendingCalls As Long
dwMaxNumConference As Long
dwMaxNumTransConf As Long
dwAddrCapFlags As Long
dwCallFeatures As Long
dwRemoveFromConfCaps As Long
dwRemoveFromConfState As Long
dwTransferModes As Long
dwParkModes As Long
dwForwardModes As Long
dwMaxForwardEntries As Long
dwMaxSpecificEntries As Long
dwMinFwdNumRings As Long
dwMaxFwdNumRings As Long
dwMaxCallCompletions As Long
dwCallCompletionConds As Long
dwCallCompletionModes As Long
dwNumCompletionMessages As Long
dwCompletionMsgTextEntrySize As Long
dwCompletionMsgTextSize As Long
dwCompletionMsgTextOffset As Long
End Type
Global Const LINEADDRESSCAPS_FIXEDSIZE = 176
Type LINEADDRESSCAPS_STR
Mem As String * LINEADDRESSCAPS_FIXEDSIZE
End Type
You'll notice a set of constants that appear before the type declaration. These can be used to set various TAPI parameters within the data structure. Some declarations are return values that can be read once TAPI has set or modified the data within the structure. The TAPILINE.BAS module contains many of these sets of constants and data structure declarations. The VBTAPI folder also contains a similar module for phone device declarations. Although the TAPILINE control currently only supports line devices, a future version may provide support for phone devices.
For now, you can load the TAPILINE.BAS module into your Visual Basic programs that use the TAPILINE.OCX control.
The TAPICALL.BAS module contains several routines needed to support TAPI calls using TAPILINE.OCX and the PSTAPIDLL file. Again, typing them all in is boring. Instead, this section reviews several of the more important example routines. You can load the TAPICALL.BAS module into your Visual Basic projects and use these routines without having to re-enter all the code.
The most important routine in the TAPICALL.BAS module is the TAPICallBackHandler function. This routine takes the parameters returned in the TAPICallBack event of the TAPILINE.OCX and dispatches messages based on the return values. Listing 26.8 shows the code for the TAPICallBackHandler.
Listing 26.8. Code for the TAPICallBackHandler function.
Public Function TapiCallBackHandler(hDevice As Long, dwMessage As Long, dwInstance As Long, dwParam1 As Long, dwParam2 As Long, dwParam3 As Long) As String
'
' handle messages from TAPI control
'
Dim cMsg As String
'
Select Case dwMessage
Case LINE_ADDRESSSTATE '(= 0&)
cMsg = "MSG: Line_AddressState"
cMsg = cMsg & "..."
cMsg = cMsg & "AddressID=" & CStr(dwParam1)
cMsg = cMsg & ", State=" & LineAddressStateMsg(dwParam2)
Case LINE_CALLINFO '(= 1&)
cMsg = "MSG: Line_CallInfo"
Case LINE_CALLSTATE '(= 2&)
cMsg = "MSG: Line_CallState"
cMsg = cMsg & "..."
cMsg = cMsg & "CallState=" & LineCallStateMsg(dwParam1)
'
Select Case dwParam1
Case LINECALLSTATE_BUSY
cMsg = cMsg & ", StateDependent=" & ÂLineCallStateBusyMsg(dwParam2)
Case LINECALLSTATE_DIALTONE
cMsg = cMsg & ", StateDependent=" & ÂLineCallStateDialtoneMsg(dwParam2)
Case LINECALLSTATE_DISCONNECTED
cMsg = cMsg & ", StateDependent=" & ÂLineCallStateDisconnectedMsg(dwParam2)
Case Else
cMsg = cMsg & ", StateDependent=" & CStr(dwParam2)
End Select
'
cMsg = cMsg & ", Privilege=" & CStr(dwParam3)
Case LINE_CLOSE '(= 3&)
cMsg = "MSG: Line_Close"
Case LINE_DEVSPECIFIC '(= 4&)
cMsg = "MSG: Line_DevSpecific"
Case LINE_DEVSPECIFICFEATURE '(= 5&)
cMsg = "MSG: Line_DevSpecificFeature"
Case LINE_GATHERDIGITS '(= 6&)
cMsg = "MSG: Line_GatherDigits"
Case LINE_GENERATE '(= 7&)
cMsg = "MSG: Line_Generate"
Case LINE_LINEDEVSTATE '(= 8&)
cMsg = "MSG: Line_LineDevState"
Case LINE_MONITORDIGITS '(= 9&)
cMsg = "MSG: Line_MonitorDigits"
Case LINE_MONITORMEDIA '(= 10&)
cMsg = "MSG: Line_MonitorMedia"
Case LINE_MONITORTONE '(= 11&)
cMsg = "MSG: Line_MonitorTone"
Case LINE_REPLY '(= 12&)
cMsg = "MSG: Line_Reply...idRequest=" & CStr(dwParam1) & " - Status = " Â& LineErr(dwParam2)
Case LINE_REQUEST '(= 13&)
cMsg = "MSG: Line_Request"
Case Else
cMsg = "MSG: Unknown Message..." + CStr(dwMessage)
End Select
'
TapiCallBackHandler = cMsg
'
End Function
This routine is designed to turn the callback MessageID value and other parameters into a meaningful message to display in a status box on a form. In production applications, you could use this same SELECT CASE structure to enclose calls to subroutines and functions that fire appropriate Visual Basic code based on the messages received.
You'll also notice that there are several calls to other support routines that translate parameters into meaningful strings for extended messages. These routines could be replaced by Visual Basic code that performs other tasks based on the parameters passed by TAPI into the TAPICallBack event.
There are several functions that convert call-state parameters into messages. These routines could be used to fire off Visual Basic code based on the state of the current call. Listing 26.9 shows one of these routines.
Listing 26.9. A sample CallState message function.
Public Function LineCallStateDisconnectedMsg(dwParam As Long) As String
'
' handle message values
'
Dim cReturn As String
'
Select Case dwParam
Case LINEDISCONNECTMODE_NORMAL ' &H1&
cReturn = "Normal"
Case LINEDISCONNECTMODE_UNKNOWN ' &H2&
cReturn = "Unknown"
Case LINEDISCONNECTMODE_REJECT ' &H4&
cReturn = "Rejected"
Case LINEDISCONNECTMODE_PICKUP ' &H8&
cReturn = "Picked Up"
Case LINEDISCONNECTMODE_FORWARDED ' &H10&
cReturn = "Forwarded"
Case LINEDISCONNECTMODE_BUSY ' &H20&
cReturn = "Busy"
Case LINEDISCONNECTMODE_NOANSWER ' &H40&
cReturn = "No Answer"
Case LINEDISCONNECTMODE_BADADDRESS ' &H80&
cReturn = "Invalid Address"
Case LINEDISCONNECTMODE_UNREAchABLE ' &H100&
cReturn = "Unreachable"
Case LINEDISCONNECTMODE_CONGESTION ' &H200&
cReturn = "Congested Network"
Case LINEDISCONNECTMODE_IncOMPATIBLE ' &H400&
cReturn = "Incompatible Equipment"
Case LINEDISCONNECTMODE_UNAVAIL ' &H800&
cReturn = "Reason Unavailable"
Case Else
cReturn = "Unknown LineCallStateDisconnected Msg [" & CStr(dwParam) & Â"]"
End Select
'
LineCallStateDisconnectedMsg = cReturn
'
End Function
This routine handles one of the parameters returned from a line disconnect event.
Some of the TAPI functions return data in variable-length strings. These data strings usually contain several items, separated by zeros. You need two routines to help read the data in these strings. First, you need a routine to clean out the zero character (0) values in a returned string. Second, you need a routine that can pick a block of characters out of the data string based on an offset and a string size. This offset and size are returned as part of the fixed-size data structure.
The Clean function removes all character string 0 values from the returned data. Listing 26.10 shows how this is done.
Listing 26.10. The Clean function.
Function Clean(c As String) As String
'
' strip 0s from string
'
Dim l As Integer
Dim x As Integer
Dim s As String
Dim n As Integer
'
l = Len
s = ""
For x = 1 To Len
If Mid(c, x, 1) <> Chr(0) Then
s = s + Mid(c, x, 1)
Else
s = s + " "
End If
Next
'
Clean = s
End Function
You'll notice that the routine replaces all character zeros with character 32 (space). This maintains the original size of the string, but prevents Visual Basic from encountering errors when it tries to read a string that contains character 0 values.
The second routine needed to handle the variable strings is one that picks out a substring based on the offset and size values found in the fixed data structure. Listing 26.11 shows how the GetOffset function works.
Listing 26.11. The GetOffset function.
Public Function GetOffset(lLenStru As Long, lOffset As Long, lSize As Long, ÂcExtraData As String) As String
'
' return the data at the offset
'
GetOffset = Mid(cExtraData, (lOffset - lLenStru) + 1, lSize)
'
End Function
TAPI returns an offset value computed from the start of the original data structure. For this reason, the length of the data structure is passed as a first parameter into the function. This length is the size of the fixed portion of the data structure. The GetOffset routine subtracts the fixed-length amount to get the starting position in the cExtraData string space. This position is used to pick out a data string that is the length of lSize. The resulting string is then returned to the calling program.
That gives you a good idea of how the support routines work and how they are used throughout the program. In the next section, you'll build a demonstration program that uses the tools you have reviewed so far.
For our example program, you'll build a form that has a series of buttons you can press to invoke various TAPI service requests. The status of your requests will be displayed in a scrollable text box on the form. In a real application, you'd capture the status information and use it to control program flow. But for now, you'll see each message sent back from TAPI and you'll see how you can write code to capture those messages.
First, start Visual Basic and open a new project. Then add the TAPILINE.OCX control to the form.
Tip |
If you do not see the TAPILINE.OCX in your Visual Basic toolbox window, add it by using the Tools | Custom Controls menu option. For more information on adding the TAPILINE.OCX to your project see the TAPILINE.OCX section of this chapter. |
Next, add the TAPILINE.BAS and TAPICALL.BAS modules to your project (File | Add File...). You can find these in the VBTAPI folder on the CD-ROM.
Now you're ready to place the controls on the form. Refer to Figure 26.4 and Table 26.4 when laying out the form.
Figure 26.4 : Laying out the TAPITest form
Control | Property | Setting |
VB.Form | Name | frmTapiLine |
Caption | "Form1" | |
Height | 6000 | |
Left | 1035 | |
Top | 1305 | |
Width | 10260 | |
VB.CommandButton | Name | cmdLineConfProv |
Caption | "LineConfProv" | |
Height | 450 | |
Left | 2580 | |
TabIndex | 15 | |
Top | 5040 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineDeallocate |
Caption | "LineDealloc" | |
Height | 450 | |
Left | 7620 | |
TabIndex | 14 | |
Top | 4500 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineGetInfo |
Caption | "LineGetInfo" | |
Height | 450 | |
Left | 1320 | |
TabIndex | 13 | |
Top | 5040 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineShowHandles |
Caption | "Show Handles" | |
Height | 450 | |
Left | 60 | |
TabIndex | 12 | |
Top | 5040 | |
Width | 1200 | |
VB.TextBox | Name | Text1 |
BackColor | &H00C0C0C0& | |
Font | name="MS LineDraw" | |
charset=2 | ||
weight=400 | ||
size=8.25 | ||
underline=0 'False | ||
italic=0 'False | ||
strikethrough=0 'False | ||
Height | 3915 | |
Left | 120 | |
MultiLine | -1 'True | |
ScrollBars | 3 'Both | |
TabIndex | 11 | |
Top | 420 | |
Width | 9915 | |
VB.CommandButton | Name | cmdLineAbout |
Caption | "TAPI About" | |
Height | 450 | |
Left | 5100 | |
TabIndex | 10 | |
Top | 5040 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineDrop |
Caption | "Line Drop" | |
Height | 450 | |
Left | 6360 | |
TabIndex | 9 | |
Top | 4500 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineDialProps |
Caption | "Dialing Props" | |
Height | 450 | |
Left | 7620 | |
TabIndex | 8 | |
Top | 5040 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineAddrStatus |
Caption | "Addr Status" | |
Height | 450 | |
Left | 3840 | |
TabIndex | 7 | |
Top | 5040 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineConfDialog |
Caption | "Config Dialog" | |
Height | 450 | |
Left | 6360 | |
TabIndex | 6 | |
Top | 5040 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineDevCaps |
Caption | "Get DevCaps" | |
Height | 450 | |
Left | 2580 | |
TabIndex | 5 | |
Top | 4500 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineClose |
Caption | "Close" | |
Height | 450 | |
Left | 8880 | |
TabIndex | 4 | |
Top | 4500 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineMakeCall |
Caption | "Line Make Call" | |
Height | 450 | |
Left | 5100 | |
TabIndex | 3 | |
Top | 4500 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineOpen |
Caption | "Line Open" | |
Height | 450 | |
Left | 3840 | |
TabIndex | 2 | |
Top | 4500 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineNegApi |
Caption | "Line Neg" | |
Height | 450 | |
Left | 1320 | |
TabIndex | 1 | |
Top | 4500 | |
Width | 1200 | |
VB.CommandButton | Name | cmdLineInit |
Caption | "Line Initialize" | |
Height | 450 | |
Left | 60 | |
TabIndex | 0 | |
Top | 4500 | |
Width | 1200 | |
VB.Label | Name | Label1 |
BorderStyle | 1 'Fixed Single | |
Caption | "Status Messages and Call | |
Progress:" | ||
Height | 255 | |
Left | 120 | |
TabIndex | 16 | |
Top | 120 | |
Width | 9915 | |
TapilineLib.Tapiline | Name | Tapiline1 |
Left | 9180 | |
Top | 5100 |
After completing the form, save the form as TAPITEST.FRM and the project as TAPITEST.VBP. Now you're ready to place code into the form.
There are two sets of code for the TAPILine form. The first set is for the support routines. These are called by several other routines on the form. Next you get to add the code behind all the buttons. This code is the actual TAPI service requests.
Before adding code behind the buttons on the form, you need to add a few support routines to the project. First, three form-level declarations are needed. Add the code in Listing 26.12 to the general declaration area of the form.
Listing 26.12. Form-level variables.
Option Explicit
Dim nline As Integer ' line to select
Dim lNumDev As Long ' number of devices
Dim cLine As String
Next, you need to add code to clear the values in four key properties used in this project. Create a subroutine called ClearHandles and add the code shown in Listing 26.13.
Listing 26.13. The ClearHandles routine.
Public Sub ClearHandles()
'
' set all control handles to zero
'
Me.Tapiline1.LineApp = 0
Me.Tapiline1.LineHandle = 0
Me.Tapiline1.HandleToCall = 0
Me.Tapiline1.AddressID = 0
'
End Sub
You'll also need a routine to display the contents of these same four properties. Add a subroutine called ShowHandles and add the code in Listing 26.14.
Listing 26.14. The ShowHandles routine.
Public Sub ShowHandles()
'
AddText Me.Text1, "LineApp (Session)......" & Hex(Tapiline1.LineApp)
AddText Me.Text1, "LineHandle (Line)......" & Hex(Tapiline1.LineHandle)
AddText Me.Text1, "HandleToCall (Call)...." & Hex(Tapiline1.HandleToCall)
AddText Me.Text1, "AddressID (internal)..." & Hex(Tapiline1.AddressID)
'
AddText Me.Text1, cLine ' msg separator
'
End Sub
Next, add a new function called GetVarInfo. This will be used to parse some of the return values from the GetDevCaps TAPI function. Place the code shown in Listing 26.15 into the GetVarInfo function.
Listing 26.15. The GetVarInfo function.
Function GetVarInfo(nSize As Long, nOffset As Long, cString As String, nLen As ÂLong) As String
Dim cValue As String
'
If nSize <> 0 Then
cValue = Mid(cString, ((nOffset - nLen - 3)), nSize)
Else
cValue = ""
End If
'
GetVarInfo = cValue
'
End Function
Next comes a routine to fill the LINECALLPARAMS data structure before placing a call. This takes a bit of coding, so it's better to place it in its own routine. You can modify this routine to contain parameters that meet your modem's specifications. Add a subroutine called FillCallParams and enter the code from Listing 26.16.
Listing 26.16. The FillCallParams routine.
Function GetVarInfo(nSize As Long, nOffset As Long, cString As String, nLen As ÂLong) As String
Dim cValue As String
'
If nSize <> 0 Then
cValue = Mid(cString, ((nOffset - nLen - 3)), nSize)
Else
cValue = ""
End If
'
GetVarInfo = cValue
'
End Function
The last support routine you need to code for this project is the one used to read the LINECALLINFO data structure. This structure is quite long and contains a great deal of data. This routine (LocalGetLineInfo) reads the data, cleans up the returned strings, and then calls a routine in the TAPICALL.BAS file to actually show the results. Add the code from Listing 26.17 to your form.
Listing 26.17. The LocalGetLineInfo routine.
Function GetVarInfo(nSize As Long, nOffset As Long, cString As String, nLen As ÂLong) As String
Dim cValue As String
'
If nSize <> 0 Then
cValue = Mid(cString, ((nOffset - nLen - 3)), nSize)
Else
cValue = ""
End If
'
GetVarInfo = cValue
'
End Function
So you've added the pre-built BAS modules and you've entered the support routines-now you're ready to build the real TAPI code! First, you need to add some code to the Form_Load and Form_Unload events. Listing 26.18 shows the code for the Form_Load event.
Listing 26.18. The Form_Load event code.
Private Sub Form_Load()
Text1 = ""
Me.Caption = "TAPILine Test Form"
'
Me.Left = (Screen.Width - Me.Width) / 2
Me.Top = (Screen.Height - Me.Height) / 2
'
cLine = String(80, 45) ' for message box
'
ClearHandles ' clear out control handles
'
End Sub
This code sets the form caption, centers the form on the screen, initializes a display line, and clears the handle values.
Next, add the Form_Unload event code shown in Listing 26.19.
Listing 26.19. The Form_Unload event code.
Private Sub Form_Unload(Cancel As Integer)
'
' be sure to close the line before leaving
'
Dim a As Long
a = Tapiline1.LineClose
'
End Sub
This code just makes sure the TAPI session is closed out before exiting the program.
The next code you need to add is the code for the TAPICallBack event of the TAPILINE1 control. All you need to do is pass the parameter list to the TAPICallBackHandler function and then display the results. Listing 26.20 shows the code you need to add to the TAPICallBack event.
Listing 26.20. Code for the TapiLine1_TapiCallBack event.
Private Sub Tapiline1_TapiCallBack(ByVal hDevice As Long, ByVal dwMessage As Long, ÂByVal dwInstance As Long, ByVal dwParam1 As Long, ByVal dwParam2 As Long, ByVal ÂdwParam3 As Long)
'
' send all messages to generic handler
'
Dim cMsg As String
'
cMsg = TapiCallBackHandler(hDevice, dwMessage, dwInstance, dwParam1, dwParam2, ÂdwParam3)
AddText Me.Text1, cMsg
'
AddText Me.Text1, cLine ' msg separator
'
End Sub
Now you're ready to start programming TAPI from Visual Basic! First add the code shown in Listing 26.21 to the cmdLineInit_Click event.
Listing 26.21. The cmdLineInit_Click code.
Private Sub cmdLineInit_Click()
'
' initialize TAPI interface'
'
Dim a As Long
'
a = Me.Tapiline1.LineInitialize("TAPITEST")
If a < 0 Then
AddText Me.Text1, "<<<ERROR>>> LineInit..." & LineErr(a)
End If
'
lNumDev = Tapiline1.NumDevices
AddText Me.Text1, "LineInit (NumDev: " & CStr(lNumDev) & ")"
'
AddText Me.Text1, cLine ' msg separator
'
End Sub
This code initializes TAPI services for your program and displays the number of TAPI devices by reading the property value set by the LineInitialize method.
Next add the code for the cmdLineNegAPI_Click event. This code walks through all the devices found by TAPI and makes sure they all support the current TAPI version. Add the code shown in Listing 26.22.
Listing 26.22. The cmdLineNegAPI_Click code.
Private Sub cmdLineNegApi_Click()
'
' get api info for all devices
'
Dim a As Long
Dim x As Integer
' 65536= 10000, 65540 = 10004 (version 1.0, version 1.4)
For x = 0 To lNumDev - 1
a = Me.Tapiline1.LineNegotiateAPIVersion(x, 65536, 65540)
If a < 0 Then
AddText Me.Text1, "<<<ERROR>>> LineNegAPI..." & LineErr(a)
Else
AddText Me.Text1, "LineNegAPI... Dev #" & CStr(x) & " OK"
End If
Next x
'
AddText Me.Text1, cLine ' msg separator
'
End Sub
Now save and run the project. After clicking the first two buttons, you should see a number of lines on your screen along with messages saying the API negotiation routine was successful (see Figure 26.5).
Figure 26.5 : Results from line initialize and NegAPI calls
The next set of code collects the device capabilities of all the line devices recognized by TAPI. Add the code from Listing 26.23 to the cmdLineGetDevCaps_Click event of the form.
Listing 26.23. The cmdLineGetDevCaps_Click code.
Private Sub cmdLineDevCaps_Click()
'
' display capabilites of each line
'
Dim a As Long
Dim b As LINEDEVCAPS
Dim c As String * 2048
Dim x As Integer
'
Dim nSize As Long
Dim nOffset As Long
Dim cValue As String
'
For x = 0 To lNumDev - 1
' make the call to get dev caps
a = Tapiline1.LineGetDevCaps(x)
If a < 0 Then
AddText Me.Text1, "<<<ERROR>>> DevCaps..." & LineErr(a)
End If
' read the results
LineDevCapsFunc TAPI_READ, b, c
'
' strip out non-printables
c = Clean
'
' show user device capabilities
AddText Me.Text1, "Line Device #" & CStr(x)
AddText Me.Text1, "TerminalCaps..." & GetVarInfo(b.dwTerminalCapsSize, b.dwTerminalCapsOffset, c, Len(b))
AddText Me.Text1, "ProviderInfo..." & GetVarInfo(b.dwProviderInfoSize, b.dwProviderInfoOffset, c, Len(b))
AddText Me.Text1, "TerminalText..." & GetVarInfo(b.dwTerminalTextSize, b.dwTerminalTextOffset, c, Len(b))
AddText Me.Text1, "DevSpecific..." & GetVarInfo(b.dwDevSpecificSize, b.dwDevSpecificOffset, c, Len(b))
AddText Me.Text1, "LineName..." & GetVarInfo(b.dwLineNameSize, b.dwLineNameOffset, c, Len(b))
AddText Me.Text1, "TotalSize..." & CStr(b.dwTotalSize)
AddText Me.Text1, "NeededSize..." & CStr(b.dwNeededSize)
AddText Me.Text1, "UsedSize..." & CStr(b.dwUsedSize)
AddText Me.Text1, "MaxNumActiveCalls..." & CStr(b.dwMaxNumActiveCalls)
AddText Me.Text1, cLine ' msg separator
Next x
'
End Sub
Not only does this routine get the capabilities of each device, the routine also displays the results in the text box on screen. You can scroll through this screen to inspect the various devices recognized by TAPI.
After initializing, negotiating the API, and getting the device capabilities, you are now ready to open a line for outbound calls. The code behind the cmdLineOpen_Click event will handle this task. Add the code from Listing 26.24 to the project.
Listing 26.24. The cmdLineOpen_Click event code.
Private Sub cmdLineOpen_Click()
'
' open a selected line
' and show results
'
Dim a As Long
Dim b As LINECALLPARAMS
Dim c As String * 2048
Dim s As String
Dim cValue As String
'
' get line number from user
nline = InputBox("Enter Line to Open:")
'
' perform the open
a = Me.Tapiline1.LineOpen(nline, 0, LINECALLPRIVILEGE_NONE, ÂLINEMEDIAMODE_INTERACTIVEVOICE)
If a < 0 Then
AddText Me.Text1, "<<<ERROR>>> LineOpen..." & LineErr(a)
End If
'
' get parameters
FillCallParams ' prep area first
LineCallParamsFunc TAPI_READ, b, c ' then read it
'
' show them to user
AddText Me.Text1, "TotalSize..." & CStr(b.dwTotalSize)
AddText Me.Text1, "BearerMode..." & CStr(b.dwBearerMode)
AddText Me.Text1, "MinRate..." & CStr(b.dwMinRate)
AddText Me.Text1, "MaxRate..." & CStr(b.dwMaxRate)
AddText Me.Text1, "MediaMode..." & CStr(b.dwMediaMode)
AddText Me.Text1, "CallParamFlags..." & CStr(b.dwCallParamFlags)
AddText Me.Text1, "AddressMode..." & CStr(b.dwAddressMode)
AddText Me.Text1, "AddressID..." & CStr(b.dwAddressID)
AddText Me.Text1, "OrigAddressSize..." & CStr(b.dwOrigAddressSize)
AddText Me.Text1, "OrigAddressOffset..." & CStr(b.dwOrigAddressOffset)
AddText Me.Text1, "Originating Address..." & GetOffset(Len(b), Âc;b.dwOrigAddressOffset, b.dwOrigAddressSize, c)
'
AddText Me.Text1, cLine ' msg separator
'
End Sub
You'll notice that the routine first prompts the user for a line number. For now, select a line that is capable of handling outbound voice calls. In a production application, you could inspect the values returned by the GetDevCaps method to locate a line device with the needed capabilities.
Next, the routine performs a line-open and then sets the LINECALLPARAMS structure and displays the results. Setting the LINECALLPARAMS structure will affect how the call is finally placed. This is optional. If no LINECALLPARAMS are set, TAPI will use the default values for the selected line device. Figure 26.6 shows how the status box looks after selecting a line and displaying the call parameters.
Figure 26.6 : Displaying call parameters on an open line
After a line is opened successfully, you are ready to place an outbound call. Add the code shown in Listing 26.25 in the cmdLineMakeCall_Click event.
Listing 26.25. The cmdLineMakeCall_Click event code.
Private Sub cmdLineMakeCall_Click()
'
' make a real call
'
Dim a As Long
Dim b As LINECALLPARAMS
Dim c As String * 2048
Dim cAddress As String
'
' read current parameters
LineCallParamsFunc TAPI_READ, b, c
'
' show them to the user
AddText Me.Text1, "TotalSize..." & CStr(b.dwTotalSize)
AddText Me.Text1, "BearerMode..." & CStr(b.dwBearerMode)
AddText Me.Text1, "MinRate..." & CStr(b.dwMinRate)
AddText Me.Text1, "MaxRate..." & CStr(b.dwMaxRate)
AddText Me.Text1, "MediaMode..." & CStr(b.dwMediaMode)
AddText Me.Text1, "CallParamFlags..." & CStr(b.dwCallParamFlags)
AddText Me.Text1, "AddressMode..." & CStr(b.dwAddressMode)
AddText Me.Text1, "AddressID..." & CStr(b.dwAddressID)
'
' get phone number to dial
cAddress = InputBox("Enter Address to Dial:", "Dialing String")
'
' make the call
a = Me.Tapiline1.LineMakeCall(cAddress, 1)
If a < 0 Then
AddText Me.Text1, "<<<ERROR>>> LineMakeCall..." & LineErr(a)
End If
'
AddText Me.Text1, cLine ' message separator
'
End Sub
This code reads the LINECALLPARAMS structure, displays the results, and then prompts the user for a phone number. After the number is entered, the LineMakeCall method is invoked to place the call.
Once the call is placed, several TAPI messages cross through the TAPICallBack event. When you run the program and place a call, you'll see the progress messages appear in the status box. Figure 26.7 shows an example of what you should see when you run the program.
Figure 26.7 : Monitoring call progress
The next three buttons handle code that drops the current call, de-allocates the line handle, and closes the line device. All these steps should occur at the end of a call. Listing 26.26 shows the code for the three button routines (cmdLineDrop, cmdLineDealloc, and cmdLineClose). Add this code to your project.
Listing 26.26. The cmdLineDrop, cmdLineDealloc, and cmdLineClose code.
Private Sub cmdLineDrop_Click()
'
' drop idle line
'
Dim lRtn As Long
'
lRtn = Tapiline1.LineDrop("", 0)
If lRtn < 0 Then
AddText Me.Text1, "<<<ERROR>>> LineDrop..." & LineErr(lRtn)
Else
AddText Me.Text1, "LineDrop Successful"
End If
'
AddText Me.Text1, cLine ' msg separator
'
End Sub
Private Sub cmdLineDeallocate_Click()
'
' de-allocate memory from unused line
'
Dim lRtn As Long
'
lRtn = Tapiline1.LineDeallocateCall
If lRtn < 0 Then
AddText Me.Text1, "<<<ERROR>>> LineDeallocateCall..." & LineErr(lRtn)
Else
AddText Me.Text1, "LineDeallocateCall Successful"
End If
'
Me.Tapiline1.HandleToCall = 0 ' clear call handle
'
AddText Me.Text1, cLine ' msg separator
'
End Sub
Private Sub cmdLineClose_Click()
'
' close open line
'
Dim a As Long
'
a = Tapiline1.LineClose
If a < 0 Then
AddText Me.Text1, "<<<ERROR>>> LineClose..." & LineErr(a)
Else
AddText Me.Text1, "Line Close Successful"
End If
'
Me.Tapiline1.LineHandle = 0 ' clear line handle
'
AddText Me.Text1, cLine ' msg separator
'
End Sub
Notice that the cmdLineDealloc_Click event contains code that clears the HandletoCall property of the TAPILine control. Also, the cmdLineClose_Click event contains code that clears the LineHandle property. It is a good idea to clear these handles when you are done with a call. Figure 26.8 shows how the status messages look as you drop, de-allocate, and close a line.
Figure 26.8 : Dropping de-allocating and closing the line
Those are the steps to completing an outbound call using the TAPILine control. The other routines in this project all illustrate additional line device functions you can access from the TAPILINE.OCX.
Once a line is open and a call is active, you can get call information about the line through the LineGetCallInfo method. You can also get information about the address originating the call (that's you!) using the LineGetAddressStatus method. Listing 26.27 shows the code for these two buttons. Add this code to your project.
Listing 26.27. The cmdLineGetCallInfo and cmdLineGetAddrStatus code.
Private Sub cmdLineGetInfo_Click()
'
' get lots of info on this line
'
LocalGetLineInfo
'
End Sub
Private Sub cmdLineAddrStatus_Click()
'
' get address status of the line
'
Dim udtAddr As LINEADDRESSSTATUS
Dim c As String * 2048
Dim lRtn As Long
'
' make the call to GetAddressStatus
lRtn = Tapiline1.LineGetAddressStatus
If lRtn < 0 Then
AddText Me.Text1, "<<<ERROR>>> LineGetAddressStatus..." & LineErr(lRtn)
Exit Sub
End If
'
' get the results
LineAddressStatusFunc TAPI_READ, udtAddr, c
'
' show them to user
AddText Me.Text1, "TotalSize..." & CStr(udtAddr.dwTotalSize)
AddText Me.Text1, "NeededSize..." & CStr(udtAddr.dwNeededSize)
AddText Me.Text1, "UsedSize..." & CStr(udtAddr.dwUsedSize)
AddText Me.Text1, "NumInUse..." & CStr(udtAddr.dwNumInUse)
AddText Me.Text1, "NumActiveCalls..." & CStr(udtAddr.dwNumActiveCalls)
AddText Me.Text1, "NumOnHoldCalls..." & CStr(udtAddr.dwNumOnHoldCalls)
AddText Me.Text1, "NumOnHoldPendCalls..." & CStr(udtAddr.dwNumOnHoldPendCalls)
AddText Me.Text1, "AddressFeatures..." & CStr(udtAddr.dwAddressFeatures)
AddText Me.Text1, "NumRingsNoAnswer..." & CStr(udtAddr.dwNumRingsNoAnswer)
AddText Me.Text1, "ForwardNumEntries..." & CStr(udtAddr.dwForwardNumEntries)
'
AddText Me.Text1, cLine ' msg separator
'
End Sub
The cmdLineGetCallInfo_Click code simply calls a routine you build earlier. This displays information about the active call on the specified line device. The cmdLineGetAddrStatus_Click code gets information about the originating address (or extension). When you run your project and place a call, you can monitor the call information and address status by pressing these two buttons during the call (see Figure 26.9).
Figure 26.9 : Checking call information and address status
You can also watch the values of call handles change as you progress through completing a call. Add the code shown in Listing 26.28 to the cmdShowHandles_Click event.
Listing 26.28. The cmdShowHandles_Click event code.
Private Sub cmdLineShowHandles_Click()
'
' show handle properties
'
ShowHandles
'
End Sub
Save the project and then run it. Now you can press the cmdShowHandles button at various times-while you open a line, place a call and then drop, de-allocate, and close the line-to monitor the creation and clearing of handles throughout the call process.
The TAPILINE control supports four dialog boxes that you can call from within Visual Basic. They are:
The About box is supplied by the TAPILINE control itself. All you need to do is call the AboutBox method (see Figure 26.10).
Figure 26.10 : The TAPILINE control About box
The Provider Configuration dialog box is called by using the LineConfigProvider method. This brings up a dialog box supplied by the TAPI Service Provider. The list of TAPI Service Providers is kept in the TELEPHON.INI file in the WINDOWS\SYSTEM directory.
Note |
You'll learn more about the TELEPHON.INI file in Chapter 27, "TAPI Behind the Scenes-The TELEPHON.INI File." |
Figure 26.11 shows the dialog box that appears on workstations where the UniModemV device driver is installed.
Figure 26.11 : The TAPI Services Provider dialog box
The Line Configuration dialog box is called using the LineConfigDialog method. This brings up a dialog box supplied by the operating system. Figure 26.12 shows an example line configuration dialog box.
Figure 26.12 : The TAPI line configuration dialog box
Tip |
Don't be confused by the similarity of the dialog boxes from the LineConfigDialog and the LineConfigProvider methods. The first method (LineConfigDialog) calls the dialog box for configuring the device associated with the selected line. The second method (LineConfigProvider) calls the dialog box for configuring the device access for the selected TAPI service provider. A TSP may have access to more than one device. That is why you can use the LineConfigProvider dialog box to access all the devices on the workstation, but you can only access one device from LineConfigDialog. |
The last dialog box supported by the TAPILINE control is the Dialing Properties dialog box. This is called using the LineTranslateDialog method. You must invoke the LineInitialize method before you call this dialog box. This is the only dialog box that requires that TAPI be up and running. Figure 26.13 shows the Dialing Properties dialog box.
Figure 26.13 : The Dialing properties dialog box
Listing 26.29 shows the code for the four buttons mentioned above. Add this code to your project.
Listing 26.29. The code for the dialog boxes.
Private Sub cmdLineAbout_Click()
'
' show TAPILine about box
'
Tapiline1.AboutBox
'
End Sub
Private Sub cmdLineConfProv_Click()
'
' call provider's config
'
Dim lRtn As Long
'
Tapiline1.PermanentProviderID = InputBox("Enter PermProviderID:")
AddText Me.Text1, "PermProvider..." & CStr(Tapiline1.PermanentProviderID)
lRtn = Tapiline1.LineConfigProvider(Me.hWnd)
If lRtn < 0 Then
AddText Me.Text1, "<<<ERROR>>> LineConfigProvider..." & LineErr(lRtn)
Else
AddText Me.Text1, "LineConfigProvider successfull"
End If
'
AddText Me.Text1, cLine ' msg separator
'
End Sub
Private Sub cmdLineConfDialog_Click()
'
' show config dialog(s)
'
Dim a As Long
Dim n As Integer
Dim x As Integer
Dim y As Integer
Dim z As Integer
'
' get a device from user
n = InputBox("Enter Device # (-1 for all):")
'
' set loop params
If n = -1 Then
' user wants them all!
y = 0
z = lNumDev - 1
Else
' user just wants one
y = n
z = n
End If
'
' call up dialog(s)
For x = y To z
a = Tapiline1.LineConfigDialog(x, Me.hWnd, "comm")
If a <> 0 Then
MsgBox LineErr(a), vbCritical, "lineConfigDialog Error!"
End If
Next x
'
End Sub
Private Sub cmdLineDialProps_Click()
'
' show the dialing properties dialog
'
Dim lReturn As Long
Dim nDevice As Integer
Dim x As Integer
'
' get device from user
nDevice = InputBox("Enter Device # (-1 for all):")
If nDevice <> -1 Then
' user wants just one
lReturn = Tapiline1.LineTranslateDialog(nDevice, Me.hWnd, "")
If lReturn <> 0 Then
MsgBox LineErr(lReturn), vbCritical, "LineTranslateDialog Error!"
End If
Else
' show them all to user
For x = 0 To lNumDev - 1
lReturn = Tapiline1.LineTranslateDialog(x, Me.hWnd, "")
If lReturn <> 0 Then
MsgBox LineErr(lReturn), vbCritical, "LineTranslateDialog Error!"
End If
Next x
End If
'
End Sub
That is all the code for the TAPITEST.VBP project. You can use the code here to place simple voice outbound calls and watch your progress using the status window. Later in this section, you use the code shown here to build a complete telephony application in Visual Basic.
In this chapter you learned the properties, methods, and events of the TAPILINE control found on the CD-ROM that accompanies this book. You also learned how to use this control to gain access to TAPI services from within Visual Basic programs.
You learned how to perform the following TAPI service requests:
You also learned how to monitor call progress using TAPI messages and the LineGetCallInfo and LineGetAddress methods. Finally, you learned how to call the four TAPI dialog boxes to gain access to configuration dialogs to customize your TAPI interface.
In the next chapter you'll learn about the TELEPHON.INI file. This file contains control information affected by the dialog boxes you learned about in this chapter.