With the .NET Compact Framework Microsoft released a uniform development
platform for the development of desktop and Pocket PC applications. This new
platform should make life much easier for the Pocket PC developer by
offering a uniform Visual Studio .NET development environment. Based on
eTrainSoft, a mobile training data acquisition application for the Pocket
PC, this article shows how to develop mobile GUI applications using the .NET
Compact Framework, with a special focus on the GUI and data synchronization
aspects.
This project was part of a larger project in the context of mobile
training acquisition and analysis for professional athletes. The Compaq iPAQ
is used for mobile training data acquisition for professional triathletes.
This data is transferred to a PC in a well-formed and valid XML data file.
The task of this project was to develop a sophisticated GUI application on
the Compaq iPAQ 3970 with the .NET Compact Framework using C#. The
application should be easy to use, taking advantage of the GUI capabilities
of the .NET Compact Framework. In the project we used the first .NET
Compact Framework beta, but this article will also reflect the changes with
the new VS.NET 2003 beta. The article assumes that you are already familiar
with the VS.NET IDE and the design of GUI applications; it will highlight
some details that are important for .NET Compact Framework GUI development
(and others), rather than giving you an introduction to GUI development with
VS.NET.
The .NET Compact Framework
With the appearance of the .NET Compact Framework the Windows CE world
has also been connected to the bright new .NET world. In Microsoft's words,
.NET supports a kind of "platform independence," in the sense that it
supports any Windows operating system. The .NET Compact Framework is part of
the Smart Device Extensions (SDE) for Visual Studio 2003. The .NET Compact
Framework is an adapted version of the standard .NET Framework, optimized
for low-memory resources (in the sense of Microsoft) and for small graphical
devices. The complete library and the runtime environment require roughly
1.3MB of memory on the target device. However, nothing is free. Of course,
this resource reduction results in reduced functionality compared to its
"big brother," the standard .NET Framework.
A very new feature compared to former versions is the bytecode
compatibility of both frameworks. That means that .NET Compact Framework
assemblies can be run seamlessly on the PC and on the small device, as long
as no GUI and no special .NET Compact Framework classes are used. The same
is true vice versa.
The Application
The concept for the eTrainSoft mobile training data acquisition
application was developed in conjunction with a professional triathlete,
driven by the athlete's need to automate the logging of training data. The
application should allow easy logging of the athlete's daily training
sessions and should give him a weekly overview of his training performance.
The data is transferred to a PC in a standard XML data file, which can
be used for further analysis on the PC. In the next step, we synchronize the
data with a central data server using Web services.
Smart Device Extensions
Smart Device Extensions contain the .NET runtimes for different
processor architectures and an emulator for Pocket PC and Windows CE
devices. "Windows CE" is the general term for subnotebooks and similar
devices having a keyboard, while "Pocket PC" is the term for smaller devices
with no keyboard, although these also run Windows CE.
Figure 1 shows the Smart Device Application Wizard, which allows the
creation of SDE for VB.NET and C#; C++ and J++ are currently not supported.
The Wizard distinguishes between "Windows CE" and "Pocket PC" platforms
and allows the creation of four different project types for each platform.
- Windows Application
- Class Library
- Non-graphical Application (or "console application" for Windows CE)
- Empty Project
The application types are well known from the standard .NET Framework.
The "Non-graphical Application" is special for the Pocket PC. This is for
background applications on a Pocket PC and is very similar to a console
application on a desktop.
The project can be run directly on a connected device. If the .NET
environment is not yet installed, it will be deployed automatically. By
default, the project assembly and any other required files will be deployed
into the Windows folder. However, I recommend setting the "Output File
Folder" in the project settings to another folder, for example, a custom
subfolder of the "Program Files" folder (which is the standard on desktop
installations).
In the eTrainSoft application we took advantage of the bytecode
compatibility and developed a common business logic assembly that runs on
the Pocket PC and on the Desktop PC for data synchronization.
We needed only to add the assembly to the project as a reference. During
development it is also recommended to add the "System.SR" component to
device projects. With this component, exceptions will be a bit more verbose.
To save memory on small devices, most exceptions do not contain detailed
descriptions. The System.SR dll contains the complete string resources for
the exceptions. When a project is distributed, this dll is generally not
included.
The Emulator
Usually the project will be executed directly on the device. However,
developing and debugging are much easier if you first run the program on the
included emulator. The deployment of the application to the emulator is
faster than to the device, and the program also runs faster on the PC
processor. If you trace through the code step-by-step, the communication
with the device always takes a few seconds, but there is no delay with the
emulator.
To run the emulator, the TCP/IP protocol must be installed on the
operating system of the development computer. If your PC is connected to the
network, you will have installed TCP/IP and need do nothing else. Otherwise
you have to install the Microsoft Loopback Adapter.
To deploy your application to the emulator, you must select Pocket PC
Emulator in the Device Extension toolbar of VS.NET, as shown in Figure 2.
Using the Connect to Device button and the Deployment Device dropdown list
you can start the emulator without downloading and running the project.
Using the emulator also has a few disadvantages. First, there is no way
to get a connection via ActiveSync. This means that you cannot synchronize
and exchange files with the virtual device. To transfer a file to the
emulator, you must first add it to the VS.NET project you are going to deploy. Then you change the Build Action file property of the file to Content. With the next deployment, the file will be downloaded to the program directory. Second, although the emulator itself computes quickly, the graphical user interface is slower. Finally, the
memory of the emulator is limited to 16MB. So although the emulator is a
very useful development tool, it cannot replace real hardware.
Device Controls
The list of GUI controls for the .NET Compact Framework is slightly
reduced compared to those for standard .NET Framework applications.
Table 1 lists all of the controls for standard .NET Framework for
Windows applications and highlights those that are also available in the
.NET Compact Framework. Note: the InputPanel control, which stands for the
keyboard on the Pocket PC is, of course, only available for the .NET Compact
Framework.
A lot of controls have been added to the .NET Compact Framework since
the beta. Controls we were missing in our project include the OpenFileDialog
and SaveFileDialog. Also now available is DataGrid-Control, which is very
handy.
While some controls can be omitted without any problems or even don't
make sense for the .NET Compact Framework, the omission of others is painful
and there is no particular reason why they are not available. In this
category are the DateTimePicker control and the MonthCalendar control. Both
were heavily missed in our project especially since both were available in
the Windows CE operating system. According to older articles both controls
(together with even more) were expected to be available, but haven't yet
been implemented unfortunately.
In our eTrainSoft application date selection is necessary because it is
used as a navigation element. The user should be able to query for and edit
the training data on a per-date base. Since neither control was available,
we found a wrapper from Tim Wilson that creates the control through system
calls during runtime. Although this solution works fine, it has one major
drawback; the control doesn't yet support event-handling, since handling of
Windows Messages wasn't documented at that time. At MSDN there is now
documentation available about how to handle Windows Messages in the Compact
Framework. So to be able to recognize user inputs, the application
continuously polls the DateTimePicker this will eventually be replaced with a proper solution.
The eTrainSoft GUI
The .NET Compact Framework also supports the "localizable" property of
the forms for internationalization of your application. This property
determines whether the property values of a form are stored in resource
files appropriate to the currently chosen language for the form.
We used the tab control for our two main views, the daily and weekly
training session overview. Figure 3 shows the daily overview of the training
session of the athlete.
The control always places itself at the top, independent of the tab
settings, and uses the complete window size. We placed the tabs at the
bottom row. You can enforce the tab control behavior using a Panel.
We noticed other restrictions on the controls. The text of a label can
only be aligned to the top. The image in a picture box cannot be scaled.
Sometimes it is simpler to write your own control. This is fairly
straightforward; you just derive your class from the class Control and
overwrite the OnPaint method. This method receives the PaintEventArgs
object, which, among others, contains a Graphics object. You can now use
this Graphics object to draw, write, and insert pictures into your GUI. Any
Control in eTrainSoft, that shows a data record is implemented this way.
GUI Manipulation
As is common in Windows, the GUI cannot be changed by another thread. To
overcome this restriction in .NET, you can use the function Control.Invoke.
This method receives a delegate, which can be executed in the GUI thread. In
our beta version, this function was not yet available, so we used a global
timer as a workaround (System.Windows.Forms.Timer, not the System.Threading.Timer). The external thread registers its desired function at the timer, which executes the function
three times a second. With the new Everett version, this can be solved very
easily with the now-supported Control.Invoke method.
Forms
Forms for the Pocket PC can be created and designed more or less the
same way as for standard Windows applications. Figure 4 shows the session
input form in design mode. There are only few things that might be taken
into consideration. For example, I found the default grid size of 8x8 too
coarse, so I changed it to 4x4. You can change the default grid size under
Tools/Options/Windows Forms Designer.
The menu is always at the bottom and works only with Pocket PCs. The
input panel symbol is always automatically shown to the right side of the
menu bar. If only the input panel is needed, you can add it with an empty
menu bar. If you set the WindowState property on the form to Maximized and
you do not have a menu, the title bar with the start menu also disappears
and you have full-screen form.
Single Program Instances
On the Pocket PC, there is no user-friendly way to switch between
running programs. The only way to do this is via the Settings>
System>Memory>Running Programs command. By default, clicking on the
application a second time would start another instance of the program.
However, a standard Pocket PC program should start only once and should
bring an already-running instance to the front if it is executed a second
time. To implement this behavior, I used the system calls FindWindow and
SetForegroundWindow, as shown in Listing 1. Both are imported with DllImport
from coredll.dll. The first function returns a handle of the window with the
requested name. The second function shows the window of the passed handle to
the user.
The Application.Run method catches all exceptions and rethrows them;
dealing with this is laborious for developers. They do not know where the
exception happened and have to discover the error through other means, as
this information is not part of the exception. As a conclusion, you can
handle nearly all GUI tasks with the .NET Compact Framework, but you have to
do a little bit more work than you would using the standard .NET Framework.
Data Synchronization with the Desktop
Data should not typically stay on the PDA. You may want to back up your
data on your desktop computer or you may want to edit and analyze the data
using a more comfortable big screen with mouse and keyboard, as we did. So
the data has to be transmitted from the PDA to a central data store and back
to the mobile device. In Microsoft's PDA world there are two technologies
that can be used to achieve this: ActiveSync and RAPI (remote application
programming interface).
You can develop your own ActiveSync Service Provider. This method is the
most user-friendly, as the synchronization takes place in the well-known
ActiveSync environment. You can also configure and automate the
synchronization therein. To achieve this, you must implement your
synchronization logic in COM objects with a given interface. On the .NET
Compact Framework this cannot be implemented without a major additional
effort.
RAPI allows you to remotely make system calls on the Pocket PC from
Windows. This API is not (yet) part of .NET, but you may easily include it
via DllImport or wrappers from the Internet. For eTrainSoft we used this
technology to read the data from an XML file to the desktop computer. After
synchronization the updated data is written back the same way. As an
alternative to manually starting synchronization, you can configure the
synchronization to be automatically started after an ActiveSync procedure.
To achieve this, the eTrainSoft synchronization tool has to be registered in
the Registry under HKEY_CURRENT_USER\Software\Microsoft\Windows CE Services\End Callback. Active-Sync starts this program after the synchronization.
However, a problem arose from the fact that files were used as a
persistent data store on the Pocket PC. If the Pocket PC application is
running (and has loaded the content of the file into memory) during the
synchronization, the synchronization will change the content of the file
without notifying the running application. So the next save of the
eTrainSoft application would overwrite the just-synchronized data. We solved
this problem by starting a TCP server to the local loopback interface on the
Pocket PC. After a connection, the program locks the file internally for a
few seconds. Each new connection renews the lock. After a timeout the XML
file is reimported into the application. The synchronization tool regularly
starts a little program that opens the requested TCP connection.
Another option would be to use SQL Server CE. This allows
synchronization via a network and IIS to a SQL Server. In this case you do
not have to write an extra piece of software. ActiveSync may also
synchronize a Pocket Access database, but unfortunately there are no .NET
drivers for Pocket Access at the moment.
Summary
With the .NET Compact Framework Microsoft offers a very handy
environment for Pocket PC programming. Since the Pocket PC device has fewer
resources, the feature set is limited compared to the standard .NET
Framework. However the available functionality is fairly complete and only a
few features, however important, are missing.
To allow productive use the Compact Framework still needs to mature a
bit more, mainly in the area of GUI programming (e.g., missing date
controls). Some important features for Pocket PC programming, such as
support for synchronization and single program instances, should be offered
in the future.
Smart Device Extensions is fully integrated into Visual Studio and needs
no other IDE such as eMbedded Visual C++. The integrated documentation has
one major disadvantage. Developers have to filter the relevant information
from the complete .NET documentation. A separate documentation of the .NET
Compact Framework class libraries would be more practical.
Despite the optimization for minimal resource usage, you have to pay
tribute to .NET and the JIT compilation. The eTrainSoft .NET application
uses more than 2MB RAM even if it is not very feature rich. Nonetheless,
.NET's benefits of easier programming and hardware-independent assemblies
outweigh this disadvantage.
References
Bucheli, K. (2003). Diploma Thesis "eTrainsoft .NET" (German):
www.hst.fhso.ch/StuPro/vz99/prj1286/index.html
Luthiger, J. (2002). "eTrainSoft Concept" (German):
http://babylon.hst.fhso.ch/~luthiger/etrainsoft
Roof, L. (2001). "First Look at Smart Device Extensions." MSDN:
www.Tonked.com
Wilson, T. (2002). "DateTimePicker Wrapper,"
www.innovativedss.com/public/datetimepicker.txt
Creating the ActiveSync Service Provider:
http://msdn.microsoft.com/library/default.asp?url=/
library/en-us/wceactsy/htm/ceconCreatingActiveSyncServiceProvider.asp
Working with RAPI:
http://msdn.microsoft.com/library/default.asp?
url=/library/en-us/wceconct/htm/_wcesdk_working_with_rapi.asp
Using rapi.dll in vb.net:
www.dotnet247.com/247reference/msgs/25/128810.aspx
A RAPI Wrapper:
www.innovativedss.com/forums/topic.asp?TOPIC_ID=122
File Transfer through ActiveSnyc from Mobile Unit to a Desktop:
http://groups.google.ch/groups?hl=de&lr=&ie=
UTF-8&oe=UTF-8&selm=eEiv2N5LCHA.3380%40cpmsftngxa08
About The Authors
Konrad Bucheli has just finished his study of
informatics and telecommunications at the University of Applied Sciences
Solothurn Northwestern Switzerland. He based his thesis on the eTrainSoft
project discussed in this article. Konrad works as a software development
engineer at Supercomputing Systems in Zurich, Switzerland.
konrad.bucheli@scs.ch
Martin Kropp is a professor of computer science at the University of Applied
Sciences Solothurn Northwestern Switzerland. He teaches software
engineering with an emphasis on object-oriented
technology. His current focus is the .NET Framework. He has conducted
several student projects on .NET, with special emphasis on interoperability
capabilities.
martin.kropp@fhso.ch
Listing 1
static void Main()
{
int hwnd = FindWindow(null, TITLE);
if(hwnd!=0)
{
//show application already running and exit
SetForegroundWindow(hwnd);
}
else
{
HandheldGui Gui = new HandheldGui();
Application.Run(Gui);
}
}
[DllImport("coredll.dll",EntryPoint="FindWindow")]
private static extern int FindWindow(string lpClassName,string
lpWindowName);
[DllImport("coredll.dll",EntryPoint="SetForegroundWindow")]
private static extern int SetForegroundWindow(int hwnd);
All Rights Reserved
Copyright © 2004 SYS-CON Media, Inc.
E-mail:
info@sys-con.com