HomeDigital EditionSearch Dotnet Cd
ASP.NET C# Certification Exams The CLI Data Access Editorials Extending .NET Fundamentals Interoperability Interviews Migrate Mobile .NET Mono .NET Interface Object-Oriented Programming Open Source Optimization Product/Book Reviews Security Source Code UML Visual Studio .NET

In the March issue of .NET Developer's Journal Miguel de Icaza, project leader for the Mono project, wrote an article introducing Mono. In the same issue Dennis Hayes showed us how we could download and evaluate Mono. Since then a lot has happened...

Background
The Mono project, which was launched by Ximian, Inc., in July 2001, led by CTO de Icaza, has come a long way. By using the technical documentation that Microsoft submitted to ECMA (the European Computer Manufacturers Association), Mono developers have been able to create an implementation of the Common Language Infrastructure (CLI), a C# compiler, and close to 4,000 classes. Several spin-off effects have already been noticed, with companies using Mono in commercial software and new projects starting more or less every week. If you want to know more about the latest version of Mono, or the Mono project and related projects, please see the main project site at www.go-mono.com.

In May, Mono version 0.24 was released, which contained ­ among many other things ­ a new code generation engine and a graphical user interface (GUI) toolkit binding called Gtk# (pronounced GTK-sharp).

The updates to Mono mentioned above were important. The new code generation engine provided developers with an excellent opportunity to port Mono to different hardware architectures, in our case ARM (Advanced RISC Machine)­ based architectures. ARM, in particular one of its latest reincarnations, called XScale, is commonly used in PDAs such as iPAQ and Zaurus. But we should not forget to mention that ports of Mono to other hardware also exist, most notably PPC, S/390, and soon SPARC.

Gtk#, the .NET language binding for the GTK+ toolkit, was included in a Mono release for the first time. Gtk# gives a developer bindings to several libraries (GNOME and GTK) that are more or less a de facto standard on a Linux distribution. These libraries have been used for a long period of time, should be considered stable, and help a developer create cross-platform GUI applications for Unix and Windows. As a side note we must mention the Qt# language bindings that bind to the Qt toolkit. Qt# might be the better binding for PDAs using Qt as their main GUI toolkit.

Handhelds and Linux
Several PDAs come with Linux pre-installed, most notably the Sharp Zaurus. But a developer or user can install Linux on an iPAQ handheld, thanks to the work of the developers at www.handhelds.org. Using Linux on your iPAQ is a pleasant experience, although it should be noted that a certain level of Linux knowledge is necessary for the more complicated procedures such as installation. We have the thttpd Web server installed on our iPAQ 3970, serving HTML pages to visitors while everything is administrated via SSH Secure Shell. Of course, since the Mono project also contains an ASP.NET implementation, it is only a matter of time before we have it on our iPAQ.

We installed the Familiar Linux distribution with GPE (GNU PDA Environment) on our iPAQ. By doing so we had instant access to several libraries that Gtk# can bind to. For installation instructions and more, please see www.handhelds.org.

The remainder of this article will present three application examples covering different aspects of development that are useful to a developer. First, we will demonstrate how to create a simple Hello World command-line application on the iPAQ. Second, we'll discuss how to create and deploy a simple Hello World GUI application created with Gtk#, and finally we will show you how to write a simple GUI that uses googleGateway (XML-RPC Web service) to help users with their spelling.

Instructions for installing Mono on your workstation can of course be found at the Mono Web site. We are used to working with Linux workstations, so we will use a Linux workstation for this article. But since both Mono and Gtk# can be run under the Windows operating system you have freedom of choice. In short, everything in this article is developed on Linux and later transferred to the iPAQ.

Create a Simple Command-Line Application
Let's focus now on development and write a simple command-line application.

using System;

class HelloWorld {

public static void Main() {

Console.WriteLine(``Hello Mono Developers!'');

}

}

This example is the standard Hello World application that most, if not all, programming languages use as an introductory example. Save the code in the file hello.cs and compile it into Intermediate Language using the command-line Mono C# compiler mcs:

mcs hello.cs

This command produces the executable hello.exe.

The iPAQ handhelds and other Linux handhelds have a large number of applications available to them. A lightweight package manager called iPKG was developed to help users install and manage applications. If a developer creates an iPKG package of the application and then provides it via a package feed, anyone with a connection to the Internet can download and install it automatically, either through a GUI or via the command line, like this:

ipkg install MyApp

This snippet invokes iPKG and tells it to download and install an application called MyApp if it exists in any of the known feeds. A user can easily add feeds to iPKG and have instant access to new software.

To install and run our example on the iPAQ you must first have Mono installed. A feed is provided at the http://amy.udd.htu.se/~malte/mono Web site, which you can use to install Mono. The packages you should install are named mono and gtk-sharp. Add the mono::handhelds feed into your iPKG configuration and install mono and gtk-sharp by typing:

ipkg install mono
ipkg install gtk-sharp

If, on the other hand, you have a Zaurus and wish to run Mono, then you should install GLib-2.0 instead of gtk-sharp, as there is at the moment no easy way to use Gtk# on Zaurus, which uses the Qt toolkit. GLib-2.0, which does not ship with the Zaurus, provides you with the functionality required to run Mono.

If you open up a shell and type mono (JIT) or mint (interpreter), you should see the Mono or Mint help being written to the console. Mint is an interpreter that is slower but also smaller and can be appropriate for this type of development. Mono, on the other hand, is the JIT compilation engine, which is faster but also larger and still in early development stages on ARM architecture.

Next, download the Hello World application to the iPAQ and run it with the interpreter by typing the following in a console window:

mint hello.exe

Create and Deploy a Simple GUI Application
Next we create a simple GUI application that takes advantage of Gtk# (see Listing 1). The code is fairly straightforward and should not be difficult to understand, but the first few lines are probably new to most .NET developers.

The Gtk, GtkSharp, and Gdk namespaces provide basic functionality for using a GUI in our application. After declaring the namespaces, we initialize the application, create a dialog, retrieve an image from the assembly, and add it to the dialog. Then we add a Delete- EventHandler, and show the dialog. A DeleteEvent is fired whenever a user chooses to close a window. Finally, we instruct the application to run, which essentially means starting the event loop and waiting to process any incoming events. Let's compile the example:

mcs /r:gtk-sharp,gdk-sharp /res:mono.png hello-gtk.cs

Since we wish to use assemblies that are not part of the standard library we must make sure to pass them as references to the compiler. We will also include the image in the assembly.

Start up the application by typing mint hello-gtk.exe and view the simple GUI application ­ written in C# using Gtk# and Mono ­ on an iPAQ running Linux (see Figure 1). Of course, we could add this application to the start menu and then start it by simply clicking an icon, but for the sake of brevity we will leave this out for now.

Figure 1

XML-RPC and Handhelds
Charles Cook recently released the XML-RPC.NET library, a .NET implementation of XML-RPC. This library allows applications to make remote procedure calls using HTTP as the transport and XML as the encoding. We chose to present a remoting example that used XML-based encoding rather than binary, as binary-style remoting is implementation specific and would restrict the application to communicating only with another Mono application. The same limitation is of course also valid from other implementations' viewpoints. To become truly cross-platform, XML-based encoding is the ideal way to go.

Using Mono, Gtk#, and XML-RPC.NET we will now develop a simple GUI application that consumes an XML-RPC service provided by xmlrpc.com. The Web service is an XML-RPC gateway to Google's Web APIs. You will need a license key, which you can get free from Google, to run this example. As you will notice, it is extremely easy and straightforward to use Gtk# and XML-RPC. The complete source code for this application can be found in Listing 2.

Let's look now at one of the less obvious parts. In Main we have the creation of the main window within a try/catch statement. The reason for that is that the picture is downloaded and later added to the window. If no picture can be retrieved, then there probably is no connection, thus rendering the application useless. The rest of the code should be fairly self-explanatory. To try it out, compile the source code like this:

mcs /r:gtk-sharp,gdk-sharp,CookComputing.XmlRpc
google.cs

Run the application in the same manner as we did before: mint google.exe. When the window is shown, enter a poorly spelled word and click the button. After a while you should see a suggested spelling delivered by way of the XML-RPC gateway from one of Google's servers (see Figure 2).

Figure 2

Conclusion
In this article we presented some of the things Mono already is capable of doing on PDAs. Using Gtk# and Mono, developing graphical user interfaces on PDAs is a small task, and third-party libraries such as XML-RPC.NET can easily be fit, here giving us the opportunity to develop a simple application that consumed a Web service. In similar fashion it is simple to work with another graphical toolkit, for instance by compiling with the Qt# bindings an application would be ready to be deployed in a Qt-based environment.

Mono and the technologies surrounding it are in constant development. Over the past few months we have seen the Mono project advance at an astonishing pace, but as always, the team welcomes developers and users who would like to help out. You can find details about how you can contribute at www.go-mono.com/contributing.html. We welcome you!

References

  • The Mono project: www.go-mono.com
  • Ximian: www.ximian.com
  • Gtk# project: http://gtksharp.sf.net
  • Qt# project: http://qtcsharp.sf.net
  • XML-RPC.NET: www.xml-rpc.net
  • mono::handhelds: http://amy.udd.htu.se/~malte/mono
  • iPKG feed: http://amy.udd.htu.se/~malte/mono/feed
  • Google API: www.google.com/apis
  • Linux on iPAQ: http://handhelds.org
  • XML-RPC.Com: www.xmlrpc.com/googleGateway
  • GNOME: www.gnome.org
  • GTK: www.gtk.org

    About The Authors
    Malte Hildingson is a student at the University of Trollhättan/Uddevalla. tds00mahi@thn.htu.se

    Richard Torkar is a PhD student at the University of Trollhättan/Uddevalla. richard.torkar@htu.se

    	
    
    
    
    Listing 1
    
    using Gdk;
    using Gtk; 
    using GtkSharp;
    using System;
    class Hello
    {
    public static void Main()
    {
    Application.Init();
    Dialog d = new Dialog();
    d.Title = "Go Mono!";
    d.VBox.Add(new Gtk.Image(
    new Pixbuf (null, ``mono.png'')));
    d.SetDefaultSize(128, 64);
    d.HasSeparator = false;
    d.DeleteEvent += new DeleteEventHandler(Deleted);
    d.ShowAll();
    Application.Run();
    
    }
    
    public static void Deleted(object o, DeleteEventArgs args)
    
    {
    Application.Quit();
    }
    
    } 
    
    
    Listing 2
    
    using System;
    using System.Net;
    using System.Threading;
    using Gtk;
    using GtkSharp;
    using CookComputing.XmlRpc;
    
    [XmlRpcUrl("http://google.xmlrpc.com/RPC2")]
    internal interface IGoogle
    
    {
    
    [XmlRpcMethod("googleGateway.spellingSuggestion")]
    
    string SuggestSpelling(string phrase, string key);
    
    }
    
    public class GoogleWindow : Window
    
    {
    static string Key = @"YOUR-GOOGLE-KEY-HERE";
    static string ImageUri =
    
    @"http://amy.udd.htu.se/malte/mono/ndj/google.png";
    private IGoogle google;
    private Entry entry;
    private Label label;
    private Button button;
    
    public static void Main()
    {
    Application.Init();
    
    try
    {
    new GoogleWindow().ShowAll();
    }
    catch (Exception e)
    {
    MessageDialog dialog;
    dialog = new MessageDialog(null,
    DialogFlags.Modal,
    MessageType.Error, ButtonsType.Ok,
    "An error occured: " + e.Message);
    dialog.Run();
    return;
    }
    
    Application.Run();
    }
    
    public GoogleWindow() : base("Google Spells")
    
    {
    Container vbox = new VBox(false, 4);
    Container hbox = new HBox(false, 4);
    vbox.BorderWidth = 2;
    hbox.BorderWidth = 2;
    
    entry = new Entry();
    
    entry.Activated += new
    EventHandler(this.RequestLookup);
    vbox.Add(entry);
    
    WebClient client = new WebClient();
    Gdk.Pixbuf pixels = new
    Gdk.Pixbuf(client.OpenRead(ImageUri));
    hbox.Add(new Image(pixels));
    
    button = new Button("Suggest");
    button.Clicked += new
    EventHandler(this.RequestLookup);
    hbox.Add(button);
    vbox.Add(hbox);
    
    label = new Label("");
    vbox.Add(label);
    Add(vbox);
    
    DeleteEvent += new
    DeleteEventHandler(this.RequestDelete);
    }
    
    private void RequestLookup(object sender, EventArgs args)
    {
    if (google == null)
    google = (IGoogle)
    XmlRpcProxyGen.Create(typeof(IGoogle));
    
    try
    {
    string s =
    google.SuggestSpelling(entry.Text, Key);
    
    if (s.Length > 0)
    label.Text = "Suggestion: " + s;
    else
    label.Text = "No suggestion";
    }
    catch (Exception e)
    {
    label.Text = e.Message;
    } 
    
    entry.GrabFocus();
    entry.SelectRegion(0, entry.Text.Length);
    }
    
    private void RequestDelete(object sender,
    DeleteEventArgs args)
    {
    Application.Quit();
    }
    }
    

    All Rights Reserved
    Copyright ©  2004 SYS-CON Media, Inc.

      E-mail: info@sys-con.com