30 Days of Windows Mobile – Day 08: Rotate Me

December 14th, 2008

Rotate Me iconRotate Me is a simple application which demonstrates how to programmatically rotate the screen of a Windows Mobile device.

As discussed previously dynamic screen orientation changes was first introduced in Pocket PC 2003 Second Edition. There are four orientations understood by the operating system as shown below (I have also listed their typical orientations on a 240×320 QVGA device).

  • DMDO_0 – 0 degrees (portrait)
  • DMDO_90 – 90 degrees (landscape)
  • DMDO_180 – 180 degrees (upside down portrait)
  • DMDO_270 – 270 degrees (upside down landscape)

Determining the current screen orientation

The ChangeDisplaySettingsEx API acts a little like a catch all kitchen sink. It can be used to query and set the current state of various display related properties.

In order to query the current state of a property you pass in the CDS_TEST flag and specify the field(s) you want to query in the dmFields bitmask, as shown below.

static DWORD GetScreenOrientation()
{
  DEVMODE deviceMode;
 
  memset(&deviceMode, 0, sizeof(deviceMode));
  deviceMode.dmSize = sizeof(deviceMode);
  deviceMode.dmFields = DM_DISPLAYORIENTATION;
 
  // Query the DM_DISPLAYORIENTATION property
  if (ChangeDisplaySettingsEx(NULL, &deviceMode,
    NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL)
    return deviceMode.dmDisplayOrientation;
  else
    return DMDO_DEFAULT;
}

Notice in this example we default to returning DMDO_DEFAULT (which is defined as DMDO_0) if the query fails. This seemed like a sensible default value to assume in the case of an error.

Changing the current screen orientation

To change the value of a display property we use a very similar code snippet, except we use the CDS_RESET flag and pre-populate the field in the DEVMODE structure with the desired value.

static void SetScreenOrientation(DWORD dwOrientation)
{
  DEVMODE deviceMode;
 
  memset(&deviceMode, 0, sizeof(deviceMode));
  deviceMode.dmSize = sizeof(deviceMode);
  deviceMode.dmFields = DM_DISPLAYORIENTATION;
  deviceMode.dmDisplayOrientation = dwOrientation;
 
  // Set the DM_DISPLAYORIENTATION property to the
  // specified orientation
  ChangeDisplaySettingsEx(NULL, &deviceMode,
    NULL, CDS_RESET, NULL);
}

Sample Application

[Download rotateme.zip - 20.8 KB]

The small sample application available for download demonstrates using the above functions to change the screen orientation. Each time you run the application it will toggle the screen between 0 and 90 degrees rotation and then promptly quit. There is not even any user interface!

30 Days of Windows Mobile – Day 07: Mobile FX

December 13th, 2008

Screenshot of Mobile FX ApplicationMobile FX is a fun sound effects engine for Windows Mobile. It displays a series of graphical buttons which clicked produce different sound effects. The user interface is driven by an XML based configuration file that enables the user to change which sound effects are available.

This is the 7th application in the 30 days of Windows Mobile series and marks my current re-commitment to progress in converting the number of applications currently sitting on my harddrive into blog posts. My hat is off to Chris Craft who managed 30 applications in 30 days. Although I took a similar amount of time to convert his C# applications into C++, it is taking me a lot longer to write the associated blog posts…

Mobile FX is an interesting application, in order to develop it in native code we will need to cover a number of new technologies and APIs which we have not covered before.

Creating controls at runtime

Up until now all of our applications have statically placed controls within the user interface via a dialog resource located in a *.rc resource file.

This application however specifies a variable number of sound effects within an XML based configuration file. Since the number of button controls required could change, it is easier to create the controls dynamically at runtime. The CreateWindow API enables us to create a control at runtime as shown below

// Create a static (label) control at runtime
HWND hWndPicture = CreateWindow(_T("static"),
  NULL,
  WS_CHILD | WS_VISIBLE | SS_BITMAP | SS_NOTIFY, 
  left, top, width, height,
  hDlg, NULL,
  GetModuleHandle(NULL),
  NULL);

The first string parameter to CreateWindow specifies the type of control to create. A future blog post will discuss how to register your own custom controls so that they can be created via CreateWindow. The other parameters specify various properties related to the new control, such as its style, location and size.

If we want to make use of the GetDlgItem function to reference the newly created control we need to associate an ID with it. One way to do this is to use the SetWindowLong function as demonstrated below:

// Associate the id '1234' with the control 'hWnd'
SetWindowLong(hWnd, GWL_ID, 1234);

Turning relative paths into full paths

Most file based APIs within Windows CE require absolute file paths which start at the root of the filesystem (i.e. we must specify “\path\to\some\file.txt” instead of “file.txt”).

If we want to use relative file paths within our application we must manually convert them into absolute paths before passing them to system APIs. The OS provides no concept of a current working directory.

To convert a path specified relative to the directory the application is installed in we can make use of the following helper routine.

void GetFullPathToFile(LPTSTR pszFullPath, LPCTSTR pszFilename)
{
  // Find the path to the current executable
  GetModuleFileName(GetModuleHandle(NULL),
    pszFullPath, MAX_PATH);
 
  // Strip off the exe filename and replace it with
  // the path provided by our second parameter.
  wcscpy(wcsrchr(pszFullPath, '\\') + 1, pszFilename);
}

The trick is to use the GetModuleHandle and GetModuleFileName APIs to determine the path of the current executable. Once this is found we can use string manipulation functions to remove the *.exe file name and replace it with the name of the file we expect to find in the same folder.

An example use of the function is shown below.

// Place the absolute path to "test.wav" into szPath
TCHAR szPath[MAX_MATH];
GetFullPathToFile(szPath, L"test.wav");

Playing sounds

Instead of using the SndPlaySync API I decided to use an older API called PlaySound. Unlike SndPlaySync the PlaySound API is available on devices prior to Windows Mobile 6, the disadvantage however is that it only supports *.wav files (refer to my blog post about “Making use of new APIs within older applications” for one technique to support the use of new APIs while still allowing limited functionality on older devices).

To play a sound effect we simply pass the full path to the required *.wav file to PlaySound along with a couple of flags.

// Start to asyncronously play a sound
LPCTSTR pszSoundEffect = _T("\\path\\to\\some.wav");
PlaySound(pszSoundEffect, NULL,
  SND_ASYNC | SND_FILENAME | SND_NODEFAULT);

This code snippet makes use of the SND_ASYNC flag. This means that the call to PlaySound does not block until the sound effect finishes playing. Instead the call returns immediately and the sound effect plays in the background.

Playing the sound effects asynchronously enables the user to interrupt the currently playing sound by selecting another sound effect. To stop any currently playing sound effects you can pass in NULL for the sound effect filename.

// Stop any currently playing sounds
PlaySound(NULL, NULL, SND_FILENAME);

Using Common Object Model (COM) objects

The early origins of the .NET runtime can be traced to the older COM and COM+ frameworks. As an example of this the commonly referenced mscorlib assembly at one stage stood for “Microsoft COM Object Runtime (COR) library“.

The Common Object Model (COM) framework can be considered to have many of the same design goals as the Common Language Runtime (CLR), such as the ability for objects written in various languages to interoperate with each other. The first step of using COM objects within an application is to initialise the framework by calling the CoInitializeEx API.

// Initilise the COM framework
CoInitializeEx(NULL, COINIT_MULTITHREADED);

Once we have initialised the COM runtime we can request objects to be created by calling the CoCreateInstance API, passing in the class id (CLSID) of the specific class we want to create an instance of. A CLSID is a unique GUID value which uniquely identifies a class. It enables the COM framework to lookup the registry to find details about how and where the class is implemented.

// Create an instance of the 'AAA" class and return a pointer
// to the newly created object in the pThingy variable
IAAA *pThingy = NULL;
CoCreateInstance(CLSID_AAA, NULL, CLSCTX_INPROC_SERVER,
  IID_IAAA, (void**)&pThingy);
 
  // ... use the object ...
 
// Release our reference to the object
pThingy->Release();

Unlike the CLR framework the COM framework does not implement garbage collection, instead it is a reference counted API. Each object has a counter associated with it. Whenever an object is passed to another section of code its reference counter should be increased via a call to the AddRef method. Likewise when a section of code finishes using an object it should decrement the reference counter by calling the Release method. If Release causes the reference counter to decrease to zero the object’s resources are automatically freed. AddRef and Release are both part of an interface called IUnknown.

Drawing PNGs

Previous applications in this series have utilised Windows Bitmap (*.bmp) formatted images. This application is different since the application includes PNG formatted images to display on the sound effect buttons.

Prior to Windows Mobile 5.0 there was no general purpose API to manipulate images compressed in common image formats such as JPEGs, PNGs or GIFs (although there were options such as SHLoadImageFile). Windows Mobile 5.0 introduced a COM based Imaging API that offers a large number of image codecs as well as image manipulation functionality.

One benefit of using this API with PNG files is the ability for it to keep alpha transparency information in order to draw non rectangular images over top of existing content. The following subroutine can be used to draw a PNG onto an existing GDI device context.

// Draw an alpha blended image on the device context 'hdc'
// within the rectangle defined by 'prcBounds'.
static BOOL DrawAlphaImage(HDC hDC, RECT * prcBounds,
                           WCHAR * pszImageFileName)
{
  // Create an instance of the ImagingFactory class
  IImagingFactory *pFactory = NULL;
  HRESULT hr = CoCreateInstance(CLSID_ImagingFactory, NULL,
      CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void**)&pFactory);
  if (hr == S_OK)
  {
    // Call the CreateImageFromFile method to load the image
    // into memory.
    IImage *pImage = NULL;
    hr = pFactory->CreateImageFromFile(pszImageFileName, &pImage);
    if (hr == S_OK)
    {
      // And finally draw the image onto the device context
      hr = pImage->Draw(hDC, prcBounds, NULL);
 
      // Free the COM objects
      pImage->Release();
      pImage = NULL;
    }
 
    pFactory->Release();
    pFactory = NULL;
  }
 
  return (hr == S_OK);
}

Parsing XML

This is the first application that has required the parsing of an XML document. For this we can use another COM based API, the Microsoft (MSXML) DOM Parser. The first step is to create an instance of the DOM Document class.

// Create an instance of the XML Document class
IXMLDOMDocument *pDoc = NULL;
HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL,
  CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pDoc);
if (hr == S_OK)
{
  // ... use the DOM document ...
}

Once we have an instance of the DOM document we can load an XML document into it by specifying the path to the XML file.

// Load the XML file
VARIANT_BOOL bSuccess = VARIANT_FALSE;
VARIANT filename;
 
VariantInit(&filename);
V_BSTR(&filename) = SysAllocString(L"\\path\\to\\doc.xml");
V_VT(&filename) = VT_BSTR;
 
hr = pDoc->load(filename, &bSuccess);
if (hr == S_OK && bSuccess == VARIANT_TRUE)
{
  // ... make use of the document ...
}

There is a small amount of complexity here due to the load method making use of the VARIANT datatype (essentially a strongly typed container which can hold data of various datatypes).

Once we have loaded the XML document into memory we can query against it in a number of ways, including selecting a set of nodes via an XPATH expression.

IXMLDOMNodeList *pNodes = NULL;
LONG len = 0;
BSTR xpath = SysAllocString(L"/MobileFX/SoundPack/Buttons");
 
// Execute an XPATH query to obtain the set of nodes
// which match the predicate
if (pDoc->selectNodes(xpath, &pNodes) == S_OK
  && pNodes->get_length(&len) == S_OK)
{
  // Then iterate over each of the nodes
  // returned
  for (LONG i = 0; i < len; i++)
  {
    // Fetch the next node
    IXMLDOMNode *pNode = NULL;
    if (pNodes->get_item(i, &pNode) == S_OK)
    {
      // ... process the node ...
 
      pNode->Release();
    }
  }
}
 
pNodes->Release();

Reading the contents of the XML configuration file enables us to glue together a number of the code snippets shown previously. For each button found in the XML document we can dynamically create a button control, draw the PNG based icon onto it and load the sound effect specified by a relative path.

Sample Project

[Download mobilefx.zip - 2.34 MB]

The sample application available for download can be a lot of fun. However there are a couple of activities left as exercises for the interested developer. These would make great learning experiences, for example:

  • Add a menu item that allows the user to switch between multiple sound pack XML configuration files.
  • Add scrolling so a sound pack XML configuration file with more than 16 sound effects can be scrolled through to access additional sound effects.
  • Modify the CreateTile function so the sound effect images do not need to be “pre-buttonized”? The round edges and glossy finish should be able to be applied over top of a standard rectangular image by making multiple calls to the DrawAlphaImage function. Take a look at a tool such as Axialis IconWorkshop for some inspiration, and if you have a copy of Visual Studio 2008 you can download a special version for free! The iPhone does a similar thing for application and website shortcut icons.

Making a CAB file which doesn’t prompt for installation location

December 11th, 2008

Screenshot showing application being installed on a Windows Mobile deviceWhen developing bespoke line of business applications it is common for your solution to require some form of hard reset recovery.

A common technique for implementing this is to package the application as a CAB file and then use a device specific technique to ensure that this file survives and automatically installs after a hard reset.

One problem you may come across in implementing this scenario is that a Smart Device CAB project created by Visual Studio will by default prompt the user to select where to install the application if one or more storage cards are present. This blog post covers one technique to remove this prompt when you want to reduce user interaction and need to hard-code the installation location of your application.

Finding an explanation

The first step towards finding a solution is to determine the reason why we are seeing the current behaviour. We can find an answer within the User Selected Installation section of the CAB Wizard documentation available on MSDN. This document states the following:

The user is prompted for the preferred installation volume only if the following two conditions are met:

  1. The application developer has created an %installdir% variable in the [CEStrings] section of the .inf file.
  2. The device has more than one storage volume available (such as a secondary MultiMedia card storage).

We obviously can not control the number of storage volumes present on a user’s device, but what is an *.inf file and how can we control the content of it’s [CEStrings] section?

Manually rebuilding a CAB file

The Smart Device CAB project type within Visual Studio is a simple GUI front end to a command line utility called CAB Wizard (cabwiz). When Visual Studio builds your project it takes the settings you have specified and behind the scenes generates a specially formatted text file (an *.inf file) which instructs the command line utility how to create your application’s CAB file.

Unfortunately for us the Visual Studio IDE always includes an %installdir% variable within the [CEStrings] section of the file it generates and there is no option that allows us to override this behaviour.

One possible work around to remove this variable is to allow Visual Studio to generate it’s *.inf file and then manually edit it and re-run the cabwiz utility by hand.

First we need to determine where the *.inf file is stored and the proper command line required to execute cabwiz.exe. This information can easily be found by looking at the Output Window of Visual Studio after you build your solution. Near the end of the log you should see a section that looks similar to the following:

------ Build started: Project: BespokeLOBApplicationCAB, Configuration: Debug ------
Building file 'C:\BespokeLOBApplicationCAB.cab'...
 
"C:\Program Files\Microsoft Visual Studio 9.0\smartdevices\sdk\sdktools\cabwiz.exe"
    "C:\Project\BespokeLOBApplicationCAB.inf"
    /dest "C:\Project\"
    /err CabWiz.log
 
Windows CE CAB Wizard

If you open the inf file specified in the above command line you should be able to find and then delete a line declaring the %installdir% variable (as highlighted in the screenshot below).

Screenshot showing the line which needs removed from the CAB's *.INF file

Once you have saved this change the last step is to open a MSDOS command prompt window and execute the command line discovered above to re-generate your CAB file. This new CAB file won’t prompt for an installation directory due to the lack of the %installdir% variable.

One thing to be aware of is that removing the %installdir% variable means placing files in the “Application Folder” directory within the File System Editor window will cause an error when you run cabwiz. Instead you should build up your directory structure by hand by right clicking in the file system editor and selecting the option to add new Custom Folders.

Sample Application

[Download BespokeLOBApplication.zip - 18.1KB]

A small sample application is available for download which demonstrates this technique. A “dummy” application called BespokeLOBApplication is packaged into a CAB file via a Smart Device CAB project.

Notice if you build the CAB via the Visual Studio interface that the user will be prompted to select an installation location even though every file specified in the filesystem editor is deployed to a hard-coded location.

If you then alter the CAB file using the technique outlined above the user will not be prompted to select an installation location during installation.

For your convenience the download also contains two pre-built cab files called BespokeLOB_Prompt.cab and BespokeLOB_NoPrompt.cab to demonstrate the principal.

One disadvantage of this technique is that manual edits to the *.inf file will be lost the next time you rebuild your project via Visual Studio. If the structure of your CAB file does not change that often one solution is to remove the Smart Device CAB project from your solution and instead build your CAB file by executing the command line discovered above via a custom Post Build step.

DNUG Meeting: How to wow your audience and still talk geek

October 12th, 2008
Photo of Bryce Saunders
Date: Tuesday 21st October 2008
Time: Gather at 5:30 pm, starting at 6:00 pm
Location: Canterbury Innovation Incubator
Presenter: Bryce Saunders

Every developer at one stage or another has to provide a technical presentation to their boss, or an important client. Being able to convey technical concepts in a clear and concise manor is a valuable skill to have.

Bryce intends to cover techniques to handle nervousness, ways to structure your presentation to convey your points, and how to look like a pro while doing it.

The presentation is also an ideal way to gain a confidence boost for those keen to give presenting a go at the Christchurch Code Camp in November (http://www.codecamp.net.nz).

Christchurch .NET Code Camp 2008

October 12th, 2008

Where will you be on the 1st of November? The answer if you are a .NET developer should be the Christchurch .NET Code Camp!

This is a chance to talk, socialise and connect with other developers within the local community. A wide range of presentations will be provided from 5 minute lightning talks to 1 hour hardcore technical deep dives. The theme this year is “keeping it real” with a real focus on discussing currently available tools and technologies in a way that you can immediately utilise within your own projects.

The event is free (with lunch provided) and runs from 9am to 6pm. For more details see http://www.codecamp.net.nz.

Call to action:

The Christchurch .NET Code Camp organisers would like to thank our current sponsors who have made this event possible.

Intergen Microsoft MVP Program
Trimble Navigation Altova
CodeSmith Tools ComponentSource
Typemock    

Intercept SMS messages

September 23rd, 2008

Screenshot of SMS Device Control sample applicationMany TV game shows use SMS text messages for viewer voting and other forms of participation. This blog post discusses how a Windows Mobile application can automatically respond to incoming SMS text messages to create such services.

Creating a Message Interceptor

The first step in catching received SMS text messages is to create an instance of the MessageInterceptor class that lives in the Microsoft.WindowsMobile.PocketOutlook assembly. You need to be careful about where you define this instance as if it goes out of scope and is garbage collected the message interception will stop.

MessageInterceptor interceptor =
  new MessageInterceptor(InterceptionAction.NotifyAndDelete);

An InterceptionAction is passed to the constructor. This parameter defines the behaviour which occurs when a message is received. The two options are:

  • Notify – The message interceptor gets a chance to process the message but it is also received by the standard SMS inbox application.
  • NotifyAndDelete – The message does not become visible to the user and is only seen by the message interceptor.

Specifying an interception condition

A message interceptor that processed and potentially deleted every message would not be very useful. You can define a message condition to reduce the number of messages caught by a message interceptor.

interceptor.MessageCondition = new MessageCondition(
  MessageProperty.Body, 
  MessagePropertyComparisonType.StartsWith, "CKF:");

A message condition describes a MessageProperty (such as text message body or sender’s phone number) that should be compared against a specific value. A MessagePropertyComparisionType (such as Contains, EndsWith, StartsWith, or Equal) defines how to perform the comparison.

Only SMS text messages that pass the comparison will be forwarded to the message interceptor. In the code sample above, our message interceptor will intercept any message that begins with the special prefix “CKF:”. Any SMS message that does not match this condition will be placed into the standard SMS inbox.

Transient Interceptors

Now that we have configured the message interceptor we can finally request that it listens for incoming SMS text messages. We do this by registering a MessageReceived event handler.

interceptor.MessageReceived += SmsInterceptor_MessageReceived;

When we no longer desire to listen to incoming SMS text messages we simply remove our event handler.

interceptor.MessageReceived -= SmsInterceptor_MessageReceived;

When the last event handler unhooks itself from the MessageReceived event the message interception process will be disabled.

While enabled any received text message will be passed to our MessageReceived event handler for processing.

void SmsInterceptor_MessageReceived(object sender, 
         MessageInterceptorEventArgs e)
{
  SmsMessage msg = e.Message as SmsMessage;
  if (msg != null)
  {
    // Process the SMS text message 
    ....
  }
}

Persistent Interceptors

One flaw of solely using the MessageReceived event is that if your application exits you will stop intercepting SMS messages.

If you need to continue to intercept messages while your application is shutdown you need to use a persistent message interceptor.

In order to enable persistent message interception you simply need to call the EnableApplicationLauncher method.

string appId = "ChrisTec-SmsDeviceControl";
interceptor.EnableApplicationLauncher(appId);

The appid parameter is a unique string which uniquely identifies this particular message interceptor. No two message interceptors should use the same value. Common suggestions are to use a randomly generated GUID or a string that contains a company or product specific prefix.

To disable persistent message interception you call a matching DisableApplicationLauncher method.

interceptor.DisableApplicationLauncher();

When an SMS that matches the specified message condition is received by the PDA and the application is not running the OS will automatically restart the application. As part of your application’s startup procedure you need to recreate a new MessageInterceptor instance.

The easiest way to create an instance with an identical configuration is to use an additional constructor overload that reads the values out of the registry location used to store the interceptor details while the application is not running.

if (MessageInterceptor.IsApplicationLauncherEnabled(appId))
{
  // Persistent message interceptor has been enabled, so
  // pick up the settings from the registry
  interceptor = new MessageInterceptor(appId);
}
else
{
  // A persistent message interceptor is not enabled, so
  // create a new instance and manually setup the
  // interceptor
  interceptor = new MessageInterceptor(...);
  interceptor.MessageCondition = new MessageCondition(...);
}

As demonstrated in the above code snippet, it is common to see start up code that makes use of the MessageInterceptor.IsApplicationLauncherEnabled method. This method checks if a persistent message interceptor is currently enabled, allowing the application to determine if it needs to register the application launcher or can simply pick up the pre-existing settings.

Sample Application

[Download SmsDeviceControl.zip - 10KB]

A sample application is available for download. The application demonstrates one possible way for a Windows Mobile application to respond to special SMS text messages.

Once the application is ran (and the enabled checkbox is checked) the application will respond to any SMS text message sent to the device that starts with the “CKF:” prefix.

The application parses the contents of the SMS messages it intercepts and interprets them as commands. The following three commands are currently understood:

  • GAME – launches the solitaire game on the PDA
  • HELLO – displays a message box on the PDA’s screen
  • MESSAGE your_message – displays your message on the PDA’s screen

For example an SMS text message containing the text “CKF: MESSAGE Hello World!” would cause the PDA’s screen to display the text “Hello World!”.

If you send an SMS text message with the CKF: prefix that isn’t one of the above commands the application will programatically send an error response message back to the sender.

As SMS text messages are processed you should note that the message counter increases. However if you exit the application and then send an additional text message the counter should restart at 1. This occurs since the counter is not persistent so it does not survive the application re-launch.

Sending SMS messages programatically

September 15th, 2008

Screenshot of Send SMS applicationWhen developing line of business applications for field service agents it can be handy to have the application send SMS text messages to alert customers of updated status information, such as the potential for the service agent to arrive late for an appointment. This blog post discusses how to send SMS text messages programatically via the .NET Compact Framework.

Supported Platforms

This blog post makes use of classes within the Microsoft.WindowsMobile.PocketOutlook assembly. This assembly is not part of the .NET Compact Framework, instead it is shipped as part of the Windows Mobile operating system.

The assembly was first introduced as part of Windows Mobile 5.0. If you need to send SMS messages from a Windows Mobile 2003 device you will need to utilise a third party component such as the Mobile In The Hand product (which provides a compatible interface) or manually wrap the underlying native APIs.

In order for the demos in this blog post to work you need to add references to the following two assemblies:

If you forget the reference to the Microsoft.WindowsMobile assembly you will get the following compile time error:

The type ‘Microsoft.WindowsMobile.IApplicationLauncher’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘Microsoft.WindowsMobile, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′.

Creating an SMS Message

To create a new SMS text message you need to create an instance of the SmsMessage class and then set its various properties.

using Microsoft.WindowsMobile.PocketOutlook;
 
SmsMessage message = new SmsMessage();
message.To.Add(new Recipient("Jane Doe", "+1 45 123456"));
message.Body = "Would you like to go to lunch?";

The Body property is a string which contains the message you want to send. Notice that the To property is a collection of recipients, so a single SMS can be addressed to one or more recipients.

There is even a constructor overload which helps with the common case of a simple message intended for a single recipient:

SmsMessage message = new SmsMessage("+1 45 123456",
  "Would you like to go to lunch?");

Sending an SMS Message

Once we have created the SMS message we need a way to cause it to be sent. There are a couple of ways to achieve this.

The easiest is to call the send method on the SmsMessage instance as shown below:

// Send the SMS to its recipient(s)
message.Send();

Calling the send method sends the SMS message behind the scenes with no visual indication that something is occurring.

Alternatively if you would like to give the user a chance to review and edit the contents of the message before it is sent you can display the message within the built in messaging application via the MessagingApplication.DisplayComposeForm method.

// Display the new SMS in the standard
// messaging application
MessagingApplication.DisplayComposeForm(message);

The third and final way is to create an instance of the OutlookSession class and use it’s SmsAccount property as follows:

using (OutlookSession session = new OutlookSession())
{
  session.SmsAccount.Send(message);
}

Testing within an Emulator


The Windows Mobile 6 SDK introduced a Cellular Emulator tool which makes it easy to test applications which interact with cellular phone based functionality. One advantage of using this tool to test SMS sending applications is that it avoids the charges typically associated with sending SMS messages via real devices.

You can find the Cellular Emulator within your desktop’s Windows start menu. The first step in using the Cellular Emulator is to connect it to your device emulator. This can be achieved by following the Cellular Emulator Quick Start instructions available on MSDN.

If you need further assistance configuring the Cellular Emulator, Jim Wilson has created a great video titled “How Do I: Configure the Device Emulator to Use an Emulated Cellular Connection?“.

Once correctly configured you can switch to the SMS tab of the Cellular Emulator to send messages to, or view messages received from the device emulator.

Screenshot of SMS tab within the Cellular Emulator application

Demo Application

[Download sendsms.zip - 9KB]

A small example application is available for download which demonstrates how to send SMS messages programatically. It displays a simple form to capture the desired message and recipient phone number and then demonstrates a few techniques for sending the message.

Of note is a checkbox which makes the program append onto the end of the user’s message the current battery charge status. This is a lead into the next blog post which will discuss how to programmatically respond to a Windows Mobile device receiving a SMS text message.

30 Days of Windows Mobile – Day 06: Pocket PasswordGen

September 11th, 2008

Screenshot of PasswordGen applicationIf you are like me you will have access to a number of password protected online services. Each time I am requested to change my password for one of these services, I struggle to come up with a unique yet strong password.

The following application is designed to make the process of creating new passwords much easier. It allows the user to specify the allowable types of characters in their password and optionally shows the password in a phonetic form to make it easier to remember, or quote over a phone.

Defining a datastructure

The first challenge with this application was to determine how to store the required lookup data. For each character that could be used in the generated password we must be able to determine its equivalent phonetic form. This can be represented by the following data structure:

typedef struct {
  TCHAR character;
  LPCTSTR phonetic;
} PhoneticLetter;

We can construct an array of PhoneticLetter entries for each character category that the user can select to include in the generated password.

// Define a lookup table for lower case letters
static PhoneticLetter gbl_lowerCase[] = {
  { 'a', _T("Alpha") },
  { 'b', _T("Bravo") },
  ...
  { 'z', _T("Zulu") }
};

Helper functions can then be written to randomly select letters from these arrays and to convert between character and phonetic forms.

Generating cryptographic strength numbers

In order to generate unique passwords we need a way to pick a character at random. Using a cryptographic strength random number generator is an ideal technique since any weakness in our random number generation algorithm could be used to exploit the passwords we generate.

By using the Windows Cryptographic APIs we can produce a stream of cryptographic strength random numbers. To do this we need to include the wincrypt.h header file and then call the CryptGenRandom function as shown below:

DWORD dwRandomSeed;
HCRYPTPROV hCrypt;
 
// Acquire the cryptographic context	
if (CryptAcquireContext(&hCrypt, NULL, NULL, PROV_RSA_FULL,
                          CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
{
  // Generate some random bytes.
  // Second parameter is number of bytes to generate
  // Third parameter is where to store generated bytes
  if (CryptGenRandom(hCrypt,
           sizeof(dwRandomSeed),
           (BYTE*)&dwRandomSeed))
  {
    // dwRandomSeed contains a random value
  }
 
  CryptReleaseContext(hCrypt, 0);
}

CryptGenRandom is designed to generate an arbitrary amount of random data. By passing in a DWORD for the third parameter we’ll get 32bits (4 bytes) worth of random data.

Changing Fonts

By default controls within a dialog will utilise the standard dialog font. From the screenshot above you will notice that the “Password” label is slightly larger and bolder than the other labels.

To change the font used by a specific control we can send it the desired font via a WM_SETFONT window message. The following example uses the CreateFontIndirect function to create a new font and then sends it to the password label control via a WM_SETFONT message.

// Create a new font by filling out a LOGFONT
// structure with the desired style details
// and calling CreateFontIndirect
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT));
HDC hdc = GetDC(NULL);
lf.lfHeight = -9 * GetDeviceCaps(hdc, LOGPIXELSY) / 72;
ReleaseDC(NULL, hdc);
lf.lfWeight = FW_BOLD;
HFONT hFont = CreateFontIndirect(&lf);
 
// Pass the font to the control via
// the WM_SETFONT message
SendDlgItemMessage(hDlg, IDC_LABEL_PASSWORD,
  WM_SETFONT, (WPARAM)hFont, 0);

Using Checkboxes

Just like radio buttons, a checkbox is another form of button control. You can send the BM_GETCHECK window message to a checkbox to determine it’s current state as shown below:

HWND hWndCtrl = GetDlgItem(hDlg, IDC_CHECKBOX1);
if (SendMessage(hWndCtrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
{
   // the checkbox is checked
}

Interacting with the Clipboard

You might be using your PDA’s webbrowser to create an account for an online service. Rather than manually retyping the newly generated password, it may be easier to copy and paste it between applications.

As discussed in a previous blog post adding a SIPPREF control to a dialog will automatically provide a cut/copy/paste popup menu.

To programatically copy something to the clipboard we need to open the clipboard via a call to the OpenClipboard function.

if (OpenClipboard(NULL))
 
{
  ... do something with the clipboard ...
 
  CloseClipboard();
}

Once the clipboard is opened you then can call functions such as EmptyClipboard or SetClipboardData to alter with the contents of the clipboard buffer.

Sample Application

[Download pocketpasswordgen.zip - 61KB]

The C++ source code and a CAB file for this sample application can be downloaded. If you have any questions about the source code or would like to discuss native Windows Mobile development further please leave a comment on this blog entry.

30 Days of Windows Mobile – Day 05: Mobile Capture

September 8th, 2008

Screenshot of Mobile Capture applicationAfter a long hiatus I am back into blogging while I convert Chris Craft’s 30 Days of Windows Mobile demo applications into native C.

The next application in the series is a screen capture utility that runs directly on a Windows Mobile based PDA.

It has a ton of features and is ideal for capturing screenshots for user manuals etc. Once the settings have been configured the application will minimise itself and stay out of sight. A sound effect plays when a screenshot is captured and the file can then be found in the root directory of the device.

Creating numeric up-down controls

An up-down control is a pair of arrow buttons that can be associated with an edit control to allow the user to adjust the value without needing to use the keyboard.

To set the allowable range and current value of an up-down control you can send it the UDM_SETRANGE32 and UDM_SETPOS window messages as demonstrated in the following example.

// Set the range of the spinbox to 1 to 60
// and the current value to 10
SendDlgItemMessage(hDlg, IDC_SPIN_DELAYTIMER,  
  UDM_SETRANGE32, 1, 60);
SendDlgItemMessage(hDlg, IDC_SPIN_DELAYTIMER, 
  UDM_SETPOS, MAKELPARAM(10, 0));

The easiest way to associate an up-down control with an edit control is to place it immediately after the edit control in the dialog tab order and then specify the UDS_AUTOBUDDY and UDS_ALIGNRIGHT window styles. The UDS_ALIGNRIGHT window style means the up-down control will automatically resize and move to sit on the right edge of the edit control. While UDS_AUTOBUDDYINT means changing the up-down control’s value will automatically update the text within the edit control.

Using Radio Buttons

When clicked radio buttons send a standard WM_COMMAND window message just like a regular button. You can also determine a radio button’s current state be sending it the BM_GETCHECK window message as shown below:

if (SendDlgItemMessage(hDlg, IDC_CHECKBOX, BM_GETCHECK, 0, 0)
  == BST_CHECKED)
{
  // do something if the radio button is checked
}

To group a number of radio buttons together and make them mutually exclusive, they should be placed consecutively in the dialog’s tab order and then the first one should have the WS_GROUP window style set.

Capturing Hardware Buttons

One mode of this application starts the screen capture process when a specified hardware button is pressed.

To override the default behaviour of a hardware button and use it for an application specific purpose we can make use of the RegisterHotKey function:

// Register the VK_APP1 (typically Contacts)
// button as a hotkey for our dialog.
RegisterHotKey(hDlg, 1234, MOD_WIN, VK_APP1);

You can refer to the Windows Mobile documentation for a list of standard hardware button key codes suitable for registration.

When we are finished with a hardware button and want to return it to its default behaviour we can call the matching UnregisterHotKey function:

UnregisterHotKey(hDlg, 1234);

While the hotkey is registered the dialog will be sent WM_HOTKEY window messages whenever the hardware button is pressed. The unique id value we passed to the RegisterHotKey function is provided to us to help determine which hotkey was pressed in case we register more than one.

case WM_HOTKEY:
  if (wParam == 1234)
  {
    // hotkey button has been pressed
  }
  break;

Finding Hardware Buttons

Although we could hardcode the combobox list of available hardware buttons, it is better to query the device for this list, as the number of available buttons can vary between devices.

We can query the HKLM\Software\Microsoft\Shell\Keys registry key to find a list of available hardware buttons.

It is of interest to note that many buttons will be listed twice. Many buttons can have a different behaviour associated with them depending upon if they are held down for a short or long period of time.

Taking a screenshot

Calling the GetDC function and passing in the special HWND_DESKTOP value obtains a device context for the entire screen. A device context is roughly analogous to a managed System.Drawing.Graphics instance.

By using the BitBlt function we can copy the bitmap data associated with a rectangular region of one device context into another.

The CreateCompatibleDC and CreateCompatibleBtmap functions can be utilised to create an offscreen bitmap and associated device context suitable for storing the screenshot.

// Save a rectangular area of the screen
// specified by "pRect" to a file specified by "pszFilename".
void Snapshot(WCHAR *pszFilename, RECT *pRect)
{
  HDC hdcSrc = GetDC(HWND_DESKTOP);
 
  // Create a new bitmap of the required size and a device
  // context to allow us to draw onto it.
  int width = pRect->right - pRect->left;
  int height = pRect->bottom - pRect->top;
 
  HDC hdcDest = CreateCompatibleDC(hdcSrc);
  HBITMAP hbmp = CreateCompatibleBitmap(hdcSrc, width, height);
  SelectObject(hdcDest, hbmp);
 
  // Blit (copy) from the source device context (the screen)
  // to the device context that is associated with our
  // offscreen bitmap buffer.
  BitBlt(hdcDest, 0, 0, width, height,
    hdcSrc, pRect->left, pRect->top, SRCCOPY);
 
  // Finally save our bitmap to disk
  SaveBitmap(pszFilename, hdcDest, hbmp);
 
  // Free the resources
  DeleteDC(hdcDest);
  DeleteObject(hbmp);
 
  ReleaseDC(HWND_DESKTOP, hdcSrc);
}

Saving a bitmap to file

As discussed by Chris Tacke there are two types of bitmap objects. Device Dependant Bitmaps (DDBs) and Device Independent Bitmaps (DIBs). A bitmap file is basically the raw pixel data of a DIB written to disk with BITMAPFILEHEADER and BITMAPINFOHEADER headers attached to describe the format of the data.

Within the source code available for download there is a small function called SaveBitmap which accepts an HBITMAP and saves the contents to a file.

Sample Application

[Download mobilecapture.zip - 68KB]

The C++ source code and a CAB file for this sample application can be downloaded. If you have any questions about the source code or would like to discuss native Windows Mobile development further please leave a comment on this blog entry.

DNUG Meeting: Kapow! Become a Visual Studio 2008 super hero!

August 28th, 2008
Photo of Kirk Jackson
Date: Wednesday 10th September 2008
Time: Gather at 5:30 pm, starting at 6:00 pm
Location: Canterbury Innovation Incubator
Presenter: Kirk Jackson

Bap! Impress your colleagues and improve your performance by unleashing the power of Visual Studio.

Fresh from presenting at TechED Kirk will look at new keyboard shortcuts, new options, the powerful ‘Quick Command’ system, macros, tweaking IDE performance, and more that will make any developer using Visual Studio instantly more productive.

The entire session is hands-on inside the IDE and applicable to any language, including Microsoft Visual Basic, Visual C#, and Visual C++. If you’ve been using Microsoft Visual Studio 2005 or have never touched Visual Studio, you’re guaranteed to walk away a VS power user.