Click here to Skip to main content
Click here to Skip to main content
Go to top

Cross-Platform .NET Development: Using Mono, Portable.NET, and Microsoft .NET - By Mark Easton, Jason King

, 2 Nov 2004
Rate this:
Please Sign up or sign in to vote.
Sample from the book - Chapter 5
Title Cross-Platform .NET Development: Using Mono, Portable.NET, and Microsoft .NET
Authors Mark Easton, Jason King
Publisher www.apress.com
Published Sep 2004
ISBN 1-59059-330-8
Price USD 49.99
Pages 560

The Spice of Life:

GUI Toolkits

“There are two major products that came out of Berkeley: LSD and UNIX. We don’t believe this to be a coincidence.” -Jeremy S. Anderson

SPAWNED IN THE EARLY 1970S, the decade of sartorial flamboyance that brought us sequined jump suits, ridiculously flared trousers, and the expression “Fat Elvis phase,” the graphical user interface (GUI) has grown from a hacker’s convenience tool into the public facade of the multibillion-dollar business that we all know and love. The impact that a good user interface has on an application should not be underestimated, and many projects, careers, and fortunes have been lost and found in the twinkling of a treeview.

So, the world is full of shallow aesthetes, but so what? It’s fun to pander to them, and the best thing about graphical interfaces is that they provide a chance to make manifest the underlying artistry that is software development. For those of you who don’t think that software is art, take a moment when you finish your next project to remind yourself that you’ve created something that didn’t previously exist. If creation-even when infused with logic-isn’t art, then call me a sandal-wearing, beard-chewing techie (brown kaftan and disastrous personal hygiene included).

TIP To read more about the history of the GUI, visit the excellent Web site http://www.toastytech.com/guis.

Philosophical ramblings aside, it’s time to delve into the exciting jumble of GUI tools that are available for .NET and that can help make the difference between a professional, cross-platform GUI application and a jarring profusion of pixel soup.

Topography of a .NET Graphical User Interface

Because this book deals with a variety of CLI implementations and operating systems, a good place to start is to figure out how an ideal managed GUI might work. After that, we’ll take a look at how each of the CLI implementations shapes up to the ideal implementation.

An Ideal Managed Windowing System

For the cross-platform developer dreaming of effortless portability, the ideal .NET rendering system would be written entirely in managed code.A sensible approach would involve the following steps:

  1. Creating a basic rendering system for displaying primitive items-such as lines and rectangles-on a device such as a screen, printer, or file.
  2. Developing a higher-level drawing library that encapsulates more-advanced functionality by using the basic rendering system.
  3. Designing a class hierarchy that uses the high-level rendering library and catches the user input to produce a windowing system.

Although there’s nothing wrong with this approach, it raises the question of when to leave the safe haven of managed code for the dangerous world of unsafe code and memory addresses. If this approach were taken to the extreme, the rendering system would depend on video drivers written to a managed interface, say IVideoDriver, and hardware vendors would release video drivers that conformed to the interface, as illustrated by Figure 5-1.

Of course, if hardware manufacturers wrote part of their video drivers in managed code, it wouldn’t just be a performance disaster but it would seriously overstep the boundaries of user code, and it might irreparably sour the relationship between kernel and user code.

In contrast to the managed approach, from a performance point of view, it would be ideal if all the code were tightly written assembler code, without a whiff of managed code.

Treading the fine line between these two approaches involves carefully separating functionality between managed and unmanaged code to deliver a compromise in performance and portability. Because device drivers are intrinsically linked to the host operating system and most operating systems provide some common rendering functionality, a more realistic split would use managed windowing and drawing systems, with an unmanaged rendering system calling to the device drivers, as shown in Figure 5-2.

While it’s one thing trying to balance tip-top performance with easily portable code, the main complaint against the managed approach that’s shown in Figure 5-2 is that it invariably leads to a standardized interface that is styled the same way on all platforms, but is contrary to each platform’s native look and feel.

Because some people prefer their applications to look the same across all platforms and others prefer their applications to fit in with the native feel of the operating system, frankly, a cross-platform GUI developer just can’t win.

The Basic .NET Windowing System

Having considered an ideal approach for implementing a cross-platform windowing system, it makes sense to root ourselves in the realities of .NET windowing systems and take a quick, conceptual look at the route taken by the different CLI implementations.

Because Microsoft .NET provides the System.Drawing.dll assembly for drawing and the System.Windows.Forms.dll assembly for windowing, it should come as no surprise that the other CLI implementations have also chosen to implement these assemblies. What’s interesting is to see how each CLI implementation has taken a significantly different approach to achieve this goal.

Microsoft .NET Framework

The .NET Framework currently implements both low-level rendering and higher-level controls by using Platform Invoke (P/Invoke) to call the Win32 API.

While it would be tempting to condemn Microsoft for reusing and extending the life of legacy technology, because the company’s approach helped achieve an early release of .NET and fits perfectly into the Windows user interface, it’s fair to say that Microsoft’s implementation demonstrates a shrewd use of technology. While Windows Longhorn looks set to break Microsoft’s reliance on the legacy Win32 API, in the meantime, the .NET Framework relies on the design that’s illustrated in Figure 5-3.

Because Microsoft .NET is only available for Windows, its use of Windows native functionality should come as no surprise, because it provides good performance with little concern for portability.

However, while it’s perfectly acceptable that Microsoft’s implementation isn’t portable, because System.Windows.Forms encapsulates the Windows GUI rather than a generic windowing system, one common complaint is that it should really be called Microsoft.Windows.Forms, with anything scoped within the System namespace being platform independent.

Mono

Mono’s approach to providing GUI functionality has evolved over time, and with multiple rendering back ends and multiple deployment platforms, the world of the GUI has been a tricky route to negotiate. It remains to be seen exactly where it will all end.

For its implementation of System.Drawing, Mono uses GDI+ on Windows, and Cairo on platforms running X Windows. As shown in Figure 5-4, while Platform Invoke is used to call directly into Gdiplus.dll on Windows, on non-Windows platforms, a library that mimics GDI+ is used. This library in turn passes all calls on to the Cairo library.

NOTE Cairo provides modern vector graphics functionality and features, including antialiased text rendering and mathematical transforms. Its ethos is to provide a uniform output on all media, although currently only X Windows and an in-memory image buffer implementation exist. Cairo plans to add support for the Portable Document Format (PDF) and PostScript outputs, which could elegantly lead into cross-platform printing support. See http://www.cairographics.org for more details.

While Mono’s implementation of System.Drawing is relatively straightforward, things are not so simple in regard to GUI toolkits. While we discuss a number of alternative GUI toolkits later in the chapter, three GUI implementations are currently directly related to Mono: System.Windows.Forms, implemented using Winelib; System.Windows.Forms, implemented using Gtk#; and Gtk#, a managed code wrapper for GTK+ that can be used as an alternative for System.Windows.Forms. Figure 5-5 shows these strategies in action.

Drowning Your Sorrows: Wine

While it often seems that a bottle is the answer to your cross-platform development woes, some help is at hand in the form of the Wine project.

Wine is an adaptability layer for Windows programs and provides an environment that allows Windows programs to be loaded on different operating systems and executed with varying degrees of success. Wine consists of the following two separate parts:

  • The wine program, which loads Windows binaries and marshals calls to the Windows API functions
  • The Winelib library, which implements an ever-increasing subset of the functions from the Win32 API libraries

Although the wine program only runs on x86 hardware and can only be used for running native Windows applications, the Winelib libraries can be used as replacements for their Windows counterparts and can be accessed from .NET applications by using Platform Invoke.

For more information on the Wine project, visit http://www.winehq.com.

TIP Because both of Mono’s System.Windows.Forms implementations are currently heavily in development, they aren’t as reliable as Gtk#, and therefore our advice is to use Gtk# where possible.

Because Gtk# has a strong following in the open source community, choosing between Gtk# and System.Windows.Forms is both a political and a practical dilemma, not made any easier by the fact that both namespaces will eventually work on a variety of platforms. As you would expect, the Gtk# namespace is not directly interchangeable with System.Windows.Forms. This means to effectively use Gtk#, you need to learn all about its types and peccadilloes, although that’s a small price to pay if System.Windows.Forms doesn’t meet your needs.

As you can see from Figure 5-6, a number of supporting assemblies are required for the Gtk# namespace. Each Gtk# assembly not only calls directly into the equivalent GTK+ shared library, but each Gtk# assembly also calls into a C shared library that acts as glue code and exposes some higher-level facilities that are not provided by the GTK+ libraries.

Portable.NET

Unlike Microsoft .NET and Mono, Portable.NET’s graphical architecture tends toward the linear design that was advocated in Figure 5-2, with System.Windows.Forms building on the rendering functionality that is provided by System.Drawing. This results in all the controls being written in managed code.

To provide a portable rendering system, System.Drawing uses a helper name-space, System.Drawing.Toolkit, that defines a number of interfaces that can be used when wrapping arbitrary rendering engines. To date, Portable.NET has created wrappers for Win32, which provides Windows portability, and for X Windows, which provides portability to GNU/Linux, Mac OS X, and other UNIX-based operating systems. This architecture is illustrated in Figure 5-7.

This architecture could well prove to be the purist’s choice, because it strives to accommodate a good, portable design. As other rendering systems are brought into the fold, the core of the System.Drawing and System.Windows.Forms namespaces will remain uncluttered, and the Portable.NET community has started discussing wrapping up the Mac OS X Cocoa APIs for a more Mac-native feel on Mac OS X.

TIP For those who are concerned with authoring controls or who have a general interest in how widgets work, the source code for Portable.NET’s implementation of System.Windows.Forms is an invaluable resource, although should you choose to use it as the basis for your own controls, the usual licensing rules apply.

Alternative GUI Toolkits

Having examined the standard graphical systems that are included with Mono, Portable.NET, and Microsoft .NET, it’s now time to investigate a range of alternative GUI toolkits, each of which provides its own set of features and challenges, while helping to spice up the already colorful life of the cross-platform developer. While developers from a stringent Windows background might be inclined to shun these toolkits and stick with System.Windows.Forms, you have a number of good reasons to embrace these alternative GUI toolkits. Not only are some of toolkits easily portable across different platforms, but they also offer different feature sets, and some of them can provide a native look and feel on any platform that they are deployed on. It’s also worth noting that when Microsoft releases Windows Longhorn in 2006, it will herald the arrival of a new Windows GUI system, Avalon, and will undoubtedly replace System.Windows.Forms as the preferred tool for developing Windows GUIs.

NOTE Promising the latest in vector graphics–based GUIs and using its own XML language, XAML, Avalon is set to be the future of GUI development on Windows. Luckily, an open source vector graphics library, VG.NET, is already available for .NET. While VG.NET is not identical to Avalon, it offers a number of similar features-such as exporting to MyXaml, an open source implementation XAML-and unlike Avalon, it’s available for use today. Downloads and more information on VG.NET are available from http://www.vgdotnet.org, and details of MyXaml can be found at http://www.myxaml.com.The one advantage of investing in System.Windows.Forms is that although its days are numbered, because Mono and PNET are both implementing their own version, System.Windows.Forms is likely to be the most popular .NET GUI toolkit for the foreseeable future.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Profox Jase
Web Developer
United Kingdom United Kingdom
Profox Jase
Co-Author, "Cross-Platform .NET Development: Using Mono, Portable.NET, and Microsoft .NET"
(Apress, 2004, ISBN: 1-59059-330-8)
The Book

Comments and Discussions

 
QuestionHow will .NET develop software for cross-platform Pinmemberbhag8-Aug-06 0:37 
GeneralCheckout wx.NET PinsussJ Tilly14-Dec-04 16:58 
GeneralWiggle was a little worm... PinmemberProfox Jase4-Nov-04 23:43 
GeneralPrediction: It's all going to get much, much worse. PinmemberDon Clugston4-Nov-04 11:47 
GeneralRe: Prediction: It's all going to get much, much worse. Pinmemberafinnell4-Nov-04 14:54 
GeneralRe: Prediction: It's all going to get much, much worse. PinmemberDon Clugston4-Nov-04 15:49 
GeneralRe: Prediction: It's all going to get much, much worse. Pinmemberafinnell4-Nov-04 17:41 
GeneralRe: Prediction: It's all going to get much, much worse. Pinmemberafinnell4-Nov-04 17:43 
GeneralRe: Prediction: It's all going to get much, much worse. PinmemberDon Clugston4-Nov-04 20:13 
> Abstracting the processor also allows the .NET framework (we are really talking about the CLI here) to run on different processors like the G5 and Sparc chips.
 
True, but those chips have limited, and shrinking market share. The situation has radically changed since the 80's where there was a diversity of chips. We're reaching a monopoly. The time for abstracting the CPU was in 1985, not today.
 
>You are missing the point. Would you suggest a company has different builds that run on 486, 586, P3, p4, and p5? Most companies would just build with an instruction set with 386 instructions. While this allows the applications to work on newer generations of machines it won't take advantage of the newer op codes.
 
I think there is a real misconception, exemplified by the
"Just-in-time means run-it-fast" article, that the different opcodes added by newer processers make a big difference.
As I said, there are actually very few cases where the new instructions are generated by compilers. You need to conciously structure your code to get it to produce SSE instructions - this would apply to JIT just as much as native compilation. Almost all of the impact is on multimedia libraries (ie, part of the OS), where there has been a concious effort to use them. Similarly, moving from 16:16bit far pointers to 32 bit huge pointers made a big difference to the order you would do operations (and to data structures). As usual, it's changes to algorithms that make real differences. A VB introsort will outrun an asm bubblesort eventually.
 
So here's what I'd like to see:
===============================
 
There's a very interesting library FFTW "the Fastest Fourier Transform in the West". When you give it a problem, it constructs several different algorithms for solving it, times each of them, and then uses the quickest one in future. You can't predict at compile time which will be quickest, because it is heavily dependent on the cache size, etc. Interestingly, you can't write a general-purpose FFT solver that's faster even with hand-crafted asm.
Kind of sounds like a JIT compiler, doesn't it? Except that it's at a much higher level. We're talking about replacing thousands of instructions. There's no way a JIT compiler could work that out - it would need to be told.
(I suspect it's one of those NP-complete problems).
You need a way of saying: these two functions are equivalent, although they use very different algorithms.
Once you've worked out which is fastest on this system, throw the others away.
Example, with a mythical __choosefastest keyword:
 
class X {
__choosefastest void sortfunc(data d);
};
 
__choosefastest void X::sortfunc(data d) {
// use bubblesort
}
 
__choosefastest void X::sortfunc(data d) {
// use quicksort
}
 
Now if someone could work out how to do that with .NET, and show genuine performance benefit, I'd become a convert. But IL seems to be at the wrong level of abstraction, and the comments about .NET code taking benefit of future CPU improvements seem to be little more than hype at present. It's REALLY hard to create a good traditional compiler, and to expect to do better with a JIT compiler is extremely optimistic. Still, I concede it could happen, and probably will eventually.
 
PART II: USER INTERFACE
 
In terms of legacy apps, I was referring to command-line tools with no interactive interface at all. An interesting thing about them is they don't date very much. The command-line compiler for VS 2003 doesn't look much different to the 1970's compilers. The changes are entirely value-adding (the compiler is *much* more sophisticated) rather than window-dressing. In fact, the core code in all modern C++ compilers was written over 10 years ago (for different CPU's!!)
 
By contrast, UIs have been a disaster for code reuse. Especially in the DOS days! The Windows APIs provided a level of abstraction which was a huge improvement. But even so, modern programs contain far too much UI code.
AFAIK, .NET hasn't made much progress on that, it seems to encourage UI code to get into everything.
Some kind of XML description, independent of the program code, may well be the way forward. If Longhorn does succeed in ripping UI code from apps, that will be genuine progress.
 
-Don.
GeneralRe: Prediction: It's all going to get much, much worse. Pinmemberafinnell5-Nov-04 4:56 
GeneralRe: Prediction: It's all going to get much, much worse. PinmemberMatthew Ellis11-Apr-05 3:10 
GeneralWine sucks Pinmemberweiqj3-Nov-04 6:05 
QuestionIsn't Mono throwing Wine out? PinprotectorMarc Clifton3-Nov-04 2:58 
GeneralCross-platform UI biggest mistake PinmemberGroovBird3-Nov-04 2:00 
GeneralRe: Cross-platform UI biggest mistake PinmemberDaniel Turini3-Nov-04 2:13 
GeneralRe: Cross-platform UI biggest mistake PinmemberMartin Friedrich3-Nov-04 2:45 
GeneralRe: Cross-platform UI biggest mistake PinmemberGroovBird3-Nov-04 5:07 
GeneralRe: Cross-platform UI biggest mistake PinprotectorMarc Clifton3-Nov-04 2:56 
GeneralRe: Cross-platform UI biggest mistake PinsussTownDrunk4-Nov-04 12:08 
GeneralRe: Cross-platform UI biggest mistake Pinmembervaniacilli5-Nov-04 2:05 
GeneralRe: Cross-platform UI biggest mistake PinmemberSpeedySpeedy10-Nov-04 2:51 
GeneralRe: Cross-platform UI biggest mistake PinmemberSamJost10-Nov-04 22:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140926.1 | Last Updated 3 Nov 2004
Article Copyright 2004 by Profox Jase
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid