Day 3: Outlook Notes Mobile

outlooknotes1 outlooknotes2

This isn't really so much a complaint about Windows Mobile development, but more so about hole in the platform's user experience.

If you're an avid Windows Mobile user, you are familiar with the Notes application: you can create a short text or image note and have it sync to your desktop. Then the desktop will sync it to Exchange. However, there's a couple problems:

  1. Only Pocket PCs come with the notes applications: Smartphones do not.
  2. You must use your desktop ActiveSync connection to sync with Exchange; it does not sync directly.

To resolve this, a few months ago I wrote an application that allows you to view, edit, and create notes on your Windows Mobile device, and sync directly with Exchange.

Download Outlook Notes Mobile.

Usage:

  1. Start Outlook Notes Mobile.
  2. Go to settings.
  3. Enter the same login information you provided ActiveSync. (The server will be in the format of "mydomain.com" or "mail.mydomain.com", ask your SysAdmin).
  4. Synchronize. (There is no automatic synchronization).

Note:

If you have problems getting this application to work, it may be due to your Exchange server setup. The Microsoft "recommended" Exchange deployment does not expose the Exchange Web Service (it redirects all requests to the OWA client).

HTC Touch Diamond Stylus Sensor API

StylusSensor

I spent a bit of time figuring out how to determine the stylus on the HTC Touch Diamond. It only took like 5 minutes: it was exactly where I suspected, a registry key that toggled depending on the stylus state. So basically it's really easy to access. I rolled access to this registry key up in the Sensor SDK.

(HKEY_CURRENT_USER\ControlPanel\Keybd\StylusOutStatus for those curious.)

The new HTCStylusSensor has 2 members:

StylusState

This property is has a value that is either StylusIn or StylusOut.

StylusStateChanged

This event fires whenever the StylusState property changes.

Click here if you want to download the APIs and source to access the G-Sensor, Light Sensor, Nav Sensor, or Stylus Sensor.

 

I will be releasing an tool shortly that allows users to launch any application, shortcut, sound file, etc, when the stylus is removed from the device.

Day 2: Serialization of Complex Types and XmlAttributes

This isn't really a rant about Windows Mobile per se, but it's an issue I seem to run into on a consistent basis: you can't deserialize an XmlAttribute into a struct. Consider the following code:

using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;

namespace SmartDeviceProject2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            XmlSerializer ser = new XmlSerializer(typeof(Foo));

            string xml = "<Foo Moo=\"2,3\"/>";
            MemoryStream mem = new MemoryStream();
            StreamWriter writer = new StreamWriter(mem);
            writer.Write(xml);
            writer.Flush();
            mem.Seek(0, SeekOrigin.Begin);
            Foo f = (Foo)ser.Deserialize(mem);
        }
    }

    public struct Bar : IFormattable
    {
        public int X;
        public int Y;
        public static Bar Parse(string s)
        {
            string[] strings = s.Split(',');
            Bar ret = new Bar();
            ret.X = int.Parse(strings[0]);
            ret.Y = int.Parse(strings[1]);
            return ret;
        }
        public override string ToString()
        {
            return string.Format("{0},{1}", X, Y);
        }

        #region IFormattable Members

        public string ToString(string format, IFormatProvider formatProvider)
        {
            return ToString();
        }

        #endregion
    }

    public struct Foo
    {
        [XmlAttribute]
        public Bar Moo;
    }
}

Attempting to run this code on the desktop would fail on the line that instantiates the XmlSerializer: "Cannot serialize member 'Moo' of type SmartDeviceProject2.Foo. XmlAttribute/XmlText cannot be used to encode complex types.".

However, on .NET CF 2.0, it fails on deserialization with the cryptic message: "The type SmartDeviceProject2.Bar was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."

But my gripe is the following: I have a struct, it is IFormattable, and it can be Parsed (like int.Parse, DateTime.Parse, et al). Why is that not sufficient enough for serialization to and from an XmlAttribute string?

Anyways, here is the workaround:

  1. For all types that you want to be deserialized from attributes, explicitly give them the [XmlElement] attribute. Yes, you read that right.
  2. Create an XmlSerializer. Attach a new method to the UnknownAttribute event.
  3. Whenever this event is fired, use a combination of the attribute name and reflection to find the PropertyInfo/FieldInfo for what XmlSerializer can't deserialize. Then find that object type's static Parse method, and call it on the attribute string. Then use that PropertyInfo/FieldInfo to set the property.

The new code would look something like this (you will need to add your own code to handle if it is a Property, since my sample is only looking for fields):

private void button1_Click(object sender, EventArgs e)
{
    XmlSerializer ser = new XmlSerializer(typeof(Foo));

    string xml = "<Foo Moo=\"2,3\"/>";
    MemoryStream mem = new MemoryStream();
    StreamWriter writer = new StreamWriter(mem);
    writer.Write(xml);
    writer.Flush();
    mem.Seek(0, SeekOrigin.Begin);
    ser.UnknownAttribute += new XmlAttributeEventHandler(ser_UnknownAttribute);
    Foo f = (Foo)ser.Deserialize(mem);
}

void ser_UnknownAttribute(object sender, XmlAttributeEventArgs e)
{
    FieldInfo field = e.ObjectBeingDeserialized.GetType().GetField(e.Attr.Name);
    MethodInfo parse = field.FieldType.GetMethod("Parse");
    field.SetValue(e.ObjectBeingDeserialized, parse.Invoke(null, new object[] { e.Attr.Value }));
}
public struct Foo
{
    [XmlElement]
    public Bar Moo;
}

Unfortunately I have not figured out a similar workaround for serialization...

Day 1 - Windows Mobile OpenFileDialog and SaveFileDialog, why are you so terrible?

Yeah, so whoever the UX person is behind the Windows Mobile version OpenFileDialog and SaveFileDialog, they need to reevaluate their career choice. Here's a screen shot of these beauties in action:

save open

What the hell is with the OpenFileDialog? You can't browse through the file system to find what you want. You gotta bust out the stylus (problem #1) and search for the file. And even then it has to be in the path of your My Documents folder (problem #2).

I try to avoid these dialogs like the plague, but finally ended up needing an OpenFileDialog. I ended up writing my own out of principle:

goodopen

Don't get me wrong, this isn't the end all be all of Windows Mobile OpenFileDialogs, but it is infinitely better than the stock version. It works basically like the standard OpenFileDialog:

  1. Create an instance.
  2. Set a filter if need be.
  3. Set the initial directory if need be.
  4. ShowDialog

I still want to tweak it a bit more so that the fonts and such are all customizable via the developer, and eventually write a SaveFileDialog (probably just throw a TextBox at the bottom). But this will do for now; you can download the assemblies for the Windows Mobile OpenFileDialog here. You'll need to deploy all the assemblies to use it, but the type in particular you should be interested in is WindowsMobile.CommonDialogs.OpenFileDialog.

Klaxon Bug Fixes - New Release

Spent some time fixing Klaxon bugs today:

  • Fixed bug where Klaxon immediately closes because it thinks it was shook when the alarm starts (bug in HTC G-Sensor being initialized). I haven't experienced this myself, but I think that is what is happening from the indication in the various logs I received.
  • Fixed bug where disabling an alarm does not actually disable it.
  • Made Home Screen integration optional: The "My Windows Alarm is firing with Klaxon" bug/issue is tricky. This is happening because I tried to integrate Klaxon alarm with the HTC home screen. I am enabling the Windows in the registry to achieve this, but since this goes around Windows, the alarm never actually gets scheduled and should not fire; but apparently for some people it is. To get integration working properly, do the following:
    • Disable all Windows alarms.
    • Start Klaxon, and turn on the new setting to enable Home Screen integration.
    • DO NOT USE WINDOWS ALARMS ANYMORE! DO NOT EVEN LOOK AT THEM! OPENING THAT FORM WILL CAUSE WINDOWS ALARMS TO RESCHEDULE THEMSELVES! Using Windows alarms while trying to use Klaxon integration is what is causing the problem. If you must use Windows alarm with Klaxon, I would turn home screen integration off.
  • Klaxon now restores your original volume after the alarm is shut off.
  • Clicking the alarm now opens the Edit form.

Click here for the updated version of Klaxon.

30 Days of Bitching about .NET Compact Framework

If you're an aficionado of .NET Compact Framework development, you've probably stumbled across Chris Craft's blog and read 30 Days of .NET [Windows Mobile Applications].

All in all it was a great series. There were a good number of "fillers" so to speak, but the gems more than made up for it.

The tag line of my blog is "I like Windows Mobile development. Does that make me a masochist?"; and it is quite amazing how often that statement really rings true. Windows Mobile is by necessity a subset of the fully featured desktop version of Windows. And the same goes for .NET and it's little brother .NET Compact Framework. I retract that statement; "little brother" does not do .NET justice when comparing it to CF. I think "adopted bastard red headed stepchild" seems more fitting, don't you? [0][1]

Anyhow, the purpose of this post was to announce that in a sort of satirical homage to Chris' series I will be blogging/bitching the next 30 days about all the pitfalls of Windows Mobile and .NET CF. And if we're lucky, I'll describe any workarounds I may have found. Ok, I'll be up front: don't check this page every day expecting an update; I've been rather busy lately. However, I have more than enough to work with that I can catch up with any amount backlog should I fall behind.

And with that; I'll start with an easy one!

Day 0:

WPF or Silverlight. I want it on Windows Mobile. One of the more annoying aspects of Windows Mobile development is that there are so many screen resolutions to support. Designing an application that looks good on any screen resolution is quite a chore. To implement this properly, one would need a set of classes that allow you to lay out your screen elements in relative measurements rather than absolute dimensions.

The full version of .NET has a TableLayoutPanel class which has the aforementioned behavior. However, that class does not exist on .NET CF. In fact, no intelligent layout code exists from anything released by Microsoft. The Android SDK comes with this sort of UI framework in their V1 product. And I'm not too familiar with the iPhone SDK, but my guess is that when you are supporting a single screen size, it's probably not a huge issue.

Solutions:

Though I can't release the source, I basically wrote a bunch of WPF style classes to do intelligent layout. These classes include StackPanel, DockPanel, WrapPanel, Grid, and ItemsControl. You can probably just grab the WindowlessControls assembly (don't ask me why I called it that) out of any number of my released projects and try to figure out how to use it (hello ILDASM). I should also mention that all the controls support transparencies and "bubbling" up events to its parents; similar to WPF. The ItemsControl is also data driven and rendered using a ContentPresenter similar to WPF.

 

I somewhat lied about Silverlight not being available on Windows Mobile. It is, but it's in beta. The problem is that it requires it to be hosted in a browser. Unfortunately the WebBrowser control in Windows Mobile is not as fully featured, and does not give you access to the DOM. That makes reacting to events on the Silverlight control in non JavaScript code impossible; or at least I thought.

Recently I figured out a way how to invoke C# code through JavaScript. The first step is to get from JavaScript into unmanaged code:

  1. Create an ActiveX control project.
  2. Embed a WebBrowser in your Windows Forms application.
  3. Embed that ActiveX control in your browser HTML. (using <object>)
  4. Funnel all Silverlight events from JavaScript into your ActiveX control.  Now you are in unmanaged code.

Now to get from unmanaged code into managed code:

  1. In your ActiveX control project, create a DLL export that accepts and stores a function pointer or a COM object. This function pointer or COM object will be passed in from managed code.
  2. Create a DLLImport to that function. Pass in a pointer to a method/COM object in managed code.
  3. When JavaScript is invoked, your ActiveX is being called into. Now from that point, you can then call into the managed function pointer you provided earlier. I'll leave the exercise of passing and parsing arbitrary arguments up to the reader. You can basically invoke any method name and any method signatures of any C# function from JavaScript by using a crafty combination of string parsing and reflection. The solution I had was quite elegant for being a giant hack in the grand scheme of things.

And there you go! You are now creating Silverlight thick client applications just like on the desktop!

 

[0] I speak in jest. I do not mean any offense to anyone who is adopted, a bastard, or a step child. I did mean the red head remark though.

[1] Real developers zero index their blog footnotes.

C++: Your best friend and worst enemy

I just spent 2 hours looking for a bug until I found it in this rather innocuous bit of code:

SyncItem* item = NULL;
if (ret)
{
    SyncItem* item = new SyncItem;
    item->setKey(key);
    item->setData(data, memUsed);
}
if (data != NULL)
    LocalFree(data);
return item;

Extension Methods

Apparently I completely missed the introduction of the extension methods feature with .NET 3.5/CLR 2.0/C#. It's not doing anything new from the old version of the CLR per se, but it is very handy syntactic sugar. Basically it takes a static method and uses the first argument to fake out a thiscall.

using System;
using System.Runtime.CompilerServices;

namespace ExtensionMethods
{
    public static class ExtensionMethods
    {
        [Extension]
        public static void PrintMe(this string someString)
        {
            Console.WriteLine(someString);
        }
    }
}
using System;

namespace ExtensionMethods
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            string coolString = "hello world";
            coolString.PrintMe();                   // pretty neat!
        }
    }
}

Compile Time Generics in C# and VB... sort of

I've had a major gripe with .NET for a while; a feature that I was addicted to in C++, but is just not feasible in (or implemented, I don't know which) in .NET: Compile Time Generics.

I seem to constantly run into scenarios where I want to templatize a class, but it is not possible for one reason or another. For example, consider this template struct that would work perfectly fine in C++:

namespace TaskTest
{
    unsafe struct Vector<MyVectorType, MyVectorSize>
    {
        public fixed MyVectorType Items[MyVectorSize];

        public static Vector operator+(Vector one, Vector two)
        {
            for (int i = 0; i < MyVectorSize; i++)
            {
                one.Items[i] += two.Items[i];
            }
            return one;
        }
    }
}

This is a very useful struct when doing any low level graphics related development (OpenGL, Direct3D), but it is not available on .NET Framework. (Well, .NET 3.5 on full blown Windows has a Vector3D)

Incidentally, the fixed size array means it's contents are actually a part of the total memory footprint of the structure. I.e., if you were to get a pointer to that structure, the first 4 bytes would be the first element in the array. If it were a regular array, the first 4 bytes would be a pointer to that array object. This is useful because you can pass an array of managed Vectors to OpenGL and all the data is in one contiguous block of memory.

Anyhow, I digress; I needed to templatize this structure into several flavors: Vector4f (4 floats), Vector3f, Vector4i (4 ints), Vector3i, Vector4d... etc, etc. Then imagine doing this again for Matrix3f, Matrix4f... etc.

But this is not possible with .NET generics for a couple reasons:

  1. You can't pass in an int value as a template argument.
  2. You can't constrain the template type MyVectorType to require an operator+ be implemented. You get a compile time error on the line of code that attempts to add the types.

Or consider this classic example:

namespace TaskTest
{
    public partial class FunkyControl<MyControlType> : MyControlType
    {
        bool myHasGottenFocus = false;
        protected override void OnGotFocus(EventArgs e)
        {
            if (myHasGottenFocus)
                return;
            myHasGottenFocus = true;
            MessageBox.Show("Funky!");
        }
    }
}

This class takes any System.Windows.Forms.Control inheriting type and overrides it so when the user first puts focus on it, it pops up a MessageBox. Or it may not even be a System.Windows.Control, it may just be an object that has a virtual OnGotFocus method. However this scenario is not possible either: the generic parameter can not be the base class of the resultant type.

So, my awesome hack of a solution was to create an MSBuild Task that basically looks at a code file and does a copy, paste, search, and replace to generate new code files with your resultant types:

using System;
using System.Collections.Generic;
using System.Text;

// @CompileTimeGeneric Vector4f::MyVectorSize:4;<MyVectorType>:;MyVectorType:float;Vector:Vector4f@
// @CompileTimeGeneric Vector3f::MyVectorSize:3;<MyVectorType>:;MyVectorType:float;Vector:Vector3f@

namespace TaskTest
{
    unsafe struct Vector<MyVectorType>
    {
        public fixed MyVectorType Items[MyVectorSize];

        public static Vector operator+(Vector one, Vector two)
        {
            for (int i = 0; i < MyVectorSize; i++)
            {
                one.Items[i] += two.Items[i];
            }
            return one;
        }
    }
}

Note the comments. The build task locate the files you wish to create from the contents of the input file by searching for a certain regular expression match.

A sample match would be the following:

@CompileTimeGeneric OutputFileWithoutExtension1:Search1:Replace1;Search2:Replace2@

@CompileTimeGeneric OutputFileWithoutExtension2:Search1:Replace1@

The search and replace takes place in the order listed. One input file can generate as many output files as you need. Unfortunately this isn't a full blown implementation of generics like C++: it doesn't support recursive instantiation of generic types (like using the compiler to calculate out the Nth value in the Fibonacci series). But it works well enough for what I need!

Here is the full source for the Tasks.dll and Tasks.Targets.xml. You will need to add the Tasks.Targets.xml file to your project.

<Import Project="..\Tasks.Targets.xml" />

And for all files that you want to generate Compile Time Generics, change the Build action to "CompileTimeGeneric" in the properties window:

CTGThumbnail

That should do it! The task will create temporary files containing the generics in the bin\obj directory and add them to your Compile list.

P.S. Yes, I know this is a complete hack.

P.P.S. No, I am not proud of this code by any means. It's a means to an end; a way to save time without sacrificing performance so I can do development on more interesting stuff.

P.P.P.S. Mmm, template metaprogramming. I miss you.

Sensory Overload

SensoryOverload

A few days ago I published the Managed OpenGL ES wrapper. As a proof of concept, I went so far as to create a simple game for the HTC Touch Diamond that utilizes the G-Sensor, Nav Sensor, and the 3D hardware capabilities of the device. The end result is a simple "Asteroids" type game I call Sensory Overload.

The game is simple:

  • Move the ship by tilting the device.
  • Don't run into an asteroid.
  • Blow up the asteroids into tiny pieces.
  • When an asteroid spawns (it will be faded out), you have 5 seconds to get away from it before it can hurt you.
  • Rotate the Nav sensor clockwise to fire a bullet.
  • Rotate the Nav sensor counter clockwise to fire a spray of bullets. You can only use this special ability once every 5 seconds.
  • Asteroids spawn every 15 seconds.

This is mostly intended as a demo or proof of concept to provide other developers starting ground to create their own amazing games for the HTC Touch Diamond.

Known Bugs:

  • Small asteroids are hard to explode. The bullets travel "through" them between repaints, so they never actually collide. I may fix this in the future.

Click here to download the full source to Sensory Overload.

Click here to download the Sensory Overload CAB file to play the game.

.NET Compact Framework wrapper for OpenGL ES

OpenGL Test

Around a year ago today, I began writing an extensive UI framework for Windows Mobile. It turned out great, however I continually run into the limitations and performance issues of GDI/GDI+ on mobile devices. One of the steps I wanted to take into really improving performance was to utilize the hardware acceleration that we will begin to see in the new wave of Windows Mobile devices; in my case the HTC Touch Diamond.

The first step towards that end is to utilize one of the two 3D APIs available on the Windows Mobile platform. Direct3D Mobile .NET was not a reasonable option: it has limited support and is supposedly being phased out in Windows Mobile 7. In addition, the D3DM implementation on the HTC Touch Diamond is a just a wrapper around OpenGL ES... I find it a little distasteful that than an operating system specific 3D API is actually just a wrapper around a cross platform 3D API, hehe. And on the other hand, OpenGL ES does not have a managed API.

In My Humble Opinion, UI development should generally be in managed code. Although unmanaged code undoubtedly provides superior performance, the developer sacrifices too much of the ease and speed of managed development.

For that reason, I've started work on a managed wrapper for OpenGL ES: I now have a working set of wrappers for OpenGL ES. I won't take all the credit though. Most of the PInvokes were mass imported via the PInvoke Interop Assistant written by Jared Parsons.

The screen shot above is of the sample "Hello World" application written in Managed OpenGL ES. The code download includes the full source for the wrapper and the sample.

For those wanting to learn OpenGL, I highly recommend reading the NeHe OpenGL series. It's the best OpenGL tutorial on the Internet; I've practically had it book marked for 8 years.

Future work will include converting the various OpenGL constants into enums (I.e., GL_TRIANGLES, GL_TEXTURE0, etc) so that arguments are not so loosely typed.

Notes:

  • The sample uses floating point math, so not all devices may support it.
  • If your device does not have an implementation of OpenGL ES (hardware or software), you can get the free software implementation, Vincent 3D. Just drop the libgles_cm.dll into your \Windows directory. Vincent 3D is a fixed point implementation, so it does not support the sample either. I will probably convert the sample to fixed point eventually.

Windows Mobile Bar Code Manager and API

While I was checking out of the grocery store tonight, I realized I had left my "preferred savings" card in my car's glove compartment as usual. Naturally, my train of thought derailed into Windows Mobile development and how I could make my life easier. The answer was simple: why can't I save all my bar codes into a program and have the cashier scan the image from my cell phone? It would save wallet space and be really cool to boot!

After a quick investigation into how bar codes work, I began coding. The end result is the following:

barcode barcodeedit

Above, I have two of my grocery cards entered into my Bar Code manager. In the editor screen, one can enter a bar code number and view it in real time.

The API (BarCode.dll) is simple:

  1. Create a BarCodeSerializer object.
  2. Set the DisplayNumber property to your bar code number you want to process.
  3. Use the IsValid property verify it is a valid 12 digit bar code.
  4. Use the MakeValid property to make a valid 12 digit bar code from an 11 digit number. Some cards only show 11 of the 12 digits. The 12th is used as a "check" digit.
  5. Use the CreateBitmap method to create a bitmap of approximately the desired dimensions.

In a possible future release, I might extend the bar code manager to take a picture with a high resolution camera and import a bar code number. That would be an interesting computer vision problem!

Download the Bar Code Manager and API here.

Another Klaxon Release

As promised, I implemented more bug fixes and features for this release. Download Klaxon here.

  • The light sensor will only turn off your alarm if the phone is face up. This fixes the issue where the alarm gets shut off if the phones if flipped face down to snooze.
  • If the phone is snoozing, a sensor can not be used to turn the alarm off. The off button must be manually pressed. This is a precaution to ensure the phone doesn't get erroneously turned off.
  • The shake off function is implemented differently now: if at any point, the phone is subject to 20 G's of force, it will turn off. Previously, it was using an orientation change count. The G measurement method is much more reliable.
  • As a silent confirmation, the phone will vibrate once if you put it into Snooze mode. It will Vibrate twice if you turned it off.
  • All the sensor actions are configurable: you can now manually configure what you want the alarm to do when you shake it, flip it, or turn on the light.
  • Implemented some of the UI clean up changes. This includes bigger Vista style check boxes and radio buttons.
  • Implemented an About box which gives you information about your Klaxon version and the author.
  • Fixed a bug where the registry entries were not being deleted properly when an alarm was deleted.
  • Fixed a bug where the device would go to sleep after a Snooze and not wake up to alarm the user.
  • Fixed a bug where the Delay setting was not being saved after editing it.