Object Pascal is a high-level, compiled, strongly typed language that supports structured and object-oriented design. Its benefits include easy-to-read code, quick compilation, and the use of multiple unit files for modular programming.
Object Pascal has special features that support Delphi's component framework and RAD environment. For the most part, descriptions and examples in this manual assume that you are using Object Pascal to develop Delphi applications.
Programs are usually divided into source-code modules called units. Each program begins with a heading, which specifies a name for the program. The heading is followed by an optional uses clause, then a block of declarations and statements. The uses clause lists units that are linked into the program; these units, which can be shared by different programs, often have uses clauses of their own.
The uses clause provides the compiler with information about dependencies among modules. Because this information is stored in the modules themselves, Object Pascal programs do not require makefiles, header files, or preprocessor "include" directives. (Delphi's Project Manager generates a makefile each time a project is loaded in the IDE, but saves these files only for project groups that include more than one project.)
For further discussion of program structure and dependencies, see Chapter 3, "Programs and units."
The compiler expects to find Pascal source code in files of three kinds:
Unit source files contain most of the code in an application. Each Delphi application has a single project file and several unit files; the project file--which corresponds to the "main" program file in traditional Pascal--organizes the unit files into an application. Delphi automatically maintains a project file for each application.
If you are compiling a program from the command line, you can put all your source code into unit (.PAS) files. But if you use the Delphi IDE to build your application, you must have a project (.DPR) file.
Package source files are similar to project files, but they are used to construct special dynamic-link libraries called packages. For more information about packages, see Chapter 9, "Dynamic-link libraries and packages."
In addition to source-code modules, Delphi uses several non-Pascal files to build applications. These files are maintained automatically by Delphi and include
A form (.DFM) file is either a text file or a compiled Windows resource file that can contain bitmaps, strings, and so forth. Each form file represents a single Delphi form, which usually corresponds to a window or dialog box in a Windows application. The Delphi IDE allows you to view and edit form files as text, and to save form files as either text or binary. Although the default behavior is to save form files as text, they are usually not edited manually; it is more common to use Delphi's visual design tools for this purpose. Each Delphi project has at least one form, and each form has an associated unit (.PAS) file that, by default, has the same name as the form file.
In addition to form files, each Delphi project uses a standard Windows resource (.RES) file to hold the bitmap for the application's icon. By default, this file has the same name as the project (.DPR) file. To change an application's icon, use Delphi's Project Options dialog.
A project options (.DOF) file contains compiler and linker settings, search directories, version information, and so forth. Each project has an associated project options file with the same name as the project (.DPR) file. Usually, the options in this file are set from Delphi's Project Options dialog.
Various tools in the Delphi IDE store data in files of other types. Desktop settings (.DSK) files contain information about the arrangement of windows and other configuration options; .DSK files can be project-specific or environment-wide. The Integrated Translation Environment generates .RPS and .DFN files that contain information about resource localization. The Data Module Designer maintains diagram descriptions in .DTI files. These files have no direct effect on compilation.
The first time you build an application or a standard dynamic-link library, the compiler produces a .DCU (Delphi compiled unit) file for each new unit used in your project; all the .DCU files in your project are then linked to create a single .EXE (executable) or .DLL file. The first time you build a package, the compiler produces a .DCU file for each new unit contained in the package, and then creates both a .DCP and a .BPL file. (For more information about dynamic-link libraries and packages, see Chapter 9, "Dynamic-link libraries and packages.") If you use the -GD switch, the linker generates a map file and a .DRC file; the .DRC file, which contains string resources, can be compiled into a resource file.
When you rebuild a project, individual units are not recompiled unless their source (.PAS) files have changed since the last compilation, or their .DCU files cannot be found, or you explicitly tell the compiler to reprocess them. In fact, it is not necessary for a unit's source file to be present at all, as long as the compiler can find the .DCU file.
The examples that follow illustrate basic features of Object Pascal and Delphi programming. The first two examples are not Delphi applications, but you can compile them from the command line.
The program below is a simple console application that you can compile and run from the command prompt.
program Greeting;
{$APPTYPE CONSOLE}
var MyMessage: string;
begin
MyMessage := 'Hello world!';
Writeln(MyMessage);
end.
The first line declares a program called Greeting. The {$APPTYPE CONSOLE} directive tells the compiler that this is a console application, to be run from the command line. The next line declares a variable called MyMessage, which holds a string. (Object Pascal has genuine string data types.) The program then assigns the string "Hello world!" to the variable MyMessage, and sends the contents of MyMessage to the standard output using the Writeln procedure. (Writeln is defined implicitly in the System unit, which the compiler automatically includes in every application.)
If you have Delphi installed and your Path includes the Delphi\Bin directory (where DCC32.EXE and DCC32.CFG reside), you can type this program into a file called GREETING.PAS or GREETING.DPR and compile it by entering
DCC32 GREETING
on the command line. The resulting executable (GREETING.EXE) prints the message "Hello world!"
Aside from its simplicity, this example differs in several important ways from programs that you are likely to write with Delphi. First, it is a console application. Delphi is typically used to write Windows applications with graphical interfaces; hence, in a Delphi application you would not ordinarily call Writeln. Moreover, the entire example program (save for Writeln) is in a single file. In a Delphi application, the program heading--the first line of the example--would be placed in a separate project file that would not contain any of the actual application logic, other than a few calls to methods defined in unit files.
The next example shows a program that is divided into two files: a project file and a unit file. The project file, which you can save as GREETING.DPR, looks like this:
program Greeting;
{$APPTYPE CONSOLE}
uses Unit1;
begin
PrintMessage('Hello World!');
end.
The first line declares a program called Greeting, which, once again, is a console application. The uses Unit1; clause tells the compiler that Greeting includes a unit called Unit1. Finally, the program calls the PrintMessage procedure, passing to it the string "Hello World!" Where does the PrintMessage procedure come from? It's defined in Unit1. Here's the source code for Unit1, which you can save in a file called UNIT1.PAS:
unit Unit1; interface procedure PrintMessage(msg: string); implementation procedure PrintMessage(msg: string); begin Writeln(msg); end; end.
Unit1 defines a procedure called PrintMessage that takes a single string as an argument and sends the string to the standard output. (In Pascal, routines that do not return a value are called procedures. Routines that return a value are called functions.) Notice that PrintMessage is declared twice in Unit1. The first declaration, under the reserved word interface, makes PrintMessage available to other modules (such as Greeting) that use Unit1. The second declaration, under the reserved word implementation, actually defines PrintMessage.
You can now compile Greeting from the command line by entering
DCC32 GREETING
There's no need to include Unit1 as a command-line argument. When the compiler processes GREETING.DPR, it automatically looks for unit files that the Greeting program depends on. The resulting executable (GREETING.EXE) does the same thing as our first example: it prints the message "Hello world!"
Our next example is a Windows application built with Delphi's Visual Component Library (VCL). This program uses Delphi-generated form and resource files, so you won't be able to compile it from the source code alone. But it illustrates important features of Object Pascal. In addition to multiple units, the program uses classes and objects, which are discussed in "Classes and objects."
The program includes a project file and two new unit files. First, the project file:
program Greeting; { comments are enclosed in braces }
uses
Forms,
Unit1 { the unit for Form1 },
Unit2 { the unit for Form2 };
{$R *.RES} { this directive links the project's resource file }
begin
{ calls to Application }
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
Application.Run;
end.
Once again, our program is called Greeting. It uses three units: Forms, which is part of the VCL; Unit1, which is associated with the application's main form (Form1); and Unit2, which is associated with another form (Form2).
The program makes a series of calls to an object named Application, which is an instance of the TApplication class defined in the Forms unit. (Every Delphi project has an automatically generated Application object.) Two of these calls invoke a TApplication method named CreateForm. The first call to CreateForm creates Form1, an instance of the TForm1 class defined in Unit1. The second call to CreateForm creates Form2, an instance of the TForm2 class defined in Unit2.
unit Unit1;
interface
uses { these units are part of Delphi's Visual Component Library (VCL) }
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
uses Unit2; { this is where Form2 is defined }
{$R *.DFM} { this directive links Unit1's form file }
procedure TForm1.Button1Click(Sender: TObject);
begin
Form1.Hide;
Form2.Show;
end;
end.
Unit1 creates a class named TForm1 (derived from the VCL's TForm) and an instance of this class, Form1. TForm1 includes a button--Button1, an instance of TButton--and a procedure named TForm1.Button1Click that is called at runtime whenever the user presses Button1. TForm1.Button1Click does two things: it hides Form1 (the call to Form1.Hide) and it displays Form2 (the call to Form2.Show). Form2 is defined in Unit2:
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm2 = class(TForm)
Label1: TLabel;
CancelButton: TButton;
procedure CancelButtonClick(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
end;
var
Form2: TForm2;
implementation
uses Unit1;
{$R *.DFM}
procedure TForm2.CancelButtonClick(Sender: TObject);
begin
Form2.Close;
end;
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Form1.Show;
end;
end.
Unit2 creates a class named TForm2 and an instance of this class, Form2. TForm2 includes a button (CancelButton, an instance of TButton) and a label (Label1, an instance of TLabel). You can't see this from the source code, but Label1 displays a caption that reads "Hello world!" The caption is defined in Form2's form file, UNIT2.DFM.
Unit2 defines two procedures. TForm2.CancelButtonClick is called at runtime whenever the user presses CancelButton; it closes Form2. TForm2.FormClose is called at runtime whenever Form2 closes; it reopens Form1. These procedures (along with Unit1's TForm1.Button1Click) are known as event handlers because they respond to events that occur while the program is running. Event handlers are assigned to specific events by the form (.DFM) files for Form1 and Form2.
When the Greeting program starts, Form1 is displayed and Form2 is invisible. (By default, only the first form created in the project file is visible at runtime. This is called the project's main form.) When the user presses the button on Form1, Form1 disappears and is replaced by Form2, which displays the "Hello world!" greeting. When the user closes Form2 (by pressing CancelButton or the Close button on the title bar), Form1 reappears.
pubsweb@inprise.com
Copyright © 1999, Inprise Corporation. All rights reserved.