肆无忌惮
青青子矜,悠悠我心,纵我不往,子宁不之? 青青子佩,悠悠我思,纵我不往,子宁不来?
posts - 20,comments - 8,trackbacks - 0

     前些日子感觉得练习一下VC了,所以就有想,平时发短信那么累,手机键盘又不好用,而我又有数据线,为什么不可以用电脑直接发送短信呢?想法一出来,就开始找资料开始行动吧!

    由于程序涉及的方面很多,因此只讲关键的主要的部分。

    首先,得了解手机和电脑之间是通过什么通讯的,我的手机是有红外接口,电脑上接一个红外适配器,就可以与手机连接了,而Windows是把红外设备当作一个串口来看待的,所以关键就是在于如何用程序来控制COM端口来发送和接收数据。在网上找了很多资料然后就开始编写代码:

    列举出系统中的所有的串口:这个需要操作注册表来实现,代码如下:

void CSendMsgDlg::GetAllCom()
{
 HKEY hKey;
 LONG ret;
 OSVERSIONINFO  osvi;
 BOOL bOsVersionInfoEx;
 char keyinfo[100],comm_name[200],ValueName[200];
 int i;
 DWORD sType,Reserved,cbData,cbValueName;

 ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 
 memset(keyinfo,0,100);
 strcpy(keyinfo,"HARDWARE\\DEVICEMAP\\SERIALCOMM");
    i=0; sType=REG_SZ;Reserved=0;
 bOsVersionInfoEx =GetVersionEx(&osvi);
    ret=RegOpenKeyEx(HKEY_LOCAL_MACHINE,keyinfo,0,KEY_ALL_ACCESS,&hKey);
 if (ret==ERROR_SUCCESS){
  if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
  {
   do
   {
    cbData=200;cbValueName=200;
    memset(comm_name,0,200);
    memset(ValueName,0,200);
    ret=RegEnumValue(hKey,i,ValueName,&cbValueName,NULL,&sType,(LPBYTE)comm_name,&cbData);
    if (ret==ERROR_SUCCESS)
    {
     //m_list.Add(comm_name);
     m_comm.AddString(comm_name);
     i++;
    }
   }while (ret==ERROR_SUCCESS);
  }
 }
 RegCloseKey(hKey);
}

得到所有的串口了,现在就应该打开串口了,一般来说计算机自己有两个串口,而红外线的标志一般是COM3。

打开串口的代码:

void CSendMsgDlg::OnButton1()
{
 char str[100];
 DWORD dwThreadID;
 memset(str,0,100);
 int sel = m_comm.GetCurSel();
 if(sel == -1)
 {
  AfxMessageBox("对不起,请选择一个接口!");
  return;
 }
 m_comm.GetLBText(sel,str);
 m_hCom = CreateFile(str,
      GENERIC_READ | GENERIC_WRITE,
      0,NULL,OPEN_EXISTING,
      FILE_FLAG_OVERLAPPED,
      NULL);

 if(m_hCom == INVALID_HANDLE_VALUE)
 {
  AfxMessageBox("对不起,连接失败!");
  return;
 }

 ASSERT(m_hCom!=INVALID_HANDLE_VALUE);
 
 SetCommMask(m_hCom, EV_RXCHAR|EV_TXEMPTY );//设置事件驱动的类型
 
 SetupComm( m_hCom, 1024,512) ; //设置输入、输出缓冲区的大小
 
 PurgeComm( m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); //清干净输入、输出缓冲区
 
 COMMTIMEOUTS CommTimeOuts ; //定义超时结构,并填写该结构

 CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
 CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
 CommTimeOuts.ReadTotalTimeoutConstant = 0;
 CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
 CommTimeOuts.WriteTotalTimeoutConstant = 5000;
 
 
 SetCommTimeouts( m_hCom, &CommTimeOuts ) ;//设置读写操作所允许的超时
 
 DCB dcb;
 
 GetCommState(m_hCom, &dcb ) ; //读串口原来的参数设置
 
 dcb.BaudRate =9600;
 
 dcb.ByteSize =8;
 
 dcb.Parity = NOPARITY;
 
 dcb.StopBits = ONESTOPBIT ;
 
 dcb.fBinary = TRUE ;
 
 dcb.fParity = FALSE;
 
 SetCommState(m_hCom, &dcb ) ; //串口参数配置
 memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
 memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );

 m_OverlappedRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
 m_OverlappedWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
 m_hExit = CreateEvent(NULL,NULL,FALSE,NULL);

 hCommWatchThread = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,0,(LPTHREAD_START_ROUTINE)CommWatchProc,this,0, &dwThreadID );

 if(hCommWatchThread == NULL)
 {
  AfxMessageBox("对不起,连接失败!");
  return;
 }

 

 ASSERT(hCommWatchThread!=NULL);

 m_bConnected = true;

 m_type = 0;

 SendData("AT\r\n",strlen("AT\r\n"));
 PurgeComm(m_hCom, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

 m_conn.EnableWindow(false);
 m_view.EnableWindow(true);
 m_send.EnableWindow(true);
 
}

由于在CreateFile里面设置了一个参数“FILE_FLAG_OVERLAPPED”,所以与串口要按照异步的方式进行通讯,所以启动一个线程专门作为接收数据的线程:

UINT CSendMsgDlg::CommWatchProc(LPARAM parm)
{

 CSendMsgDlg * dlg = (CSendMsgDlg *)parm;
 HANDLE m_hComDev = dlg->m_hCom;
 DWORD dwBytesRead;
 char buffer[8000];
 
 DWORD ret;

 while(true)
 {
  memset(buffer,0,8000);
  int r = dlg->ReadData(buffer,8000);
 // TRACE("%s",buffer);
  if(strlen(buffer) != 0)
   dlg->ProcessData(buffer);
  Sleep(1000);
 }
 return 0;
}

下面是读写COM口的函数:

int CSendMsgDlg::SendData(char *buffer, DWORD dwBytesWritten)
{
 BOOL bWriteStat;
 DWORD dwBytesRead;
 bWriteStat = WriteFile(m_hCom, buffer, dwBytesWritten, &dwBytesWritten, &m_OverlappedWrite );
    if(!bWriteStat)
  {
     if(GetLastError()==ERROR_IO_PENDING)
  {
  WaitForSingleObject(m_OverlappedRead.hEvent,1000);
   return ((int)dwBytesRead);
  }
  return(0);
  }
  return ((int)dwBytesRead);
}

int CSendMsgDlg::ReadData(char *buffer, DWORD dwBytesRead)
{
 BOOL   bReadStatus;
    bReadStatus = ReadFile( m_hCom, buffer, dwBytesRead, &dwBytesRead,&m_OverlappedRead);
    if(!bReadStatus)
  {
     if(GetLastError()==ERROR_IO_PENDING)
  {
       WaitForSingleObject(m_OverlappedRead.hEvent,1000);
   return ((int)dwBytesRead);
  }
  return(0);
  }
  return ((int)dwBytesRead);
}
当然了,这里的方法并不是唯一选择。

上面主要是对COM口的操作,这跟手机和短信无关,下面的部分就是与手机短信有关的部分了:

首先,得知道如何利用手机的AT指令集,我们现在需要的指令不多,只有读短信和发短信。

关于AT指令的其他命令网上有很多资料这里也不再提及了

命令:AT+CMGL

命令说明:获取短信列表

格式举例:

AT+CMGL
+CMGL: 1, 1, ,38
0891683108200205f0240D91683128500474F7000850403191611200126211572856FE4E6699865B
664E6054620021
+CMGL: 2, 1, ,70
0891683108200205f0240D91683128500474F70008504031919113003262114E0076F45C31662F4E
09597D5B66751F0020563F563F51765B9E6211662F57287BEE74039986770B4EBA5BB68DF3821E
+CMGL: 3, 1, ,64
0891683108200205f0240D91683128500474F70008504031913272002C5F53713667094E864E0D8F
C790FD662F59274E005C0F59B959B94E864F608001725B8FD860F354035AE98349
+CMGL: 4, 1, ,82
0891683108200205f0240D91683128500474F70008504031918284003E4F608D767D27542C4F6076
848BFE542700206B6A5FC3773C8FD84E0D5C1100204E004F1A80015E0863D095EE4F604F6053EF52
2B556590FD4E0D4F1A0020
+CMGL: 5, 1, ,154
0891683108200205f0240D91683128500474F70008504031916344008690A34F60600E4E484E0D4E
CE59345F0059CB542C002080AF5B9A662F5FEB80038BD54E864F60624D77406025002056F0559D54
96556189814E0D5C3157507B2C4E006392572880015E08773C76AE5E954E0B5C314E0D56F04E8600
20621173B05728592959294E5F662F4EE5549655617EF46301751F547D554A89814E0D65E9776177
404E86
+CMGL: 6, 1, ,88
0891683108200205f0240D91683128500474F70008504031914422004490A34F605C3153BB4E7090
1A51FA9898768480015E08002089814E0D5C31627E4EBA66FF4F6080030020603B776189C95BB966
1380D662404EE56211767D59294E0D7761
+CMGL: 7, 1, ,63
0891683108701305f0240BA13178855898F10008503013011285202C4F60684C4E0A7684004C0049
004E005500584E2D5348501F621162FF5BBF820D88C54E004E0B884C4E0DFF1F
+CMGL: 8, 1, ,62
0891683108200205f0240D91683128500474F70008504031913523002A54CE54404F6090A34E4880
6A660E597D597D770B4E66591A505A70B9989880AF5B9A5C3180FD8FC77684
+CMGL: 9, 1, ,32
0891683108301105f0040D91683139116779F30008503013120565000C53EF4EE563A752364E8654
17
+CMGL: 10, 1, ,36
0891683108301105f0040D91683139116779F300085030131285230010662F4E0D662F7F51901F5F
886162554A
+CMGL: 11, 1, ,38
0891683108301105f0040D91683139116779F30008503013220031001259295440002090A3662F4E
0D662F4E2D6BD2
+CMGL: 12, 1, ,38
0891683108301105f0040D91683139116779F30008503013221055001290A36211548B529E554A91
CD542F884C5417
+CMGL: 16, 1, ,151
0891683108705305f0040BA13178536816F3000850402090311220848FD979CD65F650194F605728
4E0A73ED4E865427FF0C621160F395EE95EE4F604E004E9B4E8B60C530024F6053EF4EE5544A8BC9
621153BB5E74672C79D1658779D159276982662F591A5C114E0A7EBF541730029EBB70E64F604E86
30024F604E5F628A5F2068A6534E768475358BDD544A8BC962115427FF0C514D5F97621165E0804A

+CMGL: 17, 1, ,102
0891683108301105f0040D91683139116779F300085040306112230052636E8BF46C5F6D9B768400
28003400305929653B514B59275B6682F18BED56DB7EA700290020633A597D7684002E002053EF4E
E55E2E4F608BA1521260278FC77EA7002E00204F604E708BD598984E865417
+CMGL: 18, 1, ,85
0891683108705305f0040BA13178536816F3000850404022206220424ECA59298BB25230534A8DEF
5C316CA175354E86FF0C611F89C9602A602A768430024F604EE5540E8FD8662F53EB621155E654AA
5427611F89C96BD48F834EB25207
+CMGL: 20, 1, ,56
0891683108705505f0040D91683175804276F800085040508182950024534E4E3A76847EB34E9B9E
1F4EBA5E26774088AB5B504E0A73ED3000771F768460506016
+CMGL: 21, 1, ,41
0891683108701305f0040BA13178858581F80008504080905461201666534F1F300067094E8B76F8
6C42300056DE75358BDD
+CMGL: 22, 1, ,90
0891683108705505f0040D91683175804276F8000850408011033000464F60660E59297ED9623F4E
1C62534E2A75358BDD300053F778016211665A4E0A544A8BC94F603000621190A353EF4EE54E0A7F
514E8630004ECA592998864E867B148BB0672C
+CMGL: 23, 1, ,66
0891683108705505f0040D91683175804276F80008504080223543002E0031003300350030003700
330031003400320036003253EB52185E086BCD30004F605E2E6211628A94B153E07740
+CMGL: 24, 1, ,52
0891683108705505f0040D91683175804276F8000850408022757100200031003600350030002062
1173B057286CA194B1300089817B4953D15DE58D44
+CMGL: 25, 1, ,38
0891683108705505f0040D91683175804276F8000850408022950400124F6073B057284E0D4F1A99
7F6B7B54273000
+CMGL: 26, 1, ,48
0891683108705505f0040D91683175804276F80008504080322082001C534E4E3A898162DB4E2A51
99006A00610076006176844F6067654E0D
+CMGL: 27, 1, ,44
0891683108200205f0240D91683128500474F7000850409000416200184F60771F5F3A4EE5540E53
EF4E0D65629A9A62704F604E86
+CMGL: 28, 1, ,74
0891683108200205f0240D91683128500474F700085040900081500036621165394E864EE5540E4E
0D4F1A6B3A8D1F60A880014EBA5BB64E86002C4F606B3A8D1F621162114E5F4E0D4F1A62A5602876
84002E
+CMGL: 29, 1, ,82
0891683108200205f0240D91683128500474F70008504090002273003E62116DF14FE15584670955
8462A560766709607662A5002C5BF94E864F607ED9621163024E86591A5C115C0F65F64E864EC04E
4865F650195230592A9633
+CMGL: 30, 1, ,82
0891683108200205f0240D91683128500474F70008504090009222003E62118FD85F975929592963
D091924F60002054CE4F608FD94E2A783481115B5000204F608D767D277ED9621163024E0A8FC751
E05929621168C067E553BB
+CMGL: 31, 1, ,58
0891683108200205f0240D91683128500474F7000850409000535400266211521A6D825B8C630775
326CB97B495E725B8C4E8662115C31776100204F60572873A95565
+CMGL: 32, 1, ,108
0891683108200205f0240D91683128500474F700085040900014410058776189C94E4B524D6D8263
0775326CB95C314F1A505A4E2A597D68A6800C4E1468A690FD4F1A5B9E73B04E0D4FE14F608BD58B
D5002C62114E0D8DDF4F6073A94E86660E59298FD85F9765E98D7751FA53BB73A900380038
+CMGL: 33, 1, ,76
0891683108200205f0240D91683128500474F7000850409000542200385FD84E864F60662F753776
844E864E0D8FC76CA14E8B73B057286D41884C75374EBA6D82630775326CB90020621177414E0D5F
00773C4E86
+CMGL: 34, 1, ,154
0891683108200205f0240D91683128500474F7000850401190207100864E00592954B14FE9676552
304E0053E38BB8613F4E9565C1002C62115F2F4E0B81708BB84E864E2A613F8FD85F804E9591CC62
544E2A786C5E01002E4F604E5F60F38BB8613F4F464F605F2F817065F64E0D5C0F5FC37FFB51654E
9591CC002E621188AB60CA54464E86002C5583558381EA8BED9053003A00208FD8771F7075563F00
200021
+CMGL: 35, 1, ,66
0891683108705505f0040D91683175804276F80008504031418592002E653E4E2A00760073007376
845B8988C565874EF65230670D52A156684E0A97623000628A57305740544A8BC96211
+CMGL: 36, 1, ,42
0891683108200205f0240D91683128500474F70008504031815581001680017CCA6D82795E522B5F
D87ED96211630200510051
+CMGL: 37, 1, ,72
0891683108200205f0240D91683128500474F70008504031819571003454CE54DF4F608FD84E0A8B
FE002C626B76F273ED5427003F770B676562116BCF592965E94E0A90FD5F9763D091924F604E006B
21
+CMGL: 38, 1, ,158
0891683108705505f0040D91683157011065F00008504001227091008A84288FBE59C66D3E624B4E
0B53BB89C25BDF654C60C5002C4E0D4E004F1A513F624B4E0B53065FD956DE6765002C752898DF63
07548C4E2D63074F5C51FA0056578B624B52BF002C84288FBE59C69AD8517476848BF4201C62114E
EC80DC52294E86003F201D624B4E0B8BF4201C522B4ED65988626F4E86002C5C31526954B14EEC4F
E94E863002201D
+CMGL: 40, 1, ,34
0891683108200205f0240D91683128500474F70008504001226243000E84288FBE6BCD662F621190
E84E0B

呵呵有点长了,这是刚刚我从我手机中读取出来的数据,是经过编码以后的,有兴趣的话可以“翻译”出来看看是什么内容:)

关于SMS PDU格式的说明,推荐一个地址:

http://shuixin13.mblogger.cn/posts/10087.aspx

这里的资料已经够全了,基本可以包括所有的操作。

OK,读取手机短信不是我们的主要目的,在这里就不罗索了,只要仔细研究一下SMS PDU格式的那个文档,基本就不会有什么问题,我们的主要目的是发短信,现在就着重讲讲这一部分好了:

发短信的指令格式和编码格式也可以参考上面的地址,里面讲的也很详细了,我也不在这里罗嗦了,现在的关键问题是,如何根据格式来编码和解码。

首先,我们先建立一个Class来保存要发送的数据,每个字段用相应的类型表示,还要有一个“打包”的函数,就是把每一部分的数据组合起来。

class CMsgSend 
{
public:
 CString GetMsgData();
 void Pack(CString c_number,CString s_number,CString msg);
 CMsgSend();
 virtual ~CMsgSend();
 CString m_strData;
 CString SCA;
 CString PDUType;
 CString MR;
 CString DA;
 CString PID;
 CString DCS;
 CString VP;
 CString UDL;
 CString UD;
};
其中m_strData保存“打包”以后的数据,其他各个成员变量的含义请参照文档。

Pack是打包函数,需要三个参数:短信服务中心号码、接收短信手机号码和信息内容。

另外,我们还需要一个工具类来实现编码和解码:

class CMyTools 
{
public:
 static void HexToChar(CString sHex,char *p);//将十六进制转换为字符数组
 static CString DeCodeChinese(CString strSrc);//中文解码
 static CString EnCodeChinese(CString strSrc);//中文编码
 static CString SwapConvert(CString str);//交换,例如1234567890变换为2143658709,具体什么用看文档
 static BYTE HexToChar(CString str);//十六进制转换为字符类型
 static CString DeCodeEnglish(CString srcStr);//英文解码
 static CString EnCodeEnglish(CString srcStr);//英文编码
};

CString CMyTools::EnCodeEnglish(CString srcStr)
{
 CString result;
 BYTE cur,c1,c2;
 CString tmp;
 int len,i=0,j=0;
 len = srcStr.GetLength() - 1;
 result = "";
 while(i <= len)
 {
  c1 = srcStr.GetAt(i);
  if(i < len)
  {
   c2 = srcStr.GetAt(i+1);
   cur = (c1 >> j) | (c2 << (7-j) & 0xff);
  }
  else
   cur = (c1 >> j) & 0x7f;
  tmp.Format("%2.2X",cur);
  result = result + tmp;
  i++;
  j = (j+1) % 7;
  if(j == 0)
   i++;
 }
 return result;
}

CString CMyTools::DeCodeEnglish(CString srcStr)
{
 CString strDest,strData;
 int n = 0,i,flag = 0,j = 0;
 strData = "";
 int len = srcStr.GetLength();
 for(i=0;i<len-1;i+=2)
 {
  CString strTmp;
  char tmp;
  strTmp.Format("0x%1c%1c",srcStr.GetAt(i),srcStr.GetAt(i+1));
  tmp = HexToChar((LPSTR)(LPCTSTR)strTmp);
  strData = strData + tmp;
 }

 len = len/2 + len/2/8;
 for(i = 0;i<len;i++)
 {
  strDest = strDest + " ";
 }
 for(i=0;i<len;i++)
 {
  BYTE c1,c2;
  if(i == 0)
  {
   c1 = strData.GetAt(i);
   strDest.SetAt(i,c1 & 0x7f);
  }
  else
  {
   c1 = strData.GetAt(j);
   c2 = strData.GetAt(j+1);
   strDest.SetAt(i,(c2 << n) | (c1  >> (8 - n)));
   strDest.SetAt(i,strDest.GetAt(i) & 0x7f);
   if(i%8 != 0)
    j++;
  }
  n = (i % 8) + 1;
 }
 return strDest;
}

BYTE CMyTools::HexToChar(CString hex)
{
 int base = 1;
 int ret = 0;
 for(int i=hex.GetLength()-1;i>=0;i--)
 {
  char chex = hex.GetAt(i);
  int ihex;
  if(chex >= 'A' && chex <='F')
  {
   ihex = 15 - ('F' - chex);
  }
  else
  if(chex >= 'a' && chex <='f')
  {
   ihex = 15 - ('f' - chex);
  }
  else
   ihex = chex - '0';
  ret += ihex * base;
  base*=16;
 }
 return ret;
}

CString CMyTools::SwapConvert(CString str)
{
 CString result;
 result = str;
 for(int i=0;i<strlen(str);i+=2)
 {
  result.SetAt(i,str.GetAt(i+1));
  result.SetAt(i+1,str.GetAt(i));
 }
 return result;
}

CString CMyTools::EnCodeChinese(CString strSrc)
{

 CString strResult = "",strTmp,str;
 char lpBuff;
 int len = strSrc.GetLength();
 int i;
 WCHAR * wc;
 wc = new WCHAR[len];

 for(i=0;i<strSrc.GetLength();i++)
 {
  if((strSrc.GetAt(i) & 0x80) >> 7 == 0)
   len++;
 }

 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,(LPSTR)(LPCTSTR)strSrc,len,wc,len/2);
 for(i=0;i<len/2;i++)
 {
  strTmp.Format("%4.4X",wc[i]);
  strResult += strTmp;
 }
 return strResult;
}

CString CMyTools::DeCodeChinese(CString strSrc)
{
 char *pBuf;
 CString strMsg = strSrc;
 int nLength = strMsg.GetLength();
 if (nLength%2 == 1)
 {
  strMsg = strMsg.Left(nLength-1);
  int nNewLen = strMsg.GetLength();
  pBuf = new char[nNewLen/2];
 }
 else
 {
  pBuf = new char[nLength/2];
 }
 HexToChar(strMsg,pBuf);
 int i = 0,nZero = 0;
 while ((i = strMsg.Find("00",i))>=0)
 {
  i += 2;
  nZero++;
 }
 char u_ret[255];
 memset(u_ret,0,255);
 int nResult=WideCharToMultiByte(
          CP_ACP,    // code page
          WC_COMPOSITECHECK, // character-type options
          (LPCWSTR)pBuf,  // string to map
          nLength/4,     //str.GetLength(),  // number of bytes in string
          (LPSTR)u_ret,  // wide-character buffer
          sizeof(u_ret),     // size of buffer
          NULL,
          NULL
           );
 
 CString sMessage;
 sMessage.Format("%s",u_ret);
 return sMessage;
}

void CMyTools::HexToChar(CString sHex, char *p)
{
unsigned char byteToHex[] =
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 'A', 'B', 'C', 'D', 'E', 'F'};
 int nLen = sHex.GetLength();
 char *chBuf = p,//记录内存块的首地址
    *pch;
 CString sTemp,sLeft,sRight;
 for (int i=0; i<nLen/4; i++)
 {
  sTemp = sHex.Left(4);
  sHex.Delete(0,4);
  sLeft = sTemp.Left(2);
  sRight = sTemp.Right(2);
  *chBuf = (char)strtoul(sRight.GetBuffer(2),&pch,16);
  chBuf++;
  sRight.ReleaseBuffer();
  *chBuf = (char)strtoul(sLeft.GetBuffer(2),&pch,16);
  chBuf++;         
  sLeft.ReleaseBuffer();
 }
 *chBuf='\0';

}

编码解码的工具都全了,现在来看“打包”函数:

void CMsgSend::Pack(CString c_number,CString s_number,CString msg)
{
 int len;


 SCA= "00";

 //PDUTtpe
 PDUType = "31";

 //MR
 MR = "00";

 //DA
 s_number = s_number + "F";
 len = s_number.GetLength();
 DA.Format("%2.2X81",len-1);
 DA = DA + CMyTools::SwapConvert(s_number);

 //PID
 PID = "00";

 //DCS
 DCS = "08";

 //VP
 VP = "A7";

 //UD
 UD = CMyTools::EnCodeChinese(msg);

 //UDL
 UDL.Format("%2.2X",UD.GetLength()/2);


 m_strData = SCA + PDUType + MR + DA + PID + DCS + VP + UDL + UD;
}
例如我想给13875998800发送一条内容是hello的信息,短信中心号码为8613800731500,我们可以这样调用:

msg.Pack("8613800731500","13875998800","hello");
 sendMsg = msg.GetMsgData();
 m.Format("AT+CMGS=%d\r\n",(sendMsg.GetLength()-msg.SCA.GetLength())/2);
 SendData((LPSTR)(LPCTSTR)m,m.GetLength());
 m.Format("%s%c",sendMsg,26);
 SendData((LPSTR)(LPCTSTR)m,m.GetLength());

具体的编码过程上面文档里面说的已经够详细了,也不在这里多说。

这里由于篇幅原因省略了很多东西,反正原理就是这些,核心代码也就是上面的一些编码解码的东西了,有些代码我也是从网上找到然后修改了一下来用的。

其实用AT指令还可以干很多事情,甚至拨打电话之类的都没问题,拨打电话的AT指令很简单:

ATD13875998800,只要发送这个指令过去,手机就会拨打13875998800这个号码。不过经过实践,发现被叫的手机无法正常的接听,提示要与电脑设备连接才可以接听,具体如何实现就没研究过了.....


 

posted on 2006-04-27 13:47 江可 阅读(1848) 评论(1)  编辑 收藏 引用 所属分类: 随心所欲

FeedBack:
# re: 用VC实现发送和接收短信
2010-01-25 15:02 | Cream
谢谢你的分享!!!  回复  更多评论
  
只有注册用户登录后才能发表评论。