📄 ch28.htm
字号:
</b></p>
</blockquote>
<blockquote>
<tt><font FACE="Courier"><p>Public Sub ClearHandles()<br>
'<br>
' set all control handles to zero<br>
'<br>
Tapiline1.LineHandle = 0<br>
Tapiline1.HandleToCall = 0<br>
Tapiline1.AddressID = 0<br>
'<br>
End Sub</font></tt> </p>
</blockquote>
<hr>
<p>These properties are all set when a call is accepted on a line device. Once a call is
ended, you need to clear these properties in preparation for the next call. </p>
<p>Save the form (<tt><font FACE="Courier">TAPIANS.FRM</font></tt>) and project (<tt><font
FACE="Courier">TAPIANS.VBP</font></tt>) before continuing. </p>
<h4>Adding the <tt><font FACE="Courier">TapiCallBack</font></tt> Event Code</h4>
<p>The next code you need to add to the project relates to detecting and responding to
TAPI messages (<tt><font FACE="Courier">TapiCallBack</font></tt>). The <tt><font
FACE="Courier">TapiCallBack</font></tt> event of the <tt><font FACE="Courier">TAPILINE</font></tt>
control receives all messages generated by the TAPI system. As mentioned in earlier
chapters, there are several different messages, each with their own set of accompanying
parameters </p>
<p align="center">.</p>
<div align="center"><center>
<table BORDERCOLOR="#000000" BORDER="1" WIDTH="80%">
<tr>
<td><b>Note</b></td>
</tr>
<tr>
<td><blockquote>
<p>For more information on TAPI messages, their use, and meaning, refer to <a
HREF="ch23.htm">Chapter 23</a>, "TAPI Architecture." </p>
</blockquote>
</td>
</tr>
</table>
</center></div>
<p>In this example, you need to keep track of only two messages:
<ul>
<li><tt><font FACE="Courier">LINE_CALLSTATE</font></tt> </li>
<li><tt><font FACE="Courier">LINE_CLOSE</font></tt> </li>
</ul>
<p>The <tt><font FACE="Courier">LINE_CALLSTATE</font></tt> message is sent whenever the
state of the selected line has changed. This program will watch for messages that indicate
there is a new call on the line (<tt><font FACE="Courier">dwParam1 = LINECALLSTATE_OFFERED</font></tt>)
or when the party on the other end of the line closed the call unexpectedly (<tt><font
FACE="Courier">dwParam1 = LINECALLSTATE_IDLE</font></tt>). The <tt><font FACE="Courier">LINE_CLOSE</font></tt>
message is sent whenever the user ends the call normally. </p>
<p>You can monitor the message activity by adding code to the <tt><font FACE="Courier">TapiCallBack</font></tt>
event that checks each message sent by TAPI. This is done using a <tt><font FACE="Courier">SELECT
CASE</font></tt> structure to compare the incoming message to a list of messages for which
you are waiting. The code in Listing 28.7 shows how this is done. Add this code to the <tt><font
FACE="Courier">TapiCallBack</font></tt> event. </p>
<hr>
<blockquote>
<b><p>Listing 28.7. Adding code to the <tt><font FACE="Courier">TapiCallBack</font></tt>
event.<br>
</b></p>
</blockquote>
<blockquote>
<tt><font FACE="Courier"><p>Private Sub Tapiline1_TapiCallBack(ByVal hDevice As Long,
ByVal dwMessage As Long, <font FACE="ZAPFDINGBATS">Â</font>ByVal dwInstance As Long,
ByVal dwParam1 As Long, ByVal dwParam2 As Long, ByVal <font FACE="ZAPFDINGBATS">Â</font>dwParam3
As Long)<br>
'<br>
' handle TAPI messages<br>
'<br>
Dim cMsg As String<br>
'<br>
' handle call actions<br>
Select Case dwMessage<br>
Case LINE_CALLSTATE ' state of call on
line changed<br>
Select Case
dwParam1<br>
Case
LINECALLSTATE_OFFERING ' get call handle<br>
Tapiline1.HandleToCall
= hDevice ' update handle to call<br>
MMControl1.Command
= "play" ' ring me!<br>
Case
LINECALLSTATE_IDLE ' they hung up on me!<br>
Tapiline1.LineDeallocateCall
' dump pointer<br>
Tapiline1.HandleToCall
= 0 ' clear property<br>
AddText
txtStatus, "LineDeallocate Successful"<br>
End Select<br>
Case LINE_CLOSE ' line was closed<br>
cmdButton_Click 2
' force hangup<br>
End Select<br>
'<br>
' report status to user<br>
cMsg = TapiCallBackHandler(hDevice, dwMessage, dwInstance,
dwParam1, dwParam2, <font FACE="ZAPFDINGBATS">Â</font>dwParam3)<br>
AddText txtStatus, cMsg<br>
'<br>
End Sub</font></tt> </p>
</blockquote>
<hr>
<p>The code in Listing 28.7 shows the <tt><font FACE="Courier">SELECT CASE</font></tt>
structure monitoring two messages-<tt><font FACE="Courier">LINE_CALLSTATE</font></tt> and <tt><font
FACE="Courier">LINE_CLOSE</font></tt>. When the <tt><font FACE="Courier">LINE_CALLSTATE</font></tt>
message appears, additional checking is performed to determine the exact state of the
call. If a new call is appearing on the line (<tt><font FACE="Courier">LINECALLSTATE_OFFERING</font></tt>),
the program updates the <tt><font FACE="Courier">HandleToCall</font></tt> property and
then rings the workstation to tell the user a call is coming in. </p>
<p>If the call state has changed to completed (<tt><font FACE="Courier">LINECALLSTATE_IDLE</font></tt>),
the routine releases memory allocated to the call and clears the <tt><font FACE="Courier">HandleToCall</font></tt>
property in preparation for the next incoming call. </p>
<p>When the <tt><font FACE="Courier">LINE_CLOSE</font></tt> message appears, that means
the user has completed the call. The code here makes a call to the <tt><font
FACE="Courier">cmdButton</font></tt> array that will act as if the user pressed the <tt><font
FACE="Courier">HangUp</font></tt> button (you'll code that in just a moment). </p>
<p>You'll also notice that the routine contains calls to the <tt><font FACE="Courier">TapiCallBackHandler</font></tt>
function. This function interprets the TAPI message and creates a text string that can be
shown to the user to indicate the progress of the call. </p>
<h4>Coding the <tt><font FACE="Courier">cmdButton</font></tt> Array</h4>
<p>The last code you need to add will handle the user's actions on the command buttons.
There are four possible actions that the user can select:
<ul>
<li><tt><font FACE="Courier">Start</font></tt> opens the selected line for incoming calls. </li>
<li><tt><font FACE="Courier">Answer</font></tt> is used to accept an incoming (ringing)
call. </li>
<li><tt><font FACE="Courier">HangUp</font></tt> is used to end a call connection. </li>
<li><tt><font FACE="Courier">Exit</font></tt> ends TAPI services and stops the program. </li>
</ul>
<p>Listing 28.8 shows the complete code for the <tt><font FACE="Courier">cmdButton_Click</font></tt>
event. </p>
<hr>
<blockquote>
<b><p>Listing 28.8. The code for the <tt><font FACE="Courier">cmdButton_Click</font></tt>
event.<br>
</b></p>
</blockquote>
<blockquote>
<tt><font FACE="Courier"><p>Private Sub cmdButton_Click(Index As Integer)<br>
'<br>
' open a line for monitoring<br>
'<br>
Dim lRtn As Long<br>
Dim lPrivilege As Long<br>
Dim lMediaMode As Long<br>
'<br>
' check for start up selection only<br>
If Index = 0 Then<br>
If lstLines.ListIndex = -1 Then<br>
MsgBox
"Select a line first!", vbInformation<br>
Exit Sub<br>
End If<br>
End If<br>
'<br>
' set line parameters<br>
lPrivilege = LINECALLPRIVILEGE_OWNER + LINECALLPRIVILEGE_MONITOR<br>
lMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE <br>
'<br>
' react to user selection<br>
Select Case Index<br>
Case 0 ' start looking<br>
lRtn =
Tapiline1.LineOpen(lstLines.ListIndex, 0, lPrivilege, <font FACE="ZAPFDINGBATS">Â</font>lMediaMode)
<br>
If lRtn < 0
Then<br>
AddText
txtStatus, "<<LineOpen ERROR>> " & LineErr(lRtn) <br>
Else <br>
AddText
txtStatus, "LineOpen Successful"<br>
AddText
txtStatus, "Waiting for an incoming call..."<br>
'
<br>
cmdButton(0).Enabled
= False<br>
cmdButton(1).Enabled
= True<br>
cmdButton(2).Enabled
= True<br>
'
<br>
End If<br>
Case 1 ' answer call<br>
lRtn =
Tapiline1.LineAnswer("", 0) ' only needed for ISDN <br>
If (lRtn < 0)
Then<br>
AddText
txtStatus, "<<LineAnswer ERROR>> " & LineErr(lRtn)<br>
Else <br>
AddText
txtStatus, "LineAnswer Successful"<br>
End If<br>
Case 2 ' disconnect call<br>
Tapiline1.LineDrop
"", 0 ' no parms unless ISDN!<br>
Tapiline1.LineClose
<br>
' <br>
cmdButton(0).Enabled
= True<br>
cmdButton(1).Enabled
= False<br>
cmdButton(2).Enabled
= False<br>
' <br>
ClearHandles '
clean up control handles<br>
AddText txtStatus,
"Line Dropped and Closed"<br>
Case 3 ' exit program<br>
Unload Me<br>
End Select<br>
'<br>
End Sub</font></tt> </p>
</blockquote>
<hr>
<p>There's a lot going on in this code section, so it is worth reviewing in greater
detail. </p>
<p>First, if the user has pressed the <tt><font FACE="Courier">Start</font></tt> button,
the code checks to make sure a line device has been selected from the list box. If no line
device was selected, the user gets an error message, and the code exits the procedure (see
Listing 28.9). </p>
<hr>
<blockquote>
<b><p>Listing 28.9. Checking for a selected line device.<br>
</b></p>
</blockquote>
<blockquote>
<tt><font FACE="Courier"><p>' check for start up selection only<br>
If Index = 0 Then<br>
If lstLines.ListIndex = -1 Then<br>
MsgBox
"Select a line first!", vbInformation<br>
Exit Sub<br>
End If<br>
End If</font></tt> </p>
</blockquote>
<hr>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -