Windows Mobile发送短信应用分为两种,一是调用Windows Mobile自有的发送短信窗口,将接收用户的手机号码传递给该窗口,完成短信发送(暂且称为窗口短信),另一种是通过调用API将文本发送给指定的号 码,这中发送方式对于用户是无感知的(暂且称为无感知短信,下面对这两种方式的实现分别介绍。
窗口短信:
窗口短信实现比较简单, 可以直接使用下面的启动参数启动系统的EXE文件即可, System.Diagnostics.Process.Start("tmail.exe", "-transport /"SMS/" -to /"" + 手机号码 + "/" -body /"短信内容/"");但要注意的是,在发送完毕后,短信列表页面会在你关闭发送信息窗口后呈现出来,可以在页面的关闭事件中,使用FindWind方 法,找到系统的【短信】窗口,将其关闭即可。
无感知短信
1.Windows Mobile 5.0及以上版本
无感知短信 接口与Mobile操作系统的版本有关,如果是基于Windows Mobile5.0 的设备 ,完成短信发送比较容易,因为微软已经给你封装好了底层的API,可以直接进行调用,引用 Microsoft.WindowsMobile.PocketOutlook.dll后,使用SmsMessage smsSend = new SmsMessage(phone, sms);smsSend.Send();方法便可以完成对一条短息的发送。
///.h文件
#include <sms.h>
#pragma comment (lib, "sms.lib")
#define MAXLEN 1024
#define SENDMODE 1 //是发送还是接收
bool SendSMS(bool bSendConfirmation,bool bUseDefaultSMSC,TCHAR* pszCenterPhone,TCHAR * pszDUserPhone,TCHAR* pszMessage);
bool RecvSMS(TCHAR* pszRecvMsg,int nRecvLen);
///cpp文件
bool SendSMS(bool bSendConfirmation,bool bUseDefaultSMSC,TCHAR* pszCenterPhone,TCHAR * pszDUserPhone,TCHAR* pszMessage)
{
SMS_HANDLE smshHandle;
SMS_ADDRESS smsaSource;
SMS_ADDRESS smsaDestination;
TEXT_PROVIDER_SPECIFIC_DATA tpsd;
SMS_MESSAGE_ID smsmidMessageID=0;
HRESULT hr=0;
TCHAR *lpszMessage = pszMessage;
// 打开SMS
if(FAILED(SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smshHandle, NULL)))
{
//printf(("SmsOpen failed!"));
MessageBox(NULL,_T("SmsOpen 失败."),_T("提示"),MB_OK);
return false;
}
// 建立短信中心地址(号码)
if(!bUseDefaultSMSC)
{
smsaSource.smsatAddressType = SMSAT_INTERNATIONAL;
_tcsncpy(smsaSource.ptsAddress, pszCenterPhone, SMS_MAX_ADDRESS_LENGTH);
}
// 创建目标地址(号码)
memset (&smsaDestination, 0, sizeof (smsaDestination));
smsaDestination.smsatAddressType = SMSAT_INTERNATIONAL;
_tcsncpy(smsaDestination.ptsAddress, pszDUserPhone, SMS_MAX_ADDRESS_LENGTH);
// 设置提供者服务
memset (&tpsd, 0, sizeof (tpsd));
tpsd.dwMessageOptions = bSendConfirmation ? PS_MESSAGE_OPTION_STATUSREPORT : PS_MESSAGE_OPTION_NONE;
tpsd.psMessageClass = PS_MESSAGE_CLASS1;
tpsd.psReplaceOption = PSRO_NONE;
// 发送
if(SUCCEEDED(hr=SmsSendMessage(smshHandle, ((bUseDefaultSMSC) ? NULL : &smsaSource),
&smsaDestination, NULL, (PBYTE) lpszMessage,
_tcslen(lpszMessage) * sizeof(TCHAR), (PBYTE) &tpsd,
sizeof(TEXT_PROVIDER_SPECIFIC_DATA), SMSDE_OPTIMAL,
SMS_OPTION_DELIVERY_NONE, &smsmidMessageID)))
{
MessageBox(NULL,_T("发送成功"),_T("提示"),MB_OK);
}
else
{
MessageBox(NULL,_T("发送发送"),_T("提示"),MB_OK);
VERIFY(SUCCEEDED(SmsClose(smshHandle)));
return false;
}
//关闭
VERIFY(SUCCEEDED(SmsClose(smshHandle)));
return true;
}
bool RecvSMS(TCHAR* pszRecvMsg,int nRecvLen)
{
SMS_HANDLE smshHandle = 0;
SMS_MESSAGE_ID smsmidMessageID = 0;
HRESULT hRet = 0;
SMS_HANDLE smshRecieveHandle;
DWORD dwReturn = 0;
HANDLE hSmsEvent;
dwReturn = SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_RECEIVE, &smshRecieveHandle, &hSmsEvent);
// 程序会在此等待模块来短信,直到超时或者有短信来到
dwReturn = WaitForSingleObject(hSmsEvent, INFINITE);
// 判断是否成功接收到短信
if(dwReturn == WAIT_ABANDONED || dwReturn == WAIT_TIMEOUT)
{
return FALSE;
}
// 成功接收到短信,先设置好短信大小
DWORD dwMessageSize = nRecvLen;
// 初始化短信结构
SMS_ADDRESS smscAddress;
SMS_ADDRESS inAddress;
SYSTEMTIME rcvTime;
TEXT_PROVIDER_SPECIFIC_DATA txtProviderData;
DWORD dwProviderLength = 0;
dwProviderLength = sizeof(TEXT_PROVIDER_SPECIFIC_DATA);
memset(&txtProviderData, 0, dwProviderLength);
memset(&smscAddress, 0, sizeof(SMS_ADDRESS));
memset(&inAddress, 0, sizeof(SMS_ADDRESS));
memset(&rcvTime, 0, sizeof(SYSTEMTIME));
TCHAR *tchMsgBuffer = pszRecvMsg;
// 把短信从模块里读出来放到buffer里,执行完以后,tchMsgBuffer里存放的就是接收到短信的UNICODE编码
DWORD dwBytesRead = 0;
hRet = SmsReadMessage(
smshRecieveHandle,
&smscAddress,
&inAddress,
&rcvTime,
(LPBYTE)tchMsgBuffer,
dwMessageSize,
(LPBYTE)&txtProviderData,
dwProviderLength,
&dwBytesRead
);
SmsClose(smshHandle);
SmsClose(smshRecieveHandle);
smshHandle = NULL;
if(FAILED(hRet))
{
return FALSE;
}
return TRUE;
}
CString GetSMSCenterPhone()
{
CString strSmsCenter;
SMS_ADDRESS smsaCenter;
UINT hRet = SmsGetSMSC(&smsaCenter);
if(FAILED(hRet))
{
return _T("");
}
strSmsCenter = smsaCenter.ptsAddress;
return strSmsCenter;
}
//格式转换
CString abc;
TCHAR *pData = (TCHAR*)(LPCTSTR)abc;
调用方式:
void test()
{
#ifdef SENDMODE
SendSMS(true,true,_T("138xxxxxxxx"),_T("+86136xxxxxxxx"),_T("测试.短信发送成功."));
#else
int nRecvLen = MAXLEN;
TCHAR *pRecvBuf = NULL;
pRecvBuf = (TCHAR *)LocalAlloc(LPTR,nRecvLen*sizeof(TCHAR));
if(!pRecvBuf)
{
RecvSMS(pRecvBuf,nRecvLen);
}
LocalFree(pRecvBuf);
pRecvBuf = NULL;
#endif
}
补充下,上面的是在手机发送给手机的情况下成功了,下面的就是在一个短信中心项目中测试的情况.(没有想到短信中心和一般手机上的情况不一样的.唉)
bool CUserSMSRegisterView::SendSMS(bool bSendConfirmation,bool bUseDefaultSMSC,TCHAR* pszCenterPhone,TCHAR * pszDUserPhone,TCHAR* pszMessage)
{
//SendMessage(NN_MESSAGE, NNF_STATUS_NOTIFY,NULL);
SMS_HANDLE smshHandle;
SMS_ADDRESS smsaSource;
SMS_ADDRESS smsaDestination;
TEXT_PROVIDER_SPECIFIC_DATA tpsd;
SMS_MESSAGE_ID smsmidMessageID=0;
HRESULT hr=0;
//TCHAR *lpszMessage = _T("ZXZQ");
TCHAR *lpszMessage = pszMessage;
// 打开SMS
if(FAILED(SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smshHandle, NULL)))
{
CSNormalView::CloseNotify();
ShowMessage(_T("SmsOpen 失败."));
return false;
}
建立短信中心地址(号码)
;
//_tcsncpy(smsaSource.ptsAddress, pszCenterPhone, SMS_MAX_ADDRESS_LENGTH);
//}
//if(!bUseDefaultSMSC)
//{
// smsaSource.smsatAddressType = SMSAT_NATIONAL;
// _tcsncpy(smsaSource.ptsAddress, _T("13800755500"), SMS_MAX_ADDRESS_LENGTH);
//}
// 创建目标地址(号码)
memset (&smsaDestination, 0, sizeof (smsaDestination));
smsaDestination.smsatAddressType = SMSAT_NATIONAL;
_tcsncpy(smsaDestination.ptsAddress, pszDUserPhone, SMS_MAX_ADDRESS_LENGTH);
//_tcsncpy(smsaDestination.ptsAddress, _T("955580788"), SMS_MAX_ADDRESS_LENGTH);
// 设置提供者服务
memset (&tpsd, 0, sizeof (tpsd));
//tpsd.dwMessageOptions = bSendConfirmation ? PS_MESSAGE_OPTION_STATUSREPORT : PS_MESSAGE_OPTION_NONE;
tpsd.dwMessageOptions = PS_MESSAGE_OPTION_NONE;
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;
// 发送
if(SUCCEEDED(hr=SmsSendMessage(smshHandle,NULL,
&smsaDestination, NULL, (PBYTE) lpszMessage,
_tcslen(lpszMessage) * sizeof(TCHAR), (PBYTE) &tpsd,
sizeof(TEXT_PROVIDER_SPECIFIC_DATA), SMSDE_OPTIMAL,
SMS_OPTION_DELIVERY_NONE, &smsmidMessageID)))
{
//::MessageBox(NULL,_T("发送成功"),_T("提示"),MB_OK);
}
else
{
VERIFY(SUCCEEDED(SmsClose(smshHandle)));
CSNormalView::CloseNotify();
ShowMessage(_T("发送失败"));
return false;
}
//关闭
VERIFY(SUCCEEDED(SmsClose(smshHandle)));
//CSNormalView::CloseNotify();
ShowMessage(_T("短信发送成功"));
return true;
}
SendSMS(true,true,_T("13800755500"),_T("9555xxxx"),_T("ZXZQ"));
//以下是相关资料
#include <sms.h> //要支持短信发送就要包含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打开的句柄