he long-awaited Smartphone 2003 platform finally supports the .NET Compact Framework. With this support, developers can now write managed Smartphone applications using C# or VB.NET. However, the current Smartphone 2003 SDK for the .NET Compact Framework has some rough edges: Not all functions that a developer needs are provided in the class library, nor are they available in the controls Toolbox. For example, Context Menus and Tab controls are not natively supported, which makes navigating the user interface of a Smartphone application less intuitive. (See the sidebar, “Compact Framework Controls,” for a full list of supported controls.)
Also, the functionality for changing the input modes (alphanumeric, numeric, or T9 [predictive text input]) for a TextBox control is not available as a managed class; instead platform invoke is required. So, in this article, I will show you some of the ways to overcome these limitations of the Smartphone 2003 SDK.
Changing Text Input Modes
Unlike Pocket PCs, a Smartphone does not contain a built-in SIP (Soft Input Panel) for data input (since the Smartphone does not support touch-screen). Instead, Smartphone users have to rely on the numeric keypad for alphanumeric input. Applications designed for the Smartphone must consider this limitation.
|What You Need
Microsoft Visual Studio .NET 2003 and Smartphone 2003 SDK
For example, a textbox for entering phone numbers should only allow users to enter numeric inputs when using the numeric keypad. To do so, you can set the input mode of a TextBox control to accept either alphanumeric or numeric input. However, in the Smartphone 2003 SDK you cannot directly set the input mode of a TextBox control. Rather, you have to resort to Platform Invoke (P/Invoke) to use the API provided by the operating system.
|Figure 1. Populating the Windows Form: Create two main menu items and four submenu items.|
In this section, I will create a Smartphone application with two TextBox controls, one that accepts text and one that accepts numbers. This will illustrate how to set the input mode. And as an added bonus, the example also shows how to create a textbox that accepts multiple lines of input, instead of just one.
First, populate the default Windows Form with the following controls:
The MainMenu control should have two main items named Exit and Input Modes. The Input Modes menu item should have four sub-menu items named Spell, T9, Numbers, and Text (see Figure 1):
You need to set the Multiline property of the TextBox2 control to True in order to stretch the TextBox control vertically.
To call an API at the operating system level using P/Invoke, you need to import the following namespace:
Next, declare the functions (within the class definition of the Windows Form) that you want to use to set the input modes of text boxes:
' Interop declarations
_Private Shared Function GetCapture() As IntPtrEnd Function _Private Shared Function GetWindow(ByVal hWnd As IntPtr, _ ByVal uCmd As Integer) As IntPtrEnd Function _Private Shared Function SendMessage(ByVal hWnd As _ IntPtr, ByVal msg As UInt16, _ ByVal wParam As UInt16, _ ByVal lParam As UInt16) _ As UInt16End Function
Declare the following enumeration and subroutine (within the class definition of the Windows Form) to set the input mode for the TextBox control:
' Input mode enumerationPublic Enum InputMode Spell = 0 T9 = 1 Numbers = 2 Text = 3End Enum
The SetInputMode() subroutine will invoke the SendMessage() API to change the text input mode of the TextBox control:
Public Shared Sub SetInputMode(ByVal ctrl As Control, _ ByVal mode As InputMode) Dim GW_CHILD As Integer = 5 Dim EM_SETINPUTMODE As UInt16 = UInt16.Parse(222) ' Get the handle for the current control ctrl.Capture = True Dim h As IntPtr = GetCapture() ctrl.Capture = False ' Get the child window for the control Dim hEditbox As IntPtr = GetWindow(h, GW_CHILD) ' Set the input mode SendMessage(hEditbox, EM_SETINPUTMODE, _ UInt16.Parse(0), _ UInt16.Parse(mode))End Sub
Service the Click event of each MenuItem control to call the SetInputMode() function with the respective mode:
Private Sub mnuSpell_Click(ByVal sender As _ System.Object, _ ByVal e As System.EventArgs) _ Handles mnuSpell.Click SetInputMode(TextBox1, InputMode.Spell) End SubPrivate Sub mnuT9_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles mnuT9.Click SetInputMode(TextBox1, InputMode.T9)End SubPrivate Sub mnuNumbers_Click(ByVal sender As _ System.Object, _ ByVal e As System.EventArgs) _ Handles mnuNumbers.Click SetInputMode(TextBox1, InputMode.Numbers)End SubPrivate Sub mnuText_Click(ByVal sender As _ System.Object, _ ByVal e As System.EventArgs) _ Handles mnuText.Click SetInputMode(TextBox1, InputMode.Text)End Sub
Press F5 to debug and run the application. Figure 2 shows entering text in Text mode and Numeric mode respectively:
Figure 3 shows the second TextBox control supporting multiple lines of text. When the action button on the phone is depressed, the TextBox control expands to a full window, which is a normal, default behavior of the Smartphone.
Figure 2. Switching Input Modes: Text is entered on the left, while the numeric mode, right, only accepts numbers.
Figure 3. Multiple Lines: Normally limited to just one line, the sample application accepts multiple lines of input.
|Author’s Note: Note that T9 input is not supported on the emulator.|
Improvising Context Menus
The ContextMenu control in the .NET Compact Framework is a useful control to display contextual information related to a particular control. For example, you can tap and hold onto an item in the TreeView control and a context menu may be displayed to show the list of options that you can select pertaining to the item selected.
|Figure 4. Populating the Windows Form: The MainMenu control has a sub-menu item called “dummy.”|
The Smartphone 2003 SDK does not support the ContextMenu control. To support context menu in the Smartphone platform, you need to improvise one using the MainMenu control. To illustrate this example, I will create a new Smartphone application and use a ListView control to display a list of items. When an item in the ListView control is selected, pressing the right softkey will display a list of menu items related to the selected item.
Populate the Windows Form with the following controls:
The MainMenu control should have two menu items named Exit and Menu. The Menu item should have a sub-item named dummy, which I’ll explain in a moment (see Figure 4 ).
Two events will be fired when a MainMenu item is clicked. The Click event will be fired the first time the item is clicked. Subsequent clicking will fire the Popup event.
In order to dynamically create a list of MenuItem controls under the Menu item during runtime, it is necessary to create a dummy item. If you remove sub-items during runtime, at least one item must be retained.
In the code window, code the createContextMenu() function. The createContextMenu() function will display a list of context menu items relating to the item highlighted in the ListView control at the time.
Public Sub createContextMenu() '====Remove existing menuitems Dim k As Integer 'mainmenu must contain at least one menuitem; 'else it will crash If mnuMenu.MenuItems.Count > 1 Then ' remove all but left 1 item For k = 0 To mnuMenu.MenuItems.Count - 2 ' always remove the first; the rest of ' the items will be pushed upwards mnuMenu.MenuItems.RemoveAt(0) Next End If '---the last item is now the first item '===Create a new context menu Dim j As _ System.Windows.Forms.ListView.SelectedIndexCollection ' get the index of the item selected in ' the ListView1 j = ListView1.SelectedIndices Dim i As Integer '===You can modify this section to show the items=== '===you want to display=== For i = 0 To 2 ' create 3 items in "context menu" If i = 0 Then ' the first item will be modified mnuMenu.MenuItems(0).Text = "Menu for " & _ ListView1.Items(j(0)).Text & "-0" Else '--the rest of the items will be added in Dim mni As New MenuItem mni.Text = "Menu for " & _ ListView1.Items(j(0)).Text _ & "-" & i AddHandler mni.Click, AddressOf EventHandler mnuMenu.MenuItems.Add(mni) End If NextEnd Sub
The EventHandler() subroutine will display a message when a context menu item is clicked. You can add your own code here to suit your business logic:
Sub EventHandler(ByVal sender As Object, _ ByVal e As EventArgs) ' handles events raised by the object Obj MsgBox("EventHandler caught event." & _ CType(sender, MenuItem).Text) ' Handle the eventEnd Sub
In the Click event of the Menu item, code the following to display the context menu:
Private Sub mnuMenu_Click(ByVal sender As _ System.Object, _ ByVal e As System.EventArgs) _ Handles mnuMenu.Click createContextMenu()End Sub
In the Popup event of the Menu item, code the following to also display the context menu:
Private Sub mnuMenu_Popup(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles mnuMenu.Popup createContextMenu()End Sub
In the Load event of the Windows Form, code the following to load the form and display a list of items:
|Figure 5. Just Like Normal: Though improvised, this ContextMenu control operates just like a “real” one would.|
Private Sub Form8_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load Dim i As Integer ListView1.View = View.List ListView1.FullRowSelect = True '--add some items to the ListView control For i = 0 To 4 Dim lvi As New ListViewItem("Item " & i) ListView1.Items.Add(lvi) Next '--assign an event handler to the dummy item AddHandler mnuMenu.MenuItems(0).Click, _ AddressOf EventHandler '--select the first item when loaded ListView1.Items(0).Selected = TrueEnd Sub
Press F5 to debug and run the application. Figure 5 shows what the improvised ContextMenu looks like when it’s run.
Improvising the Tab Control
|Figure 6. Populating the Windows Form: The second Panel control overlaps the first one.|
The Smartphone 2003 SDK does not support scrollable forms, which means that if you have more controls than what a single form can accommodate, you have to resort to creative techniques to display all these controls. And that can make the forms difficult to use. One way to solve that problem is to use a Tab control, to allow users to Tab their way from one control to another. But unfortunately, the Tab control isn’t supported in the .NET CF either. In this section, I will show you how to improvise a Tab control using the Panel control.
Populate the Windows Form with the following controls:
The MainMenu control should have two main items named Exit and > (named mnuLeft and mnuRight respectively). Add a Panel control to the form and drag and drop a Label and a TextBox control to the Panel control. Then, repeat the same process by adding another Panel control that completely overlaps the first Panel control (see Figure 6):
First, declare a global variable:
Dim currentPage As Integer = 1
Code the following in the Load event of the Windows Form:
Private Sub Form9_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load Panel1.Visible = True Panel2.Visible = FalseEnd Sub
Code the following for the left menu item:
Private Sub mnuLeft_Click(ByVal sender As _ System.Object, _ ByVal e As System.EventArgs) _ Handles mnuLeft.Click Select Case currentPage Case 1 : Me.Close() Case 2 : mnuLeft.Text = "Exit" mnuRight.Text = ">" Panel1.Visible = True Panel2.Visible = False currentPage -= 1 ' Case 3: etc, etc End Select End Sub
Code the following for the right menu item:
Private Sub mnuRight_Click(ByVal sender As _ System.Object, _ ByVal e As System.EventArgs) _ Handles mnuRight.Click Select Case currentPage Case 1 : mnuLeft.Text = "<" mnuRight.Text = "Done" Panel1.Visible = False Panel2.Visible = True currentPage += 1 Case 2 : MsgBox(TextBox1.Text & " " & _ TextBox2.Text) ' Case 3: etc, etc End SelectEnd Sub
Press F5 to debug and run the application. Figure 7 shows the final application running.
|Figure 7. Better Use of Space: This application improvises use of the TabControl to allow multiple panels to overlap one another. The user tabs between them to navigate.|
As you can see, much of the limitations of the Smartphone are due to the lack of a touch-screen. Unlike Pocket PCs, Smartphone users have to rely on the two soft keys on the phone for navigation. In addition, due to the memory and processing constraints of mobile devices, there is a limit to the number of managed classes supported in the .NET Compact Framework. Hence the designers of the .NET Compact Framework have to prioritize which are the most important functions to support, and inadvertently there will be some functions that you need that are not supported. As a Smartphone developer, you just have to live with these limitations and improvise your own solution to these problems! Or, wait for the next release of the .NET Compact Framework.