Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Mobile TouchPad

0.00/5 (No votes)
21 Nov 2008 1  
Mobile TouchPad lets you control your PC through your touch pad phones. You can easily connect to your desktop without configuration.

Contents

What is Mobile TouchPad?

Mobile TouchPad lets you control your PC through your touch pad phones. You can easily connect to your desktop without configuration, you only need the driver to be active (also source code included) and the standard ActiveSync enabled.

You can use it in a presentation, or to control your media center.

Introduction

I try to explain how it is simple to write code for mobile. The project consists of two solutions, two programs are needed, because one intercepts the mouse movements on mobile and the second interacts with the desktop.

I've solved some problems about:

  • ActiveSync
  • OpenNETCF Mobile Ink
  • Mouse Hook
  • Marshal
  • P/Invoke
  • Socket
  • Byte Serialization/Deserialization
  • Registry

Image 1

Info: To make the following code example easier to read, security checking and error handling are not included.

Developer Requirement

First of all, to deploy any WM application, you need the Windows Mobile 6 Professional and Standard Software Development Kits Refresh[^].

Here, you can find all the requirements for your system and you can choose the platform Pro or standard or both. You need at least one of the two. I suggest to you the 'Professional Windows Mobile 6 Professional SDK Refresh.msi', the new SDK for Pocket PC.

Please check each application's system requirements individually.

Anyway, I add brief System Requirements:

  • Microsoft Visual Studio 2005
  • Microsoft Visual Studio 2005 SP1 [^]
  • Microsoft .NET Compact Framework v2 SP2 [^]
  • For Windows XP - ActiveSync 4.5 [^]
  • For Windows Vista - Windows Mobile Device Center [^]

Image 2

Info: To deploy this project, I use Visual Studio 2005 SE EU, Vista Business, Windows Mobile Device Center, and a Samsung i900.

Additional Requirement

For the mobile ink, I prefer to use a free Mobile Ink Library. OpenNETCF Mobile Ink is a component that provides support for WM 6 Ink here [^] and is released under the MIT X11 license [^].

I use this library, first because it's free, and Open source, and also because it's very simple to use, and I show you how do that.

Using the Mobile Side Code

The mobile solution is named MobileTouchPad and you can find it under the WM folder. The mobile app will be similar to the image below.

Image 3

OpenNETCF Mobile Ink

As seen above, I use that because it can be cool to give some effect to the touch. At the moment, I write the touched line and I clear it after releasing the screen. It's very simple to use this component, The steps to use an ink in your project are:

Add Using and Reference

using OpenNETCF.WindowsMobile.Ink;
using OpenNETCF.WindowsMobile.Ink.Interfaces;

You can find it after installing the file downloaded OpenNETCF Mobile Ink (you can also find the source code in the installation dir).

Add a Panel

Add a panel or a picturebox to your form, it will be your touchPad, I've call it panelTouchPad.

Add the Overlay

Add an overlay to your panel:

IInkOverlay overlay;

Add the EventHandler for the Load

In the load form, attach the panel to the overlay:

overlay.hWnd = pictureBox1.Handle;
overlay.Enabled = true;

Add the Event Stroke

This enables the ink:

overlay = Ink.CreateInstance();
overlay.SetEventInterest(InkCollectorEventInterest.Stroke, true);

Adapt the Screen

In the Resize form, retrieve the screen coordinate and adapt the panelTouchPad to the screen:

Rectangle oScreen = Screen.PrimaryScreen.WorkingArea;
panelTouchPad.Location = new System.Drawing.Point(0, 0);
panelTouchPad.Size = new System.Drawing.Size
	(oScreen.Size.Width, oScreen.Size.Height - oScreen.Y);

Clear the Screen

overlay.Enabled = false;
overlay.Ink = InkDisp.CreateInstance();
overlay.Enabled = true;

Well, the first step has ended, now we have a very simple Mobile paint.

Mouse Move

To intercept the mouse movements simply, I use the EventHandler of MouseMove of the panelTouchPad. Here, I decided how to send data to the desktop. I save the last point every time and I send to the desktop only a step movement. The data can be (+1,0) (-1,1) (0,-1), etc.

Point pointDirection = new Point();
pointDirection.X = e.X - LastPoint.X  ;
pointDirection.Y = e.Y - LastPoint.Y  ;

SendData(pointDirection);

LastPoint.X = e.X;
LastPoint.Y = e.Y; 

Button Pressed and Double Click

To intercept the button pressed, you need to add the KeyEventHandler for KeyDown and KeyPress and send it with no movements.

private void FormTouchPad_KeyDown(object sender, KeyEventArgs e)
{
    m_buttonState = CommonStruct.MouseButtonState.ButtonPressed;     
    SendData(new Point(0,0));
}

private void FormTouchPad_KeyUp(object sender, KeyEventArgs e)
{
    m_buttonState = CommonStruct.MouseButtonState.None;
    SendData(new Point(0, 0));
}

To intercept the double click, add an event DoubleClick to the panelTouchPad and send it with no movements.

m_buttonState = CommonStruct.MouseButtonState.DblClick;
SendData(new Point(0,0));

As you can see here, I've used a common structure CommonStruct for both the solutions.

This is the enum for the button state:

public enum MouseButtonState
{
    None = 0,
    ButtonClick,
    ButtonPressed,
    DblClick
}

This is the struct for the button action:

public struct TouchPro
{
    public Point point;
    public MouseButtonState buttonState;
}

This common struct is in Common.cs.

Desktop IP

Image 4 Info: To communicate with the desktop, you need to sync the Device or the emulator. To do that, you need the ActiveSync 4.5 installed as System Requirements for Windows XP, and the Windows Mobile Device Center for Windows Vista.

After syncing it, you only need set up your connection as DMA, with this option, you are able to retrieve the desktop IP dynamically.

Image 5

To retrieve the desktop IP, I've used some registry key enabled by the ActiveSync. This key are stored in [HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts\ppp_peer] or if not exist [HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts\dtpt_peer]. If you have problems, I'll suggest to you this blog [^].

Using the Emulator

You can use the emulator to test the project, but obviously the mouse interaction can be a bit difficult.

Image 6 Attention: If you use the emulator, you must activate the cradle.

Image 7

In Visual Studio 2005, open Tools menu and choose Device Emulator Manager. In Device emulator manager, select your current emulator and select cradle.

Image 8

After ActiveSync starts, you can may notice a small tray icon like networking icon, with a plus sign turning left and right.

Image 9

Serialize/Deserialize

Using socket, I need to convert my class to byte[]. Normally on desktop, I use BinaryFormatter and MemoryStream , but on WM, that reference is missing... Anyway, I found another way using Marshaling. This is the CommonConvertion I use in my two projects (you can find it in Common.cs).

class CommonConvertion
{
    public static byte[] StructureToByteArray(object obj)
    {
        int Length = Marshal.SizeOf(obj);
        byte[] bytearray = new byte[Length];
        IntPtr ptr = Marshal.AllocHGlobal(Length);
        Marshal.StructureToPtr(obj, ptr, false);
        Marshal.Copy(ptr, bytearray, 0, Length);
        Marshal.FreeHGlobal(ptr);
        return bytearray;
    }
    public static void ByteArrayToStructure(byte[] bytearray, ref object obj)
    {
        int Length = Marshal.SizeOf(obj);
        IntPtr ptr = Marshal.AllocHGlobal(Length);
        Marshal.Copy(bytearray, 0, ptr, Length);
        obj = Marshal.PtrToStructure(ptr, obj.GetType());
        Marshal.FreeHGlobal(ptr);
    }
}

Connect and Send Data to Desktop

To send data to desktop, I prefer to use TCP/IP instead of Web service, Rapi and so on, because it's more simple (I think).

TCP Usage

Define a TcpClient and a NetworkStream used all the same during the app life:

private TcpClient m_client;
private NetworkStream m_stream;

In the constructor, add the Connection to the server and open the stream to it:

m_client = new TcpClient(server, port);
m_stream = m_client.GetStream();

If it fails (the desktop server is closed), the app tries to connect to the server every time you touch the screen and gives a message box to you... you can continue without the connection or you can go on drawing on it....

Finally, we send data as you saw before in the MouseMove. Here in the code, you can see a new method SendData. This is a method where I manage the data and send it to the desktop.

private void SendData(Point pointDirection)
{
    ...
    CommonStruct.TouchPro AddMove = new CommonStruct.TouchPro();
    AddMove.point = pointDirection;
    AddMove.buttonState = m_buttonState;
    object objTmp = (object)AddMove;
    Byte[] data = CommonConvertion.StructureToByteArray(AddMove);
	
    m_networkstream.Write(data, 0, data.Length);
    ...
}

Using the Desktop Side Code

The solution is named DriverMobileTouchPad and you can find it under x86 folder. This is a screenshot to show you its interface. Here, you must activate the server to wait for the mobile connection.

Mobile devices have several limitations, one above all is the small screen resolution. To avoid this problem, I've added the possibility to change the cursor velocity.

Image 10

Connect and Receive Data from Mobile

TCP Usage

Into the form, I've created a server waiting connection on a port:

m_tcpserver = new TcpListener(IPAddress.Any, 5000);
m_tcpserver.Start();
m_tcpserver.BeginAcceptTcpClient
   ( new AsyncCallback(DoAcceptTcpClientCallback), m_tcpserver);

Image 11Warning: Remember to open the port 5000 on your firewall.

When it's connected to a client, it begins to read stream.Read inside the DoAcceptTcpClientCallback from the opened stream and converts it to my common struct. After reading data, deserialize it with the CommonConvertion, as shown here Serialize/deserialize.

CommonStruct.TouchPro AddMove = new CommonStruct.TouchPro();
object objTmp = new object();
objTmp = (object)AddMove;
CommonConvertion.ByteArrayToStructure(bytes, iBufflen, ref objTmp);
AddMove = (CommonStruct.TouchPro)objTmp;

Mouse Interaction

For the interaction, I've created a class MouseMov. Here I use the P/Invoke to send click (pressed and release) and double click.

[DllImport("user32.dll")]
private static extern void mouse_event
   (UInt32 dwFlags, UInt32 dx, UInt32 dy, UInt32 dwData, IntPtr dwExtraInfo);
private const UInt32 MOUSEEVENTF_LEFTDOWN = 0x0002;
private const UInt32 MOUSEEVENTF_LEFTUP = 0x0004;
internal static void SendUp()
{
   mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, new System.IntPtr());
}
internal static void MoveMouse(Point p)
{
   Cursor.Position = new Point(Cursor.Position.X + p.X, Cursor.Position.Y + p.Y);
}

The MoveMouse is a simple cursor movement.

internal static void SendDown()
{
    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, new System.IntPtr());
}

Well, finally we have finished. Try to run the two solutions I've added and you can see the code in action. Let me know your problems and what you think about it. Have fun!

Links

I've found these links very useful:

History

  • 10th November, 2008 - First release - v 10 2008

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here