Spice Up Your SMS Chat on the Pocket PC

Spice Up Your SMS Chat on the Pocket PC

MS messaging is one of the most popular means of communication means in this new digital age. While SMS is best suited for asynchronous communications, it’s recently being increasingly used by many as a chat tool. Rather than viewing the series of related chat messages linearly (see left of Figure 1), using the built-in Outlook Mobile, a better way to chat is to represent them visually, complete with the photos of the recipient (if available).

Figure 1. Linear vs. Visual: Representing SMS messages.

This article demonstrates how to build a SMS chat application (see right of Figure 1) that allows your SMS messages to be represented visually. You will learn:

  • How to create a user control
  • Intercept incoming SMS messages using the .NET Compact Framework
  • Send SMS messages using .NET Compact Framework
  • Add controls dynamically to a Panel control
  • Retrieve information about users from Contacts

Creating the Application
Using Visual Studio 2005, create a new Windows Mobile 5.0 Pocket PC application and name it as SMSChat.

In the default Form1, add the following controls (see also Figure 2):

  • TextBox
  • Panel
  • MenuItem
Figure 2. The Default Form1: Populating the form with the various controls.

The Panel control will act as a container to display the chat messages sent by yourself and the sender.

If the sender’s mobile number is:

  • Already in your Contacts and has a photo attached to it, the photo of the sender will be displayed.
  • Already in your Contacts but has no photo attached to it, the name of the sender will be displayed.
  • Not in your Contacts, the phone number of the sender is displayed (assuming you have subscribed to the Caller ID service; check with your Telco).

Creating the User Control
To display the chat messages in the Panel1 control, you’ll use a user control. This user control simply uses a TextBox control and sizes it according to the amount of text to be displayed.

Author’s Note: If you are adventurous, you can format this user control as a balloon and spice up its appearance. For simplicity, I am just going to set its background color.

To create a user control, right-click on the project name in Solution Explorer and select Add | User Control…. Add a TextBox control to the default control design surface (see left of Figure 3) and set the properties of the user control and the TextBox control as follows:






















Figure 3. The User Control: Before and after modifications.

The user control will now look like that as shown on the right of Figure 3. Let’s now code the user control. Switching to the code-behind of UserControl1, first define an enumeration:

Public Enum Balloons    Left    RightEnd Enum

This enumeration allows the user of this user control to indicate its background color (more on this later).

In the UserControl1 class, declare the following two functions from the coredll.dll library:

Public Class UserControl1     _Shared Function SendMessage( _   ByVal hwnd As IntPtr, _   ByVal msg As Integer, _   ByVal wParam As Integer, _   ByVal lParam As Integer) As Integer    End Function     _    Shared Function GetCapture() As IntPtr    End Function

In the .NET Compact Framework (applies to the .NET Framework as well), there is no way you can find out how many lines a string takes up in a TextBox control, and the only way to do that is to use P/Invoke and call the native APIs. And this is the reason for declaring the two functions above.

Next, define the following member variables and constant:

    Private _balloonText As String    Private _balloonType As Balloons    Private Const EM_GETLINECOUNT = &HBA    Private hnd As IntPtr

Define the Balloons property, which allows the user to set the background color of the user control:

    Property Balloons() As Balloons        Get            Return _balloonType        End Get        Set(ByVal value As Balloons)            _balloonType = value            If _balloonType = SMSChat.Balloons.Left Then                TextBox1.BackColor = Color.LightYellow            Else                TextBox1.BackColor = Color.LightSalmon            End If        End Set    End Property

All balloons that are displayed on the left have light yellow background color. All those on the right will have light salmon background color.

Finally, define the BalloonText property, which allows user to set the TextBox control with a string:

    Public Property BalloonText()        Get            Return _balloonText        End Get        Set(ByVal value)            _balloonText = value            '---display the text in the TextBox control---            TextBox1.Text = _balloonText            '---obtain the number of lines used---            TextBox1.Capture = True            hnd = GetCapture()            TextBox1.Capture = False            Dim linecount = SendMessage(hnd, EM_GETLINECOUNT, 0, 0)            '---adjust the height of the TextBox control---            TextBox1.Height = linecount * 18            '---adjust the height of the user control---            Me.Height = TextBox1.Height + 2        End Set    End Property

Note that after setting the TextBox control with the specified string, the height of the TextBox and user controls is adjusted appropriately.

Coding the Main Application
With the user control out of the way, it’s time to code the main application created in the previous section of this article.

As we are going to intercept incoming SMS messages and then retrieve the sender’s information from Contacts, you need to add the following references (see also Figure 4):

  • Microsoft.WindowsMobile
  • Microsoft.WindowsMobile.Forms
  • Microsoft.WindowsMobile.PocketOutlook
Figure 4. References: Adding references to the needed libraries.

In the code-behind of Form1, import the following namespaces:

Imports Microsoft.WindowsMobile.PocketOutlookImports Microsoft.WindowsMobile.PocketOutlook.MessageInterception

Define the following member variables:

Public Class Form1    '---used for intercepting SMS messages---    Private msgInterceptor As MessageInterceptor    '---the SMS sender's phone number---    Private SenderPhoneNumber As String    '---used for saving user's own phone number---    Private Self As String

In the Form1_Load event, create an instance of the MessageInterceptor class so that all incoming SMS messages are intercepted and deleted after firing an event (SMSInterceptor_MessageReceived):

    Private Sub Form1_Load( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) Handles MyBase.Load        '---create an instance of the MessageInterceptor class---        msgInterceptor = New MessageInterceptor( _           InterceptionAction.NotifyAndDelete, True)        '---set the event handler for the message interceptor        AddHandler msgInterceptor.MessageReceived, _           AddressOf SMSInterceptor_MessageReceived        '---set the user's phone number---        mnuMyNumber_Click(Nothing, Nothing)    End Sub

Notice that when the form is loaded, you will be asked to set your phone number (via the My Number menu item). You need to do this so that you will be able to locate your own information in the Contacts and display your photo (if available; if not, your name). Double-click on the My Number menu item and code as follows:

Private Sub mnuMyNumber_Click( _   ByVal sender As System.Object, _   ByVal e As System.EventArgs) Handles mnuMyNumber.Click        Self = InputBox("Please enter your phone number", "My number")    End Sub

Next, define the SMSInterceptor_MessageReceived event, which is fired when a SMS message is received:

    '---event handler for the MessageReceived event---    Private Sub SMSInterceptor_MessageReceived( _       ByVal sender As Object, _       ByVal e As MessageInterceptorEventArgs)        '---extract the SMS message received---        Dim msg As SmsMessage = e.Message        '---format as "+123456789:Hello there! Howdy!"---        '---OR---        '---format as "Johnny Lee:Hello there! Howdy!"---        Dim s As String = msg.From.Name & ":" & msg.Body        '---update the textbox with the above data---        Panel1.BeginInvoke(New _           myDelegate(AddressOf updatePanelControl), _           New Object() {s})    End Sub

Here, you need to cast the message received (e.Message) as a SmsMessage object so that you can extract the sender’s name/telephone number and the message body. Note that if the sender’s number is not found in Contacts, the From.Name property will return the phone number, or else it returns the name of the sender.

With the name of the sender and the message body extracted, concatenate them with the “:” character and then call the myDelegate delegate to invoke the updatePanelControl() subroutine to display the received SMS message:

    '---delegate for updating the two TextBox controls---    Public Delegate Sub myDelegate(ByVal str As String)    '---display received SMS data---    Public Sub updatePanelControl(ByVal str As String)        '---format as "+123456789:Hello there! Howdy!"---        '---OR---        '---format as "Johnny Lee:Hello there! Howdy!"---        '---show the received data in the TextBox---        Dim fields As String() = str.Split(":")        '---add the user's message to the Panel---        AddConversation(fields(0), fields(1), Balloons.Left)    End Sub

The updatePanelControl() subroutine splits the string received and pass it to the AddConversation() subroutine, which displays the message using the user control developed earlier.

Author’s Note: For all SMS messages received, you will display the user control on the left of the Panel control.

Define the AddConversation() subroutine, as shown in Listing 1.

Observe that the AddConversation() subroutine does the following:

  • Look through all the contacts stored in Contacts, trying to match either the mobile telephone number or the name of the user. Interestingly, you should compare the name of the user (as returned by the From.Name property of the SmsMessage object) against the FileAs property in the Contact class).
  • If the user is found in Contacts, his picture is retrieved (if available). Or else his name will be used instead.
  • For messages sent by others (i.e. not yourself), you need to store its phone number so that you can use it for sending replies. For simplicity, I assume that this conversation only involves two parties – you yourself and one sender.
  • If the sender is not found in Contacts, his name will be his/her phone number (as returned by the From.Name property).
  • Finally, the message is displayed using the user control. If the user has a picture, it is then displayed under the user control, or else his name/phone number will be shown instead.

To reply a message, double-click the Reply menu item and code the following:

Private Sub mnuReply_Click( _   ByVal sender As System.Object, _   ByVal e As System.EventArgs) Handles mnuReply.Click        '---send a SMS message to the recipient---        SendSMS(SenderPhoneNumber, txtToSend.Text)        '---add the conversation to the panel---        AddConversation(Self, txtToSend.Text, Balloons.Right)    End Sub

The above subroutine calls the SendSMS() subroutine to send a SMS message to the specified user. It then adds the SMS message that you have just sent to the Panel control by calling the AddConversation() subroutine.

The SendSMS() subroutine is defined as follows:

    '---send a SMS message to a recipient---    Private Sub SendSMS( _       ByVal receiptnumber As String, _       ByVal message As String)        '---from the Microsoft.WindowsMobile.PocketOutlook namespace---        '---compose a new SMS message---        Dim SMS As New SmsMessage        '---set the body of the message---        SMS.Body = message        '---add the recipient---        SMS.To.Add(New Recipient(receiptnumber))        '---send the message---        SMS.Send()    End Sub

Finally, if you are sending a SMS message to another user (that is, you are not replying to an existing message), you use the Send To menu item, which is defined as follows:

Private Sub mnuSendTo_Click( _   ByVal sender As System.Object, _   ByVal e As System.EventArgs) Handles mnuSendTo.Click        '---prompts the user for a phone number---        Dim number As String = _           InputBox("Please enter a phone number", "Number")        '---send a SMS message to the recipient---        SendSMS(number, txtToSend.Text)        '---add the conversation to the panel---        AddConversation(Self, txtToSend.Text, Balloons.Right)    End Sub

Testing the Application
You are now ready to test the application. The first thing you need to do is to create at least two contacts in Contacts—one for yourself and one for the sender (the sender can simply use a normal mobile phone). For my example, I have created two contacts (see Figure 5).

Figure 5. New Contacts: Using the Creating two new contacts.
Figure 6. Messaging: Sending and receiving SMS messages.

Press F5 in Visual Studio 2005. Figure 6 shows the sequence on how to send a SMS message to a recipient.

Author’s Note: For this article, I am matching the Mobile telephone number in Contacts to obtain the user’s Name and Picture. Hence, be sure to enter your own phone number exactly as those entered in Contacts (see Figure 7). If you notice that your sender’s phone number is displayed instead of his name or photo (but you are sure that his name is in Contacts), check to see that the Mobile Tel entry in Contacts matches the phone number displayed in the Panel control.

When the recipient has responded, you can now type a message and click on the Reply menu item (see Figure 8).

Figure 7. The Number: Using the Mobile Telephone number for matching contacts.
Figure 8. Reply: Replying to a received SMS message.

Now, you’ve seen how to intercept incoming SMS messages and display them in a fun and visually appealing way. With some creativity, you too can inject more fun into your digital life! Have fun chatting!


Share the Post: