Our next example is an application built using VCL or CLX components in the IDE. This program uses automatically 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.
The program includes a project file and
two new unit files. First, the project file:
program
Greeting; { comments are enclosed
in braces }
uses
Forms, {change the unit name to QForms
on Linux}
Unit1 in 'Unit1.pas' { the unit for
Form1 },
Unit2 in 'Unit2.pas' { 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 VCL and CLX; 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 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.
Unit1 looks like this:
unit
Unit1;
interface
uses { these units are part of the Visual
Component Library (VCL) }
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;
{
On
Linux, the uses clause looks like this:
uses { these units are part of CLX }
SysUtils, Types, Classes, QGraphics,
QControls, QForms, QDialogs;
}
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
Form2.ShowModal;
end;
end.
Unit1 creates a class named TForm1 (derived from 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 hides Form1 and it displays Form2 (the call to Form2.ShowModal). Form2 is defined in Unit2:
unit
Unit2;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs,
StdCtrls;
{
On
Linux, the uses clause looks like this:
uses { these units are part of CLX }
SysUtils, Types, Classes, QGraphics,
QControls, QForms, QDialogs;
}
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;
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 cann’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 one procedure. TForm2.CancelButtonClick is called at
runtime whenever the user presses CancelButton; it closes Form2.
This procedure (along with Unit1’s TForm1.Button1Click) is known
as an event handler because it responds to events that occur while the
program is running. Event handlers are assigned to specific events by the form
(.dfm on Windows .xfm on Linux) 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.
Program organization: Overview
Other files used to build applications
第三个范例是一个在集成开发环境(IDE)中用VCL(Delphi)或CLX(Kylix)建立的应用程序。该程序使用自动产生的窗体文件和资源文件,因此不能只编译源代码。该范例体现了Object Pascal的重要特征。除了是多单元程序组织以外,该范例程序还使用了类和对象。
程序包括一个工程文件和两个单元文件。工程文件源代码如下:
program
Greeting; { 注释内容用花括号括起来 }
uses
Forms, { 对于Linux,这里应为QForms }
Unit1 in 'Unit1.pas' { the unit for
Form1 },
Unit2 in 'Unit2.pas' { the unit for
Form2 };
{$R
*.res} { 该编译指示将连接于工程文件同名(主文件名)的资源文件 }
begin
{ 调用Application
}
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
Application.Run;
end.
这里再一次将程序命名为Greeting。该程序引用了三个单元:Forms,是VCL的一部分(对于Linux,这里应为QForms,是CLX的一部分);Unit1,与应用程序的主窗体(Form1)相关联;Unit2,与另一个窗体(Form2)相关联。
程序中对一个名为Application的对象进行了一系列调用,该对象是Forms(在Linux中是QForms)单元中定义的TApplication类的一个实例(Borland集成开发环境为每个工程自动产生一个Application对象)。程序中两次调用TApplication类的CreateForm方法,第一次调用是创建Unit1中定义的TForm1类的实例Form1,第二次调用是创建Unit2中定义的TForm2类的实例Form2。
Unit1源代码如下:
unit
Unit1;
interface
uses { 在Delphi中,这些单元是可是化组件库(VCL)的一部分
}
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;
{
对于Linux,
uses子句应为:
uses { 在Kylix中,这些单元是CLX的一部分
}
SysUtils, Types, Classes, QGraphics,
QControls, QForms, QDialogs;
}
type
TForm1 = class(TForm)
Button1: TButton;
procedure
Button1Click(Sender: TObject);
end;
var
Form1: TForm1;
implementation
uses
Unit2; { Form2在该单元中定义 }
{$R
*.dfm} { 该编译指示将连接Unit1的窗体文件
}
procedure
TForm1.Button1Click(Sender: TObject);
begin
Form1.Hide;
Form2.ShowModal;
end;
end.
Unit1中构造了一个名为TForm1(起源于TForm)的类并声明了相应的对象实例Form1。TForm1中含有一个按钮Button1(TButton的实例)和一个名为TForm1.Button1Click的过程(运行时按下按钮Button1时调用该过程)。过程TForm1.Button1Click隐藏Form1并显示Form2(调用Form2.ShowModal)。Form2在Unit2中定义。
unit
Unit2;
interface
uses
Windows, Messages, SysUtils, Classes,
Graphics, Controls, Forms, Dialogs,
StdCtrls;
{
对于Linux,
uses子句应为:
uses { 这些单元是CLX的一部分 }
SysUtils, Types, Classes, QGraphics,
QControls, QForms, QDialogs;
}
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构造了TForm2类并声明了相映的实例Form2。TForm2中含有一个按钮(CancelButton,TButton的实例)和一个标签(Label1,TLabel的实例),从源代码中无法看出这些结构。其中,Label1显示的标题是“Hello World!”,该字符串保存在Label1的属性Caption中,相应定义在Form2的窗体文件Unit2.dfm中。
Unit2中定义了一个过程TForm2.CancelButtonClick,运行时用户无论何时按下按钮CancelButton都将调用该过程,该过程将关闭窗体Form2并显示窗体Form1。当程序在运行中时,该过程将对按下按钮CancelButton这一事件进行响应,因此该过程又叫事件处理程序(event handler)。在Borland集成开发环境中,事件处理程序通常总是和指定的事件相关联,所有的关联信息都保存在窗体文件(在Windows中是.dfm,在Linux中是.xfm)中。因此,当前范例中的事件处理程序TForm1.Button1Click和TForm2.CancelButtonClick分别与事件TForm1.Button1.OnClick和TForm2.CancelButton.OnClick相关联,关联信息分别保存在窗体Form1和Form2对应的窗体文件Unit1.dfm和Unit2.dfm(在Linux中分别是Unit1.xfm和Unit2.xfm)中。
Greeting程序开始运行时,Form1出现而Form2不可见。默认情况下,运行时只有第一个在工程文件中被创建的窗体是可见的,该窗体叫做工程的主窗体(main form)。当用户按下窗体Form1中的按钮Button1时,Form1消失而Form2出现,并且Form2中显示问候语“Hello World!”。当用户关闭窗体Form2(按下按钮CancelButton,或按下窗体标题栏中的关闭按钮,或选择窗体的系统菜单中的“关闭”菜单)时,窗体Form1重新出现。
编者注
显然,原文的源代码和译文的源代码有明显的出入。根据帮助主题内容来看,按下窗体Form1中的按钮Button1后,Form2出现而Form1消失,按下Form2中的按钮CancelButton后,Form1出现而Form2消失。因此需要对Form2的OnClose事件进行响应,已实现预期效果。事实上,原文中的代码根本无法通过编译,因为Unit2中的TForm2.FormClose事件处理程序只有声明而没有实现(在译文中已经修正)。