Glade# for Rapid Development: Simple Web Browser
Update [16/11/2005]
I had to relocate this page from Novell’s server to my own server since I can no longer host files at my previous employment. I will update this tutorial soon to reflect any change due to newer version of Mono and Gtk#.
Update [29/09/2004]
A couple of things have come up since the last version of this tutorial:
- Mozilla: because of the way Mozilla is installed in some distributions (I haven’t been able to trace what it exactly is yet), running the application in MonoDevelop causes the following failure: Unhandled Exception: System.NullReferenceException: Object reference not
set to an instance of an object
. Running the application from a terminal (the exe is in the project bin/Debug directory) solves that issue. Also make sure MOZILLA_FIVE_HOME is set. - Glade 2.6+: If you are using a very recent version of Glade which by default adds an alignement to a new frame (Glade 2.6 and newer, I believe) you can either remove the alignment from the frame or or add the WebControl to the allignment instead of the frame with something like
[Widget] Alignment alignment1;
and later in the code
//instead of frame1.Add(web); alignment1.Add(web);
Introduction
In a previous example we built a very
simple glade application using a simple editor and the Glade Interface
Builder. In this example, we’ll build a slightly more complex
application, taking advantage of more tools: a web browser.
Many applications display rich content with an HTML rendering
engine. Evolution and Monodoc, for example, use
gtkhtml to render and edit messages, Monodevelop uses the Mozilla
project’s Gecko, and Konqueror and KMail use the khtml widget.
Mono includes bindings for both gtkhtml and Gecko, but in this
example we’ll use Gecko. Gtkhtml is more suited to simple displays,
such as email messages or static documentation pages, but Gecko is
more full-featured and therefore better suited to use in a
full-fledged web browser.
We’ll use the following tools in this example:
- Mono
- GTK# (gtk-sharp)
- Gecko# (gecko-sharp, gtkmozembed#)
- Monodevelop, an IDE for Mono
Monodevelop isn’t absolutely necessary here, but we’ll
be using it in the examples and screenshots.
Project Setup
First, launch Monodevelop and then select File -> New
Solution. A dialog appears, offering you several choices for
template and project type. Select C# for your template and Glade#
Project for the project type. This will automatically fill in some
starter code for you: a window and a button, similar to the “Hello
World” code we wrote earlier.

Note: Monodevelop uses the same project terminology as Visual
Studio.NET: a “Solution” contains multiple “Projects,” each of which
contains one or more source files. Other platforms describe this
arrangement as one of “Projects” and “Sub-Projects.”
There’s one more step as we get set up: adding the gecko-sharp
assembly to the list of references we’ll be using in
Monodevelop. To do that, right click on References in the
Solutions tab on the left hand side, click Edit Reference
and check the
box marked gecko-sharp. Adding the assembly means that
Monodevelop will offer autocompletion and syntax validation on Gecko
objects as well as those in its default set of assemblies.
Name your project MyBrowser and save it in a new directory. Now
we’re ready to start.

Building the Interface
The first step is building the user interface. If you’re using
Monodevelop, you already have a glade XML file started for you, in the
MyBrowser/Resource/ directory. Double-click on that file in
the list of project files Monodevelop provides, or open it using
Glade. If you are not using Monodevelop, start Glade and create a new
GNOME project, then create a new window for it.
Double click on the window1 Glade object, so that its
properties are displayed in the Properties dialog. Then, change its
title to say “My Browser” instead of “Glade Window.

Next, click the vertical box button (
src=”http://www.frenchguys.com/Documents/glade2_img/vbox.png” align=”baseline”/>) and click in the window.
When prompted, select 2 rows. You now have a top and bottom half of
your window. The top half will consist of buttons and toolbars, and
the bottom half will be the HTML display area.
To add spaces for your buttons, create a horizontal box (
src=”http://www.frenchguys.com/Documents/glade2_img/hbox.png” align=”baseline” />) with 3 colums in the
top row of the vertical box you created earlier.


In the three colums of the top half of the window, we’ll add two
buttons and a text entry. In the Properties dialogs for the buttons
you added, go to the Widget tab and select the stock Backward and
Forward icons. Using stock icons provides application consistency
across the desktop. In addition, stock labels are already
translated, so you get free localization.
Right-click the top area and choose hbox->Select to select
the hbox. Change its Packing property so that Expand and
Fill are “No.” Now the box will take up only as much space as
it needs, rather than filling all available space.
In the bottom half of the UI, add a frame. Then, right-click
on its label and select Delete so that it is blank and
unlabeled. Later, we’ll fill the frame with the Gecko rendering
widget, which is not available in Glade.
Your UI should now look like this:

Now that looks more like a web browser! With the UI more or less
complete, save your work and quit Glade.
Start Coding
The code that the project wizard generated for us should look
pretty familiar by now:
// project created on 4/16/04 at 2:17 P
using System;
using Gtk;
using Glade;
public class GladeApp
{
public static void Main (string[] args)
{
new GladeApp (args);
}
public GladeApp (string[] args)
{
Application.Init();
Glade.XML gxml = new Glade.XML (null, "gui.glade", "window1", null);
gxml.Autoconnect (this);
Application.Run();
}
/* Connect the Signals defined in Glade */
public void OnWindowDeleteEvent (object o, DeleteEventArgs args)
{
Application.Quit ();
args.RetVal = true;
}
}
Now, we’ll add to the code. Our changes here are marked in red:
...
using Glade;
// Earlier, we added a reference to the Gecko.dll assembly. Noting
// here that we are using it lets the compiler know we're using classes
// from that namespace, so we can type WebControl directly and not
// have to specify Gecko.WebControl everywhere.
using Gecko;
public class GladeApp
{
...
As we saw earlier, Glade can automatically bind UI controls to
references, provided that indicate that the object is a
Glade.Widget, like so:
...
public class GladeApp
{
// Because frame1 and entry1 are tagged as Widgets
// the Glade runtime will bind them to UI controls with the same name
[Widget] Frame frame1;
[Widget] Entry entry1;
...
Because Glade only includes standard widgets, we couldn’t put the
browser control into our UI when we created it earlier. Instead,
we’ll write it in code, starting with a variable to refer to
it. Let’s call it “web.”
...
public class GladeApp
{
[Widget] Frame frame1;
[Widget] Entry entry1;
// Define a variable for our web control
WebControl web;
...
Now that we’ve defined a variable to refer to it, we can actually
create the control:
... Glade.XML gxml = new Glade.XML (null, "gui.glade", "window1", null); gxml.Autoconnect (this); // First we create a WebControl, using its default constructor web = new WebControl(); // Then we ask it to show itself. // This is required because of a Gecko bug, and doesn't actually show the control yet. web.Show(); // Next, we'll add the web control to our existing frame: frame1.Add(web); ...
Now things begin to get really interesting. Type “entry1.” and
you’ll get a list of possible completions. Select “Activated,” the
event called when someone types into the text entry and presses
Return. We want the entered text to be loaded as a URL, so we’ll
need to delegate a new method, load_url, to entry1.Activated.
C# supports operator overloading like C++ does, so we can do that
with a simple shortcut, literally adding the method load_url to the
list of delegates that will be fired when
entry1.Activated occurs. To do that, we’ll just add the
following line, right before “Application.Run().”
// We can define load_url later
entry1.Activated += load_url;
Of course, now we have to actually implement the load_url method we
delegated to the entry1.Activated event. We’ll get the URL from the
text entry control. In other languages, such as Java, we’d do that
by using a “getter” method, something like
entry1.getText(). In C#, we have a shortcut, again through
operator overloads. “Getter” and “setter” methods still exist, but
you can also just get or set data as a property of its parent
object: entry1.Text, instead of creating a string, setting the
string to the value of entry1.getText(), and then using the data.
That seems trivial at first, but in more complicated situations it
can clarify syntax to a great degree.
...
// Connect the Signals defined in Glade
public void OnWindowDeleteEvent (object o, DeleteEventArgs args)
{
Application.Quit ();
args.RetVal = true;
}
// A delegate signature has two parameters.
// The first one is the source object that the event was invoked on
// and the second is the list of arguments for that event.
// We have it easy here, because we already know where the event comes
// from, and don't care much about the arguments either.
void load_url( object source, EventArgs args) {
web.LoadUrl(entry1.Text);
}
...
Save your work and select Run->Compile All. Since the
gui.glade file is listed in the project’s resource file list, it
will be bundled into the executable automatically.
After compilation, you should be able to run the application by
selecting Run->Run. Test it by entering a URL such as
http://go-mono.com, and pressing Enter to trigger the entry1.Activated
event.
N.B. If you’d like to run your application from the command line, you’ll need to add MOZILLA_HOME to your LD_LIBRARY_PATH
Internationalization
Because we’ve used some stock components in our UI, Gnome will
know how to automatically localize them for us. For example, in a
terminal, go to the MyBrowser/bin/Debug/ directory, where the browser
executable was built earlier, and enter the command:
LANG=fr_FR mono MyBrowser.exe
Setting the LANG environment variable to fr_FR (French as spoken
in France, as opposed to, say, fr_CA, the Canadian (Quebecois)
dialect.)
You should see this:

For a better example, try this one:
LANG=he_IL mono MyBrowser.exe
he_IL designates Hebrew (he) as used in Israel (IL). Notice how the
button and general UI order has been inverted to reflect the
right-to-left writing direction found in Hebrew.

Further Exercises
To build on what you’ve learned so far, try the following exercises:
- Attach actions to the Forward and Back buttons. You’ll need to implement a history queue, and decide how far back it should go.
- Implement a Refresh button.
- Implement a Go button, so that entry1.Activated can be triggered without pressing Return.
- Implement a Home button.
- Add a status bar.
- Add exception handling for missing pages (404) and so forth.
- Add an application menu with an About box.
[...] Many people asked me where the “Glade# for Rapid Development: Simple Web Browser” tutorial had gone. It’s now been relocated here. [...]
[...] I recently updated my mono/glade tutorial with: [...]
[...] And what else you can do with a few lines of Mono code ? Simple Web Broser (I think this is a bit old, but still useful) [...]
[...] Mono [...]
I am trying to run the app from console. But it loads the GUI but on the web site area none displayed. Running from the IDE works fine. I dont’ know how to call the function from command line. MOZILLA_HOME? where is it. I tried export LD_LIBRARY_PATH=/usr/lib/xulrunner../:$LD_LIBRARY_PATH and exec mybrowser.exe. Does not work. Can you help please.