如何获取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,lineMakeCalldirectly returns theHCALLhandle in thelphCallparameter—this is exactly what you need to pass tolineBlindTransfer. - Call State Handling: The example uses simple polling with
lineGetCallStatusto wait for the call to connect. For a more robust solution, expand theTapiCallbackfunction to listen forLINE_CALLSTATEevents 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
lineGetDevCapsto 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
相关产品推荐
相关产品推荐

