#include <sms.h>
#pragma comment(lib,"sms.lib")
void SendSMS1(LPCTSTR lpszMessage, LPCTSTR lpszRecipient,LPCTSTR lpszSMSC,BOOL bSendConfirmation, BOOL bUseDefaultSMSC)
{
SMS_HANDLE smshHandle; //短信句柄
SMS_ADDRESS smsaDestination;//接收號碼
TEXT_PROVIDER_SPECIFIC_DATA tpsd;
SMS_MESSAGE_ID smsmidMessageID;
// 打開發送句柄
// 協議字符串, SMS_MODE_SEND:發送模式 psmshHandle:返回的句柄 phMessageAvailableEvent:通知的事件
if(FAILED(SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smshHandle, NULL)))
{
return;
}
// Create the destination address
//SMSAT_NATIONAL:國內電話 SMSAT_INTERNATIONAL:國際電話
smsaDestination.smsatAddressType = SMSAT_UNKNOWN;
_tcsncpy(smsaDestination.ptsAddress, lpszRecipient, SMS_MAX_ADDRESS_LENGTH);
// Set up provider specific data
memset(&tpsd, 0, sizeof(tpsd));
//tpsd.dwMessageOptions = PS_MESSAGE_OPTION_NONE;
tpsd.dwMessageOptions = PS_MESSAGE_OPTION_STATUSREPORT;//表示需要狀態報告
tpsd.psMessageClass = PS_MESSAGE_CLASSUNSPECIFIED;
//PS_MESSAGE_CLASS0表示短信在被接收后立即顯示且不存儲在收件箱(稱為閃信)
//PS_MESSAGE_CLASS1表示一般的情況,被接收后存儲到收件箱并發送一個確認回短信中心,發送方收到一個已被接收的狀態報告。
tpsd.psReplaceOption = PSRO_NONE;
//手動清空頭信息
ZeroMemory(tpsd.pbHeaderData, sizeof(tpsd.pbHeaderData));
tpsd.dwHeaderDataSize = 0;
tpsd.fMessageContainsEMSHeaders = FALSE;
tpsd.dwProtocolID = SMS_MSGPROTOCOL_UNKNOWN;
// Send the message, indicating success or failure
/*
*smshHandle: SmsOpen打開的句柄
?? psmsaSMSCAddress: SMSC中心
?? *psmsaDestinationAddress:發送的目的地址
?? pstValidityPeriod :發送時間的有效期
?? *pbData: 信息的內容部分
?? *dwDataSize: 信息的內容部分的長度
?? *pbProviderSpecificData:針對運營商的附加數據
?? *dwProviderSpecificDataSize :附加數據的長度
?? smsdeDataEncoding :短信編碼[SMSDE_OPTIMAL是其
推薦值]表示由短信中心決定字符的格式
?? dwOptions :其他選項
?? psmsmidMessageID: 用于得到系統回執的信息
SmsGetMessageStatus
*/
//SMSDE_GSM使用7-bit編碼
//SMSDE_UCS2使用16-bit (Unicode)編碼
if(SUCCEEDED(SmsSendMessage(smshHandle, NULL,
&smsaDestination, NULL, (PBYTE) lpszMessage,
_tcslen(lpszMessage) * sizeof(TCHAR), (PBYTE) &tpsd,
sizeof(TEXT_PROVIDER_SPECIFIC_DATA), SMSDE_UCS2,
SMS_OPTION_DELIVERY_NONE, &smsmidMessageID)))
{
//Tstr=L"發送完成";
//發送完成
MessageBox( NULL,L"SEND OK",L"MSG",MB_OK);
}
else
{
//發送失敗
//Tstr=L"發送失敗";
MessageBox(NULL,L"發送失敗",L"MSG",MB_OK);
}
// clean up
VERIFY(SUCCEEDED(SmsClose(smshHandle)));
}
注意:LPCTSTR 和 PCWSTR是寬字符,所以用16-bit (Unicode)編碼。網上的HelloSMS的程序不夠嚴謹,如果照用可能造成短信中心網關把短信給吞掉的情況,程序雖然調用成功,但是就是目標號碼收不到短信。函數參數中的后三個參數可以不用或設默認值都可以。
使用Windows CE的SMS API函數SmsSendMessage可以發送7-bit編碼和16-bit編碼的短消息(未測試8-bit編碼)。單條短消息的最大字符數分別是160和70。發送短消息全部為ASCII字符,SMS_DATA_ENCODING參數選擇SMSDE_GSM或SMSDE_OPTIMAL都可以。發送短消息不全為ASCII字符,SMS_DATA_ENCODING參數選擇SMSDE_UCS2或SMSDE_OPTIMAL都可以。建議選擇SMSDE_OPTIMAL。
發送短消息全部為ASCII字符,且字符個數超過160個時,系統會自動將短消息進行分割,但并不是按每條160進行分割,而是按每條153。發送短消息不全為ASCII字符,且字符個數超過70個時,系統會自動將短消息進行分割,但并不是按每條70進行分割,而是按每條67。
發送短消息的字符數超過160或70時,應該自行進行分割,而不應交由系統進行分割,這樣可以最大限度的利用單條短消息的最大字符數分別是160和70的條件.
上面的代碼是通過MAPI來實現,任意一部有SIM卡的PDA/PPC上都已運行。
下面的代碼是通過串口和AT指令來發送短信,需要有Gms Modem 才可以運行。
HANDLE hSerial;
int res;
unsigned long bytes;
//COM1 COM2 COM4
hSerial = CreateFile(_T("COM1:"), GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if(hSerial == NULL)
{
///L"串口打開失敗";
return;
}
///配置串口
DCB PortDCB;
PortDCB.DCBlength = sizeof(DCB);
// 默認串口參數
GetCommState(hSerial, &PortDCB);
PortDCB.BaudRate =115200 ; // baud
PortDCB.ByteSize = 8; // Number of bits/byte, 4-8
PortDCB.Parity = NOPARITY;
PortDCB.StopBits = ONESTOPBIT;
PortDCB.fBinary=TRUE;
if (! SetCommState(hSerial, &PortDCB))
{
///L"配置串口失敗";
return;
}
////配置超時值
COMMTIMEOUTS CommTimeouts;
GetCommTimeouts(hSerial, &CommTimeouts);
CommTimeouts.ReadIntervalTimeout = 100;
CommTimeouts.ReadTotalTimeoutMultiplier = 100;
CommTimeouts.ReadTotalTimeoutConstant = 100;
CommTimeouts.WriteTotalTimeoutMultiplier =100;
CommTimeouts.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hSerial, &CommTimeouts))
{
return;
}
//設置串口“感興趣”的事件
SetCommMask(hSerial, EV_RXCHAR);
//設置輸入輸出緩沖區
SetupComm(hSerial, 1024, 1024);
//初始化緩沖區中的信息
PurgeComm(hSerial, PURGE_TXCLEAR|PURGE_RXCLEAR);
//-------------------------------------串口設置完畢----------------------------------------
UpdateData(TRUE);
char str_last[2000];
int num_Length=0;
int context_length=0;
TCHAR tmp[2];
int i=0;
char addr[100]="0891683108100005F0";//短信中心號碼
char phone[100]="11000D91";
char msg[1000];
// unsigned char *msg_tmp;
unsigned char msg_tmp[1000];
char str_tmp[100]="";
char str_tmp2[50]="000800";
num_Length=m_num.GetLength();
context_length=m_context.GetLength();
m_num=L"86"+m_num;
if(num_Length%2){m_num=m_num+L"F";}
for (i=0; i <(m_num.GetLength()); ) //處理 目標電話號碼 奇偶換位
{
phone[i+9] = m_num.GetAt(i);
phone[i+8] = m_num.GetAt(i+1);
i+=2;
}
WideCharToMultiByte(CP_ACP, 0, m_context, m_context.GetLength(), str_tmp, 160, NULL, NULL);
// msg_tmp=(unsigned char *)malloc(sizeof(unsigned char ));
gsmEncodeUcs2(str_tmp,msg_tmp,context_length);//UCS2編碼
for(i=0;i<context_length*2;i++)//將編后的碼轉換為16進制以進行傳輸 前兩位預留
{
wsprintf(tmp, L"%02X", msg_tmp[i]);
msg[2*i+2]=tmp[0];
msg[2*i+3]=tmp[1];
}
wsprintf(tmp, L"%02X", context_length*2);//前兩位存儲msg的長度
msg[0]=tmp[0];
msg[1]=tmp[1];
//-------------------------------addr phone msg 全部就緒----------------------------
// 最終信息為 str_last=addr+phone+000800+msg
for(i=0;i<18 ;i++)
{
str_last[i]=addr[i];
}
for(i=0;i<22 ;i++)
{
str_last[i+18]=phone[i];
}
for(i=0;i<6 ;i++)
{
str_last[i+40]=str_tmp2[i];
}
for(i=0;i<context_length*4+2 ;i++)
{
str_last[i+46]=msg[i];
}
str_last[i+46]='\32';
//--------------------------開始發送--------------------------------------------
char str1[100]="AT+CMGS=25\r";
wsprintf(tmp, L"%02d",(context_length*4+30)/2);//計算需要發送的字節
str1[8]=tmp[0];
str1[9]=tmp[1];
char str2[100]="";
res=WriteFile(hSerial,str1,100,&bytes,NULL);
res=ReadFile(hSerial,str2,100,&bytes,NULL);
char str3[100]="";
res=WriteFile(hSerial,str_last,1000,&bytes,NULL);
res=ReadFile(hSerial,str3,100,&bytes,NULL);
//----------------------------發送結束-------------------------------------------------------
// free(msg_tmp);
CloseHandle(hSerial);
}
BOOL CSendMessage2::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
// m_num=L"15010657623";
m_num=L"13811916883";
// m_context=L"1192323 392486";
m_context=L"工作愉快!";
UpdateData(false);
return TRUE;
網上的HelloSMS的發送短信代碼,有不完善的地方。用它來發短信可能會有問題,下面這段代碼是我對它的一個改進,基本可以運行在實際的項目中:
////////////////////////////////////////////////////////////////////////////
// 發送短信
//lpszSMSC:短信中心號碼 lpszRecipient:接收號碼(目標號碼)
//lpszMessage:發送短信內容
//bUseDefaultSMSC:目標地址
//bSendConfirmation:消息發送選項
////////////////////////////////////////////////////////////////////////////
void CCellGuardApp::SendSMS( LPCTSTR lpszMessage, LPCTSTR lpszRecipient,LPCTSTR lpszSMSC,BOOL bSendConfirmation, BOOL bUseDefaultSMSC)
{
SMS_HANDLE smshHandle; //短信句柄
SMS_ADDRESS smsaDestination;//接收號碼
TEXT_PROVIDER_SPECIFIC_DATA tpsd;
SMS_MESSAGE_ID smsmidMessageID;
// 打開發送句柄
// 協議字符串, SMS_MODE_SEND:發送模式 psmshHandle:返回的句柄 phMessageAvailableEvent:通知的事件
if(FAILED(SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smshHandle, NULL)))
{
return;
}
// Create the destination address
smsaDestination.smsatAddressType = SMSAT_UNKNOWN;
_tcsncpy(smsaDestination.ptsAddress, lpszRecipient, SMS_MAX_ADDRESS_LENGTH);
// Set up provider specific data
memset(&tpsd, 0, sizeof(tpsd));
//tpsd.dwMessageOptions = PS_MESSAGE_OPTION_NONE;
tpsd.dwMessageOptions = PS_MESSAGE_OPTION_STATUSREPORT;
tpsd.psMessageClass = PS_MESSAGE_CLASSUNSPECIFIED;
tpsd.psReplaceOption = PSRO_NONE;
//tpsd.dwHeaderDataSize = 0;
ZeroMemory(tpsd.pbHeaderData, sizeof(tpsd.pbHeaderData));
tpsd.dwHeaderDataSize = 0;
tpsd.fMessageContainsEMSHeaders = FALSE;
tpsd.dwProtocolID = SMS_MSGPROTOCOL_UNKNOWN;
// Send the message, indicating success or failure
if(SUCCEEDED(SmsSendMessage(smshHandle, NULL,
&smsaDestination, NULL, (PBYTE) lpszMessage,
_tcslen(lpszMessage) * sizeof(TCHAR), (PBYTE) &tpsd,
sizeof(TEXT_PROVIDER_SPECIFIC_DATA), SMSDE_UCS2,
SMS_OPTION_DELIVERY_NONE, &smsmidMessageID)))
{
//Tstr=L"發送完成";
//發送完成
;
}
// clean up
VERIFY(SUCCEEDED(SmsClose(smshHandle)));
}