1、Delphi编程代码规范Delphi编程代码规范1. 一般的源代码格式规则 21.1 缩进 21.2 空格 21.3 边距 21.4 颜色及文字属性 21.5 beginend 22. OBJECT PASCAL 32.1 括号 32.2 保留字和关键字 32.3 过程和函数(例程) 32.4 变量 42.5 常量(const) 52.6 资源串(resourcestring) 52.7 类型 52.8 构造类型 62.9 语句 62.10 结构化异常处理 82.11 类 83. 文件 103.1 项目文件 103.2 Form文件 103.3 数据模块文件 103.4 远程数据模块文件 10
2、3.5 单元文件 103.6 文件头 113.7 函数或过程头格式如下 114. Form与数据模块 124.1 Form 124.2 数据模块 135. 包 145.1 运行期包与设计期包 145.2 文件命名标准 146. 元件 146.1 自定义的元件 146.2 元件实例的命名规则 156.3 元件性质标识名 156.4 元件的前缀 151. 一般的源代码格式规则1.1 缩进缩进就是每级间有两个空格。不要在源代码中保存制表符。这是因为,制表符的宽度随着不同的用户设置和代码管理实用程序(打印、文档及版本控制等)而不同。通过使用Tools | Editor Options菜单,在Edito
3、r Properties对话框的General页上,不要选中Use tab Character和Optimal Fill复选框,这样,制表符就不会被保存。1.2 空格遇到如下情况,需要添加空格:1) 逗号的后面;2) 冒号的后面;3) 等号的前后;4) 赋值号的前后5) 运算符(+、-、*、/)的前后。1.3 边距边距设置为80个字符。源代码一般不会因写一个单词而超过边距,但本规则比较灵活。只要可能,长度超过一行的语句应当用逗号或运算符换行。换行后,应缩进两个字符。1.4 颜色及文字属性通过使用Tools | Editor Options菜单,在Editor Properties对话框的Col
4、or页上,设置相应元素的颜色及文字属性。其中:注释(Comment): 斜体深绿色保留字(Reserved word): 粗体天蓝色字符串(String): 普通洋红色数值(Number): 普通红色其他元素取Delphi IDE缺省设置。1.5 beginendbegin语句必须单独占一行,例如,下面第一行是错误的,而第二行正确:for i := 0 to l0 do begin / 错, begin与for在同一行for i := 0 to 10 do / 对, begin在另外一行中beginend;本规则的一个特殊情况是,当begin为else语句的一部分时,例如:if some st
5、atement = thenbegin.endelse beginSomeOtherStatement;end;end语句总是单独一行。当begin不为else语句的一部分时,相应的end语句与begin语句的缩进量相同。2. OBJECT PASCAL2.1 括号在左括号与下一个字符之间没有空格。同样,右括号与前一字符间也没有空格。下面的例于演示了正确与不正确的空格。CallProc( AParameter ); / 错!CallProc(AParameter); / 正确!不要在语句中包含多余的括号。在源代码中,括号只有在确实需要时才使用。下面的例子演示了正确与不正确用法:if (i =
6、42) then / 错,括号是多余的if (i = 42)or (j = 42) then / 正确,必须使用括号2.2 保留字和关键字Object Pascal语言的保留字和关键字总是全部小写。2.3 过程和函数(例程)2.3.1 命名与格式 例程名应当以大写字母开始,且大小写交错以增加可读性。下面是一个不正确的写法:procedure thisisapoorlyformattedroutinename;改成这样写就对了:procedure ThisIsMuchMoreReadableRoutineName; 例程名应当有意义。进行一个动作的例程最好在名称前加上表示动作的动词为前缀。例如:
7、procedure FormatHardDrive; 设置输入参数值的例程名应当以Set为其前缀,例如:procedure SetUserName; 获取数值的例程名应当以Get为其前缀,例如:function GetUserName: string;2.3.2 形参 格式只要可能,同一类型的形参应当归并在一起:procedureFoo(Param1, Param2,Param3: Integer; Param4: string); 命名所有形参的名称都应当表达出它的用途。如果合适的话,形参的名称最好以字母A为前缀,例如:procedure SomeProc(AuserName: string
8、; AuserAge: integer);当参数名与类的特性或字段同名时,前缀A就有必要了。 参数顺序形参的顺序主要要考虑寄存器调用规则。最常用的参数应当作为第一个参数,按使用频率依次从左到右排。输入参数位于输出参数之前。范围大的参数应当放在范围小的参数之前。例如:SomeProc(AP1anet, AContinent, ACountry, AState, ACity);有些则例外。例如,在事件处理句柄中,TObject类型的Sender参数往往是第一个要传递的参数。 常量参数要使记录、数组、短字符串或接口类型的参数不能被例程修改,就应当把形参标以const。这样,编译器将以最有效的方式生成
9、代码,保证传递的参数不可变。如果其他类型的参数希望不被例程所修改,也可以标上const。尽管这对效率没有影响,但这给例程的调用者带来了更多的信息。 命名冲突当两个单元中含有相同名称的例程时,如果调用该例程,实际被调用的是uses子句中最后出现的那个单元中的例程。为避免这种情况,可在方法名前加想要的单元名,例如:SysUtils.FindClose(SR);或Windows.FindClose(Handle)2.4 变量2.4.1 变量的命名与格式变量的名称应当能够表达出它的用途。循环控制变量常常为单个字母,诸如I、J或K。也可以使用更有意义的名称,例如UserIndex。布尔变量名必须能清楚表
10、示出True和False值的意义。2.4.2 局部变量局部变量用于例程内部,遵循其他变量的命名规则。局部变量加前缀l_(循环控制变量除外),如l_UserName。如果需要的话,应当在例程的入口处立即初始化变量。局部的AnsiString类型的变量自动被初始化为空字符串,局部的接口和调度接口类型的变量自动被初始化为nil,局部的Variant和OleVariant类型的变量自动被初始化为Unassigned。2.4.3 全局变量一般不鼓励使用全局变量。不过,有时候需要用到。即使如此,也应当把全局变量限制在需要的环境中。例如,一个全局变量可能只在单元的Implementation部分是全局的。全
11、局数据如果将由许多单元使用,就应移动到一个公用单元里被所有对象使用。全局数据可在声明时直接初始化为一个值。注意,所有全局变量自动进行零初始化,因此,不要将全局变量初始化为诸如0、nil、或Unassigned等空值。零初始化的全局变量在.EXE文件中不占空间。零初始化的数据保存在虚拟的数据段中,而虚拟数据段只在应用程序启动时才分配内存。非零初始化的全局数据则在.EXE文件中占空间。2.5 常量(const)常量的命名应当能够表达出它的用途。如果有类别,该类别的所有常量加前缀,前缀为类别缩写的小写字母;例如:对于文件打开方式(File Open Modes),定义常量:fmOpenRead =
12、$0000;fmOpenWrite = $0001;如果无类别,常量的前缀为con。例如:conProductName = GBG2000;2.6 资源串(resourcestring)如果在模块中有提示信息类的字符串,把该字符串定义为资源串。资源串的命名应当能够表达出它的用途。如果有类别,该类别的所有资源串加前缀,前缀为类别缩写的小写字母,同常量定义。如果无类别,资源串的前缀为rs。例如:rsFileOpenError = 文件打开失败 !;2.7 类型2.7.1 大小写规则类型标识符是保留字,应当全部小写。Win32 API类型常常全部大写,并且遵循诸如Windows.pas或其他API单
13、元中关于特定类型名的规则。对于其他变量名,第一个字母应大写,其他字母则大小写交错。下面是一些例子:varMytring: string; / 保留字WindowsHandle: HWND; / Win32 API 类型i: Integer; / 在System单元中介绍的类型标识2.7.2 浮点型不鼓励使用Real类型,因为它只是为了与老的Pascal代码兼容而保留的。通常情况下对于浮点数应当使用Double。Double可被处理器优化,是IEEE定义的标准的数据格式。当需要比Double提供的范围更大时,可以使用Extend。Extend是Intel专用的类型,Java不支持。当浮点变量的物
14、理字节数很重要时(可能使用其他语言编写的DLL),则应当使用Single。2.7.3 枚举型枚举类型名必须代表枚举的用途。名称前要加T字符作为前缀,表示这是个数据类型。枚举类型的标识符列表的前缀应包含23个小写字符,来彼此关联。例如:TSongType = (stRock, stClassical, stCountry, stAlternative, stHeavyMeta1, stRB);枚举类型的变量实例的名称与类型相同,但没有前缀T,除非为了给变量一个更加特殊的名称,诸如FavoriteSongType1、FavoriteSongType2等。2.7.4 Variant和OleVaria
15、nt一般不建议使用Variant和OleVariant。但是,当数据类型只有在运行期才知道时(常常是在COM和数据库应用程序中),这两个类型对编程就有必要。当进行诸如Automation、ActiveX控件的COM编程时,应当使用0leVariant;而对于非COM编程,则应当使用Variant。这是因为,Variant能够有效地保存Delphi的原生字符串,而OleVariant则将所有字符串转换为OLE字符串(即WideChar字符串),且没有引用计数功能。2.8 构造类型2.8.1 数组类型数组类型名应表达出该数组的用途。类型名必须加字母T为前缀。如果要声明一个指向数组类型的指针,则必须
16、加字母P为前缀,且声明在类型声明之前。例如:typePCycleArray = TCycleArray;TCycleArray = array1.100 of integer;实际上,数组类型的变量实例与类型名称相同,但没有T前缀。2.8.2 记录类型记录类型名应表达出记录的用途。类型名必须加字母T为前缀。如果要声明一个指向记录类型的指计,则必须加字母P为前缀,且其声明在类型声明之前。例如:typePEmployee = TEmployee;TEmployee = recordEmployeeName: string;EmployeeRate: Double;end;2.9 语句2.9.1 i
17、f语句在ifthen/else语句中,最有可能执行的情况应放在then子句中,不太可能的情况放在else子句中。为了避免出现许多if语句,可以使用case语句代替。如果多于5级,不要使用if语句。请改用更清楚的方法。不要在if语句中使用多余的括号。如果在if语句中有多个条件要测试,应按照计算的复杂程度从右向左排。这样,可以使代码充分利用编译器的短路估算逻辑。例如,如果Conditionl比Condition2快,Condition2比Condition3快,则if语句应这样构造:if Condition1 and Condition2 and Condition3 then如果无else子句且
18、执行语句只有一句,该执行语句写在then后,例如:if Condition then do some thing;2.9.2 case语句 概述case语句中每种情况常量应当按数字或字母的顺序排列。每种情况的动作语句应当简短且通常不超过45行代码。如果动作太复杂,应将代码单独放在一个过程或函数中。case语句的else子句只用于默认情况或错误检测。 格式case语句遵循其他一般的缩进和命名规则。2.9.3 while语句建议不要使用Exit过程来退出whi1e循环。如果需要的话,应当使用循环条件退出循环。所有对while循环进行初始化的代码应当位于while入口前,且不要被无关的语句隔开。2.
19、9.4 for语句如果循环次数是确定的,应当用for语句代替while语句。2.9.5 repeat语句repeat语句类似于while循环,且遵循同样的规则。2.9.6 with语句 概述with语句应小心使用。要避免过度使with语句,尤其是在with语句中使用多个对象或记录。例如:with Record1, Record2 do这些情况很容易迷惑编程人员,且导致检测bug困难。 格式with语句也遵循本章关于命名和缩进的规则。2.10 结构化异常处理2.10.1 概述异常处理主要用于纠正错误和保护资源。这意味着,凡是分配资源的地方,都必须使用:tryfinally来保证资源得到释放。不过
20、,如果是在单元的initialization/finalization部分或者对象的构造析构中来分配释放资源则例外。2.10.2 tryfinal1y的用法可能的情况,每个资源分配应当与:tryfinally结构匹配。例如,下面代码可能导致错误:SomeClassl := TSomeClass.Create;SomeClass2 := TSomeClass.Create;trydo some codefinallySomeClass1.Free;SomeClass2.Free;end;上述资源分配的一个安全途径是:SomeClass1 := TSomeClass.Create;trySomeC
21、lass2 := TSomeClass.Create;trydo some codefinallySomeClass2.Free;end;finallySomeClass1.Free;end;2.10.3 tryexcept的用法如果您希望在发生异常时执行一些任务,可以使用tryexcept。通常,没有必要为了简单地显示一个错误信息而使用tryexcept,因为Application对象能够自动根据上下文做到这一点。如果要在except子句中激活默认的异常处理,可以再次触发异常。2.10.4 tryexceptelse的用法不鼓励使用带else子句的tryexcept,因为这将阻塞所有的异常,
22、包括您没有准备的异常。2.11 类2.11.1 命名与格式类的名称应当表达出类的用途。类名前要加字母T,表示它是一个类型。例如:typeTCustomer = class(TObject);类的实例名称与类名相同,只不过没有前缀T。varCustomer: TCustomer;注意:关于元件的命名,请参阅“元件类型命名标准”部分。2.11.2 字段 命名与格式字段的命名遵循与变量相同的规则,只不过要加前缀F,表示这是字段。 可见性所有字段必须为私有。如果要在类的作用域之外访问字段,可借助于类的特性来实现。2.11.3 方法 命名与格式方法的命名遵循与过程和函数相同的规则。 静态方法当您不希望一
23、个方法被派生类重载时,应当使用静态方法。 虚拟方法与动态方法当您希望一个方法能被派生类重载,应当使用虚拟方法。如果类的方法要被多个派生类直接或间接地使用,则应当用动态方法。例如,某一个类含有一个被频繁重载的方法,并有100个派生类,则应将方法定义为动态的,这样,可以减少内存的开销。 抽象方法如果一个类要创建实例,则不要使用抽象方法。抽象方法只能在那些从不创建实例的基类中使用。 特性访问方法所有特性访问方法应当定义在类的私有或保护部分。特性访问方法遵循与过程和函数相同的规则。用于读的方法应当加Get前缀,用于写的方法应当加Set前缀,并且有一个叫Value的参数,其类型与特性的类型相同。例如:T
24、SomeClass = class(TObject);privateFSomeField: Integer;protectedfunction GetSomeField: Integer;procedure SetSomeField(Value: Integer);publicproperty SomeField: Integer read GetSomeField write SetSomeField;end;2.11.4 特性特性作为私有字段的访问器,遵循与字段相同的命名规则,只不过没有F前缀。特性名应为名词,而不是动词。特性是数据,而方法是动作。数组特性名应当是复数,而一般的特性应当是单
25、数。2.11.5 访问方法的使用尽管不是必须,但还是建议您使用写访问方法来访问代表私有字段的特性。3. 文件3.1 项目文件项目文件的名称应当具有描述意义。例如,“The Delphi 4 Developers Guide Bug Manager”的项目名称为DDGBugs.dpr,一个系统信息程序的名称为SysInfo.dpr。3.2 Form文件Form文件的名称应当表达出Form的用途,且具有Frm后缀。例如,About的文件名叫AboutFrm,主Form的文件名叫MainFrm。3.3 数据模块文件数据模块文件的名称应当表达出数据模块的作用,且具有DM后缀。例如,Customers数
26、据模块的文件名叫CustomersDM.dfm。3.4 远程数据模块文件远程数据模块文件的名称应当表达出远程数据模块的用途。名称后要加RDM后缀。例如,Customers远程数据模块的文件叫CustomersRDM.dfm。3.5 单元文件3.5.1 普通单元的结构 单元名单元的名称应当有描述性。例如,应用程序的主Form单元叫MainFrm.pas。 Uses子句Interface部分的Uses子句应当只包含该部分需要的单元。不要包含可能由Delphi自动添加的单元名。Implementation部分的Uses子句应当只包含在该部分需要的单元,不要有多余的单元。 Interface部分Int
27、erface部分应当只包含需要被外部单元访问的类型、变量、过程与函数的声明。而且,这些声明应当在Implementation部分之前。 Implementation部分Implementation部分包括本单元私有的类型、变量、过程与函数的声明。 Initialization部分不要在单元的Initialization部分放置花费时间很多的代码。否则,将导致应用程序启动时显得很慢。 Finalization部分确保释放所有在Initialization部分中分配的资源。3.5.2 Form单元Form单元文件的名称与相应的Form名称相同。例如:About的单元名称叫AboutFrm.pas。
28、主From的单元文件名称叫为MainFrm.pas。3.5.3 数据模块单元数据模块单元文件的名称与相应的数据模块名称相同。例如,Customers数据模单元的名称叫CustomersDM.pas。3.5.4 通用的单元通用单元的名称应当表达出它的用途。例如,一个实用工具单元的名称叫ugUtilities.pas,包含全局变量的单元名称叫CustomerGlobals.pas。注意,一个项目中单元名称必须是唯一的。3.5.5 元件单元元件单元应放在单独的路径中,以区别于定义元件的单元。它们一般与项目不放在同一路径下。单元文件名称应表达出其内容。注意,有关元件命名标准的更多信息,请参阅“自定义元
29、件”部分。3.6 文件头所有源文件和项目文件都应具有文件头。一个正确的文件头应包含以下信息:/(80 chars)/ 创建:Tujh010618 (创建信息:创建者、创建日期)/ 版权:迈特安 (版权)/ 功能: (本文件的主要功能)/ 函数: (主要函数和过程;可省)/3.7 函数或过程头格式如下/ 创建:Tujh010618 (创建信息:创建者、创建日期)/ 功能: (本函数或过程的主要功能)/ 参数:Param1/ Param2(out) (out表示输出参数)/ 返回: (类型、值)/ 说明: (备注信息、调用方法、初始化数值等)/4. Form与数据模块4.1 Form4.1.1 F
30、orm类型的命名标准Form类型的名称应当表达出Form的用途,且要加T为前缀,后跟描述性名,最后是Form。例如,About的类型名称为:TAboutForm = class(TForm)主frm的类型名称为:TMainForm = class(TForm)客户登录Form的类型名称为:TCustomerEntryForm = class(TForm)4.1.2 Form实例的命名标准Form实例的名称与相应的类型名称相同,但没有前缀T。例如,前面提到的Form类与Form实例的名称为:类型名 实例名-TAboutFo rm AboutFormTMainForm MainFormTCusto
31、merEntryForm CustomerEntryForm4.1.3 自动创建的Form除非特别原因,只有主Form才自动生成。其他所有Form必须从Project Options对话框的自动生成列表中删除。更进一步的信息,请参阅后面几节。4.1.4 模式Form实例化函数所有Form单元都应当含有实例化函数,用于创建、设置、模式显示和释放Form。这个函数将返回由Form返回的模式结果。传递给这个函数的参数遵循“参数传递”的规则。之所以要这样封装,是为了便于代码的重用和维护。Form的变量应当从单元中移走,改在实例化函数中作为局部变量定义。注意,这要求从Project Options对话框
32、的自动生成列表中移走该Form。例如,下面的单元文件演示了GetUserData的实例化函数。unit UserDataFrm;interfaceusesWindows, Messages, SysUtils, C1asses, Graphics, Controls, Forms, Dialogs, StdCtrls;typeTUserDataForm = class(TForm)edtUserName: TEdit;edtUserID: TEdit;privatePrivate declarationspublicPublic declarationsend;function GetUser
33、Data(var aUserName: String; var aUserID: Integer): Word;implementation$R*.DFMfunction GetUserData(var aUserName: String; var aUserID: Integ): Word;varUserDataForm: TUserDataFrom;beginUserDataForm := TUserDataForm.Create(Application);tryUserDataForm.Caption := Getting User Data;Result := UserDataForm
34、.ShowModal;if Result = mrOK thenbeginaUserName := UserDataForm.edtUserName.Text;aUserID := StrToInt(UserDataForm.edtUserName.Text);end;finallyUserDataForm.Free;end;end;end.4.2 数据模块4.2.1 数据模块的命名标准数据模块类型名称应表达出它的用途,且要加前缀T ,后跟描述性名称,最后是DataModule。例如,Customer数据模块的类型名称为:TCustomerDataModule = class(TDataMod
35、ule);Orders数据模块的类型名称为:TOrderDataModule = class(TDataModule);4.2.2 数据模块实例的命名标准数据模块实例的名称应当与相应的类型名称相同,但没有前缀T。例如,前面的数据模块类型、实例名称如下:类型名称 实例名-TCustomerDataModule CustomerDataModuleTOrderDataModule OrderDataModule5. 包5.1 运行期包与设计期包运行期包中应当只包含所需要的单元。那些特性编辑器和元件编辑器的单元应当放在设计期包中。注册单元也应当放在设计期包中。5.2 文件命名标准包的命名遵循下列模式
36、:iiilibvv.pkg - 设计期包iiistdvv.pkg - 运行期包其中:iii代表一个3字符的前缀,用于标识公司、个人或其他需要标识的事情。vv代表包的版本号,其中也包含了De1phi的版本号。注意:包名称中的lib或std 分别表示这是设计期包或运行期包。例如,De1phi 5开发大全中的包是这样命名的:ddgLib50.pkg - 设计期包ddgStd50.pkg - 运行期包6. 元件6.1 自定义的元件6.1.1 元件类型的命名标准元件的命名与类的命名类似,只不过它有3个字符的前缀。这些前缀用以标识公司、个人或其他实体。例如,一个时钟元件可以这样声明:TddgClock =
37、 class(TComponent)注意,作为前缀的3个字符要小写。6.1.2 元件单元元件单元只能含有一个主要元件,这是指出现在元件选项板上的元件。其他辅助性的元件或对象也可以包含在同一单元中。6.1.3 注册单元元件的注册过程应当从元件单元中移走,放在一个单独的单元中。这个注册单元用于注册所有元件、特性编辑器、元件编辑器、向导等。元件注册应当在设计期包中进行。因此,注册单元应当包含在设计期包而不是运行期包中。建议注册单元这样命名:xxxReg.pas其中,xxx为3个字符前缀,以标识公司、个人或其他实体。例如,命名为ddgReg.Pas。6.2 元件实例的命名规则元件的名称应当具有描述性。
38、Delphi没有为元件指定默认的名称。元件应当有一个小写的前缀以表明其类型,这是为了便于在Object Inspector和Code Explorer中查找元件。元件类型前缀是元件类型名变化而成的。下面的规则说明如何定义一个元件类型前缀:1) 从元件类型名中移去T 前缀。例如TButton变成Button。2) 除了第一个元音,删去所有元音字母。例如,Button变成Bttn,Edit变成Edt 。3) 压缩双字母。例如,Bttn变成Btn。4) 如发生冲突,则在某一元件前缀中加入一个元音。例如在TBatton元件的前缀中加入元音变为batn,以区别TButton的前缀。6.3 元件性质标识名
39、元件性质标识名是元件意图的描述。例如,一个用于关闭窗体的TButton元件可命名为btnClose。一个编辑人名的元件可命名为edtFirstName。6.4 元件的前缀下面是Delphi5 标准元件的前缀。6.4.1 standard页前缀 元件mm TMainMenupm TPopupMenummi TMainMenuItempmi TPopupMenuItemfm TFramelbl TLabeledt TEditmem TMemobtn TButtonck TCheckBoxrb TRadioButtonlb TListBoxcb TComboBoxscb TScrollBargb T
40、GroupBoxrg TRadioGrouppnl TPanelal TActionListac TAction6.4.2 Additional页前缀 元件bbtn TBitBtnsb TSpeedButtonme TMaskEditsg TStringGriddg TDrawGridimg TImageshp TShapebvl TBevelsbx TScrollBoxclb TCheckListBoxspl TSplitterstx TStaticTextctrb TControlBarav TApplicationEventscht TChart6.4.3 win32页前缀 元件tbc
41、TTabControlpgc TPageControlil TImageListre TRichEdittbr TTrackBarpb TProgressBarud TUpDownhk THotKeyani TAnimatedtp TDateTimePickermc TMonthCalendartv TTreeViewlv TListViewhc THeaderControlstb TStatusBartb TToolBarclb TCoolBarpgs TPageScroller6.4.4 System页前缀 元件tm TTimerpb TPaintBoxmp TMediaPlayerole
42、c TOleContainerddcc TDDEClientConvddci TDDEClientItemddsc TDDEServerConvddsi TDDEServerItem6.4.5 Data Access页前缀 元件ds TDataSourcetbl TTableqry TQuerysp TStoreProcedb TDataBasessn TSessionbm TBatchMoveusql TUpdateSQLnt TNestedTable6.4.6 Data Controls页前缀 元件dbg TDBGriddbn TDBNavigatordbt TDBTextdbe TDBE
43、ditdbm TDBMemodbi TDBImagedblb TDBListBoxdbcb TDBComboBoxdbck TDBCheckBoxdbrg TDBRadioGroupdbll TDBLookupListBoxdblc TDBLookupComboBoxdbre TDBRichEditdbcg TDBCtrlGriddbch TDBChart6.4.7 ADO页前缀 元件adon TADOConnectionadoc TADOCommandadod TADODataSetadot TADOTableadoq TADOQueryados TADOStoreProcrdsn TRDS
44、Connection6.4.8 Midas页前缀 元件prv TProvidercds TClientDataSetqcds TQueryClientDataSetdcom TDCOMConnectionolee TOleEnterpriseConnectionsck TSocketConnectionrms TRemoteServermid TMidasConnection6.4.9 Internet页前缀 元件csk TClientSocketssk TServerSocketwbd TWebDispatcherpp TPageProducertp TQueryTableProducerdstp TDataSetTableProducernmdt TNMDayTimenec TNMEchonf TNMFingernftp TNMFtpnhttp TNMHttpnMsg TNMMsgnntp TNMNNTPnpop TNMPop3nuup TNMU