windows mobile 发送短信原理和实现demo

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

}

 

补充下,上面的是在手机发送给手机的情况下成功了,下面的就是在一个短信中心项目中测试的情况.(没有想到短信中心和一般手机上的情况不一样的.唉)



/*
bSendConfirmation    是否接受确认消息
bUseDefaultSMSC      是否使用默认短消息信息中心号码
pszCenterPhone       短信中心的号码
pszDUserPhone        信息接受方号码
pszMessage           所发送的文本信息
*/

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")/*pszMessage*/;
    TCHAR  *lpszMessage = pszMessage;
    // 打开SMS
    if(FAILED(SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smshHandle, NULL)))
    {
        CSNormalView::CloseNotify();
        ShowMessage(_T("SmsOpen 失败."));
        return false;
    }
    建立短信中心地址(号码)
    /*if(!bUseDefaultSMSC)
    {
        smsaSource.smsatAddressType = SMSAT_NATIONAL/*SMSAT_INTERNATIONAL*/;
        //_tcsncpy(smsaSource.ptsAddress, pszCenterPhone, SMS_MAX_ADDRESS_LENGTH);
    //}

    //if(!bUseDefaultSMSC)
    //{
    //    smsaSource.smsatAddressType = SMSAT_NATIONAL/*SMSAT_INTERNATIONAL*/;
    //    _tcsncpy(smsaSource.ptsAddress, _T("13800755500"), SMS_MAX_ADDRESS_LENGTH);
    //}

    // 创建目标地址(号码)
    memset (&smsaDestination, 0, sizeof (smsaDestination));
    smsaDestination.smsatAddressType = SMSAT_NATIONAL/*SMSAT_INTERNATIONAL*/;
    _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/*PS_MESSAGE_CLASS1*/;


/* 这个要设置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/*((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
    {
       
        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打开的句柄
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值