📄 delphifqa.htm
字号:
下面列出Delphi所会产生的延伸档名以及含意: DPR - Delphi的Project档. 这个档本身即是个Pascal原始码的档; 其实也就是该app- lication真正的主程式. ~DP - 您前一次所储存的DPR档的备份档案. PAS - 在Delphi中, PAS档案通常是一个unit的原始程式, 不然就是一个form所对应的原 始程式(译注: 一个unit不一定要有一个form). 而一个app.实际的主程式则是放 在DPR档内. ~PA - PAS档案的备份. DFM - 这些档案会与其同名的PAS档成对出现. DFM档是二进位资料的档案, 是用来建立 其所含括的元件的初始资讯(initial data)(也就是那些您在设计时期对那些属性 所做的设定, 而不是在程式中所设定的). 您不能以一般的文字编辑器来编辑DFM 档, 但如果您在Delphi载入它, 您就能看到其本文(textual)型态的内容. (译注: 事实上您也可以在Delphi内将一个DFM档案载入後再转存成一个TXT档, 再 利用一般文字编辑器来编辑. 请参考第3.2节内的说明). ~DF - DFM档案的备份. DCU - 已编译过的unit, 就如同一个OBJ档一般. OPT - Project功能项; 也就是储存编译器以及联结器(linker)的功能设定, 还有那一个 form是main form, 那一个图示(icon)是给这个app.用的...等设定. 通常, 您应 该是在Delphi IDE环境内的Options|Project内来设定这些东西. RES - Windows资源档(resource file); Delphi会自动产生这个档案, 以在编译的时候 使用. 您可以不要去管这个档案内有些什麽东西, 但可不要将它杀掉了!! EXE - 上面的档案集合起来所做出来的可执行档案. 5.3 我如何使CPU暂停执行目前的task而去执行其它的task, 就如同VB□面的 "DoEvents"一般? 在Delphi中您可以使用Application.ProcessMessages来做到相同的功用. 有个API函式 叫Yield似乎也有相同效用, 但对大多数的Delphi应用程式来说会较不安全. Steve Teixeira <steixeir@borland.com> 做了解释: 除非能够"保证"您的application不会接收到任何的讯息(messages)(也就是说, 您 的application没有视窗存在), 否则您不应该使用Yield()函式. 然而您倒是可以呼叫Application.ProcessMessages来代替. ProcessMessages将一 个PeekMessage()回圈(loop)封装(encapsulates)起来, 所以这才是利用API来解决 这个问题的办法(API-way). 5.4 为什麽当我试著要在事件(events)中存取Sender物件时, 在编译时会得到一个错 误讯息? 如果您看过Sender的宣告(decalration), Sender其实是一个TObject类别的物件, 而所 有物件的类别型态也都是衍生自TObject. 大概因为您尝试著要存取一个TObject内所没 有的属性 ---- 例如Text, Caption, 或是其它的属性 ---- 所以才会产生这种情况. 所以如果您用了像"Sender.Text"这样的叙述, 当然就会出问题了!!但是, 如果(比方说) 您知道该事件的引动者(译注: 即sender, 请注意大小写的不同)是个TEdit的物件, 那麽 您可以用"(Sender As TEdit).Text"的方式来强定型别(译注: 即type casting. 由於 TObject是VCL中所有类别的ancestor, 当然其所产生的物件可以接受其derived classes 所产生的物件. 详细解释请参考User's Guide第226页Assigning values to object variables). 若是您无法确定其引动者一定为某个类别的物件的话, 您可以用 "if (Sender is TEdit) then <做什麽事>"的方式来检查. 请参考第5.14节. 5.5 有没有什麽工具能帮助我将我原先发展的应用程式(application)转换到Delphi上? 有一个自动翻译器(translator)能够将Visual Basic的程式码转换成Delphi的程式码. 我从一些用过这个翻译器的人那边听说过, 而且其翻译的结果似乎还不错!!我想对某些 人而言可能很有用, 但就不是所有Delphi的使用者都能享受到它的好处了!!它是由下面 这家厂商所制作的(译注: Delphi Programming Explorer的随书磁片中就附了这个程式 的demo版本): EarthTrek 7 Mountain Rd. Burlington, MA 01803 (617) 273-0308 5.6 在Delphi中有没有相当於VB中控制元件阵列(control arrays)的用法? 没有. Delphi元件的属性中并没有类似於VB元件中的Index属性, 所以您无法宣告这样的 阵列. 但是有三项理由使您会用到它, 而且每一种理由在Delphi内都可以解决掉: 理由1. 您想让一个form中的不同元件共用同样的事件处理器(event handlers). 这其实是非常简单的事情, 您只要对每个元件的同一个事件设定同一个事件处理器就好 了(译注: 请参考User's Guide第64页Associating event with an existing evnet handler)!!其实这要比设定元件阵列要好, 因为您可以让不同类别的元件共用同样的事 件处理器; 例如, 一个toolbar上的按键与一个menu内的选项(item)就可以针对它们的 Click事件呼叫同一个事件处理器. 理由2. 您想要在执行时期, 动态地配置(allocate)与释放(deallocate)元件. 这在Delphi中也很容易解决. 假设您有个按键(button)在您的form上, 而您想要每次按 下这个按键後就产生另一个新的按键, 下面这段□例告诉您该怎麽做: procedure TForm1.Button1Click(Sender: TObject); var NewButton: TButton; begin NewButton := TButton.Create(Self); NewButton.Parent := Self; end; 值得注意的是一旦这个事件结束之後, 这个NewButton变数本身就不在我们的视界 (scope)之内了, 而且我们也没有个指标指向这个新产生出来的元件. 您不能在某个元件 的事件处理器中释放掉它自己, 所以如果您要释放掉动态产生出来的元件, 您就必须在 其所归属的Form.Controls阵列中找到它, 并且/或是对指向您所产生的元件的指标串列 (list of pointer)做维护(maintain)的动作. 假如程式目前不是在该元件所属的事件处 理器中执行, 您就可以安全地呼叫该元件的Free method来释放掉它. 理由3. 您真的想要以数字指示的方式来存取元件. 我因为想要利用Delphi来撰写一个类似Reversi这个BBS线上游戏的程式当做练习, 所以 才碰到这个情况. 在我的form上有100个TShape元件, 在一个10x10的方格(grid)中. 我 在form designer中将所有的shape都弄了出来, 并且给它们每个人一个像"ShapeNN"这样 的名称(name), 但之後我又宣告了一个阵列来指向这些元件:"Board: array[1..10, 1.. 10] of ^TShape;", 并将它放在该form的Create事件中. 其实这一百行程式真的是不需 要的, 但之後我却可以在一个二维阵列中存取到每一个元件, 就像这样:"Board[3,5]^. Brush.Color := clRed;" ---- VB无可否认地在这点上就可以表现得比较好. 5.7 我该如何关闭(close)一个modal form? 还有, 有没有一个最好的方法来关闭任何 一个form? 一般来说, 您可以呼叫该form的Close method来达成, 这将导致该form的OnClose事件被 执行, 而在其中也可以决定是否真的要close. 例如在这个form中还有资料尚未储存, 那 麽您就不能一点提示都不给使用者就把该form给close了!! Close并不会释放掉该form所 占有的记忆体空间, 除非您在其OnClose事件中呼叫了该form的Release method. 如果您想无条件地将一个form给关掉, 直接呼叫该form的Release method即可. 这个 method有点像Free, 但是Release却允许在记忆体空间释放掉之前先将事件处理器(例如, OnDestroy)的执行给结束掉. 当您将一个Modal form的ModalResult属性设给一个大於零的值, 它就会"结束其modal的 状态". 如果在该modal form上您放了一个按键, 并且将该按键的ModalResult属性设了 某个值, 那麽当使用者按了那个按键之後, 该form就会关闭, 并且传回您指定该按键的 ModalResult值. 您可以藉由将该form的ShowModal method当做一个function来呼叫, 以 取得其result值; 也就是: result := Form.ShowModal;. 5.8 目前市面上有任何用Delphi发展出来的商业软体(commercial applications)吗? 就我所知, 目前还没有(译注: 就笔者所知, 国内近期内就将出现). Delphi正式上市的 时间还不够长 ---- 再给他点时间吧!!如果您能够用VB写个商业软体, 那麽您就能够用 Delphi写商业软体. 当然, Delphi本身其实就是用Delphi以及组合语言写出来的(官方说 法), 而且也绝对是个货真价实的商业产品. 5.9 我必需要有Windows API的基础才能够使用Delphi吗? 好像有一种感觉, 如果您真的想要用Delphi的话, 您就必须比在使用VB时再具备多一点 有关Windows的相关知识. 其实这并不十分正确!!您可以不需要具备太多有关Windows内 部动作的相关知识就可以使用这两种发展工具, 但是无论您用那一个, 您都必需对Win- dows API有基本的认识, 才能够做到绝大部份您想做的事. Delphi与VB不同的地方是 Delphi让您更多的能力去完成这些有趣的事, 所以是因为您不晓得该怎麽下手, 才会有 Delphi的限制好像比VB多的感觉. 5.10 我必需要有物件导向程式设计(object-oriented programming)的认识才能使用 Delphi吗? 喔!!这是当然的. Delphi的使用介面设计工具所产生的即是物件导向型态的程式码. 然 而, 其实如果您熟悉Visual Basic或是Powerbuilder的话, 您就会对OOP有足够的认知来 看待. 您并不需要制造您自己的物件就能够利用Delphi做非常多的事情, 但了解其中的 奥妙也将会成为越来越重要的关键. 5.11 Delphi□面的例外处理(exception handling)是怎麽动作的? 其基本架构如下面所示: p := new(big_thing); try blah(p); foo(p); finally dispose(p); end; 第一行所做的事情是配置一大块记忆体空间, 然後在"try"区块□面, 我执行了一些叙述 , 每一条叙述都有可能产生错误 ---- 或换句话说, "产生一个事件(raise an event)". 当有错误产生的时候, 其它在try区块内的叙述就会被忽略掉, 而直接跳到"finally"区 块内去执行. 如果没有错误产生, 则当try区块内的最後一条叙述执行完毕之後, 也会进 入finally区块内去执行. 所以无论如何, 那块先前所配置出来的记忆体空间都会被释放 掉. 这种"try/finally"架构就能够将包括Windows GPF在内的所有错误给拦下来处里. 此外, 不管是针对特定的错误或是所有的错误, 您还能够构□"except"这种区块来提供 区域性(local)的错误处理; 您还可以建立您自己的全域式(global)错误处理器, 以处理 那些不在try区块内所发生的错误. 详细资讯请参阅User's Guide中的第7章. 5.12 Delphi内是使用Pascal还是C的字串型态(style)? 两种都有. Delphi内有两种不同型态的字串操作函式, 一种是给以null字元做结尾 (null-terminated)的字串型态用的, 另一种则是给Pascal型态(Pascal-type)(也就是具 有长度位元的型态)的字串型态用的. 您将发现您会被这两种不同架构的字串所牵绊. Delphi内有许多函式将大部份常用的Windows API给包装起来. 例如MessageBox就是一个 Windows的API呼叫, 它所需要的是PChar型态(译注: 即null-terminated型态)的字串; 但是Delphi也有MessageDlg这个函式, 它则是接受Pascal型态的字串. 如果您要将一个Pascal型态的字串传给一个只接受PChar型态字串的函式使用, 您可以试 试下面这段程式. 其中假设s是一个string型态的变数, 而且还有剩馀空间可以容纳其它 的字元: s[length(s)+1] := #0; { Appends a null to the end of the string } C_Style_Function(@s[1]); { @s[1] is a PChar to the beginning of s } (译注: Delphi提供了让null-terminated字串与Pascal字串相互转换的函式, 请参考 on-line help的说明.) 5.13 Delphi如何处理Windows的callback呼叫? 就像在C□面一般: 您可以得到一个指向您的callback程序的远程(far)指标(您必需记得 加上"far"修饰字来宣告, 除非您用了{F$+}命令来强迫所有的函式都变成far), 将它设 给Windows的callback函式就可以了. 5.14 执行时期型别资讯(Run-Time Type Information, RTTI)是怎麽样个动作方式? Delphi有两个新的运算子: "as"以及"is". "as"运算子是一个有条件的(protected)型别 转换(typecast)运算子. 您可以利用这个运算子来告诉编译器, 将某个物件的型别强定 成另一种型别, 但在执行时期时如果两种类别并不相容, 您就会看到错误. 例如, 如您 有一个叫TSport的类别, 而它有两个descendant: TBasketball和TFootball, 您想要有 一个TSport类别的变数 ---- 但您也想在程式中某些特定的地方让这个转成一个包含了 TFootball的instance的变数. 所以, 您可以用(MySport as TFootball)的方式, 来存取 一些属於TFootball才有的属性. 但若是您不小心将TBasketball甚或其它无关的类别传 入, 而还想要存取TFootball的特有属性的话, 那就会有错误发生了!! "is"运算元是用来比较某个物件的instance与某个类别的物件, 以确定当使用"as"的时 候能否正常通过. 假设您您有个TSport的变数MySport, 而它目前是包含了一个TBasket- ball的instance, 那下面这几段叙述就是为真(true): (MySport is TSport) (MySport is TBasketball) not (MySport is TFootball)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -