Windows Mobile Widget 101 – Handling Form Factors

Windows Mobile Widget 101 – Handling Form Factors

So far in this series I’ve covered Getting Started, generating Start Menu Icons and a Gadget Side Note, all with a single static page that will generally display ok on all devices. However, when you get into building more complex widgets and testing on different devices you will notice that what works on higher resolution devices (Eg the HTC Diamond 2 or the HTC HD2) won’t look good on a smaller device (Eg HTC Snap). Whilst you may be thinking “Oh goodness, please don’t tell me we have to handle all the different resolutions differently,” the good news is that for the most part you only really need to worry about two classifications “high res” and “low res” devices.  Devices are typically divided into those with a width >=480 (high res) and those with a width<480 (low res).

The easiest way to change the way your widget displays for different resolutions is to use different css files to determine the style of each element. Our widget doesn’t currently use a css file, so lets add two css files in order to handle high and low resolution displays. Actually, while we’re at it we’ll include a gadget.css file which we will use in order to specify the height/width properties that were manually added to the Main.htm file in the previous post. Put all of these css files into a css folder to keep your project tidy.

In order to dynamically set the correct css file we’ll need to write some javascript. We’ll actually add two javascript files, one called main.js which will do most of the user interaction logic and one called widget.js which will contain most of the widget specific logic (the idea being that this file can be reused amongst your widgets). Again, put these files into a js folder within your project.

The last files we’re going to include are two background images, one for high res and one for low res.  In this case the files are background.png (480×328) and background_lowres.png (240×164) in the images folder. With all these files added the build files list should look like:

—————–
files.txt
—————–

config.xml
Main.htm
icon.ico
icon.png
js*.js
css*.css
images*.png

—————–
gadget_files.txt
—————–

gadget.xml
Main.htm
icon.png
js*.js
css*.css
images*.png

In this case the only difference between the high and low resolution layouts is that it’s going to use a different background image. This makes the css files relatively simple:

—————– 
highres.css
—————–

body
{
    background: transparent url(‘../images/background.png’) no-repeat center top;
}

—————– 
lowres.css
—————–

body
{
    background: transparent url(‘../images/background_lowres.png’) no-repeat center top;
}

—————– 
gadget.css
—————–

body
{
    height:200px;
    width:200px;
    border:1px solid #000000;
}

Note that the gadget.css doesn’t specify the background – instead of having a third layout we are going to combine the highres.css and the gadget.css values. This means that the gadget.css only needs to contain values that are unique to the gadget layout. You could take this approach with the low res display as well but given that most elements/class styles will change between high and low res it’s probably easier to manage as two unique layouts.

Ideally we want to specify the style sheet as early as possible in the initial loading/rendering of the widget.  This is done by hooking into the onLoad event of the body element in Main.htm. Note that you also need to include references to the javascript files:

—————– 
Main.htm
—————–

<html >http://www.w3.org/1999/xhtml">
    <head>
        <title>Hello Widget</title>
        <!– Javascript –>
        <script type="text/javascript" src="js/widget.js"></script>
        <script type="text/javascript" src="js/main.js"></script>
    </head>
    <body onload="onLoad();">
        Hello Widget World!
    </body>
</html>

In the onLoad event we simply need to determine whether the widget is running on a high or low res device and load the appropriate css files:

—————– 
Main.js
—————–

/****** Constants ******/
var HighResCss = "css\highres.css";
var LowResCss = "css\lowres.css";
var GadgetCss = "css\gadget.css";

/****** Variables ******/
var isGadget = false;

/********************************************************************
This is the entry point to Widget code.
*********************************************************************/
function onLoad() {
    // Determine if this is running as a gadget (true if System.Gadget is defined)
    if (typeof System != "undefined" && typeof System.Gadget != "undefined") {
        isGadget = true;
    }

    if (WidgetAPI.isHighResolution() == true) {
        WidgetAPI.applyCssFile(HighResCss);
    }
    else {
        WidgetAPI.applyCssFile(LowResCss);
    }

    if (isGadget == true) {
        WidgetAPI.applyCssFile(GadgetCss);
    }
}

And we of course need to implement the WidgetAPI functions in the widget.js file.  Note that to avoid confusion we create a WidgetAPI object rather than the existing window.widget object.

—————– 
Widget.js
—————–

var WidgetAPI = function () {
    return {
        // returns true or false to indicate if widget is running on a high resolution device or not
        isHighResolution: function () {
            return this.getClientWidth() >= 480;
        },

        // gets the widget’s client width
        getClientWidth: function () {
            return (document.documentElement.clientWidth==0) ? document.body.clientWidth : document.documentElement.clientWidth;
        },

        // apply css file
        applyCssFile: function (cssFileName) {
            if (typeof(cssFileName)!="undefined" && cssFileName!=null) {
                var cssNode = document.createElement(‘link’);
                if (cssNode) {
                    cssNode.setAttribute(‘rel’, ‘stylesheet’);
                    cssNode.setAttribute(‘type’, ‘text/css’);
                    cssNode.setAttribute(‘href’, cssFileName);
                    document.getElementsByTagName(‘head’)[0].appendChild(cssNode);
                }
            }
        }
    };
} ();

Running this gives the following displays: Widget (high res), Widget (low res) and Gadget

 image image

image

Note: After you have installed your widget on a device you don’t need to reinstall or upgrade your widget every time you want to see your updates.  Instead you can locate where your widget has been extracted to on the device and simply copy across the files that have changed.  For example the widget is currently extracted to Program FilesWidgetsUser17 so when I make changes, say to Main.htm, I just copy that file across to this folder. Then I just need to exit and restart the widget to see the changes take effect.

Windows Mobile Widget 101 – A Gadget Side Note

Windows Mobile Widget 101 – A Gadget Side Note

As I’ve mentioned in a previous post it is quite easy to take your Windows Mobile widget and convert it into a Windows Vista/Windows 7 gadget. In this post I’ll take the Hello World widget I built in the Getting Started and Start Menu Icons posts and walk through converting it into a gadget.

Gadgets are almost identical in structure to widgets, with one exception. Instead of a config.xml manifest file, gadgets use a gadget.xml file. So, the first step in converting your widget is to add a gadget.xml file to your project. Here is a sample file that mirrors the information I used in the config.xml file for the widget.

—————–
gadget.xml
—————–

<?xml version="1.0" encoding="utf-8" ?>
<gadget>
  <name>Hello Gadget World</name>
  <namespace>
http://www.builttoroam.com/hellogadgetworld</namespace>
  <version>0.1.0.0</version>
  <author name="Built to Roam">
    <info url="
http://www.builttoroam.com" text="Built to Roam" />
    <logo src="icon.png" />
  </author>

  <copyright>Copyright (c) 2009 Built to Roam.  All rights reserved.</copyright>
  <description>This is a sample gadget that says Hi to the world!</description>
  <icons>
    <icon width="90" height="90" src="icon.png" />
  </icons>
  <hosts>
    <host name="sidebar">
      <base type="HTML" apiVersion="1.0.0" src="Main.htm" />
      <permissions>full</permissions>
      <platform minPlatformVersion="0.3" />
    </host>
  </hosts>
</gadget>

Of course, you now need to modify your build to include this file. Now you have two options here, you can either build a single compressed file and simply change the extension between .widget and .gadget depending how you want to use it. Alternatively you can make your build slightly more intelligent:

—————–
Build.bat
—————–

cd .HelloWorld
del ..helloworld.widget /Q
..7za.exe a -tzip ..helloworld.widget -r0 @..files.txt
copy ..helloworld.widget ..helloworld.widget.zip

cd .HelloWorld
del ..helloworld.gadget /Q
..7za.exe a -tzip ..helloworld.gadget -r0 @..gadget_files.txt
copy ..helloworld.gadget ..helloworld.gadget.zip
pause

This build file now makes use of a file called gadget_files.txt which contains the file specific to building the gadget (ie includes gadget.xml and not config.xml).

—————–
gadget_files.txt
—————–

gadget.xml
Main.htm
icon.png

You can now run the build batch and it will generate a .gadget file.  Double-click this file under Windows Vista or Windows 7 and it will install and run your gadget.  Unfortunately you’re likely to see something like the following:

image

This happens because the gadget dynamically sizes to fit the content, which means that if you don’t specify a height or width for the gadget you get very minimal space allocated to it. This is simply fixed by adding size information to the body tag of the Main.htm file.

<body style="height:200px;width:200px;border:1px solid #000000">

Now if you build and run (ie double-click on the gadget file) the gadget you will see the following:

image

And there you have it – your widget is running as a gadget.  Now there are some additional features of gadgets that we aren’t using here but I’ll come back to them as we get into adding more functionality to the widget.

Windows Mobile Widget 101 – Start Menu Icons

Windows Mobile Widget 101 – Start Menu Icons

In my previous post on Getting Started with widgets I showed how easily you can create a Windows Mobile widget. However, what you would have noticed when you installed the widget is that it uses the default widget icon both during installation and on the start menu (see below). Whilst it’s not a bad icon, it doesn’t advertise your application or company brand. As such it’s recommended that you supply your own icon.


image image


 


To do this you need to supply an icon file in two formats. For Windows Mobile Professional devices (ie touch screens) you need to supply a 90×90 png image. For Windows Mobile standard you need to supply an ico file that includes images at 44×44, 22×22 at both 32 and 8 bit colour.


Here’s the step by step instructions for creating and including icons for your widget.



  • Start with a regular image and use a image editing tool to resize the image to 90×90.  I typically use Paint.NET which is a free tool that supports a wide range of image formats. If your image isn’t square you will need to crop/resize the image canvas to make it square.

  • With the image resized, simply save it as a png file, icon.png, into the same folder as you widget config.xml file.

Logo 90x90


(note that the black background indicates that the transparent area of the image – use transparency where possible so that you can see the background of the start menu behind your application icon)



  • Next, to build the ico file you will need to scale your icon to the different formats required to be contained within the ico file. For this I use another free tool, IcoFX.


    • Open IcoFX

    • Insert the original 90×90 image: File > Import Image, select your image, specify the size and resolution to import the image at.  I recommend importing the original at the original size (ie 90×90).  Doing this will not affect how it renders on the device since ico files can contain images at any resolution.


image




    • Next, add new images for each desired size and bit depth: Icon > New Image, specify size and bit depth.


image




    • Repeat for 44×44 32 bit, 44×44 8 bit, 22×22 32 bit, 22×22 8 bit.

    • Save the created ico as icon.ico in the same folder as your config.xml file.

  • The last thing to do is to update both the config.xml file and your build files list to include the icon files.


—————–
config.xml
—————–


<?xml version=”1.0″ encoding=”utf-8″ ?>
<widget http://www.w3.org/ns/widgets%22″ mce_href=’http://www.w3.org/ns/widgets”‘>http://www.w3.org/ns/widgets”
        id=”http://www.builttoroam.com/hellowidgetworld”
        version=”0.1″>
  <name>Hello Widget World</name>
  <icon src=”icon.png” />
  <icon src=”icon.ico” />
  <description>This is a sample widget that says Hi to the world!</description>
  <author href=”http://www.builttoroam.com” email=”[email protected]”>
    Built to Roam Widget Development Team
  </author>
  <content src=”Main.htm” type=”text/html”/>
</widget>



—————–
Files.txt
—————–


config.xml
Main.htm
icon.ico
icon.png


Now when you run your build batch script and then install the widget on your device you will see your icon displayed both during installation and on the start menu.


image image


Notes:



1) The widget installation screen is not displayed during installation when the widget is downloaded from marketplace. As this is the only sanctioned way to distribute widgets to a Windows Mobile device you don’t need to worry too much about getting the installation screens perfect.


2) If you include both a png and ico file in your widget (and specified in the config.xml file) you will notice that no image is displayed during installation on Windows Mobile standard.  This is a known bug but given that this isn’t displayed to the end user (see 1 above) this shouldn’t be an issue.

Windows Mobile Widget 101 – Getting Started

Windows Mobile Widget 101 – Getting Started

Over the past month or so I’ve been working on a number of projects involving Windows Mobile Widgets.  If you aren’t familiar with widgets they are essentially a mini-application published as a zip file containing html, js, css and images.  They are similar to Windows Vista/7 gadgets; in fact so much so that you can use exactly the same code to produce both a widget and desktop gadget. In this post I’ll go through creating a basic widget, including a couple of tricks that can help you build and debug your widgets.

We will of course start off with the canonical Hello World widget and for the most part I’m going to be working in Visual Studio 2010.  That’s right, you can build and debug* your widgets from within Visual Studio 2010, which makes it the only form of Windows Mobile development you can currently do with the beta.

Let’s start by building up the necessary project structure for your widget. From the File menu, select New –> Web Site, then select the Empty Web Site project template from under either the C# or VB node.  Since you are going to be writing javascript it doesn’t matter what language you select. By default this will create a new project with just a web.config file – this file is not required for your Windows Mobile widget but does enable desktop debugging so leave it in the project. Next, add a new HTML document to your project (Add New Item –> C#/VB –> HTML Page).  I typically call this Main.htm as you normally only have a single htm page within your widget that contains all the markup for your widget but the name isn’t important. Modify the html to include a title and some content between the body tags.  For example:

<html >http://www.w3.org/1999/xhtml">
   <head>
      <title>Hello Widget</title>
   </head>
   <body>
      Hello Widget World!
   </body>
</html>

When you install your widget the installer needs to locate the main html page of your widget, along with other information about your widget such as the author, title and description of the widget.  This is located in a config.xml file. Add a new xml file called config.xml to your project (Add New Item –> C#/VB –> XML File) – the name of this file is important. Add, and then modify to suit yourself, the following to the config.xml file.

<?xml version="1.0" encoding="utf-8" ?>
<widget >http://www.w3.org/ns/widgets"
        id="http://www.builttoroam.com/hellowidgetworld"
        version="0.1">
   <name>Hello Widget World</name>
   <description>This is a sample widget that says Hi to the world!</description>
   <author href="
http://www.builttoroam.com" email="[email protected]">
      Built to Roam Widget Development Team
   </author>
   <content src="Main.htm" type="text/html"/>
</widget>

You now have the minimum requirements for a Windows Mobile widget. If you press F5 to run this project in Visual Studio you will see the Main.htm web page display (if not, you may have to navigate to this page, or Set [it] as Start Page. To run your widget on a device (or emulator) there are a few more steps involved.

The first thing you need to do is to actually zip up your widget project into a .widget file.  This is essentially just a zip file, renamed with the .widget extension. As you don’t want to be doing this manually every time you make a change I created a simple batch file (yeh I know, super old school) that simply calls 7zip (free download) to zip up the relevant files.

—————–
Build.bat
—————–

cd .HelloWorld
del ..helloworld.widget /Q
..7za.exe a -tzip ..helloworld.widget -r0 @..files.txt
copy ..helloworld.widget ..helloworld.widget.zip
pause

Place this batch file in the parent folder of your Hello World widget – you don’t want to mess up your project folder with build files.  You need to download and copy the 7zip executable into this folder and you need to create a file called files.txt – this contains a list of files to include in your widget.

—————–
Files.txt
—————–

config.xml
Main.htm

Running this batch file will create two output files: helloworld.widget and helloworld.widget.zip.  The former is a .widget file that you can copy to your device and click on to install.  The latter is created just in case you want to inspect the zip file to ensure all the right files are being packaged – there is nothing worse than trying to track down a javascript issue, only to discover one of the files isn’t being correctly added to the package.

Ok, so down to business, lets get this widget to run on the emulator/device.  If you are using an emulator then you can simply cradle the emulator using WMDC, copy the file across to the device using File Explorer and then click on the copied file to run the widget installer.  This will automatically run the widget when installation is complete.  If you want to run your widget on a real device there are some additional steps. By default the widget installer is not associated with the .widget file extension.  In order to get your widget to install by clicking on it, you need to create this association by modifying the registry on the device to include the following values:

[HKEY_CLASSES_ROOTriapp] "EditFlags"=dword:00010000

[HKEY_CLASSES_ROOTriappShellOpenCommand] @="wmwidgetinstaller.exe %1"

You can do this using either Remote Registry Editor (external tool that ships with Visual Studio 2008), Pocket Controller PC or another third party registry editing tool.  Note that on most devices the HKEY_CLASSES_ROOTriapp key already exists but the HKEY_CLASSES_ROOTriappShellOpenCommand key will need to be created.  Also note that the @ in the second line corresponds to the “default” value for the key – this means that depending on your editing tool you should either leave the name component empty or use the word Default.

Once you have added these registry keys to your device, clicking on the .widget file should run the installer – if not, it is likely that the registry keys are not correct, or that the wmwidgetinstaller.exe executable can’t be located. Again, once installation is complete your widget should automatically run displaying similar to the following:

image

Note that the Title in the Main.htm file is used to populate the widget title bar and that the default Exit button and menu has been created.

Creating your first widget is as simple as that. In fact you could submit this widget, in its current form to Windows Mobile Marketplace as it conforms to all the necessary requirements for certification.

 

 

*Build and Debug is limited to desktop debugging only. You still need to deploy to an emulator and/or a real device in order to ensure your widget is going to work correctly.