天天看點

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