子佩电话录音盒连接示例


官方网站为本节内容提供了示例,下载地址:
http://www.foxtable.com/samples/caller.rar

本节的任务是设计一个窗口,以软件方式实现电话终端的管理。本例实现来电弹屏、通话录音存储、通话详单记录、自动答录、快速拨号等多项功能

. 录音盒

本节的例子以南京子佩软件科技有限公司子佩录音盒为例,该公司的网址:

http://www.luyin888.com/

需要说明的是,该公司和我们没有任何关系,类似的电话录音盒有很多,大家可以根据需要选择。

. 录音盒连接

根据说明书,连接好电话录音盒设备,并安装好设备驱动程序,正常情况下,在Windows的设备管理中,会出现下面一项:

这就是录音盒设备。

. Foxtable示例

3.1 使用SDK

3.1.1根据该设备的开发文档,将其SDK文件复制到Foxtable的安装目录下,该设备的SDK文件包括qnviccub.dllbridge.dll两个必须的DLL文件。

在编写本节内容时,其SDK的最新版本是6.6

提示:由于他们的开发包是传统的非托管DLL,所以只需复制到Foxtable安装目录即可使用,千万不要再去引用这些DLL文件。

3.2.2. 参考开发文档和例子,在全局代码中定义好API函数和必须的全局变量,由于内容较多,具体请看示例。

3.2 设计数据表

示例设计了三个表进行电话录音管理示例,具体应用需要根据实际情况自行设计表格进行管理: 

"电话记录"主要记录一次呼叫从摘机到挂机的通讯状态;表"用户管理"用来管理联系人和电话号码;表"设置"用来记录示例的一些配置。

3.3 设计设备管理窗口

例设计了一个窗口(电话录音基本功能演示)来进行设备的控制操作。

窗口分为左右2个部分,左边是设备控制,右边是设备的通讯状态。通讯状态在窗口关闭后会追加到日志文件“通讯状态.txt”中,日志文件默认保存在项目所在目录中。

3.3.1 打开设备

要使用设备必须先调用SDK打开设备,根据开发文档,打开设备的调用为:

 Dim lret As Int32 = BriSDKLib.QNV_OpenDevice(BriSDKLib.ODT_LBRIDGE, 0, "")

如果返回值大于0,则设备打开成功,设备LED灯亮。

然后就可以获取设备可用的通道数,一个设备至少有一个通道,获取通道的函数调用为:

BriSDKLib.QNV_DevInfo(0, BriSDKLib.QNV_DEVINFO_GETCHANNELS)

全部代码参考示例打开设备按钮的Click事件代码。如果想一打开窗口就自动打开设备,可以把打开设备的调用放到窗口的AfterLoad事件中。甚至,可以把打开设备的调用放到项目的AfterOpenProject事件中,那么一打开项目就可以打开设备进行监控,不用再手动操作。

3.3.2 关闭设备

    设备不用的时候,关闭设备,释放资源,关闭设备的函数调用为:

BriSDKLib.QNV_CloseDevice(BriSDKLib.ODT_ALL, 0)

示例同样在关闭窗口的事件BeforeClose中调用执行了关闭操作。如果打开设备是在项目的AfterOpenProject事件中,那么建议在项目的BeforeCloseProject中关闭设备,避免占用设备的通道,而导致无法再次被使用

3.4 设备消息处理

该设备主要使用了消息发布的方式来触发相应的事件,所以我们在全局代码定义一个自定义类进行通讯事件处理,类名称FormEventReport,类定义为: 

Public Class FormEventReport

Inherits System.Windows.Forms.Form

......

End Class 

FormEventReport类使用之前必须先打开设备。 

FormEventReport类继承自System.Windows.Forms.Form,所以实际上就是一个自定义的窗体,这样我们就可以重载基类中的DefWndProc过程来接收设备的事件消息。

首先在FormEventReport的Load过程中给设备的所有通道注册事件信息:

Private Sub FormCall_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

For i As Int16 = 0 To BriSDKLib.QNV_DevInfo(0, BriSDKLib.QNV_DEVINFO_GETCHANNELS) - 1

    'windowproc处理所有通道接收到的消息

    BriSDKLib.QNV_Event(i, BriSDKLib.QNV_EVENT_REGWND, CType(Me.Handle, Int32), "", New StringBuilder(0), 0)

Next

vars("IsEventFormOpened") = True

End Sub


然后重载DefWndProc过程,判断接收到的消息参数,进行相应的操作:
 

Protected Overrides Sub DefWndProc(ByRef m As System.Windows.Forms.Message) 

Select Case m.Msg

    Case BriSDKLib.BRI_EVENT_MESSAGE

        If True Then

            Dim EventData As BriSDKLib.TBriEvent_Data = DirectCast(Marshal.PtrToStructure(m.LParam, Gettype(BriSDKLib.TBriEvent_Data)), BriSDKLib.TBriEvent_Data)

            Select Case EventData.lEventType

                Case BriSDKLib.BriEvent_PhoneHook '电话机摘机

                    AppendStatus("电话机摘机",EventData.uChannelID)

                    drCurrentRow = DataTables("电话记录").AddNew()

                    Tables("电话记录").Position = Tables("电话记录").Rows.Count-1

                    AppendCallRecord("电话机摘机",EventData.uChannelID)

                    Exit Select

                Case BriSDKLib.BriEvent_PhoneHang '电话机挂机

......

......

End Sub

 

这里只是部分代码,完整代码请查看示例。 

做法无非就是根据系统的消息,判断是否是本录音设备的消息,如果是,则取得消息中返回的设备信息,判断是设备的那个消息类型,来进行对应的操作。比如判断到是设备的摘机事件(BriEvent_PhoneHook),就增加一条电话记录。 

示例定义了一个全局的FormEventReport类型变量EventForm,在打开设备后创建EventForm的实例,打开窗体后隐藏起来即可。因为这个窗体设计只是用来接收系统消息的,所以不需要显示。 

最后在关闭设备的时候记得注销设备的消息处理,如本示例写在关闭设备按钮中:

'删除事件接收

For i As Integer = 0 To cboCurChn.Items.Count - 1

    BriSDKLib.QNV_Event(i,BriSDKLib.QNV_EVENT_UNREGWND,CType(basemainform.Handle, Int32),Nothing,Nothing,0)

Next

3.5 用户管理

在“电话记录”单元格中右键点击,出现有“添加联系人”菜单,点击后会转到“用户管理”表,如果已经有同一个电话号码的记录,则定位到相应的记录;如果没有,则会增加一条记录,默认添加上电话号码。

3.6 其它

3.6.1 关于设备返回值

SDK某些函数的调用,返回字符串的,实际是返回了字符串的内存起始地址,即Intptr类型。所以示例使用Marshal.PtrToStructure将数据从非托管内存块封送到新分配的指定类型的托管对象中。示例定义了TBriEvent_Data结构(位于SDK库类BriSDKLib中)和CallLog_Data结构(全局代码)来取得非非托管内存块数据。例如CallLog_Data用法如下: 

1. 定义结构: 

'呼叫信息结构,用于号码,录音文件路径等

<StructLayout(LayoutKind.Sequential)> _

Public Structure CallLog_Data

<MarshalAs(UnmanagedType.ByValArray, SizeConst: = BriSDKLib.MAX_BRIEVENT_DATA)> _

Public szData As [Byte]()

End Structure 

由于未知返回值的长度是多少,所以示例统一使用SDK定义的MAX_BRIEVENT_DATA值,即600字节 

2. 获取返回的地址 

如获取呼叫号码:

Dim ipt As IntPtr = BriSDKLib.QNV_CallLog(EventData.uChannelID,BriSDKLib.QNV_CALLLOG_CALLID,Nothing,BriSDKLib.MAX_BRIEVENT_DATA) 

3. 将数据从非托管内存块封送到新分配的CallLog_Data结构中 

Dim  calllogData As CallLog_Data = DirectCast(Marshal.PtrToStructure(ipt , Gettype(CallLog_Data)), CallLog_Data) 

4. 使用Encoding.Default.GetString转换结构中的字节数组,目前封装在示例的函数ByteArrayToString中,如: 

ByteArrayToString(calllogData.szData) 

需要注意的是,转换后的字节数组长度是600字节,内容是大于实际返回值的,其中多余的字节中的数据必须处理掉,不然就会返回一些乱码,还好正常返回值后是以Null字符(chr(0))结束的,所以ByteArrayToString函数中判断取得第一个Null字符,截断后面的内容。


本页地址:http://www.foxtable.com/webhelp/topics/3045.htm