rated by 0 users
This post has 3 Replies | 2 Followers

Top 75 Contributor
Male
Posts 6
Phạm Hoài Vũ Posted: 03-27-2009 1:22 PM

 

Đây là cách mình gửi tin nhắn SMS trong Windows CE và Windows Mobile, sử dụng C++ (MFC) và .NET CF.

Trong WinCE, các chức năng liên quan đến SMS được thực hiện bởi các hàm  SmsOpen, SmsSendMessage, SmsClose trong thư viện “sms.dll”, nhưng từ WM 2005 trở về sau, “cemapi.dll” sử dụng các API đơn giản hơn để thực hiện việc này. “cemapi.dll” không được mô tả 1 cách chính thức, nhưng “sms.dll” lại được trình bày rất kĩ trong MSDN. Như vậy nếu đang chạy trên WM2k5 về sau, ta dùng hàm SendSmsMessage của cemapi.dll, nếu là WM2k3 về trước, ta dùng SmsOpen, SmsSendMessage, SmsClose trong sms.dll

Về kĩ thuật lập trình, trong .NET CF ta sẽ dùng DllImport, còn C++ thì ta sẽ dùng các hàm LoadLibrary, GetProcAddress, FreeLibrary truyền thống.

Đây là source code trong .NET CF:

   1:          internal static bool SendMessage_WM2k3(string destination, string message)
   2:          {
   3:              // SEND = 2, RECEIVE = 1
   4:              IntPtr handle;
   5:              IntPtr intPtr = IntPtr.Zero;
   6:   
   7:              if (SmsOpen("Microsoft Text SMS Protocol", 2, out handle, ref intPtr) == 0)
   8:              {
   9:                  byte[] array = new byte[0x204];
  10:                  if (destination.StartsWith("+"))
  11:                  {
  12:                      BitConverter.GetBytes(1).CopyTo(array, 0);
  13:                  }
  14:                  Encoding.Unicode.GetBytes(destination).CopyTo(array, 4);
  15:                  int dwProviderSpecificDataSize = 0xa4;
  16:                  byte[] buffer2 = new byte[dwProviderSpecificDataSize];
  17:                  BitConverter.GetBytes(1).CopyTo(buffer2, 4);    // messageclass = 1
  18:   
  19:                  int messageId;
  20:                  if(SmsSendMessage(handle, null, array, null, message, message.Length * 2, buffer2, dwProviderSpecificDataSize, 0, 0, out messageId) == 0)
  21:                  {
  22:                      SmsClose(handle);
  23:                      return true;
  24:                  }
  25:              }
  26:              return false;
  27:          }
  28:   
  29:          static Thread m_SendSMSThread;
  30:          static string m_sRecipientPhone;
  31:          static string m_sSMSContent;
  32:   
  33:          private static void SendSMS()
  34:          {
  35:              CultureInfo culture = CurrentCulture;
  36:   
  37:              if(Environment.OSVersion.Version.Major < 5)     // WM 2k3 and previous
  38:              {
  39:                  if(!SendMessage_WM2k3(m_sRecipientPhone, m_sSMSContent))
  40:                  {
  41:                      MessageBox.Show("Error");
  42:                  }
  43:                  else
  44:                  {
  45:   
  46:                      MessageBox.Show("Success");
  47:   
  48:                  }
  49:              }
  50:              else
  51:              {
  52:                  if(SendSMSMessage(m_sRecipientPhone, m_sSMSContent, false) != 0)
  53:                  {
  54:                      MessageBox.Show("Error");
  55:                  }
  56:                  else
  57:                  {
  58:                      MessageBox.Show("Success");
  59:   
  60:                  }
  61:              }
  62:           }
  63:   
  64:          public static void SendSMS(string recipient, string sContent)
  65:          {
  66:              m_sRecipientPhone = recipient;
  67:              m_sSMSContent = sContent;
  68:              m_SendSMSThread = new Thread(SendSMS);
  69:              m_SendSMSThread.Start();
  70:   
  71:          }
  72:   
  73:          [DllImport("cemapi.dll", EntryPoint = "#48", SetLastError = true)]
  74:          public static extern int SendSMSMessage(string RecipientAddress, string MessageText, bool DeliveryReportRequested);
  75:   
  76:          [DllImport("sms.dll")]
  77:          private static extern int SmsSendMessage(IntPtr smshHandle, byte[] psmsaSMSCAddress, byte[] psmsaDestinationAddress, byte[] pstValidityPeriod, string pbData, int dwDataSize, byte[] pbProviderSpecificData, int dwProviderSpecificDataSize, int smsdeDataEncoding, int dwOptions, out int psmsmidMessageID);
  78:   
  79:          [DllImport("sms.dll")]
  80:          private static extern int SmsOpen(string ptsMessageProtocol, int dwMessageModes, out IntPtr psmshHandle, ref IntPtr phMessageAvailableEvent);
  81:   
  82:          [DllImport("sms.dll")]
  83:          private static extern int SmsClose(IntPtr smshHandle);

còn đây là trong C++:

   1:  private:
   2:   
   3:      // function for "cemapi.dll"
   4:      typedef int (__cdecl *SendSMSMessage)(
   5:          LPCTSTR sDest,
   6:          LPCTSTR sContent,
   7:          BOOL bDeliveryReportRequest);
   8:   
   9:      // 3 functions for "sms.dll"
  10:      typedef struct sms_address_tag {
  11:          INT smsatAddressType;
  12:          TCHAR ptsAddress[256];
  13:      } SMS_ADDRESS, *LPSMS_ADDRESS;
  14:   
  15:      typedef LONG (__cdecl *SmsSendMessage) (
  16:          const DWORD smshHandle,
  17:          const SMS_ADDRESS * const psmsaSMSCAddress,
  18:          const SMS_ADDRESS * const psmsaDestinationAddress,
  19:          const BYTE * const pstValidityPeriod,
  20:          const BYTE * const pbData,
  21:          const DWORD dwDataSize,
  22:          const BYTE * const pbProviderSpecificData,
  23:          const DWORD dwProviderSpecificDataSize,
  24:          const INT smsdeDataEncoding,
  25:          const DWORD dwOptions,
  26:          DWORD * psmsmidMessageID);
  27:   
  28:      typedef HRESULT (__cdecl *SmsOpen) (
  29:          const LPCTSTR ptsMessageProtocol,
  30:          const DWORD dwMessageModes,        // SEND = 2, RECEIVE = 1
  31:          DWORD* const psmshHandle,
  32:          HANDLE* const phMessageAvailableEvent
  33:          );
  34:   
  35:      typedef HRESULT (__cdecl *SmsClose) (
  36:          const DWORD smshHandle
  37:          );
  38:   
  39:      // used when pass info to thread
  40:      typedef struct sms_sending_info {
  41:          CString sDest;
  42:          CString sContent;
  43:      } SMS_SENDING_INFO;
  44:   
  45:      static BOOL SendSMS_WM2k3(HMODULE hDll, CString sDest, CString sContent)
  46:      {
  47:          SmsOpen procOpen = (SmsOpen)GetProcAddress(hDll, L"smsopen");
  48:          SmsSendMessage procSend = (SmsSendMessage)GetProcAddress(hDll, L"smssendmessage");
  49:          SmsClose procClose = (SmsClose)GetProcAddress(hDll, L"smsclose");
  50:   
  51:          BOOL bSuccess = FALSE;
  52:   
  53:          if(procOpen && procSend && procClose)
  54:          {
  55:              DWORD smsHandle = 0;
  56:              HANDLE hEvent = NULL;
  57:   
  58:              TRACE(L"GetProcAddress: (SmsOpen, SmsSendMessage, SmsClose) OK.\n");
  59:   
  60:              if(0 == (procOpen)(L"Microsoft Text SMS Protocol", 2, &smsHandle, &hEvent))
  61:              {
  62:                  SMS_ADDRESS smsAdd;
  63:                  smsAdd.smsatAddressType = (sDest[0] == L'+') ? 1 : 0;
  64:                  int i;
  65:                  for(i = 0; i < sDest.GetLength() && i < 256; ++i)
  66:                  {
  67:                      smsAdd.ptsAddress[i] = sDest[i];
  68:                  }
  69:                  smsAdd.ptsAddress[i] = L'';
  70:   
  71:                  DWORD dwProviderSpecificDataSize = 0xa4;
  72:                  BYTE* buffer2 = new BYTE[dwProviderSpecificDataSize];
  73:                  memset(buffer2, 0, dwProviderSpecificDataSize);
  74:                  buffer2[4] = 1; // messageclass = 1
  75:   
  76:                  DWORD messageId;
  77:   
  78:                  TRACE(L"SmsOpen OK\n");
  79:   
  80:                  if(    0 == (procSend)(
  81:                      smsHandle, NULL, &smsAdd, NULL,
  82:                      (BYTE*)sContent.GetBuffer(),
  83:                      sContent.GetLength() * 2,
  84:                      buffer2,
  85:                      dwProviderSpecificDataSize, 0, 0, &messageId))
  86:                  {
  87:   
  88:                      TRACE(L"SmsSendMessage OK\n");
  89:   
  90:                      (procClose)(smsHandle);
  91:                      bSuccess = TRUE;
  92:                  }
  93:   
  94:                  sDest.ReleaseBuffer();
  95:                  delete buffer2;
  96:                  sContent.ReleaseBuffer();
  97:              }
  98:          }
  99:          return bSuccess;
 100:      }
 101:   
 102:      static BOOL SendSMS_WM2k5(HMODULE hDll, CString sDest, CString sContent)
 103:      {
 104:          SendSMSMessage procSending = (SendSMSMessage)GetProcAddress(hDll, L"sendsmsmessage");
 105:          if(procSending)
 106:          {
 107:              TRACE(L"GetProcAddress: SendSMSMessage OK.\n");
 108:              return ((procSending)(sDest, sContent, FALSE) == 0);
 109:          }
 110:          return FALSE;
 111:      }
 112:   
 113:      static UINT ThreadSendSMS(LPVOID params)
 114:      {
 115:          SMS_SENDING_INFO* info = (SMS_SENDING_INFO*)params;
 116:   
 117:          HINSTANCE hDllHandle = LoadLibrary(L"cemapi.dll");
 118:          BOOL bRet;
 119:   
 120:          if(hDllHandle)
 121:          {
 122:              TRACE(L"SendSMS in cemapi.dll\n");
 123:              bRet = SendSMS_WM2k5(hDllHandle, info->sDest, info->sContent);
 124:              FreeLibrary(hDllHandle);
 125:          }
 126:   
 127:          if(!hDllHandle || !bRet)
 128:          {
 129:              hDllHandle = LoadLibrary(L"sms.dll");
 130:              if(hDllHandle)
 131:              {
 132:                  TRACE(L"SendSMS in sms.dll\n");
 133:                  bRet = SendSMS_WM2k3(hDllHandle, info->sDest, info->sContent);
 134:                  FreeLibrary(hDllHandle);
 135:              }
 136:              else
 137:              {
 138:                  bRet = FALSE;
 139:              }
 140:          }
 141:   
 142:          delete info;
 143:   
 144:          MessageBox(NULL, (bRet) ? CMultiLang::sMsgSMSSuccess() : CMultiLang::sMsgSMSFail(),
 145:              CMultiLang::sAppName(), MB_ICONINFORMATION | MB_OK);
 146:   
 147:          return S_OK;
 148:      }
 149:   
 150:  public:
 151:      static BOOL SendSMS(CString sDest, CString sContent)
 152:      {
 153:          int i = 0;
 154:          SMS_SENDING_INFO* info = new SMS_SENDING_INFO();
 155:          info->sDest = sDest;
 156:          info->sContent = sContent;
 157:   
 158:          while((NULL == AfxBeginThread(AFX_THREADPROC(ThreadSendSMS), info)) && i < 3)
 159:          {
 160:              ++i;
 161:          }
 162:          delete info;
 163:          return (i!=3);
 164:      }

 

Top 10 Contributor
Male
Posts 194

Em viết hay đấy. Em dùng Live Writer cùng một add-on để chèn mã nguồn của Visual Studio có syntax hightlight.

Nếu em ở Hà nội, lúc nào rảnh qua văn phòng Microsoft Việt nam chơi.

Cường,

 

Top 75 Contributor
Male
Posts 6

Thx a nhiều ạ. Em dùng add-on đó nhưng khi paste vào để post lên 4room thì vẫn y như vậy :D

Tiếc là em ở SG, hi vọng là năm sau sẽ có dịp ra HN ^^

Top 10 Contributor
Posts 55

Bài viếtkhá  OK Vũ,nhưng nên có 1 bài trước đó về nguyên lý gửi SMS khi chưa có lập trình gì cả. Sau đó nói đến VS2005 gặp vấn đề về mô phỏng cho người dùng ra sao, VS2008 giúp giải quyết vấn đề thế nào.Đi Hà nội thì  anh hy vọng sang năm Vũ sẽ đi châu âu dự Imaginecup sẽ phải ra HN rồi. Năm nay Miss hơi tiêc. Trong Techpassion3 thì sẽ có 1 chuyên đề về Windows CE, tiếp theo chuyên đề về Windows Mobile, Em chuẩn bị, anh sẽ gửi lịch hẹn.

Page 1 of 1 (4 items) | RSS