locked
Non Editable SMS Composer RRS feed

  • Question

  • Hi,
     I can open the default SMS composer of the device using the code below
    I used this code below to open the SMS Composer directly from the application
                    SmsMessage SMSComposer = new SmsMessage("123456789","This is a sample sms");
                    MessagingApplication.DisplayComposeForm(SMSComposer);

    the SMS composer opens with the text "This is a sample sms" and the phone number is "123456789".
    If I want I can edit the text and the phone number. Is there anyway I could make the sms composer non editable, so that the user can't edit the text and the phone number.



    Please suggest me

    Tuesday, November 3, 2009 11:23 AM

Answers

  • I don't think thats possible, or I at least don't know of any way to do accomplish that.

    Try out the code I posted, just create a new C# file in your project, and send the SMS by calling SMS.SendMessage("recipient phonenumber", "the body of your message);
    • Marked as answer by warrentang Monday, November 9, 2009 4:04 AM
    Tuesday, November 3, 2009 1:31 PM

All replies

  • No I don't think what you want is possible. But you can send the message directly without launching the messaging application by calling the Send() method on your SMSComposer object.

    Tuesday, November 3, 2009 11:50 AM
  • No I don't think what you want is possible. But you can send the message directly without launching the messaging application by calling the Send() method on your SMSComposer object.

     I see. But if I use SMSComposer.Send() I can't send to different carriers , I can only send to the same carrier. Is there any way I could open  the SMS composer  and should send the SMS at  one go . Please suggest me.
    Tuesday, November 3, 2009 12:58 PM
  • I remember someone mentioning that in similar threads but I never really fully understood why. You can use the SMS API directly as an alternative, that way you are completely independent of the messaging application

    Tuesday, November 3, 2009 12:59 PM
  • I tried going through some really old code and found this wrapper for the SMS API. It's such old code that I'm not even sure if it works, but I remember I used it in my first .NETCF commercial application.


    You can use it like this:
    SMS.SendMessage("12341234", "Hello world");


    Here's the full code:

        /// <summary>
        /// Identifies the Phone Number type
        /// </summary>
        public enum SMS_ADDRESS_TYPE
        {
            /// <summary>
            /// Refers to an unknown phone number type
            /// </summary>
            SMSAT_UNKNOWN = 0,
            /// <summary>
            /// Refers to a International phone number
            /// </summary>
            SMSAT_INTERNATIONAL,
            /// <summary>
            /// Refers to a national phone number
            /// </summary>
            SMSAT_NATIONAL,
            /// <summary>
            /// Refers to a network-specific phone number
            /// </summary>
            SMSAT_NETWORKSPECIFIC,
            /// <summary>
            /// Refers to a subscriber phone number
            /// </summary>
            SMSAT_SUBSCRIBER,
            /// <summary>
            /// Refers to an alphanumeric phone number
            /// </summary>
            SMSAT_ALPHANUMERIC,
            /// <summary>
            /// Refers to an abbreviated phone number
            /// </summary>
            SMSAT_ABBREVIATED
        }

        /// <summary>
        /// Specifies the data encoding that is primarily used for outgoing text message types
        /// in SmsSendMessage() calls.
        /// </summary>
        public enum SMS_DATA_ENCODING
        {
            /// <summary>
            /// Chooses the data encoding that fully represents all of the
            /// characters in the least amount space
            /// </summary>
            SMSDE_OPTIMAL = 0,
            /// <summary>
            /// Use the default GSM 7-bit encoding specified in GSM specs 03.38:
            /// Alphabets and language specific information
            /// </summary>
            SMSDE_GSM,
            /// <summary>
            /// Use the Unicode UCS2 encoding
            /// </summary>
            SMSDE_UCS2,
        }

        /// <summary>
        /// Identifies the Message class
        /// </summary>
        public enum PROVIDER_SPECIFIC_MESSAGE_CLASS
        {
            /// <summary>
            /// The Message should be displayed immediately, but NOT stored
            /// </summary>
            PS_MESSAGE_CLASS0 = 0,
            /// <summary>
            /// The message should be stored and an acknowledgement should be sent to the
            /// Service Center when it is stored
            /// </summary>
            PS_MESSAGE_CLASS1,
            /// <summary>
            /// The message should be transfered to the SMS data field in the SIM before an acknowledgement is sent
            /// to the Service Center. If the message cannot be stored in the SIM and there is other SMS storage available,
            /// an unspecified protocol error message is returned to the Service Center.
            /// If all the SMS storage is already in use, a memory error is returned to the Service Center.
            /// </summary>
            PS_MESSAGE_CLASS2,
            /// <summary>
            /// When the message has successfuly reached the destination and can be stored,
            /// an acknowledgement is sent to the Service Center.
            /// </summary>
            PS_MESSAGE_CLASS3,
        }

        /// <summary>
        /// Identifies the message replacement type
        /// </summary>
        public enum PROVIDER_SPECIFIC_REPLACE_OPTION
        {
            /// <summary>
            /// Short message type 0, no previous notifications are replaced
            /// </summary>
            PSRO_NONE = 0,
            /// <summary>
            /// Previous notifications of type 1 are replaced with the new message and other parameter values
            /// </summary>
            PSRO_REPLACE_TYPE1,
            /// <summary>
            /// Previous notifications of type 2 are replaced with the new message and other parameter values
            /// </summary>
            PSRO_REPLACE_TYPE2,
            /// <summary>
            /// Previous notifications of type 3 are replaced with the new message and other parameter values
            /// </summary>
            PSRO_REPLACE_TYPE3,
            /// <summary>
            /// Previous notifications of type 4 are replaced with the new message and other parameter values
            /// </summary>
            PSRO_REPLACE_TYPE4,
            /// <summary>
            /// Previous notifications of type 5 are replaced with the new message and other parameter values
            /// </summary>
            PSRO_REPLACE_TYPE5,
            /// <summary>
            /// Previous notifications of type 6 are replaced with the new message and other parameter values
            /// </summary>
            PSRO_REPLACE_TYPE6,
            /// <summary>
            /// Previous notifications of type 8 are replaced with the new message and other parameter values
            /// </summary>
            PSRO_REPLACE_TYPE7,
            /// <summary>
            /// A return call can be made to the originating address
            /// </summary>
            PSRO_RETURN_CALL,
            /// <summary>
            /// Instructs the receiving application to depersonalize the phone where the depersonalization code
            /// is passed in the body of the message.
            /// </summary>
            PSRO_DEPERSONALIZATION,
        }

        /// <summary>
        /// SMS Addressing information.
        /// </summary>
        /// <remarks>Equivalent to native <b>SMS_ADDRESS</b> structure</remarks>
        public class SMS_ADDRESS
        {
            /// <summary>
            /// Length of fixed length address string
            /// </summary>
            internal const int SmsMaxLength = 256;

            /// <summary>
            /// Length, in Bytes, of the SMS_ADDRESS structure.
            /// </summary>
            public const int Length = 518;

            /// <summary>
            /// Byte array containing structure data
            /// </summary>
            private byte[] m_data;

            /// <summary>
            /// Create a new instance of SMS_ADDRESS.
            /// </summary>
            public SMS_ADDRESS()
            {
                m_data = new byte[Length];
            }

            /// <summary>
            /// Create a new instance of SMS_ADDRESS from a Byte array.
            /// </summary>
            /// <param name="data">SMS_ADDRESS data in a Byte array.</param>
            public SMS_ADDRESS(byte[] data)
            {
                if (data.Length > Length)
                    m_data = data;
            }

            /// <summary>
            /// Create a new instance of SMS_ADDRESS with a specified address.
            /// </summary>
            /// <param name="address">Address e.g. +447890123456</param>
            public SMS_ADDRESS(string address)
                : this()
            {
                Address = address;
            }

            /// <summary>
            /// Create a new instance of SMS_ADDRESS with a specified address and type.
            /// </summary>
            /// <param name="address">Address e.g. +447890123456</param>
            /// <param name="type">A member of the SMS_ADDRESS_TYPE Enumeration</param>
            public SMS_ADDRESS(string address, SMS_ADDRESS_TYPE type)
                : this(address)
            {
                Type = type;
            }

            /// <summary>
            /// Returns a flat Byte Array of the Sms Address data
            /// </summary>
            /// <returns>Byte array containing SMS_ADDRESS data.</returns>
            public byte[] ToByteArray()
            {
                return m_data;
            }

            /// <summary>
            /// Cast SMS_ADDRESS object to a byte array
            /// </summary>
            /// <param name="sa">SMS_ADDRESS object</param>
            /// <returns>Byte array containing SMS_ADDRESS data.</returns>
            public static implicit operator byte[](SMS_ADDRESS sa)
            {
                return sa.ToByteArray();
            }

            /// <summary>
            /// Cast byte array to SMS_ADDRESS object.
            /// </summary>
            /// <param name="b">Byte array containing SMS_ADDRESS data</param>
            /// <returns>SMS_ADDRESS version of the data.</returns>
            public static implicit operator SMS_ADDRESS(byte[] b)
            {
                return new SMS_ADDRESS(b);
            }

            /// <summary>
            /// The address type.
            /// </summary>
            public SMS_ADDRESS_TYPE Type
            {
                get { return (SMS_ADDRESS_TYPE)BitConverter.ToInt32(m_data, 0); }
                set { BitConverter.GetBytes((int)value).CopyTo(m_data, 0); }
            }

            /// <summary>
            /// The address in string format. For example, "127.0.0.1" or "+1.800.123.4567".
            /// </summary>
            public string Address
            {
                get
                {
                    string address = Encoding.Unicode.GetString(m_data, 4, SmsMaxLength * 2);
                    int nullindex = address.IndexOf('\0');
                    if (nullindex > -1)
                        address = address.Substring(0, nullindex);
                    return address;
                }
                set { Encoding.Unicode.GetBytes(value).CopyTo(m_data, 4); }
            }
        }

        /// <summary>
        /// Relates to the operation of Short Message Service (SMS)
        ///
        /// Refer to the GSM specification "Digital Cellular Telecommunications System (Phase 2+)"
        /// for technical realization of the SMS
        /// </summary>
        public class SMS
        {
            /// <summary>
            /// SMS Protocol to use
            /// </summary>
            private const string SMS_MSGTYPE_TEXT = "Microsoft Text SMS Protocol";

            /// <summary>
            /// Send Mode
            /// </summary>
            private const int SMS_MODE_SEND = 2;

            /// <summary>
            /// No Special Options for sending the message
            /// </summary>
            private const int SMS_OPTION_DELIVERY_NONE = 0;

            /// <summary>
            /// Max length of the recipients phone number
            /// </summary>
            private const int SMS_MAX_ADDRESS_LENGTH = 256;

            /// <summary>
            /// To use with TEXT_PROVIDER_SPECIFIC_DATA, specifies that no options are being used
            /// </summary>
            private const int PS_MESSAGE_OPTION_NONE = 0;

            /// <summary>
            /// Opens the SMS messaging component for send and/or receive access.
            /// </summary>
            /// <param name="ptsMessageProtocol">Points to a string that indiciates which SMS protocol to use</param>
            /// <param name="dwMessageModes">SMS_MODE_SEND or SMS_MODE_RECEIVE</param>
            /// <param name="psmshHandle">SMS handle to use for subsequent read/write commands</param>
            /// <param name="phMessageAvailableEvent">a Win32 event handle that is signaled when a new message is available to read</param>
            /// <returns>Returns 0x00000000 if success</returns>
            [DllImport("sms.dll")]
            private static extern int SmsOpen(string ptsMessageProtocol, int dwMessageModes,
                                              ref IntPtr psmshHandle, int phMessageAvailableEvent);

            /// <summary>
            /// Send an SMS message
            /// </summary>
            /// <param name="smshHandle">SMS handle obtained from calling SmsOpen()</param>
            /// <param name="psmsaSMSCAddress">
            /// An optional parameter indicating which Service Center the message will be routed through.
            /// It is recommended to just pass NULL
            /// </param>
            /// <param name="psmsaDestinationAddress">THe destination of the message</param>
            /// <param name="pstValidityPeriod">
            /// The duration for which the SMS mesage is valid, counted from when the Service Center
            /// receives the message. Can be NULL
            /// </param>
            /// <param name="pbData">The data portion of the message, this can be NULL</param>
            /// <param name="dwDataSize">Size in bytes of the buffer pointed to by pbData. This can be Zero</param>
            /// <param name="pbProviderSpecificData">
            /// For some providers, a provider-specific structure must be provided
            /// in addition to the previous data buffer</param>
            /// <param name="dwProviderSpecificDataSize">Size of pbProviderSpecificData</param>
            /// <param name="smsdeDataEncoding">The text encoding of the SMS message. Use the SMS_DATA_ENCODING enumeration</param>
            /// <param name="dwOptions">Optional flags, just use SMS_OPTION_DELIVERY_NONE for no special options</param>
            /// <param name="psmsmidMessageID">If not NULL, this points to a message ID on successful return</param>
            /// <returns>returns 0x00000000 (IntPtr.Zero) if successful</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,
                                                     int smsdeDataEncoding, int dwOptions, int psmsmidMessageID);

            /// <summary>
            /// Close an existing SMS messaging handle
            /// </summary>
            /// <param name="smshHandle">SMS handle to close</param>
            /// <returns>Returns 0x00000000 (IntPtr.Zero) if successful</returns>
            [DllImport("sms.dll")]
            private static extern int SmsClose(IntPtr smshHandle);

            /// <summary>
            /// allocates the specified number of bytes from the heap. In the linear Windows CE API environment,
            /// there is no difference between the local heap and the global heap.
            /// </summary>
            /// <param name="uFlags">Specifies how to allocate memory, if zero is specified, it will allocated fixed memory.</param>
            /// <param name="uBytes">Specifies the number of bytes to allocate</param>
            /// <returns></returns>
            [DllImport("coredll.dll")]
            private static extern IntPtr LocalAlloc(uint uFlags, uint uBytes);

            /// <summary>
            ///  Frees the specified local memory object and invalidates its handle
            /// </summary>
            /// <param name="hMem">Handle to the local memory object. This handle is returned by either LocalAlloc or LocalReAlloc</param>
            /// <returns>NULL if success</returns>
            [DllImport("coredll.dll")]
            internal static extern IntPtr LocalFree(IntPtr hMem);

            /// <summary>
            /// allocates the specified number of bytes from the heap. In the linear Windows CE API environment,
            /// there is no difference between the local heap and the global heap.
            /// </summary>
            private static IntPtr AllocHGlobal(IntPtr cb)
            {
                IntPtr hmem = LocalAlloc(0x40, (uint)cb);
                return hmem;
            }

            /// <summary>
            ///  Frees the specified local memory object and invalidates its handle
            /// </summary>
            private static void FreeHGlobal(IntPtr hglobal)
            {
                LocalFree(hglobal);
            }

            /// <summary>
            /// Sends an SMS messageBody
            /// </summary>
            /// <param name="phoneNumber">Recipient Phone number</param>
            /// <param name="messageBody">The Body of the message</param>
            /// <returns>returns 0 if successful</returns>
            public static int SendMessage(string phoneNumber, string messageBody)
            {
                int returnValue = 0;
                IntPtr smsHandle = new IntPtr(0);

                byte[] smsatAddressType = BitConverter.GetBytes((int)SMS_ADDRESS_TYPE.SMSAT_INTERNATIONAL);
                byte[] ptsAddress = Encoding.Unicode.GetBytes(phoneNumber);
                byte[] SMS_ADDRESSTag = new byte[smsatAddressType.Length + ptsAddress.Length];

                Array.Copy(smsatAddressType, 0, SMS_ADDRESSTag, 0, smsatAddressType.Length);
                Array.Copy(ptsAddress, 0, SMS_ADDRESSTag, smsatAddressType.Length, ptsAddress.Length);
                IntPtr SMS_ADDRESS = AllocHGlobal((IntPtr)SMS_ADDRESSTag.Length);
                Marshal.Copy(SMS_ADDRESSTag, 0, SMS_ADDRESS, SMS_ADDRESSTag.Length);

                byte[] dwMessageOptions = BitConverter.GetBytes(PS_MESSAGE_OPTION_NONE);
                byte[] psMessageClass = BitConverter.GetBytes((int)PROVIDER_SPECIFIC_MESSAGE_CLASS.PS_MESSAGE_CLASS1);
                byte[] psReplaceOption = BitConverter.GetBytes((int)PROVIDER_SPECIFIC_REPLACE_OPTION.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);

                byte[] smsMessageTag = Encoding.Unicode.GetBytes(messageBody);
                IntPtr smsMessage = AllocHGlobal((IntPtr)smsMessageTag.Length);
                Marshal.Copy(smsMessageTag, 0, smsMessage, smsMessageTag.Length);

                if (0 != SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, ref smsHandle, 0))
                    returnValue = -1;

                if (0 != SmsSendMessage(smsHandle, 0, SMS_ADDRESS, 0, smsMessage, smsMessageTag.Length,
                                        smsProviderData, smsProviderDataTag.Length, (int)SMS_DATA_ENCODING.SMSDE_GSM,
                                        SMS_OPTION_DELIVERY_NONE, 0))
                    returnValue = -2;

                FreeHGlobal(smsMessage);
                FreeHGlobal(smsProviderData);
                FreeHGlobal(SMS_ADDRESS);

                if (0 != SmsClose(smsHandle))
                    returnValue = -3;

                return returnValue;
            }
        }

    Tuesday, November 3, 2009 1:12 PM
  • OpenNETCF SDF should also have some Phone, SIM, and SMS wrappers
    Tuesday, November 3, 2009 1:14 PM
  • OpenNETCF SDF should also have some Phone, SIM, and SMS wrappers

    Thank you for this code but  as I am new to this platform its not very clear to me. Is there any possibilities that I could open the SMS composer and the function of sending the SMS should done automatically. I mean when I click a menu the SMS composer should open with some text on it and I don't have to press the "send" button on the SMS composer to send the SMS rather the function of the send button internally to send the SMS. Please suggest me.
    Tuesday, November 3, 2009 1:22 PM
  • I don't think thats possible, or I at least don't know of any way to do accomplish that.

    Try out the code I posted, just create a new C# file in your project, and send the SMS by calling SMS.SendMessage("recipient phonenumber", "the body of your message);
    • Marked as answer by warrentang Monday, November 9, 2009 4:04 AM
    Tuesday, November 3, 2009 1:31 PM
  • Did you ever try to include the country code in the recipient phone number (e.g. +45 1234 1234) ? I'm not sure it would make a difference, but maybe it's worth a try
    Tuesday, November 3, 2009 1:33 PM
  • I don't think thats possible, or I at least don't know of any way to do accomplish that.

    Try out the code I posted, just create a new C# file in your project, and send the SMS by calling SMS.SendMessage("recipient phonenumber", "the body of your message);
    I have used this code SMS.SendMessage("recipient phonenumber", "the body of your message); but this doesn't help me to send me SMS to other carriers.
    Tuesday, November 3, 2009 2:55 PM
  • But you normally can send to other carriers?
    Wednesday, November 4, 2009 9:41 AM