069_基于Windows的电话线路的数据通信程序
1.无需注册登录,支付后按照提示操作即可获取该资料.
2.资料以网页介绍的为准,下载后不会有水印.资料仅供学习参考之用.
密 惠 保
4 编码实现
4.1 程序主类的的定义
为了使程序的结构更为清晰和易于维护和升级,我把程序所要使用的数据结构封装成一个类。类的定义如下:
class CTapiLine
{
protected:
HLINEAPP m_hLineApp; //TPAIDLL的句柄
HLINE m_hLine;//线路的句柄
HCALL m_hCall;//呼叫的句柄
int m_nDevID;//设备号
HANDLE m_hLineEvent; // 线路改变事件
DWORD m_dwLineMsg;//线路消息
bool m_bConnected;//是否连接
HANDLE m_hEventFromThread;//
HANDLE m_hLineMsgThread; // TAPI 事件监听线程
bool m_bStopLineEventThread;
static DWORD WINAPI LineEventThread(LPVOID lpVoid);
long m_lEventThreadResult;
public:
HANDLE GetHandle(const char *szClassType, long *lError);
int PickupIncomingCall();
void GetErrorString(int nError, char *&szErrText);
int MakeOutgoingCall(const char *szAddress);
int GetIncomingCall();
int Close();
int Open(int nMode = 0);
CTapiLine();
virtual ~CTapiLine();
[来源:http://think58.com]
};
类里面定义了整个程序运行所需要用到的变量。在进行线路操作时调用TAPI的类成员函数需要同时取得设备和线路的状态,所以我对TAPI的类成员函数进行了封装,使这些操作都模块化。
4.2 线路操作的实现
线路的操作定义为Open和Close两个类成员函数,里面封装了TAPI的lineInitializeEx(TAPI初始化)、lineNegotiateAPIVersion(版本协调)、lineOpen(打开一条线路)、lineDrop(挂断呼叫)、lineClose(关闭一条线路)四个类成员函数进行线路操作,同时封装了在线路操作时需要用到的设备性能的取得函数lineGetDevCaps(取得设备性能)。
int CTapiLine::Open(int nMode)
{
………………………………………………………
// 初始化 TAPI.
lRet = lineInitializeEx(&m_hLineApp, NULL, NULL, "CallAnswer", &dwNumDevs, &dwTAPIVer, &stInitParams);
m_hLineEvent = stInitParams.Handles.hEvent;//得到事件的句柄
m_nDevID = -1;
//通过循环取得可以传送数据的设备号 think58好,好think58
[资料来源:http://THINK58.com]
for(int i=0;i<dwNumDevs;i++)
{
lRet=lineNegotiateAPIVersion(m_hLineApp, i, dwTAPIVer, dwTAPIVer, &dwTmpVer, &stExtID);
if(lRet != 0)
continue;
lpDevCaps=(LINEDEVCAPS*)malloc(sizeof(LINEDEVCAPS)+1024);// 取得设备的性能
………………………………………
lRet = lineGetDevCaps(m_hLineApp, i, dwTmpVer, 0, lpDevCaps);
if(lpDevCaps->dwMediaModes & dwMediaMode)
{
free(lpDevCaps);
m_nDevID = i;
break;
}
free(lpDevCaps);
}
if(m_nDevID < 0)
return LINEERR_BADDEVICEID; //没有可用的设备 内容来自think58
[资料来源:http://www.THINK58.com]
// 打开一条线路
lRet = lineOpen(m_hLineApp, m_nDevID, &m_hLine, dwTAPIVer, 0x00000000, 1,LINECALLPRIVILEGE_OWNER,dwMediaMode,NULL);
………………………………………………..
}
int CTapiLine::Close()
{………………………………………….
lineDrop(m_hCall, NULL, 0);
if(m_hLine)
lineClose(m_hLine);
………………………………….
//释放前面阶段使用到的一些缓存以及对一些信号型变量进行复位
}
4.3 呼叫的发起和应答的实现
呼叫的建立和应答使用类成员函数MakeOutgoingCall、GetIncomingCall来实现。里面封装了lineMakeCall和lineAnswer两个TAPI类成员函数。
int CTapiLine::MakeOutgoingCall(const char *szAddress)//呼出
{//呼叫前对呼叫选项的设置
………………………………………………………..
think58好,好think58
lRet = lineMakeCall(m_hLine, &m_hCall, szAddress, 0, lpCallParams);
return (lRet>=0)?0:lRet;
}
int CTapiLine::GetIncomingCall()//应答
{…………………………………………………..
lRet = lineSetNumRings(m_hLine,0,5);//设置响铃次数
lRet = lineAnswer(m_hCall, NULL, 0);
…………………………………………………
}
4.4 数据操作的实现
在程序中数据的读取单独创建一个线程,定义了一个回调函数ReadThread封装了WriteFile和ReadFile来实现数据的发送。
DWORD WINAPI CMyTapiDlg::ReadThread(LPVOID lpVoid)//接收数据
{
OVERLAPPED ov;
……………………//ov 的初始化设置
for(;!pcDlg->m_bStopReadThread;)
{
ReadFile(pcDlg->m_hSerialHandle,szBuff,512,&dwReadLen,&ov);//读数据 think58好,好think58 [资料来源:THINK58.com]
……………………………//错误处理
switch(WaitForSingleObject(ov.hEvent,INFINITE))
{
case WAIT_OBJECT_0:
GetOverlappedResult(pcDlg->m_hSerialHandle,&ov, &dwReadLen,FALSE);
return 0;
}
void CMyTapiDlg::OnBtnWrite() //发送数据
{
……………………//要使用到的变量的定义
OVERLAPPED ov;
……………………//ov 的初始化设置
GetDlgItemText(IDC_EDTWRITE,szBuff,512);
nRet=WriteFile(m_hSerialHandle,szBuff,strlen(szBuff),&dwWriteLen,&ov);//写数据
……………………………//错误处理
switch(WaitForSingleObject(ov.hEvent,INFINITE))
{
case WAIT_OBJECT_0: GetOverlappedResult(m_hSerialHandle,&ov,&dwWriteLen,FALSE);
break;
default:
break;
};
} [资料来源:http://think58.com]
5 软件测试
模块编程完结之后,设计测试用例,对GUI界面外观和功能等进行检测。首先测试GUI界面上控件的布局是否合理美观,是否方便操作。然后对界面上的每一个控件进行测试,包括对每个按钮按下后会激发什么操作,一个按钮按下后使得其他按钮的可用或者禁用是否符合逻辑,文本框中数据输入输出的测试。然后根据功能需求说明书对整个程序的进行功能测试,包括程序的打开,拨号,拨号未完成和拨号完成后挂断电话,什么时候可以取得MODEN的句柄,取得句柄后应该能否进行数据传输,数据传输的正确率进行测试。这些测试同时在Windows 2000、Windows XP 系统下同时进行。
由于经验欠缺或其它某些原因,本次完成的软件不可能是完美无缺的。测试只能尽量避免错误的产生和消除已经产生的错误,使程序中的错误密度达到尽可能低的程度,减少错误的引入,但是不可能完全杜绝软件中的错误。经过测试此软件基本能符合要求,也能实现各功能。
think58.com [资料来源:THINK58.com]
[版权所有:http://think58.com]