Edit boxes and default text selection

While working on an application of mine, I had to display ‘Help’ information. I chose to use a read-only multiline edit box along with SetWindowText() to display the text, sounds simple enough. But I ran into a small but annoying problem. The text displayed was all selected, and I thought why would the text be selected by default!?

Here is a sample program to demonstrate this,

  1. #include <windows.h>
  2. #include <aygshell.h>
  3. #include "resource.h"
  4.  
  5. HINSTANCE g_hInst;
  6.  
  7. BOOL CALLBACK EditBoxSelTextDlgProc(HWND, UINT, WPARAM, LPARAM);
  8. void AlignComponents(HWND hDlg);
  9. void InitializeComponents(HWND hDlg);
  10.  
  11. int WinMain(HINSTANCE hInst, HINSTANCE hPrevInst,
  12.             LPTSTR lpCmdLine, int nCmdShow)
  13. {
  14.     g_hInst = hInst;
  15.  
  16.     DialogBox(hInst, MAKEINTRESOURCE(IDD_PPC_EDITBOXTEXTSEL), NULL, EditBoxSelTextDlgProc);
  17.     return 0;
  18. }
  19.  
  20. BOOL CALLBACK EditBoxSelTextDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
  21. {
  22.     int wmID, wmEvent;
  23.     PAINTSTRUCT ps;
  24.     HDC hdc;
  25.  
  26.     switch(uMessage)
  27.     {
  28.         case WM_INITDIALOG:
  29.             {
  30.                 SHINITDLGINFO shidi;
  31.                 SHMENUBARINFO mbi;
  32.  
  33.                 memset(&shidi, 0, sizeof(shidi));
  34.                 memset(&mbi, 0, sizeof(mbi));
  35.  
  36.                 shidi.dwMask = SHIDIM_FLAGS;
  37.                 shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN | SHIDIF_EMPTYMENU;
  38.                 shidi.hDlg = hDlg;
  39.                 SHInitDialog(&shidi);
  40.  
  41.                 mbi.cbSize = sizeof(mbi);
  42.                 mbi.hwndParent = hDlg;
  43.                 mbi.nToolBarId = IDR_MENU_EDITBOXTEXTSEL;
  44.                 mbi.hInstRes = g_hInst;
  45.  
  46.                 if(!SHCreateMenuBar(&mbi))
  47.                 {
  48.                     printf("Error creating menu bar, errcode:0x%x\n", GetLastError());
  49.                 }
  50.  
  51.                 AlignComponents(hDlg);
  52.  
  53.                 InitializeComponents(hDlg);
  54.             }
  55.             return TRUE;
  56.  
  57.         case WM_COMMAND:
  58.             {
  59.                 wmID = LOWORD(wParam);
  60.                 wmEvent = HIWORD(wParam);
  61.  
  62.                 switch(wmID)
  63.                 {
  64.                     case IDM_EXIT:
  65.                         EndDialog(hDlg, uMessage);
  66.                         break;
  67.                 }
  68.             }
  69.             break;
  70.  
  71.         case WM_PAINT:
  72.             {
  73.                 hdc = BeginPaint(hDlg, &ps);
  74.  
  75.                 EndPaint(hDlg, &ps);
  76.             }
  77.             break;
  78.     }
  79.     return FALSE;
  80. }
  81.  
  82. void AlignComponents(HWND hDlg)
  83. {
  84.     HWND hTemp = NULL;
  85.     RECT rect = {0, 0, 0, 0};
  86.     int x=0, y=0, width=0, height=0;
  87.     const int insetX = 3;
  88.     const int insetY = 3;
  89.  
  90.     GetClientRect(hDlg, &rect);
  91.  
  92.     hTemp = GetDlgItem(hDlg, IDC_EDITBOX);
  93.     if (hTemp)
  94.     {
  95.         x = rect.left + insetX;
  96.         y = rect.top + insetY;
  97.         width = (rect.right – rect.left – 2*insetX);
  98.         height = (rect.bottom – rect.top – 2*insetY);
  99.  
  100.         MoveWindow(hTemp, x, y, width, height, FALSE);
  101.     }
  102. }
  103.  
  104. const TCHAR message[] = TEXT("Lorem ipsum dolor sit amet, consectetur adipisicing elit, \
  105. sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \
  106. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris \
  107. nisi ut aliquip ex ea commodo consequat.\
  108. \r\n\r\n\
  109. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum \
  110. dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non \
  111. proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\
  112. ");
  113.  
  114. void InitializeComponents(HWND hDlg)
  115. {
  116.     HWND hTemp = GetDlgItem(hDlg, IDC_EDITBOX);
  117.  
  118.     if (hTemp)
  119.     {
  120.         SetWindowText(hTemp, message);
  121.     }
  122. }

 

This is usual stuff. Display a dialog box from WinMain(), initialize the dialog and the menubar in dialog proc under the WM_INITDIALOG message. The functions of interest would be AlignComponents() and InitializeComponents(). The dialog contains a single multiline edit box, AlignComponents() resizes the edit box so it occupies the entire screen, and InitializeComponents() calls SetWindowText() to set the text on the edit box control.

If you run this program, here is how it’ll look,

image

So you see the problem there. Skimming through the edit box messages, I came across EM_SETSEL message. This message selects a range of characters in an edit control, and if you pass –1 to it, any current selection is removed. So after the SetWindowText() call in InitializeComponents(), I put this line,

SendMessage(hTemp, EM_SETSEL, (WPARAM)-1, (LPARAM)0);

but if it was this simple I wouldn’t be writing this post, would I? In short, it didn’t work.

I thought maybe I am sending the EM_SETSEL message too early, even before the edit control is ready to process it perhaps? So the next step was to find the right place from where the message could be sent. So, one by one, I went through all the messages sent to dialog proc until the dialog is shown and found WM_ACTIVATE could be the right place. And it indeed was.

Adding the following switch case to dialog proc did the trick,

  1. case WM_ACTIVATE:
  2.     SendMessage(GetDlgItem(hDlg, IDC_EDITBOX), EM_SETSEL,
  3.         (WPARAM)-1, (LPARAM)0);
  4.     break;

 

The edit control now shows up without any selected text.

image

HTC HD2, Accelerometer and Windows Phone 7 – Source Code

If you haven’t seen the video demo in my last post, I suggest you watch it first to get a better understanding. So in this post we are going to see how the WCF service, the .NET Compact Framework application running on HD2 and the Silverlight application running on the Windows Phone 7 emulator work together.


The Objective

We are going to write three applications, a simple WCF service hosted in a windows console application which implements two functions, one called UploadAccelData() and the other DownloadAccelData(). A .NET Compact Framework application for HD2 which calls the WCF services’ UploadAccelData() function periodically and passes it the x, y and z components of the acceleration vector. A silverlight application for Windows Phone 7 which calls into DownloadAccelData() periodically and gets the accelerometer data off it.

For those of you who want to jump straight into the code, you can download it from the following links,

Download ConsoleApp.zip – VS 2008 solution which contains two projects. One, the console application which hosts the WCF service and two the Compact Framework application which runs on HD2

Download WCFClient_WP7Emu.zip – Windows Phone 7 application which runs on the emulator

Creating the WCF service
I will be using Visual Studio 2008 for creating the service and the .net cf application. Open VS 2008 in administrator mode and create a windows console application in Visual C#. It is important that you start visual studio in administrator mode otherwise you might get an error while deploying the service depending on your access rights on the machine. Now lets add a WCF service which will be hosted by this console application. Right click on the project and select “Add –> New Item..”. In the next dialog select “WCF Service” and give a name to it. I call it “AccelerometerService”.

Creating accelerometer service

With this three files will be added to your project AccelerometerService.cs, IAccelerometerService.cs and App.Config. Open App.Config and change a few things in it, first change binding="wsHttpBinding" to binding="basicHttpBinding" since .net compact framework only supports basicHttpBinding. Next change the BaseAddress from,

<add baseAddress="http://localhost:8731/Design_Time_Addresses/ConsoleApp/AccelerometerService/" /> to

<add baseAddress="http://192.168.2.2:8731/ConsoleApp/AccelerometerService/" />

Again, it is important that you change “localhost” to the ip address of your machine. This is because we will be using this address from the compact framework application to refer to the service, so we need the address of the machine where the service is running. Using “localhost” from the compact framework application would mean a totally different thing. Here I use 192.168.2.2 which is the IP address assigned to my machine by the wireless router that I am using. Be sure to change this IP address depending on your machine setup.

Open Program.cs and add the following code in the Main() function,

static void Main(string[] args)
{
    ServiceHost accelService = new ServiceHost(typeof(AccelerometerService));

    try
    {
        accelService.Open();
        Console.WriteLine("Accel service is running at:{0}", accelService.BaseAddresses[0].AbsoluteUri);
        Console.WriteLine("Press <ENTER> to terminate the service..");

        Console.ReadLine();
    }
    catch (Exception ex)
    {
        Console.WriteLine("An exception occured while creating the serivce. {0}", ex.Message);
        accelService.Abort();
    }
}

Here we are creating an instance of our AccelerometerService and calling Open() on it to start the service. The address where the service is running is output to the console and the service waits for any key to be pressed after which it will be terminated. Now build and run your project, you should see this console window,

Console service running

Now to check our service, open internet explorer and browse to the base address that we entered above,

http://192.168.2.2:8731/ConsoleApp/AccelerometerService/

and you should see this,

sanity check for service IE

If your browser is showing the same thing then great! We are progressing well.

Now lets implement our upload and download functions. Open IAccelerometerService.cs and add the following declarations to the interface,

[OperationContract]
void UploadAccelData(int x, int y, int z);

[OperationContract]
void DownloadAccelData(out int x, out int y, out int z);

To keep things simple I am passing only the x, y and z components of the vector, other information from the accelerometer like Roll and Pitch are ignored for simplicity, though adding those shouldn’t be rocket science. We will be implementing these functions in our AccelerometerService class. Open AccelerometerService.cs and add the following member variables to the AccelerometerService class,

static int _accelX;
static int _accelY;
static int _accelZ;

and add the following function definitions to the same class,

public void UploadAccelData(int x, int y, int z)
{
        _accelX = x;
        _accelY = y;
        _accelZ = z;

        Console.WriteLine("UploadAccelData: X:{0}, Y:{1}, Z:{2}", x, y, z);

}

public void DownloadAccelData(out int x, out int y, out int z)
{
        x = _accelX;
        y = _accelY;
        z = _accelZ;
}

This completes our console app and the WCF service that it will be hosting.

Creating the Compact Framework Application for HD2
Now lets go ahead and add a smart device compact framework C# application to the same solution in VS 2008. Right click on the solution and select “Add –> New Project..”. In the Add New Project dialog select Smart Device under Visual C# and add a new project, WCFClient_HD2.

HD2 CF add new project

in the next screen select “Windows Mobile 6 Professional SDK” as the target platform and “.NET CF Version 3.5”, choose Device Application and press OK.

HD2 cf project type

I have designed the form to show the x, y and z values from the accelerometer and a button to start and stop the sensor. Also, add a timer which fires every 100ms and is initially disabled.

cf form and timer

Now to this project, we will add a reference to the WCF service. First make sure that the service is running, deploy the ConsoleApp project. Right click on WCFClient_HD2 and select “Add Web Reference..”. In the next dialog, enter the URL of the service and press Go.

 adding reference to service

If everything goes well, our AccelerometerService should be found and you will be presented with this dialog,

give a name to the web reference, in this case “AccelerometerService” and select “Add Reference” button. Now the functionalities offered by the AccelerometerService are available to our compact framework application. Next, we need to instantiate this service and use it to call the UploadAccelData() function.

Open Form1.cs and add a member variable to the Form1 class which refers to the WCF service,

WCFClient_HD2.AccelerometerService.AccelerometerService accelService =
        new WCFClient_HD2.AccelerometerService.AccelerometerService();

I am going to go a bit off topic here and talk about the Accelerometer implementation on HD2. HTC does not provide an SDK for it’s devices (which is really sad) so the functionalities like Accelerometer, Proximity sensor and other custom features are not exposed to others for use. So some folks had to find out the library, reverse engineer the implementation and figure out how to use these features. The accelerometer driver is implemented in a dll called HTCSensorSDK.dll, this dll also implements a few other sensors as well. To use the accelerometer from a native application you’ll have to load this library [using LoadLibrary()], get pointers to the exported functions and call them. And from a managed application you’ll have to P/Invoke. Take a look at this post for more information on this.

Managed code to access the accelerometer on HD2 is available online and I am using the same code in this project here. Just go ahead and add HTCSensor.cs file to your project. This file implements HTCSensor class which you can use to read data from the accelerometer. The class implements StartSensor(), ReadDataFromSensor() and StopSensor() functions. Go back to Form1.cs and add two more variables to the class,

HTCSensor htcSensor = new HTCSensor();
HTCSensorData htcSensorData;

Create handlers for the Start Sensor button and uploadTimer,

private void button1_Click(object sender, EventArgs e)
{
    Button btn = sender as Button;

    if (btn.Text.Contains("Start"))
    {
        htcSensor.StartSensor();
        uploadTimer.Enabled = true;

        btn.Text = "Stop Sensor";
    }
    else
    {
        htcSensor.StopSensor();
        uploadTimer.Enabled = false;

        lblXAxis.Text = "???";
        lblYAxis.Text = "???";
        lblZAxis.Text = "???";

        btn.Text = "Start Sensor";
    }
}

and,

private void uploadTimer_Tick(object sender, EventArgs e)
{
    htcSensor.ReadDataFromSensor(out htcSensorData);

    lblXAxis.Text = htcSensorData.tiltX.ToString();
    lblYAxis.Text = htcSensorData.tiltY.ToString();
    lblZAxis.Text = htcSensorData.tiltZ.ToString();           
}

The button handler controls the timer and starts and stops it. And whenever the timer fires, we read the data from the accelerometer and display it. Run this application on HD2, if you have one, and check if the values are being read from the sensor. I am guessing that this application should also work on HTC Touch Pro2 and HTC Diamond 2 as well, but I have not tested this on those devices. Now all that is left is hooking this with the WCF Service, so every time the timer function is called we call the UploadAccelData() function of the service and pass the x, y and z values to it. Add the following lines of code to the end of the uploadTimer_Tick() function,

try
{
    accelService.UploadAccelData(htcSensorData.tiltX, true,
        htcSensorData.tiltY, true,
        htcSensorData.tiltZ, true);
}
catch (Exception ex)
{
    Console.WriteLine("An exception occured while calling into the service.");
    Console.WriteLine("{0}", ex.Message);
}

And that is all, our compact framework application is ready! Lets test whether the values are being passed to the service. Go to the solution properties and select multiple start-up projects and make sure that both the ConsoleApp and WCFClient_HD2 are set to start,

multiple start-up projects

Press F5 to start both the console and the compact framework application. Make sure that you are deploying the compact framework application to the device and that the device is connected to the machine over Active Sync (Windows XP) or WMDC (Vista or Win 7). Once both applications are deployed press the “Start Sensor” button on the phone, the accelerometer data should be getting passed to the service and the console window should output the logs as follows,

console logs showin service accel data

 

Creating the Silverlight application for Windows Phone 7
Start Visual Studio 2010 Express for Windows Phone and create a new Silverlight Windows Phone project, WCFClient_WP7Emu.

sl app wp7 project creation

Add text blocks and a button to Mainpage.xaml. The application UI looks like this,

sl app running on emu

Now lets add to this project a reference to the WCF Service. Deploy the WCF service from Visual Studio 2008 and make sure that it is running, right click on the silverlight project and select “Add Service Reference..”, and in the next dialog enter the URL of the service and press Go,

sl adding reference to service

once the service is discovered enter a namespace “AccelerometerService” and press OK to add a reference to it.

Open Mainpage.xaml.cs and add the following member variables to the Mainpage class,

WCFClient_WP7Emu.AccelerometerService.AccelerometerServiceClient accelService;
DispatcherTimer dt;

Now in the Mainpage() constructor add the following lines of code after the InitializeComponent() call,

accelService = new WCFClient_WP7Emu.AccelerometerService.AccelerometerServiceClient();

accelService.DownloadAccelDataCompleted +=
    new EventHandler<AccelerometerService.DownloadAccelDataCompletedEventArgs>(accelService_DownloadAccelDataCompleted);

dt = new DispatcherTimer();
dt.Interval = new TimeSpan(0, 0, 0, 0, 100);
dt.Tick += new EventHandler(dt_Tick);

lblXAxis.Text = "???";
lblYAxis.Text = "???";
lblZAxis.Text = "???";

Here we create an instance of the WCF service and register a handler for the DownloadAccelDataCompleted event. In silverlight for windows phone the web service api’s will be called asynchronously, and when the web service function returns, accelService_DownloadAccelDataCompleted() will be called. So we will be getting the accelerometer values in this function. Also, create a dispatch timer which fires every 100ms. Pressing TAB while creating the handlers for DownloadAccelDataCompleted and dt.Tick event will also create the function definitions for the handlers,

void accelService_DownloadAccelDataCompleted(object sender, AccelerometerService.DownloadAccelDataCompletedEventArgs e)
{

}

void dt_Tick(object sender, EventArgs e)
{

}

Add a handler for the button “Start reading data from web service”,

private void button1_Click(object sender, RoutedEventArgs e)
{
    Button btn = sender as Button;

    if (btn.Content.ToString().Contains("Start"))
    {
        dt.Start();
        btn.Content = "Stop reading data from web service";
    }
    else
    {
        dt.Stop();
        btn.Content = "Start reading data from web service";

        lblXAxis.Text = "???";
        lblYAxis.Text = "???";
        lblZAxis.Text = "???";
    }
}

So again, this handler just starts and stops the dispatch timer. Now fill in the handlers for dt.Tick and the DownloadAccelDataCompleted() functions as below,

void accelService_DownloadAccelDataCompleted(object sender, AccelerometerService.DownloadAccelDataCompletedEventArgs e)
{
    lblXAxis.Text = e.Result.ToString();
    lblYAxis.Text = e.y.ToString();
    lblZAxis.Text = e.z.ToString();
}

void dt_Tick(object sender, EventArgs e)
{
    accelService.DownloadAccelDataAsync();
}

So everytime the dispatch timer fires, we call the DownloadAccelData() function (the asynchronous version is created when we add a reference to the WCF service). And in the DownloadAccelDataCompleted() function we update the text blocks to display the accelerometer values.

And we are done, phew! Time to test’em all. Go to visual studio 2008 and start both the ConsoleApp and WCFClient_HD2 projects, once deployed press the “Start Sensor” button on the device. Now start the silverlight application from Visual Studio 2010 and press the “Start reading data from web service” button, and if you did everything right the accelerometer data should be read on the emulator and you should be seeing something like this,

service and sl app final

The other application which I showed in the video demo where a marble moved around on the screen of the emulator can now be easily implemented using the accelerometer values. I will not be going into the details of it. If you want to know how to implement one take a look at my other post where I have the source code of the application attached, the same logic holds here as well.

It’s been a really long post, if you have an HD2 and happen to try out the source code do let me know how it goes. And if you have any suggestions on how to make this code better please do leave a comment!

HTC HD2, Accelerometer and Windows Phone 7

I had an idea and after 5 hours of work I have a demo to show you guys. Check out this video below. It shows how the accelerometer data is read from an HTC HD2 and being used on the Windows Phone 7 emulator! I just finished this up today and will be posting details and the source code soon. Apologize for the bad quality of the video, I really need to get a better cam. But hey, I had to talk, record and demo all at the same time!

 

Shake detection on HTC HD2

In the previous post I mentioned that the acceleration vector or the force vector can be used to detect gestures like shake. Here is a crude implementation of shake detection,

private const double SHAKE_THRESHOLD = 5.0f;

private bool IsShakeDetected(HTCSensorData sensorData)
{
    bool isShake = false;

    double x = (double)sensorData.tiltX / 1000;
    double y = (double)sensorData.tiltY / 1000;
    double z = (double)sensorData.tiltZ / 1000;

    double forceSqrd = x * x + y * y + z * z;

    System.Console.WriteLine("Force:{0}", forceSqrd);

    if (forceSqrd >= SHAKE_THRESHOLD)
    {
        isShake = true;
    }

    return isShake;
}

This function calculates the square of the magnitude of the force vector and if the value exceeds a certain threshold, shake is detected. After experimenting with a few threshold values, 5.0f seemed to work ok. The problem with this implementation is that it makes an assumption that if the force acting on the device is more than 5.0f, it must be experiencing shake. This, of course, can be false. If you hold and swing the device in one fast sweep, shake will be detected. Technically, that’s not a shake if you ask me. The algorithm can be improved by checking the force against the threshold continuously, say 4-5 times, will work on that when I have time. Here’s a video showing shake detection,

Mark Arteaga wrote a post on shake detection sometime back. The algorithm he used compares (x, y), (x, z) and (y, z) values against a threshold. A shake is registered when the threshold is reached or exceeded 5 times. I replaced my function with his implementation and it works nicely.

private void FuncWhereYouWantToDetectShake()
{
    if (!shaking && CheckForShake(prevSensorData, sensorData, SHAKE_THRESHOLD_LEVEL) &&
        shakeCount >= 5)
    {
        shaking = true;
        shakeCount = 0;
        //SHAKE DETECTED!
    }
    else if (CheckForShake(prevSensorData, sensorData, SHAKE_THRESHOLD_LEVEL))
    {
        shakeCount++;
    }
    else if (!CheckForShake(prevSensorData, sensorData, 200))
    {
        shakeCount = 0;
        shaking = false;
    }
    prevSensorData = sensorData;           

}

private bool CheckForShake(HTCSensorData prevData, HTCSensorData currentData, double threshold)
{
    double deltaX = Math.Abs(prevSensorData.tiltX – sensorData.tiltX);
    double deltaY = Math.Abs(prevSensorData.tiltY – sensorData.tiltY);
    double deltaZ = Math.Abs(prevSensorData.tiltZ – sensorData.tiltZ);

    return (deltaX > threshold && deltaY > threshold) ||
        (deltaX > threshold && deltaZ > threshold) ||
        (deltaY > threshold && deltaZ > threshold);
}

Update:
Source Code: AccelerometerDemo-Shake.zip

HTC HD2 and the Accelerometer

htc-hd2 A couple of weeks ago I went out and bought myself a HTC HD2. Yes, the 4.3inch monster running windows mobile, probably the best windows mobile device ever; this one running Windows Mobile 6.5. Did you just wince in pain on hearing windows mobile? Well, if it makes you feel any better let me assure you that I’ll buy a Windows Phone 7 device as soon as one is available in market. Ok?

I haven’t tweaked around with it too much yet but this week I had some time to look into the accelerometer.

The Accelerometer
The accelerometer sensor measures the gravitational force acting on it. When the phone is at rest the force acting on it is equal to 1g, move the phone around and the force changes (and that is how you detect shake and other gestures). The accelerometer reports the force as vectors along 3-axes, (x, y, z); the magnitude of the force can be calculated using the formula sqrt(x*x + y*y + z*z). If you hold the phone up facing you, the x axis is the horizontal, y axis is the vertical and z axis is along the direction from the phone pointing towards you. This co-ordinate system moves along with the phone. Now the direction along which the values of x, y and z increase and the origin of this co-ordinate system might depend on the implementation on that particular device, so here we will see how it’s implemented on HD2. With respect to HD2 the top-left corner of the phone can be considered as the origin of the co-ordinate system (see image below). Again, with the phone facing you, x axis is horizontal with values increasing towards the right; y axis is the vertical with values increasing as you go from top to bottom; z axis pointing towards you with values increasing as you move from the origin towards you.

HTC HD2 Accel Axes

Lets do a little exercise. When the phone is lying flat, face-up on a table, what is the acceleration vector? It is (0, 0, –1). These are of course ideal values, in practice there will be slight variations because of inaccuracies in the sensor. Why is the vector (0, 0, –1)? Because when the phone is lying flat, the x and y axes are along the horizontal and there is no gravitational force acting along those axes. The z axis which is pointing upwards now, experiences a gravitational pull of 1g in the opposite direction, that explains the negative sign. Now if you pick the phone up and it is facing you the acceleration vector is (0, 1, 0). When the phone is facing you, the x and the z axes form a horizontal plane and therefore the forces are zero. y axis is pointing downwards, in the same direction as the gravitational force and so the value becomes +1. Now if you turn the phone 90 degrees in counter-clockwise direction the force vector becomes (-1, 0, 0), you should be able to figure this one out. HD2 reports the vector values after scaling them by a factor of 1000. So instead of reporting 0.984, it reports 984. Here are the values that my HD2 reports:

lying flat on a table: (X:-67, Y:84, Z:-973)
facing me: (X:74, Y:974, Z:26)

Accelerometer on HD2
From João Paulo Figueira’s post on the HTC G Sensor I came to know that someone called Scott Seligman reverse engineered the G Sensor driver and figured out how to use it. It also led to a project on Codeplex called “Windows Mobile Unified Sensor API” which provided you with a managed wrapper around various sensors in several devices. I wonder how much effort it takes to reverse engineer  and figure out how to use an exported function from a dll, but I am sure it involves biting through a lot of assembly code. Anyways, the accelerometer driver in HD2 is implemented in a dll called HTCSensorSDK.dll.

If you run the dumpbin tool on this dll,
c:\iamdir> dumpbin.exe /EXPORTS HTCSensorSDK.dll

CmdPromptScrShot

you can see that it implements a few other sensors as well, like the compass and the light sensor (or proximity sensor). The functions of interest to us are HTCSensorOpen(), HTCSensorGetDataOutput() and HTCSensorClose(), which control the accelerometer and are pretty self-explanatory. Open() initializes the accelerometer sensor, GetDataOutput() returns the current (x, y, z) acceleration vector and Close() de-initializes the sensor. These functions are accessed using a combination of LoadLibrary() and GetProcAddress() apis if you want to access it through native code, or you could use the interop services and p/invokes to access it from managed code.

I modified an existing native application to access the accelerometer and there is a lot of unnecessary code in it, if you want the native app leave a comment on this post, I’ll clean it up and post it here. Meanwhile I will be posting the managed application source code here. I have tested it on HD2 and I am guessing it should work well on devices like Touch Pro 2, HTC Diamond as well.

Source Code: AccelerometerDemo-HD2.zip

Here’s a brief video of the sample managed application which uses the data returned by the accelerometer to move a marble on the screen. I shot two videos, one using my pathetic camera (VGA resolution) and the other using a desktop screen capture tool which records at 15fps, so you’ll have to live with these until I buy a better camera.

and,

Windows Phone 7 Developer Tools Beta now available

WP7 Microsoft released yesterday the beta version of the Windows Phone 7 development tools, which was up until now in CTP. You can download it from here. It installs Visual Studio 2010 Express, Silverlight and XNA 4.0 for Windows Phone 7, Windows Phone 7 emulator and Expression Blend 4 beta. Yep, Expression Blend now installs with the beta version and you don’t have to install it separately which is nice. The beta version breaks some of the namespaces and classes from the previous April refresh CTP release. The details about the changes can be found in the release notes here. And finally here is a post explaining how to migrate your app from the CTP to the beta release. You’ll also find two new developer tools with the new installation, Windows Phone Developer Registration and XAP deployment tool. If you’re lucky enough to get your hands on a WP7 developer device you can use this tool to unlock the device for side loading and testing your apps. XAP deployment tool allows you to directly deploy a .xap file to the emulator or a real device. You can find these tools in Start -> Programs -> Windows Phone Developer Tools

Update
Just a slight annoyance while installing the beta release. I uninstalled the CTP and then tried to install the beta and it threw an error saying ".NET Framework 4.0 multi-targeting pack is installed, uninstall it to continue", so I uninstalled it and ran the setup again,  guess what it installed first, yep, .NET Framework 4.0 multi-targeting pack.

Applications: The Mathematics of Movement, Part 3

Previously: Part 1, Part 2

As promised in the previous post, this post will cover two variations of the marble move program. The first one, Infinite Move, keeps the marble moving towards the click point, rebounding it off the screen edges and changing its direction when the user clicks again. The second version, Finite Move, is the same as first except that the marble does not move forever. It moves towards the click point, rebounds off the screen edges and slowly comes to rest. The amount of time that it moves depends on the distance between the click point and marble.

Infinite Move

This case is simple (actually both cases are simple). In this case all we need is the direction information which is exactly what the unit vector stores. So when the user clicks, you calculate the unit vector towards the click point and then keep updating the marbles position like crazy. And, of course, there is no stop condition. There’s a little more additional code in the bounds checking conditions. Whenever the marble goes off the screen boundaries, we need to reverse its direction.  Here is the code for mouse up event and UpdatePosition() method,

//stores the unit vector
double unitX = 0, unitY = 0;

double speed = 6;

//speed times the unit vector
double incrX = 0, incrY = 0;

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    double x = e.X – marble1.x;
    double y = e.Y – marble1.y;

    //calculate distance between click point and current marble position
    double lenSqrd = x * x + y * y;
    double len = Math.Sqrt(lenSqrd);

    //unit vector along the same direction (from marble towards click point)
    unitX = x / len;
    unitY = y / len;

    timer1.Enabled = true;
}

private void UpdatePosition()
{
    //amount by which to increment marble position
    incrX = speed * unitX;
    incrY = speed * unitY;

    marble1.x += incrX;
    marble1.y += incrY;

    //check for bounds
    if ((int)marble1.x < MinX + marbleWidth / 2)
    {
        marble1.x = MinX + marbleWidth / 2;
        unitX *= -1;
    }
    else if ((int)marble1.x > (MaxX – marbleWidth / 2))
    {
        marble1.x = MaxX – marbleWidth / 2;
        unitX *= -1;
    }

    if ((int)marble1.y < MinY + marbleHeight / 2)
    {
        marble1.y = MinY + marbleHeight / 2;
        unitY *= -1;
    }
    else if ((int)marble1.y > (MaxY – marbleHeight / 2))
    {
        marble1.y = MaxY – marbleHeight / 2;
        unitY *= -1;
    }

}

So whenever the user clicks we calculate the unit vector along that direction and also the amount by which the marble position needs to be incremented. The speed in this case is fixed at 6. You can experiment with different values. And under bounds checking, whenever the marble position goes out of bounds along the x or y direction we reverse the direction of the unit vector along that direction. Here’s a video of it running;

 

Finite Move

The code for finite move is almost exactly same as that of Infinite Move, except for the difference that the speed is not fixed and there is an end condition, so the marble comes to rest after a while. Code follows,

//unit vector along the direction of click point
double unitX = 0, unitY = 0;

//speed of the marble
double speed = 0;

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    double x = 0, y = 0;
    double lengthSqrd = 0, length = 0;

    x = e.X – marble1.x;
    y = e.Y – marble1.y;
    lengthSqrd = x * x + y * y;

    //length in pixels (between click point and current marble pos)
    length = Math.Sqrt(lengthSqrd);

    //unit vector along the same direction as vector(x, y)
    unitX = x / length;
    unitY = y / length;

    speed = length / 12;

    timer1.Enabled = true;
}

private void UpdatePosition()
{
    marble1.x += speed * unitX;
    marble1.y += speed * unitY;

    //check for bounds
    if ((int)marble1.x < MinX + marbleWidth / 2)
    {
        marble1.x = MinX + marbleWidth / 2;
        unitX *= -1;
    }
    else if ((int)marble1.x > (MaxX – marbleWidth / 2))
    {
        marble1.x = MaxX – marbleWidth / 2;
        unitX *= -1;
    }

    if ((int)marble1.y < MinY + marbleHeight / 2)
    {
        marble1.y = MinY + marbleHeight / 2;
        unitY *= -1;
    }
    else if ((int)marble1.y > (MaxY – marbleHeight / 2))
    {
        marble1.y = MaxY – marbleHeight / 2;
        unitY *= -1;
    }

    //reduce speed by 3% in every loop
    speed = speed * 0.97f;
    if ((int)speed <= 0)
    {
        timer1.Enabled = false;
    }

}

So the only difference is that the speed is calculated as a function of length when the mouse up event occurs. Again, this can be experimented with. Bounds checking is same as before. In the update and draw cycle, we reduce the speed by 3% in every cycle. Since speed is calculated as a function of length, speed = length/12, the amount of time it takes speed to reach zero is directly proportional to length. Note that the speed is in ‘pixels per 40ms’ because the timeout value of the timer is 40ms.  The readability can be improved by representing speed in ‘pixels per second’. This would require you to add some more calculations to the code, which I leave out as an exercise. Here’s a video of this second version,

 

Applications: The Mathematics of Movement, Part 2

In part 1 of this series we saw how we can make the marble move towards the click point, with a fixed speed. In this post we’ll see, first, how to get rid of Atan2(), sine() and cosine() in our calculations, and, second, reducing the speed of the marble as it approaches the destination, so it looks like the marble is easing into it’s final position. As I mentioned in one of the previous posts, this is achieved by making the speed of the marble a function of the distance between the marble and the destination point.

Getting rid of Atan2(), sine() and cosine()

Ok, to be fair we are not exactly getting rid of these trigonometric functions, rather, replacing one form with another. So instead of writing sin(θ), we write y/length. You see the point. So instead of using the trig functions as below,

double x = destX – marble1.x;
double y = destY – marble1.y;

//distance between destination and current position, before updating marble position
distanceSqrd = x * x + y * y;

double angle = Math.Atan2(y, x);

//Cos and Sin give us the unit vector, 6 is the value we use to magnify the unit vector along the same direction
incrX = speed * Math.Cos(angle);
incrY = speed * Math.Sin(angle);

marble1.x += incrX;
marble1.y += incrY;

we use the following,

double x = destX – marble1.x;
double y = destY – marble1.y;

//distance between destination and marble (before updating marble position)
lengthSqrd = x * x + y * y;
length = Math.Sqrt(lengthSqrd);

//unit vector along the same direction as vector(x, y)
unitX = x / length;
unitY = y / length;

//update marble position
incrX = speed * unitX;
incrY = speed * unitY;
marble1.x += incrX;
marble1.y += incrY;

so we replaced cos(θ) with x/length and sin(θ) with y/length. The result is the same.

 

Adding oomph to the way it moves

In the last post we had the speed of the marble fixed at 6,

double speed = 6;

to make the marble decelerate as it moves, we have to keep updating the speed of the marble in every frame such that the speed is calculated as a function of the length. So we may have, speed = length/12; ‘length’ keeps decreasing as the marble moves and so does speed. The Form1_MouseUp() function remains the same as before, here is the UpdatePosition() method,

private void UpdatePosition()
{
    double incrX = 0, incrY = 0;
    double lengthSqrd = 0, length = 0, lengthSqrdNew = 0;
    double unitX = 0, unitY = 0;
    double speed = 0;

    double x = destX – marble1.x;
    double y = destY – marble1.y;

    //distance between destination and marble (before updating marble position)
    lengthSqrd = x * x + y * y;
    length = Math.Sqrt(lengthSqrd);

    //unit vector along the same direction as vector(x, y)
    unitX = x / length;
    unitY = y / length;

    //speed as a function of length
    speed = length / 12;

    //update marble position
    incrX = speed * unitX;
    incrY = speed * unitY;
    marble1.x += incrX;
    marble1.y += incrY;

    //check for bounds
    if ((int)marble1.x < MinX + marbleWidth / 2)
    {
        marble1.x = MinX + marbleWidth / 2;
    }
    else if ((int)marble1.x > (MaxX – marbleWidth / 2))
    {
        marble1.x = MaxX – marbleWidth / 2;
    }

    if ((int)marble1.y < MinY + marbleHeight / 2)
    {
        marble1.y = MinY + marbleHeight / 2;
    }
    else if ((int)marble1.y > (MaxY – marbleHeight / 2))
    {
        marble1.y = MaxY – marbleHeight / 2;
    }

    //distance between destination and marble (after updating marble position)
    x = destX – (marble1.x);
    y = destY – (marble1.y);
    lengthSqrdNew = x * x + y * y;

    /*
     * End Condition:
     * 1. If there is not much difference between lengthSqrd and lengthSqrdNew
     * 2. If the marble has moved more than or equal to a distance of totLenToTravel (see Form1_MouseUp)
     */
    x = startPosX – marble1.x;
    y = startPosY – marble1.y;
    double totLenTraveledSqrd = x * x + y * y;
    if ((int)totLenTraveledSqrd >= (int)totLenToTravelSqrd)
    {
        System.Console.WriteLine("Stopping because Total Len has been traveled");
        timer1.Enabled = false;
    }
    else if (Math.Abs((int)lengthSqrd – (int)lengthSqrdNew) < 4)
    {
        System.Console.WriteLine("Stopping because no change in Old and New");
        timer1.Enabled = false;
    }
}

A point to note here is that, in this implementation, the marble never stops because it travelled a distance of totLenToTravelSqrd (first if condition). This happens because speed is a function of the length. During the final few frames length becomes very small and so does speed; and so the amount by which the marble shifts is quite small, and the second if condition always hits true first.

I’ll end this series with a third post. In part 3 we will cover two things, one, when the user clicks, the marble keeps moving in that direction, rebounding off the screen edges and keeps moving forever. Two, when the user clicks on the screen, the marble moves towards it, with it’s speed reducing by every frame. It doesn’t come to a halt when the destination point is reached, instead, it continues to move, rebounds off the screen edges and slowly comes to halt. The amount of time that the marble keeps moving depends on how far the user clicks from the marble. I had mentioned this second situation here.

Finally, here’s a video of this program running, 

 

Part 1, Part 3

Applications: The Mathematics of Movement, Part 1

Before you continue reading this post, a suggestion; if you haven’t read “Programming Windows Phone 7 Series” by Charles Petzold, go read it. Now. If you find 150+ pages a little too long, at least go through Chapter 5, Principles of Movement, especially the section “A Brief Review of Vectors”. This post is largely inspired from this chapter.

At this point I assume you know what vectors are, how they are represented using the pair (x, y), what a unit vector is, and given a vector how you would normalize the vector to get a unit vector.

Our task in this post is simple, a marble is drawn at a point on the screen, the user clicks at a random point on the device, say (destX, destY), and our program makes the marble move towards that point and stop when it is reached. The tricky part of this task is the word “towards”, it adds a direction to our problem, making it seem a bit, err, esoteric? Making a marble bounce around the screen is simple, all you have to do is keep incrementing the X and Y co-ordinates by a certain amount and handle the boundary conditions. Here, however, we need to find out exactly how to increment the X and Y values, so that the marble appears to move towards the point where the user clicked. And this is where vectors can be so helpful.

The code I’ll show you here is not ideal, we’ll be working with C# on Windows Mobile 6.x, so there is no built-in vector class that I can use, though I could have written one and done all the math inside the class. I think it is trivial to the actual problem that we are trying to solve and can be done pretty easily once you know what’s going on behind the scenes. In other words, this is an excuse for me being lazy.

The first approach uses the function Atan2() to solve the “towards” part of the problem. Atan2() takes a point (x, y) as input, Atan2(y, x), note that y goes first, and then it returns an angle in radians. What angle you ask. Imagine a line from the origin (0, 0), to the point (x, y). The angle which Atan2 returns is the angle the positive X-axis makes with that line, measured clockwise. The figure below makes it clear, wiki has good details about Atan2(), give it a read. Atan is short for Arc Tangent, the angle, θ,  which it returns is such that, tan(θ) = y/x

 

image

The pair (x, y) also denotes a vector. A vector whose magnitude is the length of that line, which is Sqrt(x*x + y*y), and a direction θ, as measured from positive X axis clockwise. If you’ve read that chapter from Charles Petzold’s book, this much should be clear. Now Sine and Cosine of the angle θ are special. Cosine(θ) divides x by the vectors length (adjacent by hypotenuse), thus giving us a unit vector along the X direction. And Sine(θ) divides y by the vectors length (opposite by hypotenuse), thus giving us a unit vector along the Y direction. Therefore the vector represented by the pair (cos(θ), sin(θ)), is the unit vector (or normalization) of the vector (x, y). This unit vector has a length of 1 (remember sin2(θ) + cos2(θ) = 1 ?), and a direction which is the same as vector (x, y). Now if I multiply this unit vector by some amount, then I will always get a point which is a certain distance away from the origin, but, more importantly, the point will always be on that line. For example, if I multiply the unit vector with the length of the line, I get the point (x, y). Thus, all we have to do to move the marble towards our destination point, is to multiply the unit vector by a certain amount each time and draw the marble, and the marble will magically move towards the click point.

Now time for some code. The application uses a timer based frame draw method to draw the marble on the screen. The timer is disabled initially and whenever the user clicks on the screen, the timer is enabled. The callback function for the timer follows the standard Update and Draw cycle.

private double totLenToTravelSqrd = 0;
private double startPosX = 0, startPosY = 0;
private double destX = 0, destY = 0;

private void Form1_MouseUp(object sender, MouseEventArgs e)
{
    destX = e.X;
    destY = e.Y;

    double x = marble1.x – destX;
    double y = marble1.y – destY;

    //calculate the total length to be travelled
    totLenToTravelSqrd = x * x + y * y;

    //store the start position of the marble
    startPosX = marble1.x;
    startPosY = marble1.y;

    timer1.Enabled = true;
}

private void timer1_Tick(object sender, EventArgs e)
{
    UpdatePosition();
    DrawMarble();
}

Form1_MouseUp() method is called when ever the user touches and releases the screen. In this function we save the click point in destX and destY, this is the destination point for the marble and we also enable the timer. We store a few more values which we will use in the UpdatePosition() method to detect when the marble has reached the destination and stop the timer. So we store the start position of the marble and the square of the total length to be travelled. I’ll leave out the term ‘sqrd’ when speaking of lengths from now on. The time out interval of the timer is set to 40ms, thus giving us a frame rate of about ~25fps. In the timer callback, we update the marble position and draw the marble. We know what DrawMarble() does, so here, we’ll only look at how UpdatePosition() is implemented;

private void UpdatePosition()
{
    //the vector (x, y)
    double x = destX – marble1.x;
    double y = destY – marble1.y;

    double incrX=0, incrY=0;
    double distanceSqrd=0;

    double speed = 6;

    //distance between destination and current position, before updating marble position
    distanceSqrd = x * x + y * y;

    double angle = Math.Atan2(y, x);

    //Cos and Sin give us the unit vector, 6 is the value we use to magnify the unit vector along the same direction
    incrX = speed * Math.Cos(angle);
    incrY = speed * Math.Sin(angle);

    marble1.x += incrX;
    marble1.y += incrY;

    //check for bounds
    if ((int)marble1.x < MinX + marbleWidth / 2)
    {
        marble1.x = MinX + marbleWidth / 2;
    }
    else if ((int)marble1.x > (MaxX – marbleWidth / 2))
    {
        marble1.x = MaxX – marbleWidth / 2;
    }

    if ((int)marble1.y < MinY + marbleHeight / 2)
    {
        marble1.y = MinY + marbleHeight / 2;
    }
    else if ((int)marble1.y > (MaxY – marbleHeight / 2))
    {
        marble1.y = MaxY – marbleHeight / 2;
    }

    //distance between destination and current point, after updating marble position
    x = destX – marble1.x;
    y = destY – marble1.y;
    double newDistanceSqrd = x * x + y * y;

    //length from start point to current marble position
    x = startPosX – (marble1.x);
    y = startPosY – (marble1.y);
    double lenTraveledSqrd = x * x + y * y;

    //check for end conditions
    if ((int)lenTraveledSqrd >= (int)totLenToTravelSqrd)
    {
        System.Console.WriteLine("Stopping because destination reached");
        timer1.Enabled = false;
    }
    else if (Math.Abs((int)distanceSqrd – (int)newDistanceSqrd) < 4)
    {
        System.Console.WriteLine("Stopping because no change in Old and New position");
        timer1.Enabled = false;
    }

}

Ok, so in this function, first we subtract the current marble position from the destination point to give us a vector. The first three lines of the function construct this vector (x, y). The vector (x, y) has the same length as the line from (marble1.x, marble1.y) to (destX, destY) and is in the direction pointing from (marble1.x, marble1.y) to (destX, destY). Note that marble1.x and marble1.y denote the center point of the marble. Then we use Atan2() to get the angle which this vector makes with the positive X axis and use Cosine() and Sine() of that angle to get the unit vector along that same direction. We multiply this unit vector with 6, to get the values which the position of the marble should be incremented by. This variable, speed, can be experimented with and determines how fast the marble moves towards the destination. After this, we check for bounds to make sure that the marble stays within the screen limits and finally we check for the end condition and stop the timer.

The end condition has two parts to it. The first case is the normal case, where the user clicks well inside the screen. Here, we stop when the total length travelled by the marble is greater than or equal to the total length to be travelled. Simple enough. The second case is when the user clicks on the very corners of the screen. Like I said before, the values marble1.x and marble1.y denote the center point of the marble. When the user clicks on the corner, the marble moves towards the point, and after some time tries to go outside of the screen, this is when the bounds checking comes into play and corrects the marble position so that the marble stays inside the screen. In this case the marble will never travel a distance of totLenToTravelSqrd, because of the correction is its position. So here we detect the end condition when there is not much change in marbles position. I use the value 4 in the second condition above. After experimenting with a few values, 4 seemed to work okay. There is a small thing missing in the code above. In the normal case, case 1, when the update method runs for the last time, marble position over shoots the destination point. This happens because the position is incremented in steps (which are not small enough), so in this case too, we should have corrected the marble position, so that the center point of the marble sits exactly on top of the destination point. I’ll add this later and update the post.

This has been a pretty long post already, so I’ll leave you with a video of how this program looks while running. Notice in the video that the marble moves like a bot, without any grace what so ever. And that is because the speed of the marble is fixed at 6. In the next post we will see how to make the marble move a little more elegantly. And also, if Atan2(), Sine() and Cosine() are a little too much to digest, we’ll see how to achieve the same effect without using them, in the next to next post maybe. Ciao!

 

Part 2, Part 3