You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取TAPI的HCALL句柄以实现呼叫盲转?

How to Get HCALL Handle for Blind Transfer with TAPI in Excel VBA

The tapiRequestMakeCall function you're using is a simplified high-level TAPI API that only handles initiating calls—it doesn't expose the HCALL handle you need for lineBlindTransfer. To implement blind transfer, you'll need to use the full low-level TAPI 1.x functions, which give you direct access to call handles and call state events.

Here's a step-by-step solution with code:

Step 1: Declare Required TAPI Functions and Structures

First, add these declarations to a standard VBA module (not a class module or worksheet module):

' TAPI Constants
Const LINEERR_BASE = 0
Const LINEERR_OPERATIONFAILED = (LINEERR_BASE + 4)
Const LINEERR_INVALAPPHANDLE = (LINEERR_BASE + 5)
Const LINEERR_RESOURCEUNAVAIL = (LINEERR_BASE + 8)
Const LINEERR_INVALLINEHANDLE = (LINEERR_BASE + 10)
Const LINEERR_INVALCALLHANDLE = (LINEERR_BASE + 12)
Const LINEERR_INVALADDRESS = (LINEERR_BASE + 13)
Const LINECALLSTATE_IDLE = 0
Const LINECALLSTATE_CONNECTED = 5
Const LINECALLPRIVILEGE_OWNER = 2
Const LINEOPENOPTION_NONE = 0
Const LINEINITIALIZEEXOPTION_USEEVENT = &H80000000

' TAPI Structures
Type LINEINITIALIZEEXPARAMS
    dwTotalSize As Long
    dwNeededSize As Long
    dwUsedSize As Long
    dwOptions As Long
    hEvent As Long
End Type

Type LINEOPENPARAMS
    dwTotalSize As Long
    dwNeededSize As Long
    dwUsedSize As Long
    dwDeviceID As Long
    dwPrivilege As Long
    dwMediaModes As Long
    dwLineNameSize As Long
    dwLineNameOffset As Long
End Type

' TAPI Function Declarations
Declare Function lineInitializeEx Lib "tapi32.dll" ( _
    lphLineApp As Long, _
    ByVal hInstance As Long, _
    ByVal lpfnCallback As Long, _
    ByVal lpszAppName As String, _
    lpdwNumDevs As Long, _
    lpdwAPIVersion As Long, _
    lpLineInitializeExParams As LINEINITIALIZEEXPARAMS _
) As Long

Declare Function lineOpen Lib "tapi32.dll" ( _
    ByVal hLineApp As Long, _
    ByVal dwDeviceID As Long, _
    lphLine As Long, _
    ByVal dwAPIVersion As Long, _
    ByVal dwExtVersion As Long, _
    ByVal dwCallbackInstance As Long, _
    ByVal dwPrivilege As Long, _
    ByVal dwMediaModes As Long, _
    lpLineOpenParams As LINEOPENPARAMS _
) As Long

Declare Function lineMakeCall Lib "tapi32.dll" ( _
    ByVal hLine As Long, _
    lphCall As Long, _
    ByVal lpszDestAddress As String, _
    ByVal dwCountryCode As Long, _
    lpCallParams As Any _
) As Long

Declare Function lineBlindTransfer Lib "tapi32.dll" ( _
    ByVal hCall As Long, _
    ByVal lpszDestAddress As String, _
    ByVal dwCountryCode As Long _
) As Long

Declare Function lineGetCallStatus Lib "tapi32.dll" ( _
    ByVal hCall As Long, _
    lpCallStatus As Any _
) As Long

Declare Function lineDeallocateCall Lib "tapi32.dll" ( _
    ByVal hCall As Long _
) As Long

Declare Function lineClose Lib "tapi32.dll" ( _
    ByVal hLine As Long _
) As Long

Declare Function lineShutdown Lib "tapi32.dll" ( _
    ByVal hLineApp As Long _
) As Long

' Callback function to handle TAPI events (simplified for this example)
Sub TapiCallback(ByVal hLineApp As Long, ByVal hDevice As Long, ByVal dwMessage As Long, ByVal dwCallbackInstance As Long, ByVal dwParam1 As Long, ByVal dwParam2 As Long, ByVal dwParam3 As Long)
    ' You can add logic here to track call state changes
    ' For this example, we'll rely on polling call status instead
End Sub

Step 2: Implement the Call and Transfer Workflow

Add this subroutine to handle dialing, waiting for connection, and performing blind transfer:

Sub DialAndBlindTransfer(ByVal originalNumber As String, ByVal transferNumber As String)
    Dim hLineApp As Long
    Dim numDevices As Long
    Dim tapiVersion As Long
    Dim initParams As LINEINITIALIZEEXPARAMS
    Dim openParams As LINEOPENPARAMS
    Dim hLine As Long
    Dim hCall As Long
    Dim callStatus As Long
    Dim result As Long
    
    ' Initialize TAPI
    initParams.dwTotalSize = Len(initParams)
    initParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT
    result = lineInitializeEx(hLineApp, 0, AddressOf TapiCallback, "Excel TAPI Call", numDevices, tapiVersion, initParams)
    If result < 0 Then
        MsgBox "TAPI initialization failed. Error code: " & result, vbCritical
        Exit Sub
    End If
    
    ' Open the first available line device (adjust device ID if needed)
    openParams.dwTotalSize = Len(openParams)
    openParams.dwPrivilege = LINECALLPRIVILEGE_OWNER
    result = lineOpen(hLineApp, 0, hLine, tapiVersion, 0, 0, LINECALLPRIVILEGE_OWNER, 0, openParams)
    If result < 0 Then
        MsgBox "Failed to open line. Error code: " & result, vbCritical
        lineShutdown hLineApp
        Exit Sub
    End If
    
    ' Make the initial call (returns HCALL directly)
    result = lineMakeCall(hLine, hCall, originalNumber, 0, ByVal 0&)
    If result < 0 Then
        MsgBox "Failed to dial number. Error code: " & result, vbCritical
        lineClose hLine
        lineShutdown hLineApp
        Exit Sub
    End If
    
    ' Wait for the call to connect (simple polling example)
    Do
        ' Get current call status
        result = lineGetCallStatus(hCall, callStatus)
        If result < 0 Then
            MsgBox "Failed to get call status. Error code: " & result, vbCritical
            Exit Do
        End If
        DoEvents ' Allow Excel to respond to user input
        Sleep 1000 ' Wait 1 second between checks (adjust as needed)
    Loop Until callStatus = LINECALLSTATE_CONNECTED
    
    ' Perform blind transfer once connected
    If callStatus = LINECALLSTATE_CONNECTED Then
        result = lineBlindTransfer(hCall, transferNumber, 0)
        If result < 0 Then
            MsgBox "Blind transfer failed. Error code: " & result, vbCritical
        Else
            MsgBox "Call transferred successfully to " & transferNumber, vbInformation
        End If
    End If
    
    ' Clean up resources
    lineDeallocateCall hCall
    lineClose hLine
    lineShutdown hLineApp
End Sub

' Helper function for sleep (required for polling)
Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMilliseconds As Long)

Key Notes:

  • HCALL Acquisition: Unlike tapiRequestMakeCall, lineMakeCall directly returns the HCALL handle in the lphCall parameter—this is exactly what you need to pass to lineBlindTransfer.
  • Call State Handling: The example uses simple polling with lineGetCallStatus to wait for the call to connect. For a more robust solution, expand the TapiCallback function to listen for LINE_CALLSTATE events instead of polling (this avoids unnecessary delays and is more efficient).
  • Device ID: The code uses the first available line device (ID 0). If you have multiple TAPI devices, use lineGetDevCaps to enumerate devices and select the correct one.
  • Error Handling: Always check TAPI function return values—negative values indicate errors (refer to TAPI documentation for specific error code meanings).

To test this, call the subroutine like this:

Sub TestTransfer()
    DialAndBlindTransfer "555-1234", "555-5678"
End Sub

内容的提问来源于stack exchange,提问作者hmak.soft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:50:23