词条 | Delphi |
释义 | § 基本简介 Delphi Delphi具有以下的特性:基于窗体和面向对象的方法,高速的编译器,强大的数据库支持,与Windows编程紧密结合,强大而成熟的组件技术。但最重要的还是Object Pascal语言,它才是一切的根本。 Object Pascal语言是在Pascal语言的基础上发展起来的,简单易学。 Delphi提供了各种开发工具,包括集成环境、图像编辑(Image Editor),以及各种开发数据库的应用程序,如DesktopDataBase Expert等。除此之外,还允许用户挂接其它的应用程序开发工具,如Borland公司的资源编辑器(Resourse Workshop)。 在Delphi众多的优势当中,它在数据库方面的特长显得尤为突出:适应于多种数据库结构,从客户机/服务机模式到多层数据结构模式;高效率的数据库管理系统和新一代更先进的数据库引擎;最新的数据分析手段和提供大量的企业组件。 Delphi发展从Delphi1、Delphi2到现在的Delphi5,不断添加和改进各种特性,功能越来越强大。Delphi5添加了对IDE(集成开发环境)的很多改进新特性,扩展了数据库支持(ADO和InterBase数据库),带有Internet支持的MIDAS改进版,TeamSouse版本控制工具,转换功能,框架概念以及很多的新组件与新特性。 Delphi5功能十分完善和强大,本栏目将以它为基础,介绍Delphi的开发环境、基本概念、控件的使用、常用的编程方法和编程技巧。本栏目的对象为Delphi初学者,主旨是帮助初学者更快更好掌握Delphi基本的编程方法和技巧。 § 程序之父 Anders Hejlsberg,丹麦人,曾在丹麦科技大学学习工程学。Anders Hejlsberg第一次登上软件界历史舞台是在80年代早期,因为他为MS-DOS和CP/M设计了一个Pascal编译器。当时,还是一个小公司的Borland很快雇用了他,并买下了他的编译器,改称Turbo Pascal。在Borland,Hejlsberg继续开发Turbo Pascal,并最终带领他的小组设计了Turbo Pascal的替代品、开发工具史上的奇迹:Delphi语言。 § 编程入门 Delphi Delphi是全新的可视化编程环境,为提供了一种方便、快捷的Windows应用程序开发工具。它使用了Microsoft Windows图形用户界面的许多先进特性和设计思想,采用了弹性可重复利用的完整的面向对象程序语言(Object-Oriented Language)、当今世界上最快的编辑器、最为领先的数据库技术。对于广大的程序开发人员来讲,使用Delphi开发应用软件,无疑会大大地提高编程效率。 Delphi实际上是Pascal语言的一种版本,但它与传统的Pascal语言有天壤之别。一个Delphi程序首先是应用程序框架,而这一框架正是应用程序的“骨架”。在骨架上即使没有附着任何东西,仍可以严格地按照设计运行。您的工作只是在“骨架”中加入您的程序。缺省的应用程序是一个空白的窗体(Form),您可以运行它,结果得到一个空白的被放大缩小、移动、最大最小化等,但您却没有编写一行程序。因此,可以说应用程序框架通过提供所有应用程序共有的东西,为用户应用程序的开发打下了良好的基础。Delphi已经为您做好了一切基础工作——程序框架就是一个已经完成的可运行应用程序,只是不处理任何事情。您所需要做的,只是在程序中加入完成您所需功能的代码而已。 在空白窗口的背后,应用程序的框架正在等待用户的输入。由于您并未告诉它接收到用户输入后作何反应,窗口除了响应Windows的基本操作(移动、缩放等)外,它只是接受用户的输入,然后再忽略。Delphi把Windows编程的回调、句柄处理等繁复过程都放在一个不可见的Romulam覆盖物下面,这样您可以不为它们所困扰,轻松从容地对可视部件进行编程。 面向对象的程序设计(Object-Oriented Programming,简记为OOP)是Delphi诞生的基础。OOP立意于创建软件重用代码,具备更好地模拟现实世界环境的能力,这使它被公认为是自上而下编程的优胜者。它通过给程序中加入扩展语句,把函数“封装”进Windows编程所必需的“对象”中。面向对象的编程语言使得复杂的工作条理清晰、编写容易。说它是一场革命,不是对对象本身而言,而是对它们处理工作的能力而言。对象并不与传统程序设计和编程方法兼容,只是部分面向对象反而会使情形更糟。除非整个开发环境都是面向对象的,否则对象产生的好处还没有带来的麻烦多。而Delphi是完全面向对象的,这就使得Delphi成为一种触手可及的促进软件重用的开发工具,从而具有强大的吸引力。 一些早期的具有OOP性能的程序语言如C++,Pascal,Smalltalk等,虽然具有面向对象的特征,但不能轻松地画出可视化对象,与用户交互能力较差,程序员仍然要编写大量的代码。Delphi的推出,填补了这项空白。您不必自己建立对象,只要在提供的程序框架中加入完成功能的代码,其余的都交给Delphi去做。欲生成漂亮的界面和结构良好的程序丝毫不必绞尽脑汁,Delphi将帮助您轻松地完成。它允许在一个具有真正OOP扩展的可视化编程环境中,使用它的Object Pascal语言。这种革命性的组合,使得可视化编程与面向对象的开发框架紧密地结合起来。 在这一节中,来开发一个小程序。随着开发的过程,逐步介绍Delphi的主要部件及其操作方法。建议读者按照本书介绍的过程,在您的电脑上直接操作。您将对Delphi的可视化编程有一个直观、快捷的了解,必将起到事半功倍的效果。 § 安装方法 Delphi Delphi的安装与其它应用软件并无不同。2.0版必须在Windows 95以上的操作系统中使用。启动Windows 95或Windows NT后,将Delphi的光盘放入光驱(CD-ROM)中,运行光盘上的\\INSTALL\\SETUP.EXE文件,它的安装程序会提示您正确地装入Delphi。如果您是在微软中文Windows环境中安装Delphi,请参照附录A来设置您的BDE环境,以便于处理中文数据。 为避免隐藏在Delphi后的Program Manager和曾经运行过的其它程序扰乱版面,分散您的注意力,不妨在启动Delphi前关掉其它应用程序;启动Delphi后,再最小化隐藏在后面的Delphi 2.0程序组。这样屏幕上就只留下Delphi窗口可见了。 首次加载Delphi,屏幕上会出现四个窗口: 标题为“Delphi-Project1”的Delphi主窗口 Object Inspector窗口 标题为“Form1”的窗体(Form)窗口 标题为“Unit1.PAS”的代码编辑窗口。刚启动时这一窗口的大部分被“Form1”窗体所掩盖。将“Form1”窗体移开,或单击Form1窗体下方的状态行,可以使其全部可见。在“Form1”窗体的任意可见位置单击鼠标,可以恢复主窗体可见。 Delphi的主窗口位于屏幕的上端,包括Menu(菜单)、Speed Bar(加速条)和Component Panel(部件选项板)。Menu是下拉式主菜单。Speed Bar位于主窗口的左下端,由两排共14个加速按钮组成。这些按钮是菜单功能的快捷方式,各种图标直观地表示了它能执行的动作。Component Panel由一行、若干页对象按钮所组成,利用它来选择需要的部件并将它放到窗体中去。 Object Inspector窗口含有两页:Properties页显示窗体中当前被选择部件的属性信息,并允许改变对象的属性;Events页列出了当前部件可以响应的事件。按动Object Inspector下端的“Events”页标签,使得Events页可见,这一定的事件后边的空白处,可以定义对象接受到相应事件时执行的动作。首次启动时,Object Inspector窗口显示的是当前窗体Form1的属性。Object Inspector根据对象属性的多少,决定是否有滚行显示。移动滚行条,可以查看当前对象的全部属性。 此外,Object Inspector上还有Object Selector(对象选择器),位于Object Inspector上方的下拉式菜单中。它显示了窗体上所有部件的名称和类型,也包含窗体本身。您可以用Object Selector很容易地在窗体的各个部件之间切换,也可以快速地回到窗体本身。当窗体中含有较多的对象时,您会发现这是切换对象尤其是回到窗体的最快捷途径。 想使Object Inspector一直可见,可将鼠标移到Object Inspector上,按动右键,以启动Object Inspector的弹出式菜单,将其设置为Stay On Top。这对初学者常是一个很重要的设置方式。 § 窗体窗口 Delphi Forms窗口是开展大部分设计的工作区域。首次启动Delphi 2.0时显示的是窗体Form1。可以把部件放在窗体中,通过移动位置、改变尺寸等操作随心所欲地安排它们,以此来开发应用程序的用户界面。您可以把窗体想象成一个可以放置其它部件的容器。窗体上有栅格(Grids),供放置部件时对齐位置用,在程序运行时Grids是不可见的。 一个真正的应用程序可能有不止一个窗口,您可以选用不同的窗体进行设计。其它窗体可以是对话框(Dialog Box)、数据录入框等。 代码窗口一开始处于窗体窗口之下。因为在Delphi中,设计用户界面直接在窗体中进行,运行结果和设计样板完全一致。当部件被放到窗体上时,Delphi会自动生成大部分的用户界面代码。您所应做的只是在它为您生成的框架中加入完成所需功能的程序段而已。点动Form1的状态行使代码窗口可见。 这个窗口中是代码编辑器。可以在其中书写Delphi应用程序的源代码。当程序中含有不止一个窗口时,会有几个库单元的源程序出现在代码编辑器中。代码编辑器的标题条中显示了当前正在编辑的库单元文件名。要查看某一特定程序的源代码,只需用鼠标点动写有该库单元文件名的页标签,就可以对该库单元进行编辑了。 § 用户界面 Delphi 从空白窗体开始工作。将设计一个简单的程序:在屏幕上开一个窗口,窗口中有一个图框,用三个按钮来改变图框的形状;再用一个图标按钮来进行图框的颜色设置,通过颜色编辑对话框来选择变成哪一种颜色。 在菜单上选用File|New Application菜单项来生成新的工程文件。这时,屏幕上出现窗体。 部件(Component)是建立Delphi应用程序的要素。Delphi为用户提供了丰富的部件库,既有可视的部件(如编辑框、按钮)等,也有不可视的部件(如系统定时器、数据表等)。它们按照功能分别排列在Component Panel的各页上。 移动鼠标到Component Panel上,在部件按钮上“犹豫”一、两秒钟,一个黄色小提示框就会弹出,写有该部件的名称,称之为提示(Hint)。在要选择的部件上单击左键,则该部件按钮被按下,表示部件已被当前选择。然后,将鼠标移动到窗体上,按下左键,该部件被放到窗体中。部件的轮廓线上会显现八个被称为尺寸调整器(Sizing Handles)的黑色小方块。它除了供用户调整尺寸使用之外,还可以表示该对象处于当前编辑状态。此时,按“Delete”键可以将该部件删除。 在Component Panel上,点动写有“Additional”的页标签,切换到Additional页,再移动鼠标,逐个用观看Hint的办法查看部件的名称,找到“Shape”部件(其图标为圆、方形、三角形三个几何体),将其放到窗体的左方。再按动“Standard”页标签,找到“Button”部件(图标上画有OK按钮)。Delphi允许在添加多个同类型的部件时,不必每次到部件选项板上选取。按住“Shift”键,同时在“Button”部件上单击鼠标左键,这时“Button”部件处于按下状态,并有蓝色边框,表示已经被选择固定。依次在窗体右方的三个位置单击左键,则会放置三个相同的Button部件。把鼠标光标移到部件选项板左侧的箭头图标处,这是“取消选择”按钮,它没有提示。按动它,会发现“Button”部件按钮恢复弹起状态。否则,每次“Form1”上的鼠标单击左键动作,都会导致增加一个按钮部件。 再次进入“Additional”部件页,选择一个“BitBtn”按钮(图标是有绿色对号的OK按钮),把它放到其它三个按钮部件的下面。 点动“Dialog”页标签,选择以16色网格做图标的ColorDialog部件并把它放到窗体的任意位置。因为这一部件是不可视部件,所以它的位置并不影响大局。 § 部件调整 Delphi 一般来讲,此时放置到窗体的部件是分散排列的,而且其大小不是真正需要的尺寸。除了不可视的ColorDialog部件外,其它的部件都需要进行位置、大小和显示字样的调整。Delphi提供的对齐工具和窗口栅格为这些调整提供了方便。 移动部件:只需把鼠标落到想移动的部件上,按住左键并移动光标,到合适的位置再释放左键,整个部件即被移到新位置。 调整尺寸:先把鼠标光标移动到要改变尺寸的部件上,单击左键,选中该部件,尺寸调整器会出现,把鼠标移动到其中的一个小黑色方块上,当鼠标变成拖动方向指示时,按下并拖动鼠标左键,可以放大或缩小部件。上下左右的小方块用来移动对应的各边,四个角的方块可以移动相连的两条边。如果要精确地表述部件的尺寸,可以在Object Inspector上,改变Left(表示部件左边缘到窗体左边框的象素点数)、Top(表示窗体上边框到部件上边缘的象素点数)、 Width(部件本身的宽度)、Height(部件本身的高度)等属性。关于改变部件的属性,下文还将仔细讲解。 使得一组部件对齐:用调整位置的方法可以对齐部件,但操作步骤复杂。Delphi提供的对齐工具可以使多个部件的对齐极为迅速方便。下面来使四个按钮对齐。先将四个按钮选为一组:按住并向右下方拖动鼠标左键,在窗体上画出围绕四个按钮的矩形,释放左键后,被选中的按钮周边会出现暗灰色的边框。选用Edit|Align命令,或使用弹出式菜单(在被固定的部件上单击鼠标右键激活),可以显示图1.4所示的对话框。 要使按钮沿左边对齐并使它们在垂直方向上均匀分布,先在Alignment对话框的Horizontal栏内选择“Left sides”,在“Vertical”栏内选择“Space equally”,按动OK按钮,Delphi就会自动将它们对齐。然后,您可以将它们四个作为一组来移动。在四个按钮以外的窗体上按动鼠标左键,就释放了组中的部件,使它们成为分立的部件。 利用对齐模板来对齐部件也是很方便的。首先要将要对齐的部件选成一组,选择View|Alignment Palette显示对齐模板。按照所示的方式选择即可达到对齐的目的 § 锁定部件 Delphi 如果部件已经对齐,为防止不小心移动部件,可以将部件位置锁定。选择主菜单上的Edit|Lock Controls选项,使得部件不能进行移动操作。解锁只需再次选择此项即可。 调整“Shape”部件的大小,使之与右边的按钮组相匹配。再改变窗体的大小,按住并拖动窗体右下方使之刚好包容窗体上的全部部件。这样,您的用户界面就会比较美观。及时地保存所做的工作至关重要。对设计者来讲,有两个文件需要保存:库单元文件(以.PAS为后缀)和工程文件(以.DPR为后缀)。从主菜单上选择File|Save Project As...项,Delphi会显示标题为“Save Unit1 As”的文件保存对话框,Delphi 2.0 允许用户更改存储路径,您可以在下拉式列表框中选择。最好将您的文件保存在自己的目录中。在编辑框中键入demoform.pas以保存库单元文件;然后显示标题为“Save Project As”的另一个文件保存对话框,键入sample.dpr。Delphi保存这两个文件并返回窗体窗口。不要把库单元和工程存成一样的文件名,Delphi要求两者不同。 第一次保存后,以后可以随时通过Speed Bar中的“Save All”和“Save file”来保存工程文件和库单元文件。一般来讲,当确认文件的改变后,要同时存储这两个文件。 运行工程:操作使您有了一个自己的应用程序界面。在速度条中按动“Run”按钮(绘有绿色三角图标),您可以看到,所生成的界面与您设计的界面是完全一致的。 改变对象的属性:上述的工程虽能够运行,但它对您的按动按钮操作是没有什么反应的,而且,所有部件上还写着不需要的字样。双击窗口的关闭按钮结束运行,回到设计界面。下面,将仔细讲述如何在Object Inspector中改变部件的各种属性。 用Properties页改变部件的属性值:首先要改变各种部件的标题。先给窗口命名为“Demo”。按动Object Inspector上端的Object Selector的题条或者其右端的下拉标志,找到Form1项,并点动左键,窗体被选中。在Object Inspector的Properties页中,找到Caption属性并用左键选中,将其右端的Form1改为Demo,同时,您会发现窗体的标题已经相应地做了改变。 用鼠标点中窗体中的Shape部件,Object Inspector列出了它的属性。选中Shape属性,您会发现右端出现了下拉标志。点动这一标志,可以查看对象的Shape属性可选值。它的形状可以是矩形、圆形、圆角矩形、方形等几种。这是设计后续功能的基础。 选中Button1按钮,此时Object Inspector已经显示出此按钮的一应属性。将它的Caption属性改为“&Rectangle”,“&”号使得Delphi特殊处理它后面的字符,在这里,按钮中的R字母被做了下划线处理,运行时,可以用“Alt-R”热键来按动这一按钮。同样,您可以将其它的两个按钮Button2和Button3的Caption属性改成需要的形状指示,譬如“&RoundRec”、“&Ellipse”。可以把某个按钮作为窗口上的缺省按钮,Delphi会为按钮加上有黑色的边缘。运行时,回车即相当于被按下。只需将此按钮的Default属性从False改成True,即将它设为窗体的缺省按钮。点动Default属性,在右端的值后面双击左键,或从下拉菜单中选取True,即可改变这一属性。Delphi中有许多只有True、False两个属性的部件,双击左键可以在这两个值之间切换。 汉化界面及字体选取 如果您的Windows95系统中安装了中文系统,对界面做汉化是极其方便的。例如,您可以将Button1的Caption属性改成“&R矩形”,同样地可改变其它部件的属性,将窗体做成中文的操作界面。 若对中、西文字体不满意,则可以调整Font属性以满足您的要求。Font属性的前面,有一个小小的“+”号,这说明它表征的是集属性,也即属性不再是一个单值,而是一个属性的集合。双击Font,ObjectInspector将在下面扩充显示它的其它属性。Color用来表示文本的颜色,Name定义了字体名,如System,MsSerif,Arial,宋体,黑体等。Style下又拥有四个属性:fsBold,fsItalic,fsUnderline和fsTrikeOut。如果想让字体有其中的某种风格,可把相应的属性值设成True。 Font对话框可以更为直接地设定以上属性。Font属性右侧值段有带省略号的按钮,单击它可以激活Font对话框,如图1.7所示: 这一对话框中包含了上述的全部属性,使得调整字形更为直接方便。但要申明的是,对于窗体Form来讲,Font属性改变的是窗体中其它部件的显示字形,它本身的标题字体是缺省的System字体,不能通过属性来改变。 使用图形编辑对话框 最后,用图标按钮BitBtn1来控制Shape部件的颜色。选中图标按钮,将它的Caption属性改为“&Color”(或“&C颜色”)。可以在按钮中加入一个图标来形象地表述它的功能。选用ObjectInspector中的Glyph属性,点动值段的三点按钮,弹出图形编辑对话框。 您可以通过图形编辑对话框装入图标,在本例程中,按动Load按钮,选择\\Delphi2.0\\Images\\Buttons\\Brush.bmp文件装入,Bitbtn1就成为一个图标按钮。另外,Delphi还为您提供了丰富的Windows标准图标按钮。想运用它们,改变BitBtn的Kind属性。用户不妨尝试一下,选择其它值可以生成漂亮的标准按钮,如OK,Cancel等等。这会使您在以后的程序开发中受益匪浅。 至此,界面的设计工作就已完成了。运行一下观察效果,别忘记保存您的库单元文件、工程文件。 编写事件处理过程 完成用户界面,只是建立了一个“骨架”,下面要做的便是给程序加入“灵魂”,也即,使它能够完成所要求的功能。 为用户操作建立“事件” 单击窗体上的“Rectangle”按钮,在ObjectInspector中,点动“Events”页标签,出现事件窗口。在本例程中,只关心OnClick事件,即按钮接收到左键单击时应用程序所作出的反应。在ObjectInspector窗口中双击OnClick事件右端的值段,会使得Delphi激活库代码编辑器,并将光标停在该按钮所对应的过程的begin...end之间。“Rectangle”按钮的功能是使Shape部件的形状为矩形。联系前文查看过的Shape部件的“Shape”属性,现在,要做的是在程序中控制部件的属性。 在光标处键入以下的程序段: Shape1.Shape:=stRectangle; 用同样的方法,在Button2和Button3的OnClick事件响应内复制以上语句,并分别将赋值号后的属性值改为stRoundRect和stEllipse。为防止输入错误导致程序运行出错,建议您使Shape1部件的ObjectInspector可见,检视属性Shape的各个值并对应输入。 在代码编辑器中,Delphi自动建立的过程以关键字Procedure开头,用户可以在begin…end之间加入自己的程序,也可以定义变量。这个程序块对用户的外部事件(此例中是按动按钮)进行响应。称之为事件处理过程。 使用颜色编辑对话框 图标按钮“Color”要控制部件Shape1的颜色,可以调入颜色编辑对话框,用以选择要变成的颜色。这时就要用到运行时不可视的部件ColorDialog了。同样地使图标按钮BitBtn1响应OnClick事件,在它的过程中加入以下的语句: ColorDialog1.Execute; Shape1.Brush.Color:=ColorDialog1.Color; 这样,图标按钮的功能也就完成了。 初学者可能对这样的程序段不能理解。其实也是十分简单的。查看ColorDialog的Brush属性,就会发现它是个集属性,在其下还有一个Color选项,正是想改变的属性。既然想将图形的颜色变得更加丰富多彩,它本身提供的几种颜色就已不能满足要求了。用颜色编辑器可以得到更多的色彩。程序的第一句用Execute方法,使得ColorDialog运行它本身。当用户在对话框中进行操作,选定了一种颜色时,即使得TColorDialog对象的一个属性Color置为选定颜色的值。将此值赋给Shape1的Brush属性的子属性Color,就将选定的颜色加到了图形上。 读者的要求可能会是,怎样尽快的了解这些这些方法、属性和域呢?下文对使用联机帮助的简单介绍可能会对您有所裨益。 使用联机帮助Help 事实上,使用联机帮助是您全面地了解可用的方法、对象的域、??的例程。较为简单有效的方法是使用Help中的搜索功能。如果您对一个对象知之甚少,选用主菜单中的Help|HelpTopics项,在弹出的帮助对话框,选用Indexes(“索引”)页,Delphi2.0会提示您输入要检索的主题。以您想用的部件的对象名作为检索主题词,可以参阅很多基本的信息。例如,上文的例程中,在编辑框中键入对象的名称TColorDialog,在词条中就会出现该主题,按动Display按钮显示出TColorDialog的帮助信息。查看method,可以找到能应用在CclorDialog1上的方法Execute;仔细阅读它的功能,上述的编程便不难理解了。Properties中提供了部件的所有属性,在关键属性KeyProperties前加上了“金钥匙”,提供了详尽的说明。在Task中您可以查阅该对象的其它相关主题,还可以参阅Example中的应用例程。 § 编程方法 Delphi Delphi的编程语言是以Pascal为基础的。Pascal语言具有可读性好、编写容易的特点,这使得它很适合作为基础的开发语言。同时,使用编译器创建的应用程序只生成单个可执行文件(.EXE),正是这种结合,使得Pascal成为Delphi这种先进开发环境的编程语言。 本章中,将讨论ObjectPascal的主要特点,并讲解如何在事件处理过程和其他应用程序中,使用它来编制程序代码。本章将讲解Delphi应用程序中最常用的ObjectPascal语法,而不是Pascal语言的一切细节。如果您完全不熟悉Pascal编程,请参阅一些基础的Pascal教程。如果您具有编程经验,并能熟练地使用其他流行程序语言,您将在本章的ObjectPascal中发现一些相同的概念。如果您已经熟悉了BorlandPascal,就可以快速浏览或跳过本章。 编写ObjectPascal程序代码 在前边的章节中,通过例程,已经编写了几行简单的代码。在本章中,将从熟悉Pascal编程的角度,配合实例,讲解ObjectPascal编程的基本方法。 在编写自己的ObjectPascal程序时,要注意程序的可读性。Pascal语言是英式结构语言,在程序中选择合适的缩排、大小写风格,并在需要时将程序代码分行,会使得程序代码能够很容易地被自己和他人读懂。一般的程序员都有这样的体验:如果不给程序加上适当的注解,一段时间后,自己也难以理清程序的流程。给程序及时地加上注释是良好的编程习惯。Delphi的注释需要加注在{}之间,编辑器会把它们处理成为空白。Delphi保留了BorlandPascal编辑器的风格,关键字采用黑体字,被注释的部分会变暗,这使得编程风格良好,易读易写。 § 赋值语句 Delphi 在事件处理过程中,最常用到的工作就是把一个新值赋给一个属性或变量。在设计用户界面时,可以使用ObjectInspector(ObjectInspector)来改变其属性;但有时需要在程序执行时改变属性的值,而且有些属性只能在执行时改变,这些属性在Delphi的在线帮助的“Proprety”主题中被标为执行期属性。进行这种改变,就必须使用赋值语句。 下文的赋值语句表征一个OnClick事件。当按钮按动后,将编辑框部件Edit1的Color属性置为clRed: procedureTForm1.Button1Click(Sender:TObject); begin Edit1.Color:=clRed; end; 当按动按钮后赋值语句被执行,编辑框变成红色。 在语句中,部件的名称在属性前,中间用“.”表示属性的所属关系。这样就准确地指定了要将clRed值赋给哪一部件的哪一属性。赋值号为“:=”,不论给属性还是给变量赋值,都是将右边的值赋给左边的属性或变量。 当将一个属性值、变量、常量或文本数据赋给属性或变量时,所赋值的类型和接受此值的属性或变量的类型应相同或兼容。一个属性或变量的类型定义了此属性或变量的可能值集合,也定义了程序代码可以执行的运算。在前边的例程中,编辑框部件的Color属性和clRed的类型都是TColor。可以在在线帮助中找到一个属性的类型;另外一种方法是在ObjectInspector中选定该属性值段,并按下F1键,则类型将在属性说明的结尾处列出,例如Color属性列出下边的语句: PropertyColor:TColor; 有些属性是只读(ReadOnly)的,它们只能被读取,不能被改变。请查阅在线帮助,在Delphi中这些只读属性都有注解。 标识符的说明与使用 标识符是Delphi应用程序中一些量的名称,这些量包括变量(var)、常量(const)、类型(type)、过程(procedure)、方法(Method)及其他,ObjectPascal在应用标识符时,必须首先说明它们。ObjectPascal是强类型语言,它的编译器可以检查确保赋给变量或属性的值是正确的类型,以便于您改正错误。因为ObjectPascal是编译语言,所以Delphi的执行速度要比使用解释语言快得多。在使用标识符前说明它们,可以减少程序错误并增加代码的效率。 变量 变量是程序代码中代表一个内存地址的标识符,而此地址的内存内容在程序代码执行时可以被改变。在使用变量前必须对它进行说明,即对它进行命名,并说明它的类型。在所有变量说明以前加上保留字var。变量说明左边是变量的名称,右边则是该变量的类型,中间用(:)隔开。 var Value,Sum:Integer; Line:String; 在窗体中加入一个名称为Edit1的编辑框,再加入一个名称(属性Name)为Add的按钮部件,并建立如下的事件处理过程: procedureTForm1.addClick(Sender:TObject); var X,Y:Integer; begin X:=100; Y:=20; Edit1.Text:=IntToStr(X+Y); end; 在本例中,当按动ADD按钮时,编辑框中显示值120。在ObjectPascal中,必须确保变量或属性被赋予类型相同或兼容的值。您可以尝试将赋给X的值改为100.0,或去掉IntToStr函数,在编译时会出现类型不匹配的错误,这也说明了ObjectPascal强类型语言的特点。 § 预定义类型 Delphi ObjectPascal有多个预定义的数据类型,您可以说明任何这些类型的变量: 整形:Integer的范围是-32768到32767,占2字节的内存;Shortint从-128到127,占1字节内存;Longint从-2147443648到2147483647占4字节内存;Byte从0到255,占1字节;Word从0到65535,占2字节内存。它们都是没有小数部分的数字。 实型:Single可以包含7到8位有效小数部分,占用4字节的内存;Double类可以包含15到16位有效小数部分,占用8字节的内存;Extended类型包含19到20位有效小数部分,占用10字节内存;Comp可以包含19到20位有效小数部分,占用8字节内存。以上实数类型只有在8087/80287选项[N+]打开才可以使用。Real可以包含11到12位有效小数部分,占用6字节内存。它只有在和以前BorlandPascal兼容的情况下才使用,否则应使用Double或Extended。 布尔型:Boolean,只包含true或False两个值,占用1字节内存。 字符型:Char,一个ASCII字符;字符串类型String一串最长可达255个ASCII字符。 指针型:Pointer,可以指向任何特定类型。 字符串型:PChar,是一个指向以零结尾的字符串的指针。 除了预定义类型外,Delphi还有自行定义的类型。上述例程的TColor就是这种类型。此外,用户还可以定义自己的数据类型,这部分内容将在下文中详细讲述。 整型类别和实型类别都各有五种类型,同一类别中,所有的类型与其他同类别的都相容,您可以将一种类型的值赋给相同类别中不同类型的变量或属性,而只需要这个值的范围在被赋值的变量或属性的可能值范围内。例如,对于一个Shortint型的变量,可以接受在-128到127范围内的任意整数,例如Shortint类型的7;您不能将300赋给它,因为300已经超出了Shortint的范围了。将范围检查功能打开(选用Options|Project,并在CompilerOptionsPage中选择RangeChecking),将会检查出一个范围错误;如果RangeChecking没有被打开,那么程序代码将可以执行,但被赋值的值将不是您期望的值。 在一些情况下,您可以进行不同类型的变量或属性的赋值。一般来说,可以将一个较小范围的值赋给一个较大范围的值。例如,您可以将整型值10赋给一个接受实型值的Double属性而使得值成为10.0,但如果将一个Double类型的值赋给整形变量,则会出现类型错误。如果您不清楚类型的兼容性,可以参阅Delphi的在线帮助中“TypeCompatibilityandAssignmentCompatibility”主题。 常量 常量在说明时就被赋予了一个值,在程序执行过程中是不可改变的。下面的例子说明了三个常量: const Pi=3.14159; Answer=342; ProductName="Delphi"; 象变量一样,常量也有类型。不同的是,常量假设其类型就是常量说明中其所代表的值的类型。上文的三个常量的类型分别是real型、整形、字符串型。常量用“="表示两边的值是相等的。 § 过程函数 Delphi 过程与函数是程序中执行特定工作的模块化部分。Delphi的运行库包含许多过程与函数以供您的应用程序调用。您不必了解过程与函数的逻辑,但要知道过程与函数的用途。在对象中说明的过程和函数称为方法(Method)。所有的事件处理过程都是过程,以保留字procedure开头。每一个事件处理过程只包含了当这一事件发生时需要执行的程序代码。在事件处理过程中使用Delphi已经存在的过程与函数,只需在程序代码中调用它们即可。 一个调用Delphi方法的简单例程 下文将通过对一个Memo部件的文本进行剪切、拷贝、粘贴、清除等编辑的应用程序编制,介绍使用Delphi过程和函数的调用方法。 Memo(备注)部件有一个CutToClipboard方法,实现将用户在memo中选择的文本移到剪贴板上去。由于这个功能已经被建立在此方法中了,所以您只需知道这个方法做什么以及如何使用它即可。 下面的语句表明如何调用一个名为Memo1的memo部件的CutToClipboard方法: Memo1.CutToClipboard; 通过指定Memo1的名称,说明调用哪一个部件的CutToClipboard方法。如果不指明对象名称,Delphi会显示Unknownidentifier错误。当该事件处理过程被触发,程序会执行CutToclipboard中的语句,将Memo1中的文本剪贴到剪贴板上去。 下文的例程展示了如何调用Delphi的方法,实现将备注部件的文本信息剪切、拷贝到剪贴板上;将剪贴板上的标记文本粘贴到备注中,清除备注部件中的全部文本等四个功能。 打开一个新的空窗体,加入一个memo部件和四个按钮,并排列整齐。改变按钮部件的Name属性,分别命名为Cut,Copy,Paste,Clear。您会发现,当Name属性发生改变时,Caption属性将发生相应的变化。在Caption属性前加标“&”号设立加速键 将memo部件的ScrollBars属性设为ScVertical,以便加上滚行条。将WordWrap属性设置为True,这样当用户输入文本到达Memo部件的右边缘时会自动回行。将Line属性第一行的Memo1文本删除,使得memo部件在初始显示时为空的。 为每一个按钮建立如下的事件处理过程: procedureTForm1.CutClick(Sender:TObject); begin Memo1.CutToClipboard; end; procedureTForm1.CopyClick(Sender:TObject); begin Memo1.CopyToClipboard; end; procedureTForm1.PasteClick(Sender:TObject); begin Memo1.PasteFromClipboard; end; procedureTForm1.ClearClick(Sender:TObject); begin Memo1.clear; end; 执行此程序。您可以在备注部件中输入文本,在进行了文本的标记后,可以任意地进行剪切、拷贝、粘贴和清除。当按钮被按动时,就调用相应的过程进行处理。用户可以通过查阅在线帮助进行Memo部件的TopicSearch,在MemoComponent项中查阅Method,会得到以上过程的详细说明。 调用Delphi的含参过程 有些过程要求用户指明参数。被调用的过程会在执行时使用传入的参数值,这些值在过程中被认为是已经被说明的变量。例如,LoadFromFile方法在TString对象中被说明为: ProcedureLoadFromFile(constFileName:String); 在调用这一过程时,应指明FileName参数是要装入的文件名称。下面的程序将先打开Open对话框,当您选择了一个文件后,Delphi将把该文件读入一个Memo部件: begin OpenDialog.Execute; Memo1.lines.LoadFromFile(OpenDialog.FileName); end; § 函数使用 与过程一样,函数的程序代码也执行特定的工作。它和过程的差别为:函数执行时会返回一个值,而过程则没有返回值。函数可以用来赋给一个属性或变量;也可以使用返回值来决定程序的流程。 前文中实际上已经接触过了函数。在讲述变量时,曾用到过下面的程序段:Edit1.Text:=IntToStr(X+Y);其中,IntToStr(Value)把一个LongInt类型的数值转化为字符串的值,Value是IntToStr唯一的参数,它可以是一个整形的值、变量、属性或产生整形值的表达式。调用函数,必须把返回值赋给和此返回值类型兼容的变量或属性。 有些函数返回一个True或False的布尔量,用户的程序可以根据返回值来决定跳转。下文的例程讲述了函数返回值为Boolean的判断用法: 在窗体中加入一个ColorDialog对象和一个Name属性为ChangeColor的按钮。为按钮的OnClick事件建立事件处理过程如下: procedureTForm1.ChangeColorClick(Sender:TObject); begin ifColorDialog1.Executethen Form1.Color:=ColorDialog1.Color else Form1.Color:=clRed; end; 此事件处理过程使用一个返回Boolean值的Execute方法。按动按钮,并在颜色对话框中选择一个颜色。如果按动OK按钮,ColorDialog.Execute方法将返回True,则Form1.Color将被赋值为ColorDialog1.Color,窗体显现您选用的颜色;如果按动颜色对话框的Cancel按钮,方法将返回False值,窗体将变为红色。 跳转语句 ObjectPascal的跳转语句有if和case两个。 if语句 if语句会计算一个表达式,并根据计算结果决定程序流程。在上文的例程中,根据ColorDialog.Execute的返回值,决定窗体的背景颜色。if保留字后跟随一个生成Boolean值True或False的表达式。一般用“=”作为关系运算符,比较产生一个布尔型值。当表达式为True时,执行then后的语句。否则执行else后的代码,if语句也可以不含else部分,表达式为False时自动跳到下一行程序。 if语句可以嵌套,当使用复合语句表达时,复合语句前后需加上begin…end。else保留字前不能加“;”,而且,编译器会将else语句视为属于最靠近的if语句。必要时,须使用begin…end保留字来强迫else部分属于某一级的if语句。 § case语句 case语句适用于被判断的变量或属性是整形、字符型、枚举型或子界型时(LongInt除外)。用case语句进行逻辑跳转比编写复杂的if语句容易阅读,而且程序代码整形较快。 下面的例程显示一个使用case语句的窗体: 建立如下的事件处理过程: procedureTForm1.Button1Click(Sender:TObject); var Number:Integer; begin Number:=StrToInt(Edit1.Text); caseNumberof 1,3,5,7,9:Label2.Caption:='奇数'; 0,2,4,6,8:Label2.Caption:='偶数'; 10..100: begin Label2.Caption:='在10到100之间'; Form1.Color:=clBlue; end; else Label2.Caption:='大于100或为负数'; end; end; 执行程序,当Edit1部件接受到一个值,并按动“OK”按钮触发程序后,Number便被赋值为用户输入的数值。case语句根据Number的值判断该执行哪一条语句。象if语句一样。case语句也有可选择的else部分。case语句以end结尾。 § 循环语句 ObjectPascal的循环语句有三种:repeat、while和for语句。 repeat语句 repeat语句会重复执行一行或一段语句直到某一状态为真。语句以repeat开始,以until结束,其后跟随被判断的布尔表达式。参阅以下的例程: i:=0; repeat i:=i+1; Writen(i); untili=10; 当此语句被执行时,窗体的下方会出现1到10的数字。布尔表达式i=10(注意,与其他语言不同的是,“=”是关系运算符,而不能进行赋值操作)直到repeat..until程序段的结尾才会被计算,这意味着repeat语句至少会被执行一次。 § while语句 while语句和repeat语句的不同之处是,它的布尔表达式在循环的开头进行判断。while保留字后面必须跟一个布尔表达式。如果该表达式的结果为真,循环被执行,否则会退出循环,执行while语句后面的程序。 下面的例程达到和上面的repeat例程达到同样的效果: i:=0; whilei0then test2(A);{经前置说明,调用未执行的过程Test2} writeln(A); end; procedureTest2(varA:Integer);{经前置说明的Test2的执行部分} begin A:=Adiv2; ifA>0rhen test1(A);{在Test2中调用已执行的过程Test1} end; procedureTForm1.Button1Click(Sender:TObject); begin Alpha:=15;{给Alpha赋初值} Test1(Alpha);{第一次调用Test1,递归开始} end; 按钮的OnClick事件处理过程给Alpha赋初值,并实现先减1再除2的循环递归调用,直到Alpha小于0为止。 § 程序函数 程序代码在调用一个过程或函数时,通常用参数传递数据到被调用的过程或函数中。最常用的参数有数值参数、变量参数和常量参数三种。 由被调用过程或函数定义的参数为形参,而由调用过程或函数指明的参数叫实参。在NoValue函数中,说明函数体中的AnEditBox是形参,而调用时在ifNoValue(Edit1)…中,Edit1是实参。 数值参数在运行过程中只改变其形参的值,不改变其实参的值,即参数的值不能传递到过程的外面。试看下面的例程: procedureCalculate(CalNo:Integer); begin CalNo:=CalNo*10; end; 用以下例程调用Calculate函数: Number:=StrToInt(Edit1.Text); Calculate(Number); Edit2.Text:=IntToStr(Number); Number接受由编辑框1输入的数值,经Calculate过程运算。它是一个数值型实参。在进入Calculate函数后,会把Number实参拷贝给形参CalNo,在过程中CalNo增大十倍,但并未传递出来,因此Number值并未改变,在编辑框2中显示仍然是编辑框1中的输入值。形参和实参占用不同的内存地址,在过程或函数被调用时,将实参的值复制到形参占用的内存中。因此出了过程或函数后,形参和实参的数值是不同的,但实参的值并不发生变化。如果您想改变传入的参数值,就需要使用变量参数,即在被调用程序的参数表中的形参前加上保留字var。例如:procedureCalculate(varCalNo:Integer); 则CalNo并不在内存中占据一个位置,而是指向实参Number。当一个变参被传递时,任何对形参所作的改变会反映到实参中。这是因为两个参数指向同一个地址。将上一个例程中过程头的形参CalNo前面加上var,再以同样的程序调用它,则在第二个编辑框中会显示计算的结果,把第一个编辑框中的数值放大十倍。这时形参CalNo和实参Number的值都是Nnmber初始值的10倍。 如果当过程或函数执行是要求不改变形参的值,最保险的办法是使用常量参数。在参数表的参数名称前加上保留字const可以使一个形参成为常量参数。使用常量参数代替数值参数可以保护您的参数,使您在不想改变参数值时不会意外地将新的值赋给这个参数。 定义新的数据类型 ObjectPascal有一些系统预定义的数据类型,在2.1.2中已经对它们作了介绍。您可以利用这些数据类型以建立新的数据类型来满足程序的特定需要。下面简单地叙述了您能建立的主要数据类型,如枚举型、子界型、数组型、集合型、记录型、对象型等。 § 枚举类型 一个枚举型的说明列出了所有这种类型可以包括的值: type Tdays=(Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday); 可以定义上述枚举类型的变量: var DayOfWeek:TDays; 在枚举型中,括号中的每一个值都有一个由说明它的位置决定的整形值。例如Sunday有整形值0,Monday有整形值1等。您可以把DayOfWeek说明为一个整形变量,并将一星期的每一天赋一个整形值以达到相同的效果,但用枚举型会使得程序可读性好,编写容易。当您在枚举型中列出值时,您同时说明了这个值是一个标识符。例如您的程序中如果已经含有TDays类型且说明了DayOfWeeks变量,则程序中便不能使用Monday变量,因为它已经被说明为标识符了。 § 子界类型 子界型是下列这些类型中某范围内的值:整形、布尔量、字符型或枚举型。在您想限制一个变量的取值范围时,子界型是非常有用的。 type Thours=0..23; TValidLetter='A'..'F'; TDays=(Sunday,Monday,Tuesday,Wednesday,Thursday, Friday,Saturday);{枚举型} TWorkDay=Monday..Friday;{一个TDays型的子界} 子界型限定了变量的可能取值范围。当范围检查打开时,(在库单元的Implementation后面有{$R*.DFM}字样表示范围检查打开,否则您可以在Options|Project|ComplierOptions中选择RangeCheking来打开范围检查),如果变量取到子界以外的值,会出现一个范围检查错误。 § 数组类型 数组是某种数据类型的有序组合,其中每一个元素的值由其相对位置来指定,您可以在数组的某个位置上放置数据,并在需要时使用这些数据。下面的类型说明了一个Double型的数组变量: var Check:array[1..10]ofDouble; 它表示Check指向一个含有10个Double型元素的数据串列,代表每一个元素的是1到10之间的数字,称为索引。数组的每一项由数组名称加上[]中的索引来表示。Check包含10个变量,Check[1]表示第一个变量。您也可以把数组定义成类型: type TCheck=array[1..10]ofDouble; 则变量说明改为: var Check:TCheck; 您可以通过给数组赋值等方法来使用数组。下面的语句将0.0赋给Check数组中的所有元素: forJ:=1to10do Check[J]:=0.0;, 数组也可以是多维的,下面的类型定义了一个20行、20列的数组。 type Ttable=array[1..20,1..20]ofDouble; var table1:TTable; ,;,;想将这一表格的所有数据初始化为0.0,您可以使用for循环: var Col,Row:Integer; … forCol:=1to20do forRow:=1to20do Table1[Col,Row]:=0.0; § 字符串类型 字符串类型事实上是一个一维的字符数组。当您说明一个字符串型的变量时,您应当指明这个字符串的大小,下面是说明字符串类型的例子: type MyString:string[15]; var MyName:MyString; 则变量MyName被说明成为最多可以包含15个字符。如果您没有说明字符串的大小,Delphi会认为字符串包含最大值255个字符。给字符串赋值可以直接使用单引号括起的字串赋值: MyName:='Frank.Smith'; 或MyName:='张明'; 因为MyName是一个可以包含15个字符的MyString型变量,上文的两个的变量都是有效的,一个汉字可以视作两个字符。当您给字符串型变量赋的值多于定义数值时,例如将MyName赋为‘FrankSmith.Franklin’,则Delphi只会接受前15个字符‘FrankSmith.Fran’。在内存中,字符串通常占用比所说明的大小多一个字节的空间,因为第一个位置是一个包含这个数组大小的字节。您可以使用索引值来访问字符串的字符,MyName[1]可以得到MyName的第一个字符'F'。 可以使用Delphi丰富的运算符、过程和函数来处理字符串型的变量和属性。下面介绍几个常用的运算符和Delphi过程或函数: Concat和(+)功能相同,都可以将多个字符串组合在一起,建立一个较大的字符串;Copy会返回一个字符串中的子字符串;Delete在一个字符串中从一个指定位置起删除一定数目的字符;Insert在一个字符串中插入一个字符串;Length返回字符串的长度;Pos返回一个子字符串在一个字符串中的位置,即索引值。 § 集合类型 集合类型是一群相同类型元素的组合,这些类型必须是有限类型如整形、布尔型、字符型、枚举型和子界型。在检查一个值是否属于一个特定集合时,集合类型非常有用。下面的例程可以说明集合类型的用法: 在窗体上加入一个编辑框和一个按钮,清除编辑框中的文字,在其上加上Caption为“输入元音”的标签Label,并在编辑框的下方加入一个空的标签,将按钮的Default属性改为True,建立按钮的事件处理过程如下: procedureTForm1.Button1Click(Sender:TObject); type Tvowels=setofChar; var Vowels:TVowels; begin Vowels:=['a','e','i','o','u']; ifEdit1.Text[1]inVowelsthen Lable2.Caption:='是元音'; else Lable2.Caption:='请再试'; end; 执行这个程序,在编辑框中输入字母,表达式Edit1.Text[1]inVowels的结果是布尔型的,in是运算符,用来判断字母是否存在于集合中。输入的判别结果会显示在编辑框的下方。以上就用到了集合类型TVowels。 § 记录类型 记录是您的程序可以成组访问的一群数据的集合。下面的例程说明了一个记录类型的用法: type TEmployee=record Name:string[20]; YearHired:1990..2000; Salsry:Double; Position:string[20]; end; 记录包含可以保存数据的域,每一个域有一个数据类型。上文的记录TEmployee类型就含有四个域。您可以用以下的方式说明记录型的变量: var NewEmployee,PromotedEmployee:TEmployee; 用如下的方法可以访问记录的单域: NewEmployee.Salary:=1000; 编写如下的语句可以给整个记录赋值: withPromotedEmployeedo begin Name:=''; YearHired:=1993; Salary:=2000.00 Position:='editor'; end; 您的程序可以将记录当成单一实体来操作: PromptEmployee:=NewEmployee; 以上介绍了用户常用的自定义类型。在Delphi的编程中,对象是非常重要的用户自定义数据类型。象记录一样,对象是结构化的数据类型,它包含数据的域(Field),也包含作为方法的过程和函数。在Delphi中,当您向窗体中加入一个部件,也就是向窗体对象中加入了一个域;每一个部件也是对象,每当您建立一个事件处理过程使得部件可以响应一个事件时,您即自动地在窗体中加入了一个方法。在本章第2节中,将详细讲述Delphi面向对象编程的方法和技巧。 ObjectPascal的库单元Unit Units是常量、变量、数据类型、过程和函数的集合,而且能够被多个应用程序所共享。Delphi已经拥有许多预定义的程序库单元可供您建立您的程序库单元使用。Delphi的VisualComponentLibrary由多个程序库单元组成,它们说明了对象、部件以供您的应用程序用来设计用户界面。例如,当您在窗体中加入一个CheckBox时,Delphi自动在您的程序库单元中加入了Stdctrls库单元,因为TCheckBox部件是在StdCtrls库单元中说明的。 当您设计您的窗体时,Delphi自动建立一个和您的窗体有关的库单元。您的库单元不必都和窗体有关,也可以使用预定义的只包含数学运算函数的库单元,或是自行编写数学函数库单元。在一个库单元中所有的说明都相互有关系,例如,CDialogs程序库单元包含了在您的应用程序中使用的普通对话框的所有说明。 ObjectPascal程序库单元的结构 不管一个库单元是否和一个窗体有关,库单元的结构都是相同的。其结构如下: unit interface uses {公有说明} implementation uses {私有说明} {过程和函数的执行部分} initialization{选择性的} {选择性的初始化程序} end. 程序库单元的接口部分 interface是库单元的接口部分,它决定了本库单元对其他任何库单元或程序的可见(可访问)部分。您可以在接口部分说明变量、常量、数据类型、过程和函数等等。Delphi在您设计窗体的库单元中,将窗体数据类型、窗体变量和事件处理过程都说明在这一部分。 interface标志库单元接口部分的开始。在interface中的说明对要使用这些说明的其他库单元或应用程序是可见的。一个库单元可以使用其他Unit的说明,只需要在uses子句中指明那些库单元即可。例如,您在库单元A中编写程序代码,且您想调用UnitB于interface部分说明的程序。您可以把库单元B的名称加入到A的interface部分的uses子句中,则任何A中的程序都可以调用B中说明的程序。而且,如果B中interface部分的uses子句中出现C库单元,尽管A中未曾出现C,A同样可以调用B、C库单元在interface中说明的程序。但如果B出现在A的interface部分的uses子句中,那么库单元A便不能出现在B的interface的uses子句中。因为这样会产生对库单元的循环访问。当试图编译时,会产生出现错误信息。 程序库单元的实现部分 实现部分implementation中包含interface中说明的过程、函数、事件处理过程的具体实现程序代码。这一部分可以有自己的额外说明,但这些说明是私有的,外部程序不能调用这些说明。在interface中说明的函数实体必须在implementation部分出现,可以使用标题简写:只输入procedure或function保留字,后面跟过程或函数的名称即可,其后则是程序的实现部分了。如果您在implementation部分说明任何常式,其标题并未出现在interface部分,则必须写全其标题部分。 在implementation部分的uses子句中指定的库单元,只供给本库单元的程序使用其interface中说明的程序。其他使用本库单元的库单元,不能访问这些在implementation的udes子句中库单元的说明,因为在implementation后进行的库单元包含是私有的。所以上例中,如果C出现在B的implementation部分,则A不能使用C的公有部分,除非C出现在A的uses子句中。在implementation中出现的循环访问是Delphi所允许的,如果A的implemetation的uses子句中出现B,则B的implementation部分也可以出现A。 程序库单元的初始化部分 初始化当前库单元所使用的数据,或是通过interface部分将数据提供给其他应用程序、库单元使用时,您可以在库单元中加入一个initialization部分,在库单元的end前加上您的初始化语句。当一个应用程序使用一个库单元时,在库单元中的initialization部分会先于其他的代码执行。如果一个应用程序使用了多个库单元,则每一个库单元的初始化部分都会在所有的程序代码前执行。 使用Delphi的可视化部件及其库单元 当您在窗体中加入可视化部件时,如果该部件在可视化部件库中,Delphi会在您的库单元的interface部分的uses子句中自动加上需要使用的库单元名称。但有些对象在Delphi的环境中并没有可视化部件存在,例如,您想在库单元中加入一个预定义的信息框,则您必须把MsgDlg库单元加入您的uses子句中。如果您要使用TPrinter对象的话,必须将Printer库单元加入uses子句中。在在线帮助中可以查到对象所属的预定义库单元。 要使用在??一库单元的名称,并用‘.’号隔开。例如,要在Unit2中使用Unit1中说明的Calculate函数,应使用下面的方法: Number:=Unit1.Calculate(10); 您可以在任何标识符如属性、常量、变量、数据类型、函数等之前加上库单元的名称。您可以在自由地在任何Delphi库单元中加入程序代码,但不要改变由Delphi生成的程序。 建立与窗体无关的新库单元 如果您想在工程中建立一个和任何窗体无关的新库单元,可以现选用File|NewUnit。这时一个新的库单元加入了工程,新库单元的代码如下: unitUnit2; interface implementation end. Delphi将根据您的工程中的文件数目为您的库单元选择名称,您可以在程序骨架间加入您的程序代码。 当编译您的工程时,这个新加入的库单元会被编译为一个具有.DCU后缀的文件。这个新生成的文件是链接到工程的可执行文件上的机器代码。 将库单元加入工程 将库单元加入工程是比较简单的。无论是您自己建立的库单元还是Delphi建立的与窗体有关的库单元,如果已经完成,则先打开您想加入库单元的工程(可以用OpenProject打开工程);再选用File|OpenFile,然后选择您想加入的源程序(.PAS文件),并选择OK即可。则库单元被加入到应用程序中。 § 对象编程 Delphi是基于面向对象编程的先进开发环境。面向对象的程序设计(OOP)是结构化语言的自然延伸。OOP的先进编程方法,会产生一个清晰而又容易扩展及维护的程序。一旦您为您的程序建立了一个对象,您和其他的程序员可以在其他的程序中使用这个对象,完全不必重新编制繁复的代码。对象的重复使用可以大大地节省开发时间,切实地提高您和其他人的工作效率。 什么是对象 一个对象是一个数据类型。对象就象记录一样,是一种数据结构。按最简单的理解,可以将对象理解成一个记录。但实际上,对象是一种定义不确切的术语,它常用来定义抽象的事务,是构成应用程序的项目,其内涵远比记录要丰富。在本书中,对象可被理解为可视化部件如按钮、标签、表等。 了解对象,最关键的是掌握对象的特性。一个对象,其最突出的特征有三个:封装性、继承性、多态性。 对象的封装性 对对象最基本的理解是把数据和代码组合在同一个结构中,这就是对象的封装特性。将对象的数据域封闭在对象的内部,使得外部程序必需而且只能使用正确的方法才能对要读写的数据域进行访问。封装性意味着数据和代码一起出现在同一结构中,如果需要的话,可以在数据周围砌上“围墙”,只有用对象类的方法才能在“围墙”上打开缺口。 对象的继承性 继承性的含义直接而且显然。它是指把一个新的对象定义成为已存在对象的后代;新对象继承了旧类的一切东西。在往新对象中添加任何新内容以前,父类的每一个字段和方法都已存在于子类中,父类是创建子类的基石。 对象的多态性 多态性是在对象体系中把设想和实现分开的手段。如果说继承性是系统的布局手段,多态性就是其功能实现的方法。多态性意味着某种概括的动作可以由特定的方式来实现,这取决于执行该动作的对象。多态性允许以类似的方式处理类体系中类似的对象。根据特定的任务,一个应用程序被分解成许多对象,多态性把高级设计处理的设想如新对象的创建、对象在屏幕上的重显、程序运行的其它抽象描述等,留给知道该如何完美的处理它们的对象去实现。 通过Delphi实例了解对象 让结合Delphi的实例讨论对象的概念: 当您要建立一个新工程时,Delphi将显示一个窗体作为设计的基础。在程序编辑器中,Delphi将这个窗体说明为一个新的对象类型,并同时在与窗体相关联的库单元中生成了创建这个新窗体对象的程序代码。 unitUnit1; interface usesSysUtils,Windows,Messages,Classes,Graphics,Controls,Forms,Dialogs; type TForm1=class(TForm){窗体的类型说明开始} private {Privatedeclarations} public {Publicdeclarations} end;{窗体的类型说明结束} var Form1:TForm1;{说明一个窗体变量} implementation {$R*.DFM} end. 新的窗体类型是TForm1,它是从TForm继承下来的一个对象。它具有对象的特征:含有域或方法。由于您未给窗体加入任何部件,所以它只有从TForm类中继承的域和方法,在窗体对象的类型说明中,您是看不到任何域、方法的说明的。Form1称为TForm1类型的实例(instance)。您可以说明多个对象类型的实例,例如在多文档界面(MDI)中管理多个子窗口时就要进行这样的说明。每一个实例都有自己的说明,但所有的实例却共用相同的代码。 假设您向窗体中加入了一个按钮部件,并对这个按钮建立了一个OnClick事件处理过程。再查看Unit1的源程序,会发现TForm1的类型说明部分如下: type TForm1=class(TForm) Button1:TButton; procedureButton1Click(Sender:TObject); private {Privatedeclarations} public {Publicdeclarations} end; 现在TForm1对象有了一个名为Button1的域:它是您在窗体中加入的按钮。TButton是一个对象类型,Button1是Tbutton的一个实例。它被TForm1对象所包含,作为它的数据域。每当您在窗体中加入一个部件时,部件的名称就会作为TFom1的域加入到类型说明中来。在Delphi中,您所编写的事件处理过程都是窗体对象的方法。每当您建立一个事件处理过程,就会在窗体的对象类型中说明一个方法。 当您使用ObjectInspector来改变对象(部件)的名称时,这个名称的改变会反映到程序中。例如,在ObjectInspector中将Form1的Name属性命名为ColorBox,您会发现在类型说明部分,会将前文的TForm1改为: TColorBox=class(TForm); 并且在变量说明部分,会说明ColorBox为TColorBox类型的变量,由Delphi自动产生的事件处理过程名称会自动改为TColorBox.Button1Click;但您自行编写的实现部分的代码却不会被自动修改。因此,如果您在改变Name属性前编写了程序,则您必须将事件处理过程中的对象名称进行改变。所以,原先的Form1.Color要改为ColorBox.Color。 § 数据继承 前面的TForm1类型是很简单的,因为它只含有域Button1和方法Button1Click。但是在这个窗体上,您可以改变窗体的大小、加入或删除窗体的最大最小化按钮,或设置这个窗体为MDI界面。对于一个只包含一个域和方法的对象来讲,您并没有看到显式的支持程序。在窗体上单击鼠标或用ObjectInspector的上端的ObjectSelector选中Form1对象,按动F1查阅它的在线帮助,您会在Properties和Method中找到它的继承到的全部属性和方法。这些是在TForm类型中说明的,TForm1是TForm的子类,直接继承了它所有的域、方法、属性和事件。例如窗体的颜色属性Color就是在TForm中说明的。当您在工程中加入一个新窗体时,就等于加入了一个基本模型。通过不断地在窗体中加入部件,您就自行定义了一个新的窗体。要自定义任何对象,您都将从已经存在的对象中继承域和方法,建立一个该种对象的子类。例如对象TForm1就被说明为对象TForm的子类,拥有一个窗体部件的基本属性或方法。只有当您在窗体中加入了部件或编写了事件处理过程时,Form1才成为您自己的类型。 一个比较特殊的对象是从一个范围较广或较一般的对象中继承下来的,它是这个特别对象的祖先,这个对象则称为祖先的后代。一个对象只能有一个直接的祖先,但是它可以有许多后代。TForm是TForm1类型的祖先,所有的窗体对象都是TForm的后代。 用F1查阅窗体的在线帮助时,您会发现TForm被称为component(部件)。这是因为所有的部件都是对象。 在这个结构中所有的部件都是对象。部件类型TComponent从TObject类型中继承数据和程序代码,并具有额外的可以用作特殊用途的属性、方法、事件,所以部件可以直接和用户打交道,记录它的状态并存贮到文件中等等。控制类型TControl从TComponent中继承而来,又增加了新的功能,如它可以显示一个对象。在上图中,虽然TCheckBox不是直接由TObject继承来的,但是它仍然有任何对象所拥有的属性,因为在VCL结构中,TCheckBox终究还是从TObject中继承了所有功能的特殊对象,但它还有些自行定义的独到的功能,如可以选择记录状态等。 § 对象范围 一个对象的范围决定了它的数据域、属性值、方法的活动范围和访问范围。在一个对象的说明部分说明的数据域、属性值、方法都只是在这个对象的范围中,而且只有这个对象和它的后代才能拥有它们。虽然这些方法的实际程序代码可能是在这个对象之外的程序库单元中,但这些方法仍然在这个对象的范围内,因为它们是在这个对象的说明部分中说明的。 当您在一个对象的事件处理过程中编写程序代码来访问这个对象的属性值、方法或域时,您不需要在这些标识符之前加上这个对象变量的名称。例如,如果您在一个新窗体上加入一个按钮和一个编辑框,并为这个按钮编写OnClick事件处理过程: procedureTForm1.Button1Click(Sender:Tobject); begin Color:=clFuchsia; Edit1.Color:=clLime; end; 其中的第一行语句是为整个窗体Form1着色。可以编写如下: Form1.Color:=clFuchsia; 但您可以不必加上Form1.,因为Button1Click方法是在TForm1对象的范围里。当您在一个对象的范围中时,您可以省略所有这个对象中的属性值、方法、域之前的对象标识符。但是当您编写第二个语句改变编辑框的底色时,因为此时您想访问的是TEdit1对象的Color属性,而不是TForm1类型的,所以您需要通过在属性前面加?指明,Delphi会象第一个语句一样,将窗体的颜色变成绿色。因为Edit1部件是在窗体中的,它是窗体的一个数据域,所以您同样不必指明其从属关系。 如果Edit1是在其他窗体中,那么您需要在编辑框之前加上这个船体对象的名称了。例如,如果Edit1是在Form2之中,那它是Form2说明的一个数据域,并位于Form2的范围中,那么您需要将第二句改为: Form2.Edit1.Color:=clLime; 而且需要把Unit2加入Unit1的uses子句中。 一个对象的范围扩展到这个对象的所有后代。TForm的所有属性值、方法和事件都在TForm1的范围中,因为TForm1是TForm的后代。您的应用程序不能说明和祖先的数据域重名的类型、变量等。如果Delphi显示了一个标识符被重复定义的信息,就有可能是一个数据域和其祖先对象(例如TForm)的一个数据域有了相同的名称。可以尝试改变这个标识符的名称。 重载一个方法 您可以重载(Override)一个方法。通过在后代对象中说明一个与祖先对象重名的方法,就可以重载一个方法。如果想使这个方法在后代对象中作和祖先对象中一样的工作但是使用不同的方式时,您就可以重载这个方法。Delphi不推荐您经常重载方法,除非您想建立一个新的部件。重载一个方法,Delphi编译器不会给出错误或警告提示信息。 对象公有域和私有域的说明 当使用Delphi的环境来建立应用程序时,您可以在一个TForm的后代对象中加入数据域和方法,也可以通过直接修改对象类型说明的方法来为一个对象加上域和方法,而不是把一个部件加入窗体或事件处理过程中。 您可以在对象的Public或Private部分加入新的数据域和方法。Public和Private是ObjectPascal的保留字。当您在工程中加入新的窗体时,Delphi开始建立这个新窗体对象。每一个新的对象都包含public和private指示,以便您在代码中加入数据域和方法。在public部分中说明其它库单元中对象的方法也可以访问的数据域或方法。在private部分的说明有访问的限制。如果您在private中说明域和方法,那么它在说明这个对象的库单元外是不透明的,而且不能被访问。private中可以说明只能被本库单元方法访问的数据域和本库单元对象访问的方法。过程或函数的程序代码可以放在库单元的implementation部分。[1] |
随便看 |
百科全书收录594082条中文百科知识,基本涵盖了大多数领域的百科知识,是一部内容开放、自由的电子版百科全书。