using System;using System.Runtime.InteropServices;using System.Text;
namespace SmartPhone{ /// <summary> /// SMS helper class. /// </summary> public class SMS { public SMS() { } private const string SMS_MSGTYPE_TEXT = "Microsoft Text SMS Protocol";//消息协议模式 private const int SMS_MAX_ADDRESS_LENGTH = 256; // Max length of address //短消息模式 private const int SMS_MODE_RECEIVE = 1; //以接收模式打开 private const int SMS_MODE_SEND = 2; // 以发送模式打开 private const int SMSAT_INTERNATIONAL = 1; // 国际格式 private const int PS_MESSAGE_OPTION_NONE = 0; // 没有消息选项 //提供商指定消息类型 private const int PS_MESSAGE_CLASS0 = 0; //立即显示但不存储 private const int PS_MESSAGE_CLASS1 = 1; //存储,并在存储后发送一个确认回服务中心 private const int PS_MESSAGE_CLASS2 = 2; //在向服务中心发送确认之前,先把消息转移到SIM卡上的短信区域,如果不能存储但还有空间时发送一个未指明的协议错误到服务中心 private const int PS_MESSAGE_CLASS3 = 3; //消息到达并可以存储时发送一个确认回服务中心
private const int PSRO_NONE = 0; // 没有替换项
//短信发送选项 private const int SMS_OPTION_DELIVERY_NONE = 0; // 没有发送选项 private const int SMS_OPTION_DELIVERY_NO_RETRY=1; //如果设置了该选项,则不再尝试重发,否则会按预定的时间表重发 //短信编码格式 private enum SMS_DATA_ENCODING { SMSDE_OPTIMAL=0, //最佳模式 SMSDE_GSM, //使用默认的GSM 7位编码 SMSDE_UCS2, //使用Unicode UCS2编码 } [DllImport("sms.dll")] private static extern int SmsOpen( string ptsMessageProtocol, int dwMessageModes, ref IntPtr psmshHandle, int phMessageAvailableEvent);
/// <summary> /// /// </summary> /// <param name="短信句柄"></param> /// <param name="短消息服务中心地址,推荐为NULL"></param> /// <param name="短消息目的地址"></param> /// <param name="短信的有效期,可以为NULL"></param> /// <param name="短信的数据部分,可以为NULL"></param> /// <param name="短信的数据部分大小,可以为0"></param> /// <param name="短信提供者指定数据"></param> /// <param name="短信提供者指定数据大小"></param> /// <param name="短信编码格式"></param> /// <param name="短信发送选项"></param> /// <param name="短信标识,如果不为空,则为短信发送成功后返回的ID,可以用于SmsGetMessageStatus"></param> /// <returns></returns> [DllImport("sms.dll")] private static extern int SmsSendMessage( IntPtr smshHandle, int psmsaSMSCAddress, IntPtr psmsaDestinationAddress, int pstValidityPeriod, IntPtr pbData, int dwDataSize, IntPtr pbProviderSpecificData, int dwProviderSpecificDataSize, SMS_DATA_ENCODING smsdeDataEncoding, int dwOptions, int psmsmidMessageID);
[DllImport("sms.dll")] private static extern int SmsClose(IntPtr smshHandle);
[DllImport("coredll.dll")] private static extern IntPtr LocalAlloc(uint uFlags, uint uBytes);
[DllImport("coredll.dll")] internal static extern IntPtr LocalFree(IntPtr hMem);
private static IntPtr AllocHGlobal(IntPtr cb) { IntPtr hmem;
hmem = LocalAlloc(0x40, (uint) cb); return hmem; }
private static void FreeHGlobal(IntPtr hglobal) { LocalFree(hglobal); }
public static int SendSMS(string Number, string Message) { int returnValue = 0; IntPtr smsHandle = IntPtr.Zero; try { if(Number.Substring(0,3)!="+86") //国内手机必须在手机号码前加上+86 Number ="+86"+Number; // Set address structure byte[] smsatAddressType = BitConverter.GetBytes(SMSAT_INTERNATIONAL); byte[] ptsAddress = Encoding.Unicode.GetBytes(Number); byte[] smsAddressTag = new byte[smsatAddressType.Length + ptsAddress.Length]; Array.Copy(smsatAddressType, 0, smsAddressTag, 0, smsatAddressType.Length); Array.Copy(ptsAddress, 0, smsAddressTag, smsatAddressType.Length, ptsAddress.Length); IntPtr smsAddress = AllocHGlobal((IntPtr)smsAddressTag.Length); Marshal.Copy(smsAddressTag, 0, smsAddress, smsAddressTag.Length);
// Set provider data structure byte[] dwMessageOptions = BitConverter.GetBytes(PS_MESSAGE_OPTION_NONE); byte[] psMessageClass = BitConverter.GetBytes(PS_MESSAGE_CLASS1); byte[] psReplaceOption = BitConverter.GetBytes(PSRO_NONE); byte[] smsProviderDataTag = new byte[dwMessageOptions.Length + psMessageClass.Length + psReplaceOption.Length]; Array.Copy(dwMessageOptions, 0, smsProviderDataTag, 0, dwMessageOptions.Length); Array.Copy(psMessageClass, 0, smsProviderDataTag, dwMessageOptions.Length, psMessageClass.Length); Array.Copy(psReplaceOption, 0, smsProviderDataTag, dwMessageOptions.Length + psMessageClass.Length, psReplaceOption.Length); IntPtr smsProviderData = AllocHGlobal((IntPtr) smsProviderDataTag.Length); Marshal.Copy(smsProviderDataTag, 0, smsProviderData, smsProviderDataTag.Length);
// Set message byte[] smsMessageTag = Encoding.Unicode.GetBytes(Message); IntPtr smsMessage = AllocHGlobal((IntPtr)smsMessageTag.Length); Marshal.Copy(smsMessageTag, 0, smsMessage, smsMessageTag.Length);
// Get handle if (0 != SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, ref smsHandle, 0)) returnValue = -1; // Could not open
// Send message if (0 != SmsSendMessage(smsHandle, 0, smsAddress, 0, smsMessage, smsMessageTag.Length, smsProviderData, smsProviderDataTag.Length, SMS_DATA_ENCODING.SMSDE_OPTIMAL, SMS_OPTION_DELIVERY_NONE, 0)) returnValue = -2;
FreeHGlobal(smsMessage); FreeHGlobal(smsProviderData); FreeHGlobal(smsAddress); } finally { // Release handle if (smsHandle != IntPtr.Zero) { if (0 != SmsClose(smsHandle)) returnValue = -3; // Could not close } }
return returnValue; } }}
除了使用自定义类外,还可以使用OpenNetCF这个工具包 可以到这里下载 http://www.opennetcf.org ,目前版本1.4 安装后,引用OpenNETCF.Phone 然后代码如下: .... using OpenNETCF.Phone; using OpenNETCF.Phone.Sms; private void menuItem2_Click(object sender, System.EventArgs e) { if((textBox1.Text.Trim().Length>0) &&(textBox1.Text.Trim().Length>0)) { Sms mySMS=new Sms(SmsMode.Send); SmsAddress myAddr=new SmsAddress(); myAddr.Address="+86"+textBox1.Text; myAddr.Type=AddressType.International; int smsHandle=mySMS.SendMessage(myAddr,textBox2.Text); } } 要特别注意的是,当你的系统中有Framework 1.1以及FrameWork 2.0时,加载dll会有问题,解决方法如下 将/Program Files/Microsoft Visual Studio .NET 2003/CompactFrameworkSDK/v1.0.5000/Windows CE/中的OpenNETCF.Phone.dll拷贝到项目目录中,并在项目中包含此dll文件即可。