这两天把CE板儿上的拔号程序初步完成,第一个是CE板儿上自带的MODEM无法使用,最终还是从网上看到一个牛人说改注册表然后映射到COM2口上,很简单的事情,有些时候儿没有弄过就会不知道如何下手。软件倒是费了些周章,从网上找了一个RAS的拔号软件,但他那个有点儿小问题,经过同事的指点,直接调用设置好的连接即可。比如你在CE板儿上建立了一个“我的连接”,直接把这个名字传到RASDIALPARAMS 变量里,
如下:
RASDIALPARAMS rdParams;
HRASCONN m_hRasConn = NULL;
//初始化变量
rdParams.dwSize = sizeof(RASDIALPARAMS);
wcscpy(rdParams.szEntryName,lpszName);//_T("我的连接") wcscpy(rdParams.szPhoneNumber,_T("*99***1#"));
wcscpy(rdParams.szCallbackNumber,_T(""));
wcscpy(rdParams.szUserName,_T(""));
wcscpy(rdParams.szPassword,_T(""));
wcscpy(rdParams.szDomain,_T(""));
然后直接 RasDial(NULL,NULL,&rdParams,0L,NULL,&m_hRasConn);就可以了。
在网上找到一牛人的博客,发现这牛人真牛,不但C++的写好,还顺带搞了C#的,而且还用了TAPI的方法,很是厉害。用Connection Manager
Functions系列的API又写了一个,我觉得他应该封装起来,做一个父类,然后别人就可以自由使用了,有时间自己封装一下。
接着谈RAS,这个连接当然的我们可以自己在代码里创建,如下:
LPWSTR lpszAPN = L"cmnet";
LPWSTR lpszName = L"测试连接2";
DWORD dwSize,
dwError;
TCHAR szError[100];
BYTE lpb[436];
unsigned long lpbSize = sizeof(lpb);
RASENTRY RasEntry;
dwSize = sizeof (RASENTRY);
memset (&RasEntry, 0, dwSize);
memset(lpb,0,lpbSize);
RasEntry.dwSize = dwSize;
//对应WM中的选择调制解调器与调制解调器类型
wcscpy(RasEntry.szDeviceName,L"Cellular Line");//移动线路(GPRS)
wcscpy(RasEntry.szDeviceType,L"modem");
TCHAR szLocalPhoneNumber[RAS_MaxPhoneNumber + 1] = {0};
wsprintf(szLocalPhoneNumber,L"~GPRS!%s",lpszAPN);
wcscpy(RasEntry.szLocalPhoneNumber,szLocalPhoneNumber );
RasEntry.dwfOptions = 4194304;
RasEntry.dwfNetProtocols = 4;
RasEntry.dwFramingProtocol = 1;
如果没有下面的部分,你的程序无法打开连接。注意。
//设置lpb
//Pointer to a buffer that contains device-specific configuration information.
//This is opaque TAPI device configuration information
lpb[0]=180;
lpb[1]=1;
lpb[4]=180;
lpb[5]=1;
lpb[8]=180;
lpb[9]=1;
lpb[12]=1;
lpb[16]=15;
lpb[20]=1;
lpb[24]=2;
lpb[76]=1;
lpb[80]=2;
lpb[84]=2;
//从D88位开始设置APN指令
for(int i=0,step=0;i<wcslen(lpszAPN);i++,step+=2)
{
*(lpb + 88 + step)=(BYTE)*(lpszAPN+i);
}
lpb[344]=1;
lpb[348]=1;
if (dwError = RasSetEntryProperties (NULL, lpszName,
&RasEntry, sizeof (RASENTRY),lpb, lpbSize))
{
wsprintf (szError, TEXT("Unable to create the phonebook entry.")
TEXT(" Error %ld"), dwError);
}
TCHAR buffer[256]={0};
LPWSTR key=buffer;
wcscat(key,_T("Comm\\ConnMgr\\Providers\\{7C4B7A38-5FF7-4bc1-80F6-5DA7870BB1AA}\\Connections"));//RIL_KEY
wcscat(key,L"\\");
wcscat(key,lpszName);
unsigned long val1 = 0;
unsigned long val2 = 1;
unsigned long val3 = 2;
SetRegistryDWORD(HKEY_LOCAL_MACHINE, key,_T("RequirePW") , val1); //是否需要密码RIL_REQ_PE
SetRegistryDWORD(HKEY_LOCAL_MACHINE, key,_T("Enabled") , val2); //是否为默认连接RIL_ENABLED
SetRegistryDWORD(HKEY_LOCAL_MACHINE, key,_T("EntryType") , val3);//RIL_ENT_TYPE
SetRegistrySZ(HKEY_LOCAL_MACHINE, key, _T("DestId"),
_T("{ADB0B001-10B5-3F39-27C6-9742E785FCD4}")); //一般是Internet设置;RIL_DES_ID RIL_CONN_ID
//ConnectionGUID,可以生成一个GUID;
SetRegistrySZ(HKEY_LOCAL_MACHINE, key,_T("ConnectionGUID") ,
NewGUID());
为了测试进行了简单改写,但基本还是符合原程序的,希望原作者不要介意。
如果你想在拔号时获得当前状态,可以这样:
在你的实现代码里加上这句,
const UINT WM_RASEVENT = ::RegisterWindowMessageA(RASDIALEVENT);
然后添加消息映射:
BEGIN_MESSAGE_MAP(CtestGprsDlg, CDialog)
......................
ON_REGISTERED_MESSAGE(WM_RASEVENT, &CtestGprsDlg::On
//}}AFX_MSG_MAP
..........................
END_MESSAGE_MAP()
然后添加一个消息映射函数:
LRESULT On
并实现之:
LRESULT CtestGprsDlg::On
{
RASCONNSTATE rasstate = (RASCONNSTATE)wp;
switch(rasstate)
{
case RASCS_OpenPort:
break;
case RASCS_PortOpened:
//在此处添加你的工作代码
break;
case RASCS_ConnectDevice:
break;
case RASCS_DeviceConnected:
break;
case RASCS_Authenticate:
break;
case RASCS_Authenticated:
break;
case RASCS_Connected:
break;
case RASCS_Disconnected:
break;
default:
return (LRESULT)0;
}
return (LRESULT)0;
}
这样基本就OK,该吃饭了,回头接着写。
在CE里回调和事件消息均无法截获,但在PC上是没有问题,已经过了测试,后来在CSDN上提问,有牛人指点拦截
PreTranslateMessage这个消息事件,截获WM_RASDIALEVENT消息即可达到目的,经过测试OK了,代码如下:
BOOL CGprsStateDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if(pMsg->message == WM_RASDIALEVENT)
{
switch(pMsg->wParam)
{
case RASCS_OpenPort:
//cs.m_s = _T("打开端口……");
break;
case RASCS_PortOpened:
//cs.m_s = _T("端口已打开……");
break;
case RASCS_ConnectDevice:
break;
case RASCS_DeviceConnected:
AfxGetApp()->GetMainWnd()->GetDlgItem(IDC_STATIC_STATE)->SetWindowTextW(_T("设备已连接.…"));
break;
case RASCS_Authenticate:
//cs.m_s = _T("验证用户及密码……");
break;
case RASCS_Authenticated:
break;
case RASCS_Connected:
//cs.m_s = _T("已连接");
break;
case RASCS_Disconnected:
break;
default:
return (LRESULT)0;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
另外要注意的是:RAS拨号的同步和异步问题,如果这个问题不搞清楚,就谈不上消息的截获和同步的线程监视。
dwRet = RasDial(NULL,NULL,&rdParams,0L,NULL,&m_hRasConn);//同步
dwRet = RasDial(NULL,NULL,&rdParams,0L,RasDialFunc,&m_hRasConn);//异步回调 --只支持在PC
dwRet = RasDial(NULL,NULL,&rdParams,0xFFFFFFFF,this->m_hWnd,&m_hRasConn); //异步消息--支持PC、CE
如果同步,可用线程监视同步过程,但没有取得成功,不过网上有人说成功过。后两者我都在PC上成功,CE均未成功。只在使用了PreTranslateMessage才成功。
谢谢那位高手。你的无私指点是我进步的动力。