HOME - - / - - / - - DELPHI COURSE INDEX - - / - - / - - TUTORIALS INDEX - - / - - / - - Other material for programmers

Delphi and Lazarus Course: Getting started- the "Greeting" examples

This page is information rich, and a has search button at the bottom of the page.

Please don't dismiss it because it isn't full of graphics, scripts, cookies, etc!



You will probably find the text easier to read if you make your browser window much narrower than usual. You may also want to change your browser's zoom level, to enlarge the text. Opera (at least) lets you change zoom level easily. The text will adapt nicely to the settings you decide give the best results for your needs!

The lines of sample Delphi code in these pages will not "wrap". I.e., if a line is too long to show in the width you have set your browser too, parts of the line will be "off the page". Those lines will still copy/paste properly, at least in Opera. Please feel free to send feedback on the choices I've made! (Will you forgive me for not forcing upon you a column of links on the left and a column of ads on the right?)


You want to become a fluent Delphi or Lazarus programmer with minimal struggle? You have found a series of lessons which I hope will get you there. Instead of "Abandon All Hope, Ye Who Enter Here", my message to you is "Be Filled With Hope... You Have Fun Times Ahead"! (No, I'm not saying that in an ironic tone of voice!)

This is the first lesson in the course. As such it won't be entirely typical. For instance, most of the other lessons will start with a "What You Will Learn" section. As many of you will need little of what is in this lesson, I've only put a "What You Learned" list at the end. Please do go through this lesson, anyway, though. It may be easy, but there are still things you need about my conventions and terms. If the lesson isn't easy for you, you need to get to grips with what's here before struggling with those things and the next topics at the same time! For most of you, the examples in this lesson are so dull that they won't be much fun. I am trying to make other example programs useful and fun, but for the people who need what is in this lesson, I wanted to avoid distractions. Getting started is NOT easy... Programming is like riding a bicycle: "impossible" at first, even though it is, actually, not to hard to do.... once you know how....

You can read more elsewhere, but I want this material to move along, with lots of hands-on, practical exercises, so lets get programming.....


For good reasons, the first thing may experienced people do in any language is write something to put a little message on the screen. Fire up your Delphi or Lazarus. Start a new application. Put a label on the form. Make the caption of the label "Hello World". Don't try to save what you've done, yet. (More on that in a moment.) Run it.

You should get a Window with "Hello World" in it. Click the little "X" in the upper right to close the application. Success? Good. You can carry on with this tutorial. If the above had too little explanation, then give this a try. (It has also been prepared to answer the questions of both Delphi and Lazarus students.) Your browser will open it in a new window, so you can come back here after you've done the other tutorial.

Two terms clarified, I hope:

An "application" is what most people mean when they speak of "a program". It is the software to make the computer do something. One of the delights of Delphi is that Delphi-created applications stand alone... they don't (ordinarily) need support packages, though you can write things to use them if you have a reason to.

An application is just one sort of "project" which can be developed using Delphi or Lazarus. For the time being, you will be creating applications, and don't need to worry about the other sorts of projects. Thus, a menu item saying "Save Project" can be thought of as saying "Save my application", for your purposes.

Your users will need just one file: the .exe (or application) file created by Delphi or Lazarus from several other files which you, as the program author, will create. You will need them any time you wish to revise the application.

I don't feel strongly about it, and you can ignore this advice, but I would recommend that you tell your computer NOT to "hide file extensions for known file types." We're big boys and girls! We don't need our computers "dumbed down"... and if you can see it, you can work with it.

Saving your masterpiece

It will help you when following these lessons if you use my naming conventions when saving things. For the little project we've just done, you should proceed as follows:

Use the Object Inspector to name the form "Greeting1f1". The Object Inspector is a very important floating window with, helpfully enough, "Object Inspector" in it's title bar. You can get to it by pressing F11, when your application is not currently running. (Pressing F11 if the Object Inspector already has focus will send you back to the form you were working on, or the form's code, depending on which you were working on previously. When the form or its code have focus, F12 will switch you between the two of them. Try to develop the habit of using F11 and F12.)

Whoa! As I was saying... Sorry for that little F11/F12 diversion....

Use the Object Inspector to name the form "Greeting1f1". The Object Inspector has two tabs: "Properties" and "Events". Both are vital, but it is "Properties" we want for the moment. The Object Inspector also has a drop-down list at its top. At the moment, it probably offers "Form1" and "Label1". These are the names Delphi has generated for the two objects added so far to your "Hello World" application. Select the Form1 object. Select the Object Inspector's "Properties" tab. Go down to the Name property, and change that to "greeting1f1". Make a habit of naming your forms with a name that starts with the application's name, and then has "f1" (for Form 1) tacked onto the end.

(An aside: If you select an object on the application's form before switching to the Object Inspector, you will find you have that object already selected in the Object Inspector when you get there. Before long, this will be something that you'll do without noticing.)

Resize the Object Explorer window so that it is as tall as your screen resolution allows, without overlapping the Delphi main window. I suggest you put the Delphi main window in the screen's upper left.

Now that you have named the application's form, you should save your project.

Be organized about where you save things. Have a system for the names you use for the parts.

A separate folder for each application is a Good Idea. For the moment, with "Hello World", it may be slight overkill, but get into this good working habit now. It won't be overkill later.

I'd recommend setting up the following:

My Documents\Delphi projects\DT100\
... or ...
My Documents\Lazarus projects\DT100\ ←Please note: DT100, even if you are doing the Lazarus course.
    (There are just too many references to change, if we try to create LT100 alternatives.)

... and then within that, folders called Greeting1, Greeting2, etc, making new sub folders as new projects are started. You might even want to make a "Greeting" sub-folder (for the applications this lesson will give rise to) and then within that "Greeting1", "Greeting2", etc folders. The "DT100" comes from my name for the folder in which I have everything pertaining to this course. (DT: "Delphi Tutorial") When you write the first application that is of your own devising, if it were, say, for scoring an athletics match, its files would go in something like...
My Documents\Delphi projects\ScoreAthl\

The folders ideas are recommendations, as are the following. You don't have to accept either.

I also have recommendations about what to call the different parts of each application. It will be more annoying to you if you don't bother with these recommendations, as you will find that some of the names have consequences which aren't immediately obvious or easily tweaked. Many of those names will start "DD" for "Delphi Demo". Again... please don't change the name to the more logical "LD..." if you are studying Lazarus. This will save having to discuss various tedious but trivial things.

We've already looked at calling the application's form "greeting1f1".

Do a Save All. There's an entry for this under the File menu item, or you can use the button on the SpeedBar. (SpeedBar: Group of buttons in Delphi/ Lazarus bar, upper left, just below menu line. Hover your mouse pointer over the icon that you think is "Save All", and tooltip should come up.)

As I said: Do "Save All". As with most Windows applications, if you haven't saved your work previously, the save gives rise to a "Save As..." dialog... But! Notice! You will be saving several things. After you've clicked Save All, before you click Save, first change to a suitable folder. The Save As dialog lets you create new folders, as needed. Once you have created and moved to a suitable folder, the first thing you save is the application's "unit". Call it Greeting1u1. You can explicitly make the extension .pas, or leave it to Delphi to do it for you. (This routine is explained in a more "blow by blow" manner, with every detail of the Delphi and Lazarus wrinkles, in the more elementary tutorial I commended to you earlier.)

As soon as you've saved the Unit, Delphi will throw up another Save As dialog, this time for saving the Project. (Lazarus has you save the project first, then the unit.) Save it in the same folder, but call it Greeting1. The name you give the project will be the (initial... you can change it, but why give yourself the hassle?) name for the final product which users will invoke.

Again as with most Windows work, when you have done Save All once, then subsequently when you do Save All it really will be a Save, not a Save As.

In the above I said call things Greeting1f1, Greeting1u1, etc. You don't need to use a capital letter on the name, or you might want to use Greeting1F1, Greeting1U1... if is up to you. I tend not to use capitals, except to help make the elements of a compound word clear, as in ProjectNameWithLotsOfParts. It's up to you. For the .pas file in Lazarus, the system discourages you from using any upper case letters. Probably for a reason!

Hang in there... we're nearly done with Greeting1.

Some important terms, which you will come across again and again....

"Object"... don't worry about it too much for now. It is one of those things which are quite easy to use, quite hard to describe. In what you've done so far, the form is an object, the label is an object. Why do we care? It will gradually become clear.

"Component"... The label you put on the form is a component. One of the double edged swords of working with Windows, whether by Delphi or by other means, is that you will usually "put your program together" out of "bits" which someone else has designed and provided. Great for rapid development; lousy for really understanding, controlling, quality assuring your product. Also great for ease of use for your customer... they're probably already used any of the components present in your application. All components are objects, and for a while, the only objects you need to worry about are components... but there are objects which are not components. (Components are a subset of the set "objects".)

"Property"... The form had a "name" property, the label had a "caption" property. A great deal of your Delphi programming will consist of consulting or changing properties. A great part of the learning how to program for Windows is learning what components are available and what their different properties affect. In many cases, a component has many more properties that you or I will ever want to know about. Mastering Windows programming is as much about learning what you can ignore as about learning the things you need to master.

And that, Gentle Reader, is about all the Good Stuff we need to wring from out little "Hello World" program... as it stands.

Greeting2

Start a new application.Under Delphi, use "File | New Application". Under Lazarus, "File | New...", and then select "Application" in the "Project" section.

Name the form Greeting2. Put a button, a label and an edit box on it. (Click on the relevant object on the Component Palette, move the mouse pointer to the form. Click again.) The size and position of the components doesn't much matter.

When you get to more advanced applications, it will be a good idea to give most of your components more meaningful names than the ones Delphi provides. For now, apart from regularly renaming the form, you can use the Delphi or Lazarus provided names.

Change the caption property of the Button to "Click Me".

With the application not running, double click on the button. This should bring up a window with the following...
procedure TGreeting2f1.Button1Click(Sender: TObject);
begin

end;

end.
You are actually seeing only a small part of the application's code, but you're seeing the necessary bit.

The "end." is the end of the unit. It is the only "end" which gets followed by a "." You will see "end;" over and over and over.

After the "begin", in the gap, add....
label1.caption:='Hi';
Don't miss the semicolon.

This would be a good point to save your work. If you haven't saved Greeting2 before, remember to consider putting it in its own folder.

Run your application. When you click the "Click Me" button, the caption of the label should change to "Hi". Get that much working before going on to....

Revise the line you added to the application. Make it:
label1.caption:='Hi '+edit1.text;
Save your work; run it.

Now, while the program is running, change what is in the edit box, then click the button. If you made the edit box say "Fred", then you should get "Hi Fred" when you click the button. Leave the program running, change what's in the edit box to "Frederica", click the button again.

What a boring little program! But! It does illustrate some important things:

The line of code you added to the application established the event handler for the button's "OnClick" handler. If you go to the Object Inspector, select the Button1 object, and the "Events" tab, you will see "Button1Click" in the right hand column.

Windows is an "event driven" operating system, regardless of whether you write applications for it with Delphi or with Lazarus. This may drive you crazy, but, once you get the hang of it, it makes various things "easy". Well... "easy" in computer terms.

While an application is running, "things" can happen. The clicking of a button is a pretty obvious "thing". (There are many subtle "things", too, but you don't need to worry about them for a while.)

The application will respond when "things" happen. You do not need to write a loop which, among other things, from time to time asks "Is the mouse button down?" Windows takes care of watching for that, and provides a systematic (if less than transparent) management system for you.

Again... that doesn't make everything clear, I'm sure, but "go with the flow"... I hope you'll soon not be worrying to much about the details, and that you will be enjoying the resultant functionality.

Just to give the proper names to things the program illustrates:

When we said "edit1.text", we were referring to the edit box's text property. You'll do a lot with this "dot" terminology. Consider the following non-computer, non-Delphi example:

There are many towns named Alexandria. If you wanted to refer to the one in Egypt, you might call it "egypt.alexandria". The one in Mississippi could be called usa.mississippi.alexandria. I won't labor the point just now, just realize that there will be many "text" (and other) properties amongst the components of an application, and we need an easy way to say which one we mean. There's more to it than this, but we'll come to the details later.

In our event handler, we have the two symbols ":" and "=". For Delphi (and Pascal, from which Delphi evolved) purpose, ":=" is one symbol. (":" and "=" are also used, on their own, for other things.)

When we said label1.caption:='Hi '+edit1.text, we were saying...

The caption property of the label1 component should become (stuff). The "stuff" was made up of the following: An "H", an "i", and a space, and then whatever is currently in the text property of the edit1 component. One of the features of the edit box component (of which edit1 is an "instance") is that users can type things into the component's text property while the program is running.

Save what you've done. That's about all we need to do with Greeting2, but we'll use it as an example to deal with two other things.

If you go to the window which let you enter the OnClick event handler, and scroll, you'll find lots of text. (As long as Greeting2 isn't running, you can get to the window (called the unit's editing window) by pressing F12... maybe once, maybe twice.) The text should start with "unit Greeting2u1;". Eventually you'll be able to understand all you see. The good news is that you don't really need to understand it all for a while. You need to know: Don't tinker with bits you don't yet understand.

That's one of the things dealt with.

Start Windows Explorer, and drill down to the Greeting2 folder. If, as I suggested earlier, you told Windows to show you the extensions of all files, and you are using Delphi, you will find that you have the following files:
   Greeting2.exe
   Greeting2.dpr
   Greeting2u1.pas
   Greeting2u1.dfm

Those of you studying Lazarus will find a "lib" folder and a "backup" folder, both of which you can ignore, and....
   Greeting2.exe
   Greeting2.lpr
   Greeting2u1.pas
   Greeting2u1.lfm
   Greeting2u1.lpi

The first is your application, ready (and complete) for your customers. They won't need anything beyond that one file.

The second (.dpr/ .lpr) is a file that you won't look at directly. It keeps track of the application's parts, and how they fit together.

The third (.pas) can be opened in any text editor, though you'll lose the syntax highlighting. It contains the "label1.caption:='Hi '+edit1.text" type stuff.

The last (.dfm / .lfm) stores the design of the form: What components are on it, their size and position, etc.

You may have some other files. If the extension begins with a tilde (~), then the file is a backup of something, e.g. ~pa is what your current .pas file was before the most recent save. The .dof and .dcu files are things you don't need to worry about. If you want to save a backup of your Delphi application, including the sourcecode, you need: The .dpr ("project"), .dfm ("form") and .pas ("unit", named from "Pascal") files.

If you want to save a backup of your Lazarus application, including the sourcecode, you need: The .lpr ("project"), .lfm ("form") and .pas ("unit", named from "Pascal") files.... and, as I'm not sure what it does, I'd copy the .lpi file, too... but in a simple test, only the basic 3 seemed to be essential. You can study the contents of the /lpi file in a text editor. I suspect it is an initialization file, responsible for getting Lazarus to restart set up the way you were working when you last shut your Lazarus down.

Greetings 3

Anyway! What we've done so far has been quite dull. Now, I'm afraid, we move on to something downright tedious... but essential.

Start a new application. Name the form Greeting3f1. Save the project in it's own folder ("Greeting3"), calling the unit Greeting3u1.pas and the project as Greeting3.dpr.

Put two labels, an edit box, and a button on the form.

Place label1 in front of the edit box on your form. Change label1's caption to "Age in years". By the way... always leave any edit box after making changes, so the changes get noticed. You normally leave the edit box in the course of going on to make the next change, but, just before you test out your code, leave the last edit box before invoking "Run Program". (Just click in an adjacent edit box.)

Change label2's name to laOutput. Make laOutput's caption nothing. (I.e. delete all of what's in the right hand box for "Caption" in the Object inspector).

Change the edit box's text to 50.

Change the button's caption to "Click Me". Make it's name buClickMe.

(An aside: Add another button to the form. Name it buQuit. Caption it &Quit. Double click on it, and make what you get into...
procedure TGreeting3f1.buQuitClick(Sender: TObject);
begin
application.terminate;
end;
Resize the button, making it largish. Run the application; click the button. It is just an easier-to-hit thing to click on to stop the application when it is running. Because you put the ampersand (&) in front of the Q in the button's caption, the caption should come out Quit, and you can also use alt-q to stop the application running. The ampersand will do no harm in Lazarus, but it won't always give rise to the underline. This is something that the nice Lazarus developers are working to fix. End of aside!)

Double-click on buClickMe, and make (for now) the OnClick handler be...
procedure TGreeting3f1.Button1Click(Sender: TObject);
var iDays:integer;
    sTmp:string;
begin
iDays:=5;
sTmp:=inttostr(iDays);
laOutput.caption:='Hi. You are at least '+sTmp+' days old.';
end;
(This won't "Work" yet... but we'll build it into something that does. For now the application will run, but you will always be at least 5 days old, regardless of what number you put in for age.)

We've set this up to say you are "at least" x days old, because eventually you will enter your age in years, and the program will work out how old you were, in days, at your last birthday.

Save your typing. Get that much to run.

Brace yourself: We need to cover some tiresome ground.

In the event handler we've just added, you will see
var iDays:integer;
    sTmp:string;
This "declares" two "variables". The first one is a place where we can put a number, the second a place for keeping a string of characters.

Variables are useful as "pigeonholes" where we can put things we want to keep track of or work with. In some ways properties are like variables. The "caption" property of the button for instance stores the characters "Click me". In Greetings2, the "text" property of the edit box had the name of the person to be greeted.

Before we go any further, we need to cover the idea of data "type". If someone sees a vehicle leave the scene of a crime, the police will want to know what "type" of vehicle it was. Data comes in "types", too. The different things- variables, properties, etc- which can hold data can each only hold data of a certain type.

String-type data is perhaps the simplest. String-type variables hold one or more characters, in a.... string. String-type variables can even hold "numbers"... for instance, the edit box in our present program (Greeting3) starts off with a 5 and a zero, i.e. what we usually recognize as "fifty". The good thing about variables for string-type data is that they can hold just about anything. The bad thing about such variables is that they don't permit things like arithmetic. What would "fish" plus "frog" equal? Even though "50" looks like fifty to you and me, if it is stored in a string variable, you can't do arithmetic with it.

Look at the Button1 OnClick handler. Work through it from end to beginning. laOutput's caption property is only able to hold a string. That string is supplied to it in three pieces. They are "stuck together" by using the plus sign. Note that it is not doing any arithmetic here. It can be used for arithmetic (2+2 is still 4, even in Delphi), but when you have a plus sign between two strings, the plus sign says to join them. (The fancy word is "concatenate".)

'Hi you are at least ' is one string. It is a literal string, i.e., it consists of what the string consists of. Then we have + sTmp. The plus, as I said means "join these strings". The sTmp is a variable, of type string. It could be holding almost anything.

In fact, at the moment, it holds a "string" which is just one character long, and that character is '5'. How did this come to be?

Look back two lines, to the line saying iDays:=5;

That line says "The contents of the variable iDays become (from the := symbol) five". iTmp is an integer-type variable, so this assignment is perfectly okay.

The following line is quite cute. It says "The contents of the variable sTmp become the string equivalent of whatever is in the variable iDays. (inttostr is short for INTegerToString.)

So far, so good, I hope? (Apart from the fact that the edit box is, so far, pointless.)

Change iDays:=5; to iDays:=5*365. Re-run the program. When you click the button, you should now be told that you are at least 1825 days old... the age of a 5 year old, in days. (The * means "multiply")

Change the iDays line to
iDays:=strtoint(edit1.text)*365;
Run the program. NOW what's in the edit box should matter. Leave it 50, click the button. a 50 year old is at least 18250 days old. Change the 50 in the edit box to 1, click the button- you should be told that a 1 year old is at least 365 days old.

So far so good. Now put "Fred" in the edit box and click the button. You get an error message, or, in Lazarus, a "Debugger Exception Notification"! Click OK for the Delphi message, click "Break" in the case of Lazarus...which will break into the execution of the program. Now, in either environment, Greeting3 is no longer running. You can't change what's in the edit box, for instance. However, things aren't "happy" either... F11 doesn't bring up the object explorer. What's happened is that Greeting3 has been paused. Click the run button in the SpeedBar again. Previously, this has caused Delphi or Lazarus to compile your code and start running your application. What will happen at this juncture, under Delphi, is that your RAD environment will resume running your application. You will immediately get another error message, saying "Fred is not a valid integer value." The first error message is one that you'll only see during development work, when you have asked Delphi or Lazarus to compile and run Greeting3. The second is the error message that customers will see if they put "Fred" into the edit box.

The problem is arising at the point where Delphi or Lazarus tries to turn "Fred" (the contents of edit1.text) into an integer, using the StrToInt function. Neither program can do this.

You should always try to anticipate every mistake users may make, and write your application so that survives what users do.
   Greeting2u1.lfm

You can't stop users putting non numeric content into edit1's text box. (Well... you can... but that's a story for another day.) What you can (more easily) do is to deal with such inputs, as follows:

Expand the simple...
iDays:=strtoint(edit1.text)*365;
... that you have so far. turn it into...
try
iDays:=strtoint(edit1.text)*365;
except
iDays:=0;
end;
When you run this version of the program from your RAD environment, Delphi or Lazarus, you will still get the first error message / exception notification, and you will still have to re-start the program if you put Fred in the edit box. However, you won't get the second error message, and the program will continue to run.

We'll look much more closely at try...except...end later. For now, suffice it to say the following:

The word "try" starts the block. It must be matched with its own "end;". Someplace between them, the word "except" will occur. When the application runs, it will try to do the things after the "try". If there is any problem (e.g. you are trying to convert a non-numeric string into an integer), the application will skip over any remaining lines between where it is and the word "except". It will do what is between the "except" and the "try"'s "end". (In this case, set iDays to zero.) If there was no problem, the lines of code between "except" and "end" are skipped over.

When users run the application, they will not see the error message. If users try to determine the number of days in "Fred" years, they will just be told zero. A "serious" application would also give the user some feedback, explaining the bad input, but providing that is beyond the scope of this lesson.

Greetings3 Embellishment

The "if... then..." control structure is terribly important to programmers, so we're going to incorporate an example as part of Greeting3. Make the OnClick handler as follows. You'll need to move the *365, and add the if... then... line... or just copy/ paste the code wholesale!

procedure TGreeting3f1.Button1Click(Sender: TObject);
var iDays:integer;
    sTmp:string;
begin
try
iDays:=strtoint(edit1.text);
except
iDays:=0;
end;
if iDays<(5*365) then showmessage('You are precocious!');
if iDays>(80*365) then ShowMessage('Don''t overwork your elderly eyes.');
sTmp:=inttostr(iDays*365);
laOutput.caption:='Hi. You are at least '+sTmp+' days old.';
end;
The basic ideas should be fairly obvious. The "ShowMessage" procedure is new, but it is uncomplicated. (It is built into Delphi). The way the program is written now makes iDays a poor name for the variable, but it works, as long as you, the programmer, stay un-confused. Good variable name choice is an art, one you need to work at. Notice the little "trick" illustrated: To define a string, you enclose the characters of the string in apostrophes ('s). But! What if you want an apostrophe in the string? Put a double apostrophe, as in "Don''t...", and all will be well.

There is much, much more to learn about data types, but what we've done already makes a good start.

I hope you've found this lesson useful. My energy to write further lessons will be directly related to the energy you show in giving me feedback, and in availing yourself of the programs I distribute via my freeware, shareware pages.. I'm sorry there are not more lessons, yet... but they are worth at least what I've been paid for them!



What you should have learned in "Greeting":

First lesson.
Some basic working conventions.

Delphi programming environment: Main menu
SpeedBar items
Object Inspector

Some basic terms: Component
-- Property
-- Event

Components: Label
-- Button
-- Edit Box

Making buttons respond to alt-key

Making a "Stop running" button.

Error handling.

Delphi language:
--- The "if... then..." control structure.
--- Var

Delphi procedures:
--- ShowMessage.



For more help

If you haven't already been using Delphi or Lazarus successfully for a while, you might want to read another "getting started" tutorial by me... it has also been edited for Lazarus students. It repeats some of this tutorial, but it could still be useful. Among other things, it covers getting started with the SpeedBar. (But it only refers to it as the "group of buttons" in the left part of the space below the main menu.)

In Delphi version 2, the Borland supplied helpfile had some excellent material, particularly under the Contents> Using Delphi > Basic Skills section.


Click here if you're feeling kind! (Promotes my site via "Top100Borland")
   Search this site or the web        powered by FreeFind
 
  Site search Web search
Site Map    What's New    Search
Ad from page's editor: Yes.. I do enjoy compiling these things for you... I hope they are helpful. However.. this doesn't pay my bills!!! If you find this stuff useful, (and you run an MS-DOS or Windows PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!
Click here to visit editor's Sheepdog Software (tm) freeware, shareware page.

Link to Tutorials main page Link to Delphi Course index
Here is how you can contact this page's author, Tom Boyd.


Valid HTML 4.01 Transitional Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org


If this page causes a script to run, why? Because of things like Google panels, and the code for the search button. Why do I mention scripts? Be sure you know all you need to about spyware.

....... P a g e . . . E n d s .....