最近帮别人开发纽曼来电小秘书,小踩了几个坑,在此与大家分享,给大家排排雷
坑1. 文档不够详细,函数不全,更没有介入流程介绍,总之就是一个大坑。
EnableCard()
CheckLine(Line:Word)
...
坑2. 没有注明dll使用方式,是直接引用还是DllImport?
1.直接引用的话,vs会直接报错,说明此方法错误
2.DllImport申明方法,使用正常
附P/Invoke代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Secretary
{
class Secretary
{
[DllImport("usbms.dll", EntryPoint = "LoadDRV")]
public static extern int LoadDRV();
[DllImport("usbms.dll", EntryPoint = "IsRing")]
public static extern bool IsRing(int Line);
[DllImport("usbms.dll", EntryPoint = "ReadUsbState")]
public static extern bool ReadUsbState(int line);
[DllImport("usbms.dll", EntryPoint = "IsOffHook")]
public static extern bool IsOffHook(UInt16 Line);
[DllImport("usbms.dll", EntryPoint = "GetDtmfCode")]
public static extern int GetDtmfCode(UInt16 Line);
[DllImport("usbms.dll", EntryPoint = "GetCallerIDStr")]
public static extern UInt16 GetCallerIDStr(UInt16 Line, StringBuilder IDStr);
[DllImport("usbms.dll", EntryPoint = "ReadSerialNo")]
public static extern int ReadSerialNo(UInt16 line, StringBuilder serialNo);
[DllImport("usbms.dll", EntryPoint = "GetRingNum")]
public static extern int GetRingNum(int line);
[DllImport("usbms.dll", EntryPoint = "SetPCMode")]
public static extern bool SetPCMode();
[DllImport("usbms.dll", EntryPoint = "CheckLine")]
public static extern bool CheckLine(UInt16 line);
[DllImport("usbms.dll", EntryPoint = "InitRingNum")]
public static extern void InitRingNum(int line);
[DllImport("usbms.dll", EntryPoint = "EnableCard")]
public static extern int EnableCard();
}
}
坑三. 没有C#版本DEMO,只有Delphi版本DEMO
于是苦逼的我,一遍显示器开着Delphi版本的DEMO,一遍手写C#程序,强调各位一定要把Delphi的demo逻辑理清楚,也可以按照完全模仿。
附我整理的Delphi流程(c#基本实现此流程基本的功能均能ok)
1.Init
//record对应c#中的class
type TLines = record
Status:integer;
Timer:integer;
OldRingCounter:integer;
IsLine:Boolean;
IsKeyUpOld:Boolean;
end;
//对象数组
Lines:array[0..2] of Tlines;
//对应c#中stringbuilder
Serial:array[0..10] of char;
const STATUS_FREE = 0 ;
const STATUS_RING = 1 ;
const STATUS_WAIT_FSK = 2 ;
const STATUS_WAIT_RING_END = 3 ;
const STATUS_HANGUP = 4 ;
const STATUS_WAIT_HANGUP_END = 5 ;
const STATUS_RECORD = 6 ;
const STATUS_PLAY = 7 ;
const STATUS_SEND = 8 ;
Lines[0].Status := STATUS_FREE ;
Lines[1].Status := STATUS_FREE ;
Lines[2].Status := STATUS_FREE ;
usbcount := LoadDRV;
if usbcount > 0 then
begin
str:='加载USB驱动设备成功!';
if EnableCard =1 then
begin
str:='启动USB设备成功!';
ReadSerialNo(0,Serial);
str := '序列号=';
for i:=0 to 4 do begin
str:= str+','+inttostr(ord(Serial[i]));
end;
//注意定时器启动了
Timer1.Enabled := true;
DeviceState := false;
end;
SetPCMode();
end else
begin
str:='加载USB驱动设备失败!';
end;
2.Timer
2.1 GetTrunkState(0)
//line = 0
//<> -> != =->== =:->=
if Lines[line].IsLine <> CheckLine(line) then
begin
if Lines[line].IsLine then
begin
str := '外线断开'
end else
begin
str := '外线接通'
end;
Memo1.Lines.Add(str);
Lines[line].IsLine := CheckLine(line);
end;
//对应c# switch .. case
case Lines[line].Status of
STATUS_FREE:begin
if IsRing(line) then
begin
Lines[line].OldRingCounter := GetRingNum(line);
Memo1.Lines.Add('外线振铃'+inttostr(Lines[line].OldRingCounter));
Lines[line].Status := STATUS_RING ;
end;
if IsOffHook(line) then
begin
Memo1.Lines.Add('外线摘机');
Lines[line].Status := STATUS_HANGUP ;
end;
end;
STATUS_RING:begin
if IsRing(line) then
begin
end else
begin
Lines[line].Status := STATUS_WAIT_FSK;
Lines[line].Timer := 0;
end;
end;
STATUS_WAIT_FSK:begin
setlength(str,200);
if (GetCallerIDStr(line,pchar(str))=3) then
begin
str :='外线来电='+ string((str));
Memo1.Lines.Add(str);
end;
inc(Lines[line].Timer);
if ( GetRingNum(line) > 1) or ( Lines[line].Timer > 50 ) then
begin
Lines[line].Status := STATUS_WAIT_RING_END ;
Lines[line].Timer := 0;
end;
if Lines[line].OldRingCounter <> GetRingNum(line) then
begin
Lines[line].OldRingCounter := GetRingNum(line);
Memo1.Lines.Add('外线振铃'+inttostr(Lines[line].OldRingCounter));
end;
end;
STATUS_WAIT_RING_END:begin
if IsRing(line) then
begin
if Lines[line].OldRingCounter <> GetRingNum(line) then
begin
Lines[line].OldRingCounter := GetRingNum(line);
Memo1.Lines.Add('外线振铃'+inttostr(Lines[line].OldRingCounter));
end;
Lines[line].Timer := 0;
end else if Lines[line].Timer > 50 then
begin
Memo1.Lines.Add('外线空闲');
Lines[line].Status := STATUS_FREE;
Lines[line].Timer := 0;
InitRingNum(line);
end;
inc(Lines[line].Timer);
end;
STATUS_HANGUP:begin
if not IsOffHook(line) then
begin
Memo1.Lines.Add('外线挂机');
Lines[line].Status := STATUS_FREE ;
end;
end;
STATUS_RECORD:begin
if CheckRecordEnd(line) then begin
Memo1.Lines.Add(datetimetostr(now)+'录音结束');
Lines[line].Status := STATUS_FREE ;
end;
end;
STATUS_PLAY:begin
if CheckPlayEnd(line) then begin
Memo1.Lines.Add(datetimetostr(now)+'放音结束'+inttostr(line));
Lines[line].Status := STATUS_FREE ;
end;
end;
STATUS_SEND:begin
if CheckSendEnd(line) then begin
Memo1.Lines.Add(datetimetostr(now)+'拨号结束'+inttostr(line));
Lines[line].Status := STATUS_FREE ;
end;
end;
end;
2.2 GetUserState(1)
//line = 1
if DeviceState <> ReadUsbState(line) then
begin
if DeviceState then
str := datetimetostr(now)+':设备移除'
else
str := datetimetostr(now)+':设备接入';
DeviceState := ReadUsbState(line);
Memo1.Lines.Add(str);
end;