![用组件开发一致的界面_第1页](http://file3.renrendoc.com/fileroot_temp3/2022-2/16/d7edad2b-6980-43a4-8ea5-9406284218f3/d7edad2b-6980-43a4-8ea5-9406284218f31.gif)
![用组件开发一致的界面_第2页](http://file3.renrendoc.com/fileroot_temp3/2022-2/16/d7edad2b-6980-43a4-8ea5-9406284218f3/d7edad2b-6980-43a4-8ea5-9406284218f32.gif)
![用组件开发一致的界面_第3页](http://file3.renrendoc.com/fileroot_temp3/2022-2/16/d7edad2b-6980-43a4-8ea5-9406284218f3/d7edad2b-6980-43a4-8ea5-9406284218f33.gif)
![用组件开发一致的界面_第4页](http://file3.renrendoc.com/fileroot_temp3/2022-2/16/d7edad2b-6980-43a4-8ea5-9406284218f3/d7edad2b-6980-43a4-8ea5-9406284218f34.gif)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第 11 章用组件开发一致的界面什么能算是好的界面,标准是非常主观的。许多商业应用程序都跟随着WinTel 标准:灰色的按钮和控件,白色的背景。对商务程序来说,这可能是个不错的主意,因为通过多年的熟悉使得这个界面在某种程度上较为舒服,但这是个好的界面吗?AlanCooper 是Visual Basic之父,他建议“通过坚持使他们(Microsoft和 Apple )各自独立的开发者群体遵守既定的方针,他们偷偷摸摸地阻止了来自应用者群体的革新。” Cooper,212 Cooper 认为,“我并不鼓吹忽略界面风格方面的指导,从而导致界面出现混乱。我仅仅认为应该像参议员看待说客那样来看待对界面风格
2、的指导,而绝不能像司机服从于交警那样。立法者知道说客想要削减某项经费,但说客并非来自于持有客观态度的第三方。”Cooper,212在所有的条件下都是最好的界面可能并不存在,即使在一定的条件下,界面的设计仍然是高度主观的。如果你能开发出像图 11.1 所示的新 RealPlayer 那样的界面,而且符合你的目的,那就很好了。如果你不擅长创建独一无二或非常有趣的图形用户界面,而且并没有雇佣图形设计者的预算, 那么可能会开发出与 WinTel 风格类似的应用程序。 对于商业目的而言,也许较为熟悉的风格可以避免使用方面的障碍。图 11.1 RealPlayer 8 使用了一些漂亮的图形按钮,并进行了视
3、觉人类工程学方面的尝试。还可以选用卡通标志和斑马条纹等外表只有一个问题不是主观的,它也是本章的主题,那就是界面应该是一致、连贯、完全的。不一致、不连贯、不完全,不考虑界面的风格对用户来说是不可容忍的。第 11 章示范了一些技术,可用于简化开发并确保一致性,包括如何使用定制组件、组件模板和窗体继承,以提供一致、连贯而完全的应用程序。11.1定制组件创建定制组件很有趣,而且定制组件也很有用。首先,显而易见的理由是可以重用已有的对象,并封装新的或增强的特性;其次,它可以提供一致的效用。无须绘制组件时保证相同的尺寸、风格、字体、颜色或措辞,可以对组件进行定制以确保这些目标。定制组件的三个C定制组件的三
4、个 C 是一致性、连贯性和完备性。一致性意味着组件在你的应用程序和其他地方的行为是一致的。一致性( Consistency )组件每次都表现出相同的行为和初始状态,才能提供一致性。对组件的行为或状态进行一次编程,则所有的组件实例都具有一致的外观和行为。一致性并不追求数量,注意到这一点是很重要的。定制组件无须进行大量的修改,即可提供一致性。即使组件只是重载了缺省的大小或形状,创建一个定制组件也可确保一致性。有两个直接的方法可以做到这一点。您可以子类化所有的需要微小修改的组件然后再安装;或者快速地创建组件模板,这更容易一些(参考11.2 节“创建组件模板”)。连贯性( Coherency )一致性
5、是连贯的一个方面。如果对象不具有一致性,也会缺少连贯性。连贯性是对控制流和操作的逻辑性的度量,它要求语义上相似的操作具有一致的行为。定制控件和组件模板可用于提供更为连贯的行为流程。没有一致性和连贯性,应用程序不可能是完全的。完备性( Completeness)不一致、不完全的应用程序看起来是不合逻辑且不正确的,这样必定是不完备的。如果应用程序不被用户群体所接受,也不能说是完备的。完备性度量了应用程序是否执行了所要求的任务、结果是否正确、应用程序是否具有合理的容错级别。如果程序给出正确却不合时宜的回答,也是不完备的。而迅速的提供错误的结果,仍然是错误的。如果程序的行为毫无规律、不一致、或不合逻辑
6、,那么该程序是失败的。即使程序有相应的用户群体,仍然可能失败,因为用户群体可以拒绝使用该程序,或恶意共谋使用该程序提供错误的或不合适宜的结果。为什么组件帮助你走向胜利组件是对象。每个对象都属于某个类。这意味着有一组代码需要测试、调试和扩展。如果一个类已经是完美的,那么每个实例都不会出错。这样如果类满足了 3C 标准,那么类的每个实例都会满足该标准。注意: “大而复杂的软件系统需要设计师,以便开发者能够朝着共同的目标前进。”Jacobsen,Booch,andRumbaugh62 。设计师是这样的人,他形成解决方案的概念并向程序员说清设计意图。即便开始时的进度比通常慢,也要把事情做正确, 这将会
7、节省大量金钱和思考的时间,防止在最后才发现出轨。没有经验、缺乏技术的管理者可能认为编写组件接近于消磨时间,但这是面向对象的程序设计。以非面向对象的方法去使用面向对象工具是一个错误。使用Delphi 编写结构化程序可以很快地到达beta 版,这在短期内常常会使管理者高兴,但可能使得处于beta 版的时间较长。您的程序可能永远都脱离不了beta 版。迅速得到错误的答案,仍然是错误的。无论是否能确认管理层会花大笔金钱来确保成功,都可以采取一些防御措施。从许多功能正确的组件来创建程序,可以尽可能少写代码而又能提高程序的正确性。重分解重分解是采取小的增量式改变的过程。组件可以一步就写出来,创建全新而独一
8、无二的东西,这样做代价昂贵、风险较大而且浪费时间;或者我们可以采取小的步骤,分层实现各种能力,这样就不那么昂贵,风险较低而且快速。设计师的关键作用之一 找到和减少冒险。如果没有设计师,必须由程序员来完成该工作。管理者喜欢快速而廉价。那么很清楚,许多情况下最好的选择就是对组件进行小的修改,将增量式的改变分层添加到已有的组件中。为示范进行这种小的修改所需代码的合理数量,设计了下面的组件:unit UDBShortNavigator;/ UDBShortNavigator.pas - Toggles between short list of buttons/ and long list/ Copy
9、right (c) 2000. All Rights Reserved./ by Software Conceptions, Inc. Okemos, MI USA (800) 471-5890/ Written by Paul KimmelinterfaceusesWindows, Messages, SysUtils, Classes, Graphics, Controls,Forms, Dialogs,ExtCtrls, DBCtrls;typeTNavigatorButtonSet = ( nbsFull, nbsPartial );TDBShortNavigator = class(
10、TDBNavigator)private Private declarations FButtonSet : TNavigatorButtonSet;procedure SetButtonSet(const Value: TNavigatorButtonSet); protected Protected declarations public Public declarations published Published declarations property ButtonSet : TNavigatorButtonSet read FButtonSet write SetButtonSe
11、t;end;procedure Register;implementationprocedure Register;beginRegisterComponents(PKTools, TDBShortNavigator);end; TDBShortNavigator procedure TDBShortNavigator.SetButtonSet(const Value:TNavigatorButtonSet);constFULL_SET = nbFirst, nbPrior, nbNext, nbLast, nbInsert, nbDelete, nbEdit, nbPost, nbCance
12、l, nbRefresh;PARTIAL_SET = nbFirst, nbPrior, nbNext, nbLast;SETS : arrayTNavigatorButtonSet of TButtonSet = (FULL_SET,PARTIAL_SET);beginif( FButtonSet = Value ) then exit;FButtonSet := Value;VisibleButtons := SETSFButtonSet;end;end.TDBShortNavigator 继承了 TDBNavigator ,添加了一个 ButtonSet 特性。将该特性在 nbsFull
13、 和 nbsPartial 之间切换,即可显示所有的导航按钮或仅仅显示基本的四个按钮(如图 11.2 所示)。图 11.2 TDBShortNavigator 可以快速地在显示部分或全部导航按钮之间切换很显然该组件并没有多少代码。而这正是我们所需要的。小的改变快速、便宜而且可靠。然而,有人可能认为这是不重要或不相关的。由混沌理论可知,即使蛾的翅膀振动一下也可能影响到很远的地方。那么我们可以考虑蛾困在Mark型计算机的中继转换开关中的情况。据说是COBOL 的发明者Grace Hopper 杜撰了 bug 这个词,现在整个工业界都在使用它,连世界历史上最重大的媒体事件之一Y2K 问题也是它的标志
14、。并不是说上述的导航器子类在历史上也能有这样幸运的角色;轶事能被记录本来就是戏剧性的。小的事件能够发挥值得记载的作用,并具有相当的影响。千里之行,始于足下,高级的系统正是由小块的优质代码所组成的。小的改变有什么好处除了本节开始所描述的好处之外,还包括快速、廉价、可靠等等,这些好处都是由小的、增量式的改变得到的。 TDBShortNavigator 这样的组件有利于代码的收敛。收敛是指所有该算法的代码都聚集在一起;如果没有最好的代码,那么一个实例的代码是次好的,代码多于一个实例是较差的。发散是指出现算法的多个副本;这是最坏的情况。当子类化TDBNavigator 这样的组件来进行小的改变时,可以
15、促进代码的收敛。改变可见按钮数量的所有代码都包含在同一个地方。因此只有一个代码段需要测试、调试和扩展。如果要为按钮定义三个状态,可以在同一地方快速而有效地修改代码。注意: 您可能听说过比其他的程序员多产一个数量级的程序员。也就是他个人的产量是其他人的十倍。这怎么可能呢?很显然一个人不可能比程序员的平均打字速度快十倍。这是技巧与策略方面的问题。即使最好的程序员也不太可能在语法和程序编码方面比平均程度强十倍;他只是使用了一些具有累积效应的策略。其中必有一种策略倾向于编写收敛的代码。这种程序员可以比一般人快上十倍或更多,而且其代码也可能好于平均的水平。我们提到过,修改并不重要。重要的是修改表示了什么
16、。像TDBShortNavigator这样的组件就表明了编写内聚代码的倾向。这种累积效应往往分布在程序员的职业生涯或工程的生命周期中。采取好的策略编写收敛的代码,或编写的代码只具有算法的单一副本,这是一个策略。这可能是成为高产开发者的最佳途径之一。有两个习惯可促进采用该策略,并逐渐使之成为一种第二天性。首先:考虑多次修改你的代码。我们知道谚语“天才是1%的灵感加99%的汗水”,这意味着当一个人思考解决方案时,只有出现了非常好的机会,灵感才能发挥作用。其次:当发现重复出现的代码时,立即把涉及到的算法编写为过程。随着实践的进行,这种迭代式的修改会变得更加自然,如果随时进行修改,也更容易发挥作用。反
17、之,如果等到程序完成之后才进行修改工作,可能会遇到困难。管理者和其他程序员可能不想立即投入很多时间进行修改,而这时代码已经相互纠缠在一起以至于小的修改也可能引起代码的混乱。组件化我们就继续讨论上一节的问题,如果你发现自己正在编写处理组件内部数据的代码,那么最好子类化组件以封装新的行为。 组件化的规则是: 如果代码涉及到组件内部的数据,例如组件所拥有的对象列表,那么代码实际上描述了组件的行为。对象的行为就是方法。通过将外部的、隐式的算法提升为方法,可以使代码在类的层次上趋向于收敛。类不一定是组件;任何表示类行为的代码都应该作为方法合并到类中。有三个地方可以方便地重用代码。可以子类化包括组件在内的
18、任何类,以重用代码。可以定义组件模板,这是 Delphi 新近添加的功能,利用该方法可以很容易地在一个或多个组件中重用新的行为;而且能够创建窗体或框架模板,这样就可以重用整个窗体或框架及其所包含的组件。11.2创建组件模板首先将组件添加到数据模块或窗体,设置它们的特性,创建事件处理程序,并编写代码。然后选定一个或多个组件,从 Component 菜单里选择 Create Component Template 菜单项。所有被选中的组件、 事件处理程序、 以及相关的代码, 都添加到了 VCL 面板的 Template 属性页上。选择该组件模板并将其拖动到任意的窗体或数据模块上,即可重新创建包括代码
19、在内的各个组件。将模板添加到窗体或数据模块后,可以修改其位置、大小和特性等,就像是分别添加的一样。当选择 Create Component Template 菜单项时, 会显示 Component Template Information 对话框(见图 11.3)。点击 OK ,则接受缺省的组件名、面板属性页以及组件图标,当然也可以修改这些信息。 可以给模板组件命名所喜欢的名字, 将其放置在任何面板属性页上。如果输入的属性页名字不存在, Delphi 将创建新的属性页。模板组件惟一的限制就是其图标必须是 24 24 像素位图,与其他组件的图标类似。图 11.3Component Templat
20、e Information 对话框定义组件模板编写基本的组件相当容易。创建组件模板甚至更容易。定义组件模板的步骤与创建窗体基本相同。增加组件,修改其特性,并编写事件特性。像其他单元一样,对窗体(或数据模块)进行单元测试。工作完成后,就可以创建组件模板,选择组件,并将其添加到组件模板。注意: Delphi 组件模板存储在Delphi 的 Bin 目录下的二进制文件Delphi.dct中。 Windows错误地把该文件和FoxProDataBaseContainer文件类型关联在一起。考虑第 3 章的 Edit 程序中对 Edit 菜单编写菜单。您可以花费一些时间来查找所有的 Windows Se
21、ndMessage 代码;而下一次在另一个程序里创建消息,并在应用Edit 菜单时,您还得做同样的事情。从菜单资源模板重新创建菜单您可以选择使用Insert Template 对话框中的Edit菜单,如图11.4 所示。使用MenuDesigner 上下文菜单添加一个菜单的步骤如下:图 11.4 Insert Template 对话框可以从存储的资源中重新创建菜单。但并不包括代码1从 VCL 的 Standard 属性页上选择MainMenu 组件。2双击 MainMenu 图标向窗体添加菜单。3右击MainMenu组件,显示TMainMenu组件的组件编辑器菜单,并选择MenuDesigne
22、r 菜单项(如图11.5 所示)。这样可以打开菜单编辑器,如图11.4 的背景所示。4右击鼠标,打开菜单编辑器的上下文菜单,并选择Insert From Template 菜单项,如图 11.6 所示。5从 Insert Template 对话框中(如图 11.4 所示),双击 Edit 菜单模板,以添加编辑菜单。这就是所有的工作。上述五个步骤将把 TMenuItem 组件添加到窗体类定义的开头。使用菜单资源模板需要对 OnClick 事件方法重新编写代码。更好的方法是使用组件模板,这可以包括代码。图 11.5点击 TMainMenu 组件的组件编辑器菜单上的Menu Designer 菜单项
23、图 11.6菜单设计器的上下文菜单,对于管理菜单资源模板很方便创建并安装菜单组件模板组件模板是Delphi 新增的功能。使用菜单资源模板存储菜单必须重新编写代码,而使用组件模板则不必如此。还使用上一节提到的 Edit 菜单,它是在第 3 章中实现的。我们现在把整个菜单和代码都保存为组件模板。1对 Edit 菜单编写代码(使用第3 章的例子,或步骤后列出的代码)使控件呈现正确的行为。2用代码测试Edit 菜单后,选择包含Edit 菜单的 TMainMenu 组件并点击Component| Create Component Template 菜单项。procedure TForm1.Edit1Cl
24、ick(Sender: TObject);begin/ CanUndo testUndo1.Enabled := Boolean(SendMessage(EM_CANUNDO, 0, 0 );end;procedure TForm1.Copy1Click(Sender: TObject);begin/ Copy menuprocedure TForm1.Cut1Click(Sender: TObject);begin/ Cut menuprocedure TForm1.Paste1Click(Sender: TObject);begin/ Paste menuend;procedure TFo
25、rm1.SelectAll1Click(Sender: TObject);begin/ select all textend;procedure TForm1.Undo1Click(Sender: TObject);begin/ Undo menuend;该代码与第3 章中的类似。因此我们不再对细节进行重复。现在我们已经有了Edit菜单的组件模板,每次需要菜单、相应的菜单项和代码时就可以使用该模板。使用组件模板菜单现在已经有了Edit 菜单模板,它可以像其他的组件一样使用。要使用组件模板,从Template 属性页上选择对应的模板,像其他菜单一样拖动到窗体上。菜单组件及其拥有的TMenuIte
26、ms 、以前写过的代码都可以添加到任何窗体上,而无需测试,也不会产生任何混乱的情况。扩展组件模板可以把组件模板看作组件类。当创建组件模板时(如本节的前半部分的Edit 菜单),不要删除它,当需要新的行动时,可以对该模板进行扩展。添加新的行为可以扩展已有的组件,最后我们有原来的和新的组件模板。假设现在有Edit 菜单,要对其定义Find 菜单项。使用组件面板的Dialogs 属性页上的TFindDialog 组件。按照下列步骤,即可添加Find 功能并创建新的组件模板。1把在本节开头保存的模板拖动到任意的窗体上。2从 Dialogs 属性页上拖动TFindDialog 组件到同一个窗体。3在窗体
27、上,点击Edit , Find 菜单项,并添加代码FindDialogl.Execute 。4为 TFindDialog.OnFind 事件添加事件方法, 并向事件处理程序添加一些代码以提醒用户实现查找行为。5选择TMainMenu组件和FindDialog组件并单击Component| Create ComponentTemplate菜单项,把合并的控件和代码添加到template属性页。TFindDialog组件可能的代码如下。procedure TForm1.Find1Click(Sender: TObject);beginFindDialog1.Execute;end;procedur
28、e TForm1.FindDialog1Find(Sender: TObject);beginMessageDlg( Implement find behavior!, mtInformation, mbOK, 0 );end;警告: 当存储模板组件时,确保使用惟一的名字。如果你使用已有的名字,那么 Delphi将提示你是否替换已有的模板,包括代码在内。这就是所需要的工作。通过将代码分层添加到模板中,可以对完整的组件群体和提供功能的代码创建精致的接口。然而使用组件面板也有一些缺点。组件面板并非真正的组件;它们只是写入到二进制文件 Delphi.dct 中的文本。它们提供了方便,但却放弃了灵活性
29、。回忆对 SelectAll 菜单项的前一个实现。第 3 章开始部分列出的代码中显示的 ToDo 表明,事件方法需要进行修改才能对其他类型控件做出合适的响应。 在 SelectAll 当前的实现中, 是无法响应 TComboBox 之类的控件的。不幸的是,如果你返回来完成 SelestAll 行为,可以创建新的模板。但这对包含菜单和 Find 对话框的复合模板没有影响。原来模板不会有什么改变,衍生的模板将继续使用 SelectAll 的旧版本。如果模板代码能够继承,而且可以自动更新有依赖关系的面板,那就太好了,但这并不是面向对象的继承,而是一种新型的资源流化机制。如果需要继承,那就要创建新的类
30、并进行子类化。但组件模板仍然是一种流行的方法,只会变得更好而已。对于可视化的建立多数或全部组件这个目标来说,我们已经不远了。删除组件模板Component Templates包含在 Delphi.dct 文件中。该文件不像其他的组件库,它并非软件包的库文件。因此无法像管理其他组件一样管理组件目标。为删除组件目标,需要在组件面板上找到对应的位置,并组件面板上下文菜单中点击Properties 菜单项。参考图11.7,从右边的组件列表里选取要删除的模板组件,然后点击Delete 按钮。图 11.7 Palette Properties 对话框可用于删除组件模板或隐藏组件提示:你不会意外地从图11.
31、7 所示的Palette Properties对话框中删除组件。如果选定了某个组件,Add 按钮右侧将出现一个Hide按钮; 而如果组件实际上是一个模板,那么同一位置就出现Delete 按钮。组件模板不同于组件,使用图 11.7 所示的 Palette Properties 对话框只能隐藏组件。如果你删除组件模板,也会删除所有与之相关联的代码。把组件模板中的代码保存到外部文件是个好主意,以防止意外删除。关于组件模板的最后一个问题。 组件模板方便且易于使用, 但并非实际的组件。 以 Edit 菜单为例,模板比简单的资源菜单使用起来更加方便。虽然可以创建精巧的模板,但从长远看来,将复杂的代码和相互
32、交织的组件关系封装到类的话将更为可取。11.3窗体模板与窗体继承与组件模板相比,窗体模板出现得更早一些。我们知道窗体是由TComponent 子类化而来,但如果将窗体直接安装到VCL 中,可能会出现不正确的行为;因此在Delphi的早期版本里发明了窗体模板来解决这个问题(更多的信息请参见第10 章的对话框组件部分) 。很快发现,窗体一般带有许多代码,而且大多数应用程序里会重复出现许多类型的窗体,很显然的一个例子就是About对话框。 几乎所有应用程序都有该对话框。但只是意外DFM文件与VCL无法很好的协作,就需要开发者为每个应用程序绘制一个About框并且添加必要的代码来显示该窗体吗?答案是,
33、你不必如此。最后,我们可以把窗体添加到存储库中,存储库中的窗体可以直接使用、继承和复制。注意: 在技术上,与窗体继承相关的最大的困难可能就是,如何使DFM流机制正确地工作。为了深入了解DFM 流化机制, 看第 10 章的“对象流化与窗体继承”一节。窗体继承机制现在已经工作得很好了。对于开发者来说,所有这些意味着又添加了一个强有力的方法来重用整个程序。下面的方法都可以促进代码与界面设计的重用,包括保存菜单资源,创建组件模板,将窗体添加到存储库并重用;当然最强大的方法是创建新类。创建窗体模板窗体模板是保存并添加到存储库的窗体。在上一节中,我们还记得一个包含TMainMenu 组件的窗体, 其中有编
34、辑菜单,还包括查找功能; 我们把窗体添加为组件模板。通过把窗体添加到存储库中,然后把组件模板放置到窗体上,即可迅速地启动一个主窗体。向存储库添加窗体为实验创建窗体模板的过程,我们将包含TMainMenu 和 TFindDialog 的组件模板添加到空 白窗体上(如果你在上一节中没有创建组件模板而还想继续的话,只能先把TMainMenu和 TFindDialog 组件拖动到空白窗体上)。按照下列步骤,可以将窗体添加到存储库(见图11.8)。图 11.8 MainForm 模板,其中包含 TMainMenu 和 TFindDialog 组件1右击要添加为模板的窗体,以显示窗体设计器上下文菜单。2选
35、择 Add to Repository 菜单项。3填写 Add To Repository 对话框,需要为模板窗体提供标题和描述(见图11.8),并选择要加入的属性页,输入作者信息和图标。4点击OK按钮。如果尚未保存文件,在添加到存储库之前Delphi将提示你保存文件。如果向Add To Repository对话框中的Page 组合框文本域中输入并不存在的属性页名,Delphi将创建新的属性页。这是一个对窗体模板进行组织的好方法。现在,无论何时需要带有主菜单的窗体,其中包括编辑和查找功能,只需选择New ,Other 菜单项,然后从 New Items 对话框的Forms 属性页上选择对应模板
36、(见图File,11.9)。图 11.9从 New Items 对话框选择与目标最为接近的窗体目标存储库的维护大多数人都有一个用于存放物品的地方。存储库就是个存放物品的地方。最后您可能需要对存储库中的目标重新进行组织或删除某些模板。Tools 菜单有一个Repository 菜单项,可以打开Object Repository 对话框(见图11.10)。对话框的左侧列出了所有可以修改的 Repository 属性页, 包括 Forms 属性页, 其中有用户定义窗体模板的。像 New 和 ActiveX等属性页是不可修改的。要增加、 删除、重新命名符合条件的属性页,只需选择相应的属性页并点击Add
37、 Page、Delete Page、Rename Page 中某个合适的按钮。要从Objects 列表中编辑或删除某个模板,在左侧选择包含该模板的页并在右侧的Objects 列表中点击相应的模板。例如要删除上一节定义的 FormMain 模板,首先点击左侧Pages 列表框中的Forms 项。所有的窗体模板将在右侧的 Objects 列表框中列出。找到MainForm 模板,单击以选取它并点击Delete Object按钮(如图11.10 所示,选定了Main Form 窗体)。图 11.10Object Repository对话框NEW FORM也可以在Object Repository 中
38、选择缺省的New Form 复选框, 用于表示在 Delphi 中点击 File| New | Form 菜单项时将创建哪个窗体。缺省情况下并未选定NewForm 复选框,但很容易就可以将FormMain 作为默认的新窗体(选取窗体的指令,请参见前面的章节)。选取窗体后,选定图11.10 所示的 New Form 复选框并点击OK 按钮。MAIN FORM当创建新的可执行应用程序时例如当Delphi 启动时缺省情况下主窗体是空白窗体。 另外,你还可以在Delphi中点击 Tools | Repository 菜单项打开ObjectRepository 对话框。当存储库被打开后, 选取所需的新窗
39、体作为主窗体并选定Main Form复选框(如图 11.10 所示)。这样,每次创建新应用程序时,将使用该窗体作为缺省的主窗体。向存储库添加工程可以将整个的工程添加到存储库。完整的工程由工程中的DPR 文件、所有的源代码、窗体和数据模块组成。如果要把一个或多个窗体定义为工程模板,可以使用Project 菜单将工程添加到存储库。要向存储库添加工程,首先选择要添加工程,然后点击Project | Add toRepository 菜单项。这时将显示Add to Repository 对话框,它与窗体模板的情形类似(见图 11.8),由于将添加所有窗体,所以不需要选择添加哪个窗体。将工程添加到存储库
40、后, 点击 File | New | Other 菜单项, 然后从 New Items 对话框中选择所需的工程,即可基于已有的工程启动一个新的工程。可用于放置工程模板的好地方是 Projects 属性页,尽管在添加工程时也可以创建新的属性页。提示:如果要把缺省的工程从标准的可执行程序改变为存储库中的某个工程,那么可以从Tools 菜单中打开对象存储库,并将相应的工程设置为新的缺省工程。选定一个工程后,Objects 列表框下将出现New Project复选框。 选定该复选框,则对应的工程将成为新的缺省工程。当从 New Items 对话框中选择一个工程模板时, Delphi 将提示您为该工程输
41、入路径,这时 Delphi 相应创建该工程中所有的文件。要避免选择创建工程模板时的原始路径;如果这样做你将覆盖原来的存储库文件。也可以从Object Repository对话框中删除工程模板。细节请参考前面,标题为“存储库的维护”一节。使用模板窗体当使用模板创建新窗体时,有三种选择。可以在New Items 对话框的Forms 属性页上选择 Copy 、Inherit 或 Use 三者之一。缺省情况下,将选择Copy 。您可以得到窗体的完整副本,但不会维护模板窗体与新窗体之间的进一步的关系(如果选择Use,那么实际上将修改存储库中的窗体模板;即,任何改变都会反映到窗体在存储库中的版本)。如果选
42、择Inherit ,将继承模板窗体,这里的继承指的是面向对象的意义。对窗体在存储库中版本的改变将反映到子窗体。考虑到主窗体含有Edit 菜单和 Find 对话框。 如果使用某个主窗体模板创建新的窗体,新窗体将子类化那个窗体。以后,再选择该主窗体模板以及 Use 选项,添加一个Replace 对话框,则所有的子窗体在下次编译时将自动具有Replace行为。由 DFM文件的内容可以看出原始窗体、副本窗体、以及使用模板窗体创建的子窗体之间的不同。下面的片断来自三个独立的DFM 文件,分别演示了基于Use、Inherit 、Copy方式创建窗体时数据写入DFM 文件的方式。这三个窗体都与窗体类TFor
43、mMain有关。object FormMain: TFormMainLeft = 435Top = 254Width = 418Height = 320Caption = Application Title Here上面列出的是实际的窗体。当在 New Items 对话框的 Forms 属性页中选择 Use 时,将得到模板窗体。object FormMain1: TFormMain1Left = 435Top = 254Width = 418Height = 320Caption = Application Title Here当选择该窗体是从Copy 时,得到的是TFormMain1 ,看上
44、去像是TFormMainTForm 子类化而来。所拥有的组件都被复制并流化到DFM的子类,但实际上文件中,但在模板和窗体副本之间不存在更进一步的关系。inherited FormMain4: TFormMain4Caption = FormMain4PixelsPerInch = 120TextHeight = 16end上面列出的DFM 文件是从TFormMain 继承时创建的。与前面的两个DFM 文件不同,第一个词不是object,而是 inherited 。这是个约定, 用于表示应从祖先窗体读取额外的流化信息。当要对所有的祖先都作出持久性的改变时,可修改原始窗体。若希望父窗体与子窗体之间
45、的改变互不影响,应使用复制;如果要对窗体的行为与外观在整个家族中定义并维护一个核心集合,则应使用继承。组件模板、窗体模板、工程模板是三种极好的方法,可用于在一组应用程序中维护工程内和工程间的一致性。一致性是连贯性的一个因素。即使应用程序提供了某些前所未见的功能,如果交互界面是一致的,那么经过适当的学习之后新的任务看起来也会更加连贯。在应用程序被认为具有完备性之前,它首先必须是一致和连贯的。另外,完备性还需要程序能够合乎用户的需求。11.4静态与动态的组件用法当把窗体添加到应用程序时,将把一行代码加入到DPR文件(工程源文件)中,以便在程序启动时自动创建窗体。Application.Create
46、Form(TForm1, Form1);对于 Visual Basic 程序员或尚未完全掌握对象及动态对象创建的用法的新程序员来说,这可以使得添加和使用窗体更为容易。对外行人来说, 这实际上使得Delphi 和 Visual Basic看起来很相似:创建窗体、运行程序、调用show 或 show modal,然后用户就可以使用窗体了。当在窗体上绘制组件时,也是同样。好像是有魔力一样,它们在运行时出现时,自然的就具有设计时的状态以及任何由自己编写的代码所定义的行为。Delphi 与 Visual Basic 之间的相似性在这里结束了。与 Visual Basic相比,Object Pascal(
47、 Delphi 的语言) 与 C+ 更为相似。 Delphi 像 Visual Basic 一样易于使用, 并具有 C+ 的强大功能。这意味着新的程序员也能立即开始,而经验丰富的老手则能够创建非常复杂的应用程序。Delphi 自动创建窗体或在运行时自动创建组件时,其行为是一致的。而且,已经对流化机制编码,知道如何解析组件引用、从 DFM 文件里读出属性、构造对象。当 Delphi 自动创建窗体和组件时,与手工使用代码来创建的方式是一致的。动态创建窗体到现在为止,您可能已经熟悉如何绘制程序所拥有的窗体了。有些程序员允许自动创建所有的窗体,但这会使可执行文件变得相当大并降低程序的启动速度。大多数用
48、户通常只使用某些核心功能,从来或很少使用其他功能。最终结果是用户为一些从不使用的功能付出了性能方面的代价。好一些的方法是在需要的时候才创建窗体、数据模块以及加载库。这实际上是通过推迟堆内存的分配以及窗体流数据的读取,以便降低程序启动时一次性创建窗体的成本,该技术有个名字,可以称之为惰性实例化(lazy instancing )。在 Project Options 对话框的Forms 属性页中,将窗体和数据模块从auto create 栏移动到 available 栏,即可推迟窗体的创建。虽然在启动时性能有所提高,但以后在运行时动态创建窗体是要付出代价的;除非该功能对时间要求非常高或经常使用,否
49、则在需要时动态创建窗体比一次性创建所有的窗体更为可取。有两种技术可用于创建惰性实例,分别讨论如下。显式构造显式构造是指调用窗体构造函数创建窗体,如何使用窗体,最后释放创建窗体所用的内存。Form := TForm.Create(self);tryif( Form.ShowModal = mrOK ) then/ doe herefinally Form.Free;end;如果把窗体作为模式对话框来显示, 该技术工作得很好, 因为在调用 ShowModal 时代码的运行是同步的。只要关闭窗体,内存也就被释放了。另外,您也可以显示窗体并让窗体在关闭时自行释放内存。TForm.Create(Self).Show;被创建的窗体需要一个 OnClose 事件处理程序,以便进行一些设置,这样当窗体关闭时它可以将自身从内存中释放出去。procedure TForm1.FormClose(Sender: TObject; var Action:TCloseAction);begi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- Unit3 Weather A let's learn(说课稿)-2023-2024学年人教PEP版英语四年级下册001
- 2025写场地租赁合同范文
- 2025工程建设招标投标合同履约银行保证书
- Unit 1 Playtime Lesson 3(说课稿)-2023-2024学年人教新起点版英语二年级下册
- 2023九年级历史下册 第一单元 殖民地人民的反抗与资本主义制度的扩展第3课 美国内战说课稿 新人教版
- 2025泵车租赁合同
- 2024-2025学年高中历史 专题二 近代中国资本主义的曲折发展 2.1 近代中国民族工业的兴起说课稿1 人民版必修2
- 蔬菜物资发放方案
- 养生馆前台合同范例
- 代理经营店铺合同范例
- 教学的模样读书分享
- 老年髋部骨折患者围术期下肢深静脉血栓基础预防专家共识(2024版)解读 课件
- 江苏省无锡市2024年中考语文试卷【附答案】
- 五年级上册小数脱式计算200道及答案
- 2024年秋新沪科版物理八年级上册 第二节 测量:物体的质量 教学课件
- 直播带货基本操作流程(直播带货流程完整版)
- 2024义务教育英语课程标准2022版考试题库附含答案
- 多旋翼无人机驾驶员执照(CAAC)备考试题库大全-下部分
- 浙教版七年级上册数学第4章代数式单元测试卷(含答案)
- 七年级下册第六章《人体生命活动的调节》作业设计
- 特种设备使用单位日管控、周排查、月调度示范表
评论
0/150
提交评论