天天看点

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

}

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

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打开的句柄