Creating a Pocket PC Today Screen Plug-in with the .NET Compact Framework

 

Jim Wilson
JW Hedgehog, Inc.

December, 2003

Applies to: **
   **Microsoft® .NET Compact Framework 1.0
   Microsoft Visual Studio® .NET 2003
   Microsoft eMbedded Visual C++® 3.0

Download sample

Summary: The Pocket PC Today Screen is a great way to display summary information that's easily viewed and readily accessible. By default, the Pocket PC automatically displays a summary of appointments, messages and tasks on the Today Screen. (17 printed pages)

Contents

Introduction
Using the Today Screen Plug-in Host
    Building the Today Screen Plug-in Host
    Installing the Plug-in Host Components
        Desktop Installation
        Device Installation
    Creating a Today Screen Plug-in
        The Basics
        Installing the Today Screen Plug-in
        More Involved Scenarios
TaskVision Sample
    The TaskVision Initialization Project
    The Task View Execution Project
    The PocketVisionUtil Project
Architecture
    Components
    Configuration
    Communication
    Project Wizard
Conclusion

Introduction

The Pocket PC Today Screen is a great way to display summary information that's easily viewed and readily accessible. By default, the Pocket PC automatically displays a summary of appointments, messages and tasks on the Today Screen as shown in Figure 1. Tapping an item then launches the application associated with that item.

Figure 1. The Default Pocket PC Today Screen.

The user convenience of the Today Screen makes it a valuable part of any application that needs to display summary data to the user and allow the user to easily access the application that manages the associated details. Unfortunately, the current Pocket PC API requires that Today Screen plug-ins be implemented as Windows DLLs with standard exported entry points. This requirement has historically made creating Today Screen plug-ins difficult as one has had to use Embedded Visual C++ (eVC).

Creating Today Screen plug-ins with the .NET Compact Framework is not possible as .NET Compact Framework DLLs can only contain .NET components. They cannot expose standard Windows DLL entry points.

The ".NETCF Today Screen Plug-in Host" overcomes this limitation. The Plug-in host is a combination of eVC components, .NET Compact Framework components, a .NET Compact Framework executable and a Visual Studio .NET custom project wizard. Together these pieces enable the creation of a custom Today Screen item by creating an initialization ("Init") .NET component to set the initial content of the Today Screen item and an executable ("Exec") application that can interact with the user and update the Today Screen content.

The unmanaged plug-in hosts an HTML window allowing each project to specify the HTML content to appear in the Today Screen. The "Init" project is automatically loaded when the new item is first added to the Today screen. This component need only return the HTML that should initially be displayed in the Today Screen. When the Today Screen content for this item is tapped, the "Exec" project is launched providing a user interface for the user to interact with the associated information. This program can also update the displayed HTML.

Using the Today Screen Plug-in Host

To use the ".NETCF Today Screen Plug-in Host", you must download and install the sample. Once downloaded, you'll need to build and install the support components and programs. All projects can be found in the Support sub-folder of the Plug-in host installation folder. For simplicity all of the eVC support projects are contained within a single workspace, TodayScreenSupport_UnManaged . The managed projects are contained within a single Visual Studio .NET solution, TodayScreenSupport_Managed.

Building the Today Screen Plug-in Host

To build the support pieces, do the following.

Note   The tasks must be performed in the order specified as there are some dependencies between the eVC and VS.NET projects.

  1. Download and install the Today Screen sample. This will install the source code for all Plug-in projects. See the Architecture section for the details of each project.
  2. Open the TodayScreenSupport_UnManaged workspace in eVC.
  3. Perform a Release build of both the TodayScreenDataMgr and TodayScreenPlugin_NETCFHost projects. To target actual Pocket PCs and the emulator perform both an Arm Release build and an X86 Release build.

Note   Be sure that all Library and Include folders reference the folders associated with the Pocket PC 2002 or 2003 SDKs. You can check the eVC folder settings by choosing Tools/Options and then selecting the "Directories" tab.

  1. Open the TodayScreenSupport_Managed solution in VS.NET.
  2. Perform a Release build of the entire solution.

Note   You many need to modify the directories in the TodayScreenSupportCab project's TodayScreenSupport.inf file to point to your sample installation directory.

Installing the Plug-in Host Components

To provide easy installation, all necessary CAB & Microsoft Installer (MSI) files are created as part of the TodayScreenSupport_Managed solution Release build. Although the CAB files are produced as part of a Visual Studio .NET build, they include the release DLLs produced by the eVC projects. The installation is divided into separate MSI files for desktop installation and device installation.

Desktop Installation

The desktop installation contains the Visual Studio .NET project wizard and associated support assemblies required to create .NET Compact Framework Today Screen plug-ins. The desktop installation need only be installed on desktops that will be used to create Today Screen plug-ins.

To perform the installation, simply run the TodayScreenWizard.msi contained in the Support\TodayScreenSupport_Managed\TodayScreenWizard_Installer\Release sub folder. The installer will create a new folder structure with a default installation point of C:\Program Files\.NET CF Today Screen Support.

TodayScreenWizard.msi installs the following files and folders.

Note With the exception of "Custom Today Item.vsz", paths are relative to the newly created installation folder (by default "C:\Program Files\.NET CF Today Screen Support").

File/Folder Description
Wizard\TodayScreenWizard.dll Visual Studio .NET Today Screen custom wizard
Wizard\Templates\TodayScreen_Init Folder containing the project template for Today Screen initialization ("Init") component
Wizard\Templates\TodayScreen_Exec Folder containing the project template for Today Screen executable ("Exec")
References\TodayScreenData.dll Today Screen Data Manager assembly. This assembly is referenced by both the "Init" and "Exec" projects. It manages the communication between the .NET Compact Framework plug-in assemblies and the unmanaged Today Screen component.
[VS.NET Install Folder]
\VC#\CSharpProjects\
CustomTodayItem.vsz
Visual Studio .NET wizard configuration file. This file is required to make Visual Studio .NET aware of the custom wizard.

Once installed, Visual Studio .NET will contain a "CustomTodayItem" project type as shown in figure 2.

Figure 2. Custom Today Item project in Visual Studio .NET "New Project" dialog.

Device Installation

The device installation contains the DLLs and executables (managed and unmanaged) required to host .NET Compact Framework Today screen plug-ins. This installation must be performed for any Pocket PC (or emulator) that uses a .NET Compact Framework Today Screen plug-in.

For Pocket PC devices, run the TodayScreenSupport.msi install contained in the Support\TodayScreenSupport_Managed\TodayScreenSupport_Installer\Release sub-folder. The installer automatically copies and installs the TodayScreenSupport.ARM.cab file onto the Pocket PC. The TodayScreenSupport.ARM.cab is contained in the Support\TodayScreenSupport_Managed\TodayScreenSupportCab\Release sub-folder.

For emulator installations, copy the TodayScreenSupport.X86.cab file to the emulator and expand. The TodayScreenSupport .X86.cab file is located in the Support\TodayScreenSupport_Managed\TodayScreenSupportCab\Release sub-folder.

The following files are installed onto the Pocket PC device (or emulator).

File Description
\Program Files\TodayScreenSupport\
TodayScreenPlugin_NETCFHost.dll
Unmanaged DLL that acts as the Today Screen plug-in.
\Program Files\TodayScreenSupport\
TodayScreenHost.exe
Managed executable that loads the custom managed "Init" project.
\Windows\TodayScreenDataMgr.dll Unmanaged DLL that handles the details of communication between the managed components and the unmanaged Today Screen plug-in.
\Windows\TodayScreenData.dll Managed component that wraps TodayScreenDataMgr.dll making it easily accessible to .NET Compact Framework components
\Windows\TodayScreenData.gac Global Assembly Cache (GAC) installation file for TodayScreenData.dllCreating a Today Screen Plug-in

The Basics

Once the Wizard and Pocket PC installations are complete, creating your own Today Screen plug-in takes little more then running the Visual Studio .NET Wizard and installing the newly created components. To create a simple plug-in do the following:

  1. From Visual Studio .NET choose File / New / Project.
  2. Select "Visual C# Projects" in the Project Types pane, then choose "Custom Today Item" from the Templates pane.
  3. Build the solution

The wizard creates a solution with two projects: the "Init" project and the "Exec" project. The "Init" project is a Visual Studio .NET library assembly (DLL) project. The contained class implements the ITodayScreenDataProvider interface. The interface provides two Properties, Html and Height. As you might expect, the initial HTML displayed and the height of the Today Screen are set to the values returned from these properties.

To ease the process of building simple Today Screen items, the generated component automatically returns a basic HTML string. In these cases, you can simply modify the constant "ProgramDisplayText". The text contained in ProgramDisplayText will be displayed in the Today Screen and when tapped will automatically launch the corresponding "Exec" project.

The "Exec" project is a Windows executable assembly (EXE) project. This program has no special requirements but will normally display details that correspond to the content in the Today Screen. If this program wishes to update the Today Screen content, it can call the UpdateTodayScreenInfo function (included in the generated class) passing the new HTML and desired Today Screen item height.

Installing the Today Screen Plug-in

The Custom Today Item Wizard creates a BuildCab.bat batch file in the folder where the "Exec" project source files are located. The batch file will create a single CAB file containing both the "Init" and "Exec" project assemblies.

Note The batch file only looks for the Release versions of the assemblies. If you wish to build the CAB using the Debug assemblies, modify the paths in the batch file as appropriate.

Once the CAB file is created, copy it to the Pocket PC device (or emulator) and expand. The "Init" assembly and a corresponding ".gac" file are placed in the device Windows folder. The "Exec" assembly is placed in the device Program Files folder.

Although, the installation has created the necessary registry entries, the Today Screen manager must be prodded to re-read the registry in order to be aware of the new content. For the new content to appear, do the following.

  1. On the device, tap "Start"
  2. Choose "Settings"
  3. Select the "Personal" tab (normally selected by default)
  4. Choose "Today"
  5. Select the "Items" tab
  6. Tap "OK"

These steps cause the Today Screen manager to re-read the registry and within a few moments the new Today Screen content should appear.

Note Because the "Init" project is installed into the GAC, updates can't be installed by simply copying a new DLL file but rather must be explicitly removed prior to installing the new DLL and GAC file. To remove the assembly use the CGACUTIL.exe program with the /uf option and the full assembly name (the full assembly name for each DLL can be found in the "InitType" entry of the [RegistryEntries] section of the project's ".inf" file). For example to remove the foo_init assembly from the GAC execute the following command.

cgacutil /uf foo_init,Version=1.0.0.0,Culture=neutral,PublicKeyToken=9999999999

This is obviously a very long command line to type on a Pocket PC. Entering this command line would be much easier from the desktop which we can do with the Windows Mobile Developer Power Toys "rapistart" utility. With rapistart you can issue the command shown here from the desktop and it will execute on the attached device.

rapistart cgacutil /uf foo_init,Version=1.0.0.0,Culture=neutral,PublicKeyToken=9999999999

More Involved Scenarios

The .NET Compact Framework Today Screen plug-in has been designed to make creating simple Today Screen content easy but also supports the rendering of arbitrarily complex content; even supporting scenarios where database lookups or web service calls must be made (as demonstrated by the included "TaskVision" sample described shortly).

For these more involved cases, the "Init" project can be modified to perform the necessary logic within the Html property to retrieve the associated content and return the HTML to display. By using HTML as the display format, the .NET Compact Framework Today Screen plug-in provides a rich and versatile content format.

To support the launching of one or more support programs, the plug-in architecture uses the HTML anchor tag "<a href='…'>…</a>". This tag allows the Today Screen item to have multiple "hot spots" that can each trigger the same or different programs. (Again, the included "TaskVision" example provides an example of this). These hot spots are identified by the "href" property of the anchor tag and can be any file or URL that the Pocket PC shell is capable of executing such as "exe" files, "htm" files, "pxl" files, etc. For example, to launch the program "\Program Files\My Prog\DisplayDetails.exe" when the user clicks on the word "Details" use the following HTML.

<a href='"\Program Files\My Prog\DisplayDetails.exe"'>Details</a>

Note File names containing spaces must be enclosed in quotes.

The generated "Exec" program automatically parses the command line looking for "/TodayItem=today_item_name" to identify the Today Item that launched it. This information is used to attach to the appropriate shared memory area for the Today Item. For the hot spot to launch the DisplayDetails.exe program passing the Today Item name, set the anchor tag like this.

<a href='"\Program Files\My Prog\DisplayDetails.exe" /TodayItem={0}'>Details</a>

The Today Screen plug-in automatically substitutes the Today Item name (as it is listed in the registry) for the "{0}".

TaskVision Sample

As with so many things, the easiest way to understand how the Today Screen plug-in works is an example. Since there are already excellent .NET and .NET Compact Framework examples based on the "TaskVision" project, "TaskVision" seems a great way to demonstrate how the Today Screen plug-in works.

Note For details on the desktop/server TaskVision and the .NET Compact Framework Pocket TaskVision projects visit the TaskVision Sample Application Web site.

As part of the sample install, a TaskVision_TodayScreen sub-folder containing the sample is created. The contained solution has been generated using the Today Screen plug-in wizard and been modified to use the TaskVision Web service to lookup and display the TaskVision data on the Today Screen.

The TaskVision_TodayScreen.sln solution contains the two required Today Screen plug-in projects, TaskVision_TodayScreen_Init and TaskVision_TodayScreen as well as a third project PocketVisionUtil.

To build and install the TaskVision Today Screen sample do the following

  1. Verify that the steps outlined in the "Device Installation" section of "Installing the Plug-in Host Components" have been completed
  2. Open the TaskVision_TodayScreen solution and perform a Release build of the whole solution.
  3. Open a Visual Studio .NET command prompt and run the BuildCab.bat batch file contained in the TaskVision_TodayScreen\TaskVision_TodayScreen subfolder.
  4. Copy the generated CAB file to the device and expand.

At this point the TaskVision Today Screen is installed but the Today Screen manager must be told to read the associated registry entries. To do this, we perform the same steps that are listed at the end of the "Installing the Today Screen Plug-in" section of "Creating a Today Screen Plug-in".

  1. On the device, tap "Start"
  2. Choose "Settings"
  3. Select the "Personal" tab (normally selected by default)
  4. Choose "Today"
  5. Select the "Items" tab
  6. Tap "OK"

Because the TaskVision Today Screen makes several Web service calls to retrieve the data, there may be a short delay of several seconds before the data appears on the Today Screen. Once completed, the device Today Screen should look similar to Figure 3.

Figure 3. The TaskVision Today Screen

The TaskVision Initialization Project

As with all wizard generated Today Screen plug-ins, the "Init" project, TaskVision_TodayScreen_Init, is called by the .NET Compact Framework Today Screen plug-in when the "TaskVision" Today Screen is first added to the Today Screen. In the case of TaskVision, the logic to determine the HTML is somewhat involved so is performed when the Html property is first accessed as shown here.

public string Html
{
  get
  {
    if (_html == null)
      InitializeHtmlAndHeight();
    return _html;
  }
}

The InitializeHtmlAndHeight method does the work of logging in and accessing the Web service to retrieve the Task View content. It uses the TaskVisionHtmlHelper.BuildTaskHtml function to format the task information as HTML. A fragment of the generated HTML is shown here.

<H3>Task View: <a href='"\Program Files\TaskVision_TodayScreen\TaskVision_TodayScreen.exe" /TodayItem=TaskVision_TodayScreen'>Acme</a></H3>
<table …>
  <tr …><td><strong><a href='\Windows\PocketVision'>Computer is crashing</a></strong></td></tr>

This HTML demonstrates the case of having multiple hot spots with each referencing a different application. If the user taps the word "Acme" on the Today Screen, the TaskVision_TodayScreen program is launched allowing the user to modify the displayed content whereas if the "Computer is crashing" is tapped, the PocketVision program is launched.

Note This sample uses the PocketVision program as it was originally released which doesn't support command line arguments or any other mechanism for passing information. The PocketVision sample could be easily modified to accept some identifying information for the individual task. With this modification, the HTML could be modified to pass the task identifier enabling the PocketVision program to automatically show the details for the selected task.

Figure 4. The TaskVision_TodayScreen program

The Task View Execution Project

All wizard generated Today Screen plug-ins also include an "Exec" project which for the TaskVision sample is TaskVision_TodayScreen. The "Exec" project has no specific requirements but is generally expected to either show the details behind information displayed on the corresponding Today Screen item and/or give the user the ability to modify the current content. As shown in Figure 4, the Task View "Exec" program lets the user choose what information to display leaving the TaskVision details to the existing PocketVision sample.

Once the user has made the selection and taps "Apply", the Web service is called, the data is gathered and again formatted by the TaskVisionHtmlHelper.BuildTaskHtml function. Unlike the "Init" component which need only return the desired HTML through the Html property, the "Exec" project must explicitly set the new HTML and height using the UpdateTodayScreenInfo method.

The "Apply" button click handler is shown here.

private void btnApply_Click(object sender, System.EventArgs e)
{
  // Get project information from the Project combobox
  SetStatus("Gathering Data...");
  string projectName = (string) cbProject.Text;
  int projectID = (int) cbProject.SelectedValue;

  // Use the PocketVisionUtil classes to gather the data
  DataSet dsTasks = _service.GetTasks(projectID);
  DataView dvTasks = new DataView(dsTasks.Tables[0]);
  dvTasks.RowFilter = GetRowFilter();

  // Format and update the HTML
  string html = TaskVisionHtmlHelper.BuildTaskHtml(projectName, dvTasks);
  UpdateTodayScreenInfo(html, defaultHeight);
  SetStatus("Changes Complete");
}

Callling UpdateTodayScreenInfo places the HTML and height information into shared memory where the Today Screen plug-in can access it.

The PocketVisionUtil Project

For our purposes, the PocketVisionUtil project is not very interesting. It is simply the utility and data management classes from the PocketVision sample compiled into a stand-alone library assembly (DLL) making the classes accessible to both the "Init" and "Exec" projects. In the original PocketVision sample, the classes were compiled directly into the PocketVision executable and therefore not accessible to other programs.

The one thing of note is that because the PocketVisionUtil assembly is used by the TaskVision_TodayScreen_Init assembly which is installed into the GAC, the PocketVisionUtil assembly must also be installed into the GAC. This is a good idea anyway as it is used to by both the TaskVision_TodayScreen_Init and TaskVision_TodayScreen projects.

To install the PocketVisionUtil assembly into the GAC, the TaskVision_TodayScreen_Init.gac file has been modified to include both the TaskVision_TodayScreen_Init and PocketVisionUtil assemblies as shown here.

\Windows\TaskVision_TodayScreen_Init.dll
\Windows\PocketVisionUtil.dll

Architecture

As mentioned in the introduction, the .NET Compact Framework Today Screen Plug-in system works through a combination of unmanaged eVC components and managed .NET Compact Framework components.

Components

At the heart of the system is the eVC TodayScreenPlugin_NETCFHost.dll. This DLL acts as a generic Today Screen item and has no default display. It contains an instance of the HTML window control ("HTMLWin") relying on the .NET Compact Framework components of the system to provide the HTML content.

When the Today Screen item is first activated, the Today Screen Plug-in launches the .NET Compact Framework TodayScreenHost.exe executable passing the name of the class and assembly to load which can provide the initial HTML content. The specified class must implement the ITodayScreenDataProvider interface and will normally be the "Init" project created by the Custom Today Item project wizard. The TodayScreenHost program simply loads and creates the specified class reading the Html and Height properties. It then passes the information back to TodayScreenPlugin_NETCFHost.dll.

As noted earlier, there are no specific requirements on the format or structure of the HTML although it will normally contain an anchor tag ("<a>") referencing the "Exec" project created by the Custom Today Screen project wizard. When the anchor is tapped, the "Exec" project is launched. The "Exec" project will normally either display the details behind the Today Screen entry or provide options for changing the displayed content. The "Exec" program then uses the contained UpdateTodayScreenInfo method to update the HTML displayed by the TodayScreenPlugin_NETCFHost.

Configuration

Extensions to the standard Today Screen registry entries manage the system configuration. The Pocket PC Today Screen system requires that custom entries add a new registry key. For example, in the case of the TaskVision_TodayScreen example the following registry key is added.

HKLM\Software\Microsoft\Today\Items\TaskVision_TodayScreen

The key then contains several values including the DLL to use. Normally, each Today Item is a different DLL. In our case the DLL is always TodayScreenPlugin_NETCFHost.dll. Rather then being limited to a specific display behavior, it relies on a child key, "ManagedExtension" to determine its behavior.

HKLM\Software\Microsoft\Today\Items\TaskVision_TodayScreen\ManagedExtension

The ManagedExtension key has three entries which control the initial HTML display, height and which .NET Compact Framework component is loaded to determine Today Screen content. The values are the following.

Name Type Description
InitType REG_SZ Identifies the .NET Compact Framework component to load to determine the initial HTML to display. This is normally the "Init" project created by the Custom Today Item project wizard.
InitHtml REG_SZ HTML to display while waiting for the component specified by InitType to return HTML. This is particularly useful in cased where it may take a few moments for the component to determine the HTML.
InitHeight REG_DWORD Height to use while waiting for the InitType component to return the height.Communication

The TodayScreenDataMgr_NETCFHost component displays the HTML content but relies on the .NET Compact Framework portions of the system, which are running in a different process space, to determine the HTML. To make communication between the managed and unmanaged processes as efficient as possible, the system communicates through shared memory using a memory-mapped file. The eVC DLL TodayScreenDataMgr manages the memory-mapped file details. The .NET Compact Framework DLL TodayScreenData provides a .NET Compact Framework friendly layer over TodayScreenDataMgr.

The individual components are shielded from the details of communications. In the case of the "Init" project, the component need only return the desired HTML and height through the respective properties. The TodayScreenHost application handles the details of extracting the values from the properties and passing them to the memory-mapped file. In the case of the "Exec" project, the memory details are encapsulated in the UpdateTodayScreenInfo function. The communications architecture is shown in Figure 5.

Figure 5. Communications Architecture

Project Wizard

The details of the "Custom Today Item" wizard are handled by the TodayScreenWizard project. Most of the wizard depends on template files. The wizard folder contains a sub-folder "Templates" with two sub-folders TodayScreen_Exec and TodayScreen_Init representing the "Exec" and "Init" projects respectively. When a new Visual Studio .NET project is created with the Custom Today Item wizard, most of the wizard behavior is to create the new projects by copying the template projects, changing the names and modifying the contained variable names.

As part of the project creation, the wizard dynamically generates a strong name file and a ".gac" file to install the "Init" project in the GAC. It also dynamically builds the ".inf" file and a BuildCab.bat batch file to simplify the creation of CAB files for the new project. As part of the ".inf" file creation the system has to determine the fully qualified assembly name for the "Init" assembly which includes determining the Public Key Token for the strong name file. This requires executing the SN.exe program and dynamically extracting the screen output. The details are contained in the GetPublicKeyToken function.

Conclusion

The .NET Compact Framework Today Screen Plug-in Host enables the creation of Today Screen extensions using the .NET Compact Framework. The solution consists of a combination of Embedded Visual C++ components, .NET Compact Framework assemblies and a custom Visual Studio .NET project wizard. Although there are several parts, the system installation is designed to shield the developer from these details if that is desired. For those developers wanting to know the details, the source code and installation projects are thoroughly commented.

Once installed, the system not only makes creating custom Today Screen extension in the .NET Compact Framework possible, it is now easier then ever before in any environment. If you can run a Visual Studio .NET wizard, you can now create a Today Screen extension.