HOME - - - - - - - TUTORIALS INDEX - - - - - - - - - - - - Other material for programmers

Delphi tutorial, An overview

This has good information, and a search button at the bottom of the page,

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

Click here if you want to know more about the source and format of these pages.

A comprehensive overview of everything that goes into a minimal Delphi package!

This discussion is more philosophical than most of my Tutorials. It gives you background, without much 'How To' stuff.

After you have made a start on even a tiny Delphi project, at least 7 files will have been saved on your disc. More on these files in a moment. Contrary to my usual practice, in this tutorial I allowed Delphi to use the names it liked for things. I am using Delphi version 2.

When you are at work on a Delphi project, your main attention will be on two things:

More on these in a moment.


You will likely NOT be particularly aware of another element, the .dpr file. However, I am going to start with it, because it is in overall charge. It is, you might say, the 'parcel' within which everything else is held.

For a simple project, the .dpr file looks like...
program Project1;

  Unit1 in 'UNIT1.PAS' {Form1};

{$R *.RES}

  Application.CreateForm(TForm1, Form1);
You can examine .dpr files (and .opt, .dof, and .pas) files simply by opening them with Notepad. For a .dpr file, you can also open it inside Delphi using View | Units. The name of the .dpr file in the units list will be "Project1" if you haven't changed the project's name to something more sensible. (See another of my tutorials for project and unit naming suggestions.)

That may be the last time you look in a .dpr file for some time... but remember it is there. It may be involved in some mystery you someday encounter.

You do need to take a copy of the .dpr file as part of any backup you do of your project.

Details of .dpr

Just knowing it is there is probably sufficient, but for the keen among you, here is some discussion of the contents of the .dpr file. The less keen and the trusting can take my word for it and skip down to the next important stuff....

Delphi is a block structured language. Every Delphi application consists of, at least, the word "program", a name for the program ("Project1" in the example), the word "begin", and the word "end", followed by a period.

Sadly a program with only those elements won't do much! So we put "stuff" in... but only in the right places, and according to rules. But the "backbone" remains the same.

I was a teacher for 20 years. Perhaps if you know that, you can excuse a tendency to pedantry? However, I remain unrepentant, because Pascal (on which Delphi is based) was written not to deliver programs, but as hypothetical teaching language. And a very good language it is, because it is essentially fractal: You can look at it at various "magnifications", and what you see doesn't change much.

We've seen the overall pattern of the "top" layer of the application. Between the "begin" and "end." the only thing you insert is a statement, or statements separated by semicolons. It really is that simple and elegant. The catch is that there are an awful lot of different statements which can go there, and you need to master a few of them before you can accomplish much.

In the Delphi application we are looking at, in the unit we are looking at, there are three statements between the "begin" and "end.". The first says "do the "initialize" code that is defined within the "application" "object". You don't need to worry much about what that object is, or what the code does. You do need to become comfortable, soon, with the "dot notation", and the idea of objects and the things they are endowed with. "Initialize" is an example of a method. (You may have used languages with functions and procedures. Methods are similar.) The other thing objects can have is properties. (In other languages, variables are similar. No properties are present in the Delphi we've seen so far.)

So! The Delphi .dpr file we're looking at does three things... it initializes the application, creates a form, and runs. What about the other "stuff" in the .dpr file?

1) The word "uses" begins a clause that informs Delphi about things that are to be consulted or incorporated in building your application. Things are usually added to the "uses" clause for you, as needed.

2) The { and } enclose a comment. Typically, the compiler just ignores things inside { }s. That is, after all, what programmers mean by a comment! However, if the comment is defined by { }s (there are other ways to mark something as a comment), then if the first character of the comment is a $, the comment becomes a compiler switch. In this case, it is the "R" switch, defining where the compiler will find resources it needs. The *.res is part of the {$R....

And one other niggly little detail... I did say you could skip this section... If you insert {$R+} or {$R-} in your code, it means something else. (Turn range checking on or off. Aren't you glad you asked? You didn't?) Delphi isn't usually so clumsy about saying ""A" means "X", except when.... And if you have "A", and you see "B", then....". Promise!

That's enough of that! Back to essentials!


In general, it is unwise to 'tinker' with the contents of the various files Delphi creates, except through the mechanisms provided by Delphi.

Well! We've made a start! Boring, and things you don't normally need to worry about, so far.


Next we're going to deal with some odds and ends, just to be thorough. Stuff which is more useful does follow.

After a project has been run once, there is an .exe file. This is 'the program'. It is what you give to people whom you allow to use the fruits of your labors. It is all you release to the public if you want to keep control of your program. They will find it very, very hard to "look under the hood". They can use your program, but not see how it is put together.

In Delphi 1, there will be an .opt file, in Delphi 2 a .dof file. I think they hold the options you have set up for the project's development environment. (I've never needed to do anything with or about the .opt file. You don't need to copy it when you backup a project.)

There is a .res file. I think this holds, or indexes, the projects 'resources'.. a term with a specific meaning in Windows programming. (I've never needed to do anything with or about the .opt file. You don't need to copy it when you backup a project.)

For each form in the project, there is.... Simple projects have only one form. Don't be nervous of trying a project with multiple forms... they aren't hard... but many jobs can be done with just one form.

The .dfm file holds details about what size the form is, where it appears on the screen, what controls (buttons and such) it contains, where they are on the form, etc, etc. I recommend that you stay out of the .dfm form, but you can look at it if you think it will help you understand some mystery. (Right-click on the form, select "View as text".) The Delphi GUI form designer, one of the two principal tools you use in developing Delphi applications, will take care of the contents of the .dfm file for you. All is revealed in other tutorials. You need a copy of any .dfm files when you back up a project.

The .pas file holds your source code. If your program has "showmessage('Hello world');" in it, it will be in the .pas file. You need a copy of any .pas files when you back up a project. You will work with the .pas file extensively. It is where you write the bits you write to create your masterpiece. There's more on this in a moment.

The .dcu file holds a compiled version of the .pas code. It becomes more important when you work on a multi-form project. (In those circumstances, the .dcu files can speed the compilation of a new version of your application.)

One more paragraph, which you can skip, on .dcu files: Another use of .dcu files is as follows. Suppose you've created a great way to do some common task, for example converting temperatures between Fahrenheit and Celsius. Further suppose that the task isn't easy to code and that you want to make your solution available to other programmers. You can put the essential code into a unit, and explain to the other programmers how to use the unit, and send them the .dcu. They can then use what you have created... but they won't be able to see the code that does the work. This is explained in detail in my tutorial on user-created external units.

You don't need a copy of any .dcu files when you back up a project.

There are projects with units which have no form, but every project has at least one form, and every form has a .pas, .dfm, and .dcu file.

You will encounter a number of extensions starting with a tilde, e.g. .~fm, .~as. These are previous versions of files which Delphi can in some circumstances resurrect, should you need to revert to an earlier version of your work... but, like the Windows recycle bin, rely on being able to recover things from here at your peril. Work smart, and you won't need the ~ files. You don't need to take copies when you do backups.


Now let's return to the .pas files.

The .pas files hold what I, an old-timer, think of as 'the program'. In the Good Old Days, in Basic, it could have been..

    10 FOR X=1 to 10
    30 NEXT X

Of course, nothing could be so simple with Windows. This isn't Delphi's fault!

Remember that Delphi derives from Pascal? In Pascal, the program above would be:
    program hi;
    var c1:byte;
    for c1:=1 to 10 do writeln('Hello');
All right, I admit, it is a little longer... but worth it. It is worth it for various reasons connected with why programming in Pascal is so pleasant.

Now... Before I seem too critical, I must admit, the overheads I am about to describe DO bring certain benefits in their wake. I am, for instance, writing this in a wordprocessor, checking what it looks like with a web browser, and checking various things in Delphi from time to time... all on one computer, without doing anything tiresome to switch from application to application. Think that is unremarkable? Thank your date of birth that you don't remember the not-so-good old days. It wasn't always so.

When you write for Windows, you have to remember a bunch of things, if you programmed on simpler systems in the past.

1) You do not have exclusive use of the machine. Your program is only one of many sharing the machine, even when no other user launched applications are running. Your program has to fit within the framework organized by Windows. In older terms, your program is almost like a procedure which is only one of several being visited in turn by an outer loop.

(An aside: While you would probably get away with the equivalent of...

     FOR X=1 to 10: PRINT 'Hi': NEXT X

... it would be a Bad Thing to try. If for some reason the program got stuck in the loop, you would bring Windows crashing down. (Where have we had that experience?). Always put....
...inside any loop which may take even tiny amounts of time to complete, or which could POSSIBLY fail to complete.... and remember that just 'cause you haven't notice why it isn't going to complete doesn't mean that it won't! For example, the following won't 'work':

Simple Delphi Program...
var c1,c2:byte;
   for c1:=1 to 500 do c2:=c2+c1;
Yes... I know you can see why not. But variable declarations are not normally so nicely close to variable mis-uses, are they?

Don't get the idea that all loops are bad. By all means use them, even without including an application.processmessages, for things like managing the values in an array. But don't create situations where the program will be thrashing through a loop while it waits for a human. We'll cover many ways to "wait" in other tutorials.

(end of aside.)

2) (Another thing to remember when working with Windows) It isn't easy (or often desirable) to set things up so that your user is marched through a process in quite the same orderly way that used to be the rule. It may help you to think of almost any Windows application as a video recorder. It is an object. (That word! No coincidence.) The application has a certain appearance. (The appearance is defined by your form.) It behaves in certain ways. If you push the rewind button, it does that, for instance. Your program code ('for c1:=1 to 500 do c2:=c2+c1;', etc) is what determines the object's behavior. But users may want to play something back one day, rewind a tape another, etc, and you can't be sure which things uses will want to do next.


So far so good, I hope? We've looked at, dealt with, a bunch of things that are part of every Delphi application, but things that you don't have to do much with directly. Now we get to the heart of the stuff you do need to know about, work with.

When you see the next bunch of stuff, don't panic (Mr. Mannering). You'll know your way around it eventually. Furthermore, most of it is written for you by Delphi! Indeed... it is generally a bad idea to tinker with it WITHOUT allowing Delphi to assist your efforts.

That's the good news. The bad news is that almost all of the following is the 'core' of every unit's code! Every unit with a form will have almost all of the following.
unit Unit1;


  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls;

  TForm1 = class(TForm)
    Label1: TLabel;
    procedure Label1Click(Sender: TObject);
    { Private declarations }
    { Public declarations }

  Form1: TForm1;


{$R *.DFM}

procedure TForm1.Label1Click(Sender: TObject);

The unit above is for a simple form with one thing added to it: a label. The label is called Label1. It initially says 'Hi'. When you run the program, clicking on the 'Hi' changes it so that it says 'Clicked'!

Writing such a program using Delphi is not within the scope of this essay. Don't worry, you'll do similar things in other tutorials. However, just to give you an idea of what gave rise to the code above.... To create such code, the programmer would set up the form, add the label, and then add the single line...
Prior to the programmer's typing 'efforts', double clicking his/ her mouse on the label would have added (near the bottom) the....
procedure TForm1.Label1Click(Sender: TObject);
... and (near the top), the....
procedure Label1Click(Sender: TObject);
(The 'Label1: TLabel;' would have been added when the label was added to the form.)

All of the rest of what you see in the 'Simple Delphi Program' listing is common to all Delphi units! It is the 'lines' on a 'blank' page.

And that's it! You now have a pretty good overview of the parts of any Delphi project. Developing an application is 'nothing more' (!) than building on the framework described. As your work progresses, from time to time, you will 'break' something. I hope that by giving you a clear picture of the overall structure I will have prepared you find and fix errors more quickly.

One strength... and one irritation... of Pascal (on which Delphi is built) is that it is fussy about the program's structure. After many years of programming in Delphi, I often (through typos or carelessness) introduce errors into my code which make it non-compliant with the Pascal structure rules. Understand the syntax rules, and you will often easily find such mistakes. The fussiness does help you to build robust applications.

Other tutorials in this collection address two related topics:

1) How you add things to the basic framework. (For now, try not to be too adventurous.... Delphi helps you add things correctly... if you let it!) (Level 2: Adding Things To A Unit)

2) The Pascal syntax. (You can find lots of information on this in the Delphi Help files... don't overlook this valuable, if sometimes patchy or frustrating, resource.

Just before I close, let me warn you of a little "Gotcha". While all that I said above about Delphi doing much of the typing for you is true, if you tried to generate the example given, and you saved the project after double clicking on the label to generate the "skeleton" of the OnClick handler, but before adding the label1.caption:='Clicked'; between the begin and the end, then Delphi will remove the skeleton. It is only trying to keep your code tidy! There's no point in a "Does nothing" event handler, is there? (All you need to do to "fool" Delphi into leaving an empty procedure is to put something, anything, (even just a comment line) between the begin and the end.)

Which brings us neatly to a different "end"!


Was the above of any use? Please send an email, at least. (If you would be interested in more tutorials like this, say so. For my idle curiosity... Where are you, please? (City, state, country?)

Even better, download a piece of my software, try it and pass it on to someone? (See the "Offers" section below.)

Cheers, Tom Boyd

            powered by FreeFind
  Site search Web search
Site Map    What's New    Search This search merely looks for the words you enter. It won't answer "Where can I download InpOut32?"
Please visit the following to help make my site better known...

        Top 100 Borland

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!!! Sheepdog Software (tm) is supposed to help do that, so if you found this stuff useful, (and you run a Windows or MS-DOS 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 freeware, shareware page.

Link to Tutorials main page
How to email or write this page's editor, 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 site causes a script to run, it is for things like the Google panels. Be sure you know all you need to about spyware.