以下内容是暑假做中科杯项目时自己根据网上资料整理的Windows Mobile短信发送的学习笔记。
一、Window Mobile 发送短信方式主要有两种:
1.API方式
2.POOM方式
二、两种方式的优缺点比较:
1.API方式缺点:无法向小灵通发送短信
2.POOM方式的优势与缺点:
优点:和系统结合紧密,利用系统发送,省心省力
缺点:不能发送Unicode短信,因此无法发送中文短信;无法完全控制回执/闪信等方面特点。
(P.S.:闪信是一项新的短信类业务,发送闪信,对方收到闪信后无需打开,信息内容即直接显示于接收方手机屏幕上,阅读后信息不自动保存,仅有部分支持手动保存,此业务仅适用于中国移动用户对中国移动用户发送。)
结合国内环境,不发送中文短信几乎是不能接受的,加上小灵通也即将完成它的历史使命,所以在做中科杯的时候,我采用的是API方式发送短信。以下内容主要是介绍用API方式发送短信。
三、API方式发送短信:
1.在windows mobile中发送SMS主要需要调用以下三个API:
①SmsOpen
②SmsSendMessage
③SmsClose
头文件<sms.h> 库<sms.lib>
2.API具体介绍:
(1)HRESULT SmsOpen (
const LPCTSTR ptsMessageProtocol,
const DWORD dwMessageModes,
SMS_HANDLE* const psmshHandle,
HANDLE* const phMessageAvailableEvent);
参数:
ptsMessageProtocol:协议字符串
dwMessageModes:
SMS_MODE_RECEIVE:接收模式
SMS_MODE_SEND: 发送模式
psmshHandle:返回的句柄
phMessageAvailableEvent:通知的事件
返回值:标准HRESULT返回值
(2)HRESULT SmsSendMessage (
const SMS_HANDLE smshHandle,
const SMS_ADDRESS * const psmsaSMSCAddress,
const SMS_ADDRESS * const psmaDestinationAddress,
const SYSTEMTIME * const pstValidityPedriod,
const BYTE * const pbData,
const DWORD dwDataSize,
const BYTE * const pbProviderSpecificData,
const DWORD dwProviderSpecificDataSize,
const SMS_DATA_ENCODING smsdeDataEncoding,
const DWORD dwOptions,
SMS_MESSAGE_ID * psmsmidMessageID);
参数:
smshHandle:SmsOpen打开的句柄
psmsaSMSCAddress:SMSC中心
psmaDestinationAddress:发送短信目的地址
pstValidityPedriod:发送时间的有效期
pbData:信息的内容部分
dwDataSize:信息内容部分的长度
pbProviderSpecificData:针对运营商的附加数据
dwProviderSpecificDataSize:附加数据长度
smsdeDataEncoding:短信编码(SMSDE_OPTIMAL是其推荐值)
dwOptions:其他选项
psmsmidMessageID:用于得到系统回执的信息
发送目的地地址结构定义:
typedef struct sms_address_tag{
SMS_ADDRESS_TYPE smsatAddressType;
TCHAR ptsAddress[SMS_MAX_ADDRESS_LENGTH];
} SMS_ADDRESS, *LPSMS_ADDRESS;
SMS_ADDRESS_TYPE:
①SMS_UNKOWN:默认
②SMS_INTERNATIONAL:国际电话
③SMS_NATIONAL:国内电话
针对运营商的附加数据结构定义:
typedef struct text_provider_specific_data_tag{
DWORD dwMessageOptions;
PROVIDER_SPECIFIC_MESSAGE_CLASS psMessageClass;
PROVIDER_SPECIFIC_REPLACE_OPTION psReplaceOption;
DWORD dwHeaderDataSize;
BYTE pbHeaderData[SMS_DATAGRAM_SIZE];
BOOL fMessageContainsEMSHeaders;
DWORD dwProtocolID;
} TEXT_PROVIDER_SPECIFIC_DATA;
①psMessageClass:
PS_MESSAGE_CLASS0到PS_MESSAGE_CLASS3(0为闪信,1为普通,2和3很少用到)
PS_MESSAGE_CLASSUNSPECIFIED(很少用到)
②dwMessageOptions
PS_MESSAGE_OPTION_STATUSREPTRT 状态报告
PS_MESSAGE_OPTION_NONE 无回执
③psReplaceOption
PSRO_NONE 一般用这个
PSRO_REPLACE_TYPE1- PSRO_REPLACE_TYPE7
(3)HRESULT SmsOpen (
const SMS_HANDLE smshHandle);
参数:smshHandle:SmsOpen返回的句柄
返回值:标准HRESULT返回值
四、例程
TCHAR* szMessage =new TCHAR[200]; //短信内容
lstrcpy(szMessage,m_strContent);
TCHAR *szDest=new TCHAR [30]; //发送短信目的地号码
lstrcpy(szDest,m_strNumber);
HRESULT hr = E_FAIL;
SMS_HANDLE smsHandle;
int destSize = 0;
destSize = lstrlen(szDest); //短信地址长度
if((*szDest == '0')||(destSize < 1)|| (destSize>=SMS_MAX_ADDRESS_LENGTH))
//短信地址长度不合法
{
AfxMessageBox(_T("错误:短信地址长度不合法!"));
}
DWORD dwDataSize =0; //短信内容长度
int datalen = lstrlen(szMessage);
if(datalen ==0)//短信内容为空
{
AfxMessageBox(_T("错误:短信内容为空!"));
}
dwDataSize =_tcslen(szMessage)*sizeof(TCHAR);//得到短信内容长度
hr = SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smsHandle, NULL);
if(hr!=S_OK) //打开句柄失败
{
AfxMessageBox(_T("错误:打开句柄失败!"));
}
else
{
//设置发送目的地地址结构
SMS_ADDRESS smsaDestAddr ;
memset(&smsaDestAddr, 0 ,sizeof(SMS_ADDRESS));
smsaDestAddr.smsatAddressType = SMSAT_UNKNOWN;
// 目的地号码
for(int i=0;i<=destSize;i++)
smsaDestAddr.ptsAddress[i]=szDest[i];
// 设置运营商数据
TEXT_PROVIDER_SPECIFIC_DATA tpsp;
memset(&tpsp , 0 ,sizeof(TEXT_PROVIDER_SPECIFIC_DATA));
tpsp.dwMessageOptions = PS_MESSAGE_OPTION_NONE;
tpsp.psMessageClass = PS_MESSAGE_CLASS1;
tpsp.psReplaceOption = PSRO_NONE;
SMS_MESSAGE_ID smsmidMessageID =0;
//调用SmsSendMessage发送短信
hr = SmsSendMessage(smsHandle,
NULL,
&smsaDestAddr,
NULL,
(BYTE *)szMessage,
dwDataSize,
(BYTE *)&tpsp,
sizeof(TEXT_PROVIDER_SPECIFIC_DATA),
SMSDE_OPTIMAL,
SMS_OPTION_DELIVERY_NONE,
&smsmidMessageID);
if(hr != S_OK)//发送失败
{
ASSERT(hr);
}
}
SmsClose(smsHandle);//关闭句柄
delete []szMessage;
delete []szDest;