~~~ 1500分 ~~~ 求救!用moden接收电话端的按键信息。急! (多加1200分) (300分)

  • 主题发起人 主题发起人 qinqijun
  • 开始时间 开始时间
Q

qinqijun

Unregistered / Unconfirmed
GUEST, unregistred user!
怎么做呀?我现在已经可以用createfile,writefile,readfile三个函数打开moden并接收和发送数据,也可以通过moden的at命令接电话和挂机及拨打电话。但就是无法在接通电话后检测到电话那一边的按键信息!急!!!!!
delphi6实现。哪个大哥来救救命呀,等着用的。QQ号:21107482,qinqijun@163.com。手机:13978070120(广西柳州)。
多谢了多谢了,在下将不胜感激。如果真的能够实现该功能,我手上的1200分将全部给出来!
 
可能要录音,然后分析它的频谱吧
 
不用的!我看过资料,直接从 moden 取它的 DTMF 码就可以实现!现在的 moden 也都有这个功能,但是就是不知道怎么用程序去取得它。
 
用Async Professional控件,一切搞定。
推荐
《Delphi串口及语音传真高级编程》

温锦山 wenjinshan@163.net http://wenjinshan.yeah.net
唐柱鹏 tzhp@163.com http://tzhp.yeah.net
 
如果你用的是 Windows NT/2000/XP的话可以参考一下msdn关于IRTCClient的描述,
或许有帮助。
 
TAPI(Telphony Application Programming Interface)可以称作电话编程接口,它是微软提供的计算机和电话网相联系的编程接口,使程序员可以利用这个接口通过电话线使用多种计算机复杂的通讯工作。TAPI能提供的功能主要有:自动拨号;以文件、传真、电子邮件的方式传送文件;访问Internet或其他形式信息服务、组织会议呼叫、使用主叫识别处理入呼叫、计算机间通过电话线的互相协作。这里提到的有的功能很早就已经广泛应用了,还有一些由于我国交换设备不提供此类功能很少问津。这里笔者不想对TAPI能实现什么功能多加讨论,只就编程谈一点体会。
  促使笔者利用TAPI编写程序主要是由于工作中经常需要发传真,而每个传真都需要确认,如果电话是功能最少的那种,每次都要花大量的时间在上面。如果确认时再没人应答,之后再来一次,效率就更低了。因此,笔者想到利用TAPI编写一个程序能用MODEM自动拨号,通话结束后记录一下内容,省了每次辛苦地看着号码拨号。下面将程序与读者共享。
  笔者利用delphi作为开发工具,原因主要是delphi开发程序方便快捷,同时数据库的使用比较简单。使用过Visual C++的朋友都知道它的帮助是十分详细的,笔者开发的许多程序都参考了其中的WIN32 SDK帮助,尤其是在编写TAPI程序时,仔细地研究了其中的TAPI部分。使用VC编写TAPI程序可以利用现成的“tapi.h”头文件,但使用delphi就需要将C++版本的头文件翻译成Object Pascal的格式,再将“tapi32.dll”中的函数引用到头文件中来。幸好这项工作不用我们去做,从Inprise公司的站点可以获得delphi 关于TAPI编程的头文件,省了不少事,笔者的头文件tapi.pas是Davide Moretti编写的,如果需要的朋友可以通过报社和笔者联系。
  首先介绍程序中用到的几个函数:lineInitialize、lineNegotiateAPIVersion、lineOpen、lineMakeCall、lineHandOff、lineShutDown、lineConfigDialog、lineCallBackProc、lineGetIcon。函数的使用过程依次是:lineInitialize初始化线路、lineNegotiateAPIVersion确定TAPI版本号、lineOpen 打开线路、lineConfigDialog显示线路设备属性、lineMakeCall自动拨出电话号码、
lineGetIcon获得线路设备图标的句柄、lineHandOff将MODEM控制线路权转到用户、lineShutDown关闭线路。这里所用的函数名和tapi32.dll中输出的函数名相同。
  由于delphi和VC中类型定义的区别,笔者有必要举例说明函数定义在VC和delphi中的区别。以lineInitialize为例,在VC中定义为
LONG lineInitialize(LPHLINEAPP lphLineApp,HINSTANCE hInstance,LINECALLBACK lpfnCallback,LPCSTR lpszAppName,LPDWORD lpdwNumDevs)。lphLineApp是线路TAPI应用的句柄指针,hInstance是实例指针,lpfnCallback指向呼叫返回处理函数,lpszAppName指向用户提供的应用程序名字符串,lpdwNumDevs指向可供使用的线路设备个数。在delphi文件tapi.pas中对此函数的定义如下:
  function lineInitialize(var lphLineApp: THLineApp;hInstance: HInst;
lpfnCallback: TLineCallback;
  lpszAppName: PChar;var lpdwNumDevs: Longint): Longint;
  其中我们定义THLineApp、TLineCallback为指向Longint的指针(&LongInt)。其他函数的定义类推,分别用delphi中的相应类型代替,如果是长指针如句柄指针可以用“&LongInt”来定义。
  下面介绍程序的代码部分,在此笔者假定读者具备delphi数据库和一般编程基础。首先用Database Desktop建立两个Paradox7表,分别为“workphone.db”和“friendphone.db”。在主form上放置TTable、TDataSource、TDBGrid、TPopupMenu控件。程序定义sAppDir:string保存应用程序所在目录,设置sAppDir:=GetCurrentDir。在弹出式菜单中定义两个过程分别在TDBGrid中载入两个数据库表。
  procedure TMainForm.friendphoneClick(Sender: TObject);
  begin
  MainForm.Table1.Active:=False;
  MainForm.Table1.TableName:=sAppDir+‘friendphone.db’;
  MainForm.Caption:=‘自动拨号——朋友电话’;
  MainForm.Table1.Active:=True;
  end;
  
  procedure TMainForm.selectclassmateClick(Sender: TObject);
  begin
  MainForm.Table1.Active:=False;
  MainForm.Table1.TableName:=sAppDir+‘workphone.db’;
  MainForm.Caption:=‘自动拨号——工作电话’;
  MainForm.Table1.Active:=True;
  end;
  将TDBGrid的Options属性中的dgEditing设为True,允许用户直接修改表中的内容。在弹出菜单中定义DialPhone和DeleteRecord分别用于拨打电话号码和删除当前记录。下面主要介绍拨打电话的TAPI应用部分。电话号码是通过 MainForm.Table1.Fields.Fields[0].AsString作为字符串来传递的。
  实现的代码部分如下,其中为了文章不会太长笔者省去了不必要的错误提示和部分代码。
  变量定义
   lineApp:THLineApp;//TAPI应用句柄
   line:THLine;//线路句柄
   call:THCall;//呼叫句柄
   CallParams:TLineCallParams;//呼叫参数
   nDevs,tapiVersion,errorcode:Longint;//线路设备数、TAPI版本号、错误代码
   extid:TLineExtensionID;//TAPI扩展版本号
   lineIcon:HICON;//线路设备图标
   过程定义
   procedure lineCallback(hDevice, dwMsg, dwCallbackInstance,
   dwParam1, dwParam2, dwParam3: LongInt);//异步呼叫返回处理函数
  {$IFDEF WIN32}
   stdcall;
  {$ELSE}
   export;
  {$ENDIF}
   var
   hCall: THCall;
   begin
   if dwMsg = LINE_REPLY then { LineMakeCall的响应结果}
   if dwParam2 < 0 then {呼叫响应错误处理};
   else if dwMsg = LINE_CALLSTATE then { 呼叫状态信息 }
   begin
   hCall := THCall(hDevice); //类型转换 THCall为LongInt类型
   case dwParam1 of
   LINECALLSTATE_IDLE: {呼叫无效处理}
   if hcall <> 0 then
   begin
   lineDeallocateCall(hCall);
   end;
  LINECALLSTATE_PROCEEDING:{呼叫正常处理}
  LINECALLSTATE_DIALTONE:{检测到拨号音}
   LINECALLSTATE_DIALING: {正在拨号}
  LINECALLSTATE_DISCONNECTED:{连接已断开}
   begin{断开原因}
  if dwParam2=LINEDISCONNECTMODE_NORMAL then{正常断开}
  else if dwParam2=LINEDISCONNECTMODE_BUSY then {线路忙}
   LINECALLSTATE_BUSY:{线路忙处理}
   end;
   end;
  procedure TDialForm.(dialnumber:string);//dialnumber为电话号码字符串
  begin
  with CallParams do {CallParams的类型参考VC中的定义,将DWORD改为LongInt}
   begin
   dwTotalSize := sizeof(CallParams);
  dwBearerMode := LINEBEARERMODE_VOICE;//承载模式为语音
  dwMediaMode:=LINEMEDIAMODE_INTERACTIV
  EVOICE;//媒体模式为交互式语音
   end;
   if lineInitialize(lineApp,HInstance,lineCallBack,nil,nDevs)<0
   then //线路不能初始化处理
   else
   if nDevs=0 then //无TAPI线路设备
   begin
   lineShutDown(lineApp);
   lineApp:=0;
   end
   else
   if lineNegotiateAPIVersion(lineApp,0,$00010004,$00020000,
   tapiVersion,extid)<0 //协商TAPI版本号 TAPI1.4~TAPI2.0
   then begin {TAPI版本不兼容}
   lineShutDown(lineApp);
   lineApp:=0;
   end
   else
   errorcode:=lineOpen(lineApp,LINEMAPPER,line,tapiVersion,0,0,
  LINECALLPRIVILEGE_NONE,LINEMEDIAMODE_
  INTERACTIVEVOICE,@CallParams);//打开线路
   if errorcode<0 then {线路不能打开}
   else
   begin{线路打开成功}
   lineConfigDialog(0,Self.Handle,nil); //显示线路设备属性
   lineGetIcon(0,`tapi/line`,lineIcon);
   //lineIcon为线路设备图标句柄,可以赋值给TICON.Handle
   if lineMakeCall(line,call,PChar(dialnumber),0,@CallParams)<0 then{呼叫失败处理}
   else
   lineHandOff(call,`电话拨号程序`,LINEMEDIAMODE_INTERACTIVEVOICE);
   //在程序中应当以按钮来触发lineHandOff,从TAPI控制转为人工控制电话
   end;
  end;
  以上代码由于脱离了实际的程序显得有些凌乱,相信对delphi编程稍有了解的朋友很容易看懂。本程序运行后的效果是,首先出现一个数据库表格,用右键打开一个通讯录库文件,右键选择拨号弹出对话框显示线路处理的状态,在拨完号之后提示用户是否拿起听筒进行对话。整个过程类似系统自带的电话拨号程序,不过笔者介绍的TAPI方法可以让我们编写更多的功能和更友好的界面。今后笔者将针对TAPI编程进行深入的介绍,希望能对不太了解TAPI的朋友在开发程序时起到帮助。
 
写的是不错,不过好象是照着抄的呀!你自己用过没有的?我看了一下,介绍得满好的,但只有拨打和接听电话的操作及一些出错判断,没有我想要的接收对方按键信息(既DTMF码)的处理。另外我这里没有tapi.pas文件,你可不可以发给我?最好能带个例子程序,以及一些tapi函数的中文说明,它们的声明格式(参数类型、返回值等)。不过还是多谢了呀! qinqijun@163.com
 
发过去了。。。
 
收到了,我正在看!你那个控件的安装包好象在delphi6里安装时会出错,不过最后还是装上了。显示了5个控件的图标在Communication页,但是terminal控件显了图标不能放到窗口上,一放就出错:
Access Violation at address 40032538 in module 'rtl60.pbl'. Write of address 0000000D.
由于这个控件不能用所以例子根本看不了。你可不可以发一份delphi6的控件安装包过来给我呀?不管怎样,我还是非常感谢你。1500分等我试过可以用之后就划给你!
 
后退
顶部