Delphi代码编写标准指南

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

· 日月光华 精华区文章阅读

  
 发信人: Delphii (Delphi), 信区: VCL
标  题: Delphi编码规则
发信站: 日月光华站 (Fri Sep  7 12:03:07 2001) , 站内信件

Delphi代码编写标准指南
■■■■■■■■■■■■■■■■■■■■■■■■
目录
■■■■■■■■■■■■■■■■■■■■■■■■
一、序言
二、通用源代码格式规则
2.1 缩格
2.2 页边空格
2.3 Begin…End 配对
三、Obje ct Pascal
3.1 括号
3.2 保留字和关键字
3.3 过程和函数(例程)
    3.3.1 命名/格式化
    3.3.2 形式参数
        3.3.2.1 格式化
        3.3.2.2 命名
        3.3.2.3 参数的排序
        3.3.2.4 常量参数
        3.3.2.5 名称的冲突
3.4 变量
    3.4.1 变量的命名和格式
    3.4.2 局部变量
    3.4.3 全局变量的使用
3.5 类型
    3.5.1 大写约定
        3.5.1.1 浮点指针类型
        3.5.1.2 枚举类型
        3.5.1.3 变数和ole变数类型
    3.5.2 结构类型
        3.5.2.1 数组类型
        3.5.2.2 记录类型
3.6 语句
    3.6.1 if 语句
    3.6.2 case 语句
        3.6.2.1 一般性话题
        3.6.2.2 格式
    3.6.3 while 语句
    3.6.4 for 语句
    3.6.5 repeat 语句
    3.6.6 with  语句
        3.6.6.1 一般话题
        3.6.6.2 格式
3.7 结构异常处理
    3.7.1 一般话题
    3.7.2 try…finally的使用
    3.7.3 try…except的使用
    3.7.4 try…except…else的使用
3.8 类类型
    3.8.1 命名和格式
    3.8.2 域
        3.8.2.1 命名/格式
        3.8.2.2 可视化
    3.8.3 方法
        3.8.3.1 命名/格式
        3.8.3.2 使用静态的方法
        3.8.3.3 使用虚拟/动态的方法
        3.8.3.4 使用抽象的方法
        3.8.3.5 属性存取方法
    3.8.4 属性
        3.8.4.1 命名/格式
        3.8.4.2 使用存取的方法
四、文件
4.1 工程文件
    4.1.1 命名
4.2 窗体文件
    4.2.1 命名
4.3 数据模板文件
    4.3.1 命名
4.4 远端数据模板文件
    4.4.1 命名
4.5 Unit文件
    4.5.1 通用Unit结构
        4.5.1.1 unit的名字
        4.5.1.2 uses子句
        4.5.1.3 interface部分
        4.5.1.4 implementation部分
        4.5.1.5 initialization部分
        4.5.1.6 finalization部分
    4.5.2 窗体单元
        4.5.2.1 命名
    4.5.3 数据模板单元
        4.5.3.1 命名
    4.5.4 一般目的单元
        4.5.4.1 命名
    4.5.5 构件单元
        4.5.5.1 命名
4.6 文件头
五、窗体和数据模板
5.1 窗体
    5.1.1 窗体类型命名标准
    5.1.2 窗体实例命名标准
    5.1.3 自动创建窗体
    5.1.4 模式窗体实例化函数
5.2 数据模板
    5.2.1 数据模板命名标准
    5.2.2 数据模板实例命名标准
六、包
6.1 使用运行包和设计包的比较
6.2 文件命名标准
七、构件
7.1 用户自定义构件
7.2 构件单元
7.3 使用注册单元
7.4 构件实例命名约定
7.5 构件的前缀
7.6 Standard页
7.7 Additional页
7.8 Win32页
7.9 System页
7.10 Internet页
7.11 Data Access页
7.12 Data Controls页
7.13 Decision Cube页
7.14 QReport页
7.15 Dialogs页
7.16 Win3.1页
7.17 Samples页
7.18 ActiveX页
7.19 Midas页
■■■■■■■■■■■■■■■■■■■■■■■■
一、序言
■■■■■■■■■■■■■■■■■■■■■■■■
    本文档详述了在Delphi 4开发者指南下进行编程的代码编写标准。在通常情况下,
本文档遵循“取消”式格式的指引方针,该方针由Borland国际通过一些例外来使用。在
Delphi 4开发者指南中包含本文档的目的在于阐述一种方法,通过该方法,开发小组可
以在他们所编写的代码中保持一贯的风格。这样做的目的是使在开发小组中的每一个程
序员都可以明白其他程序员的代码。这有助于提高代码编写的可读性和使用的一贯性。

    本文档并不意味着包含了所有存在于代码中的标准。但是,它的内容已足够帮你起
个好头。你可以自由的增加修改这些标准来满足你的需要。我们不赞成你偏离这些由Bo
rland开发人员所使用的标准太远。我们推荐这么做是因为一旦有新的程序员加入到你的
开发小组中,而他们最喜欢和最熟悉的是Borland的标准。象大多数代码标准文档,本文
档也会根据需要进行改动。因此,你可以到www.xapware.com/ddg中找到最新的更新版本
。本文档不包括用户接口标准。本文档是独立的但也是同样重要的。已经有足够的第三
方书籍和Microsoft文档包括了另外一些指导方针,而我们决定并不复制这些信息,但我
们会指引你到Microsoft Developers Network 和一些资源,在那儿可以找到你所需的信
息。
■■■■■■■■■■■■■■■■■■■■■■■■
二、通用源代码格式规则
■■■■■■■■■■■■■■■■■■■■■■■■
2.1 缩格
    缩格是指在每一级有两个空格。不要在源代码中保留tab字符,这是因为tab字符会
随着不同用户的不同设置和不同的资源管理工具(打印、文档、版本控制等)而代表不
同的宽度。
    你可以通过关闭Environment选项对话框中Editor页上的“Use tab character”和
“Optimal fill”检查框(通过ools|Environment)来禁止保存tab字符。
2.2 页边空格
    页边空格会被设置成80字符宽。通常,源码不会超出这个边界,但这个方针会有一
些弹性。不管是否有可能,那些超出到另一行的语句会在一个逗号或其他操作符之后与
前面的语句相连。当一个语句被打断相连时,它应比原来的那一行语句缩进两个字符。

2.3 Begin…End 配对
    Begin 子句应写在独立的一行。例如,下面第一行是错误的写法而第二行是正确的

for I := 0 to 10 do begin  //错误,begin同for在同一行
for I := 0 to 10 do        //正确,begin出现在独立的一行
begin
    这个规则的例外是当begin子句的出现是作为一个else子句的一部分,参考例子:
if some statement then
begin
  ...
end
else begin
  someOtherStatement;
end;
    end 语句永远出现在独立的一行。
    当begin语句不是一个else子句的一部分时,相应的end语句永远缩进到与begin部分
相对应的位置。
■■■■■■■■■■■■■■■■■■■■■■■■
三、Object Pascal
■■■■■■■■■■■■■■■■■■■■■■■■
3.1 括号
    永远不要在括号与括号之间的字符中间留下空格。下面的例子示范了错误的与正确
地使用括号中的空格:
         CallProc( Aparameter );    //错误
         CallProc(Aparameter);      //正确
    永远不要在一个语句中使用不必要的括号。括号只应在源代码中需要的地方使用。
以下的例子示范了错误和正确的使用:
if (I = 42) then                    //错误 - 多余的括号
if (I = 42) or (J = 42) then        //正确 - 需要括号
3.2 保留字和关键字
    Object Pascal 保留字和关键字永远是全部小写。
3.3 过程和函数(例程)
3.3.1 命名/格式化
    例程的名字永远应该以大写的字母开头并且中间错落分明以便于可读性。下面是一
个不正确格式的过程名称:
         procedure thisisapoorlyformattedroutinename;
    下面是一个合适的大小写例程名称的例子:
         procedure ThisIsMuchMoreReadableRoutineName;
    例程的名称应该同它的内容相符。一个会导致某个行为的例程应以动词开头。例如

         procedure FormatHardDrive;
    一个用于设置输入参数的例程应以单词set作为前缀,例如:
         procedure SetUserName;
    一个用来接收某个值的例程应以单词get作为前缀,例如:
         procedure GetUserName : string;
3.3.2 形式参数
3.3.2.1 格式化
    如果有的话,相同类型的形参应合并在一个语句中:
  procedure Foo(Param1, Param2, Param3 : Integer; Param4 : string);
3.3.2.2 命名
    所有形参的名字应是十分符合它们所代表的意义,特别是应该以传送到例程中的标
志符的名称为基础。一个好的参数名称应以字符A为前缀 - 例如:
  procedure SomeProc(AuserName : string; AuserAge : integer);
    “A”前缀按约定表示该参数的名称是与类类型中的一个属性或域的名称相对应的。

3.3.2.3 参数的排序
    下面的形参的顺序重点说明了注册者调用约定调用的好处。
- 最常用的参数应放在第一位,其它的参数应按从左到右的顺序排列。
- 输入参数列表应放在输出参数列表的左边。
- 将通用的参数放在特殊参数的左边,例如:
      procedure SomeProc(Aplanet, AContinent, Acountry, Astate, Acity)
- 排序有可能有些例外,比如事件的处理。类型为TObject的Sender参数经常放在第一
位。
3.3.2.4 常量参数
    当一个参数为记录型、数组类型、ShortString、或接口类型并且在例程中不被改变
时,这些参数应做上常量标记。这样做会让编译器更加有效率的产生有关这些不改变的
参数的代码。
    而例程中另外一些非变参数也可常量来传送。尽管这样做没有产生任何效果和提高
效率,这将会给调用例程的使用者提供更多的信息。
3.3.2.5 名称的冲突
    当使用拥有两个名称相同的例程的两个单元时,如果你调用该例程时,在uses子句
中排在后面的单元中的例程将会被调用。为了解决这种“在uses子句上的模糊”冲突,
要在调用该例程时写上相关的单元的前缀,例如:
        sysUtile.FindClose(SR);

        windows.FindClose(Handle);
3.4 变量
3.4.1 变量的命名和格式
    变量的命名应以使用它们的目的相符
    循环控制变量应采用一个单独的字符作为名字,比如 I,J,或K,也可以采用更加
有意义的名字,比如 UserIndex。
    逻辑变量的名字应能充分表达准确的真或假的意思。
3.4.2 局部变量
    一个过程中的局部变量应遵循所有其它变量的使用和命名约定。临时变量的取名应
合理。
    如果必须的话,在一进入例程就应初始化局部变量。局部的AnsiString变量会自动
初始化为一个空的字符串。
    局部接口和派分接口类型变量将会自动初始化为nil,并且局部变数和ole变数类型
变量会自动初始化为Unassigned
3.4.3 全局变量的使用
    使用全局变量是不推荐的。但是,在某些时候还是必须使用,而且它们也只应在必
须使用的时候才使用。在这种时候,你应努力只在一段上下文范围内使用全局变量。例
如,一个全局变量只应在一个单元的implemntation部分内是全局的。如果打算在多个单
元类使用全局数据,你应将它们移到一个公共的单元中然后被其它所有单元使用。
    全局变量可以在var子句中直接初始化为一个值。记住,所有的全局数据会自动初始
化为0,因此不要将全局变量初始化为一个“空”值比如 0、nil、’’、Unassigned、等
等。这样做的一个理由是因为零-初始化的全局数据在exe文件中不会占据任何空间。零
-初始化数据被存储在一个虚拟的数据段,它在应用程序启动后被分配在一段内存中。
非零-初始化的全局数据在硬盘的exe文件占用空间。
3.5 类型
3.5.1 大写约定
    如果类型的名字是保留字,那么它应全部小写。Win32 API类型通常全部大写,并且
你必须遵循在Windows.pas或其他API单元中的详细类型名称的约定。对于其他变量名字
,地一个字母应为大写,而其他字母应错落有致。下面是一些例子:
      var
        MyString : string;          //保留字
        WindowHandle : HWND;        //Win32 API 类型
        I : Integer;                //在System单元中引进的类型标识符
3.5.1.1 浮点指针类型
    不推荐使用Real类型,因为它的存在只是为了向前兼容早期的Pascal代码。在通常
情况下用Double来实现浮点指针的需要。并且,Double对处理器和总线而言是做了最优
化处理的,它也是IEEE中定义的标准数据格式。只有当需要的范围超出Double所定义的
范围时才使用Extended。Extended是intel定义的类型且在Java中不支持。只有当浮点指
针变量的实际字节大小有其意义时才使用Single。(比如当使用另一种语言的DLLs时)

3.5.1.2 枚举类型
    枚举类型的名字需符合使用该类型的目的。该类型的名字需以字符T为前缀,以表明
这是一个类型。枚举类型中的标识符列表必须包含两个或三个字符的前缀来对应于该枚
举类型的名字 - 例如:
        TsongType = (stRock, stClassical, stCountry, stAlternative, stHeavyM
etal, stRB);
    一个枚举类型的实例的名字应与不要前缀的枚举类型(SongType)相同,除非有更
好的原因来赋予该变量更特殊的名字,比如:FavoriteSongType1,FavoriteSongType2
等等。
3.5.1.3 变数和ole变数类型
    通常不建议使用变数和Ole变数类型。但在只有运行时刻才能知道数据类型的程序中
必须使用该类型,这种情形多出现在COM和数据库开发中。Ole变数使用在以COM为基础的
编程中例如自动化和ActiveX控制,而变数使用在非COM的编程中,这是因为变数可以十
分有效地存储本地Delphi字符串(同一个字符串变量一样),但Ole变数会将所有的字符
串转换为Ole字符串(WideChar 字符串)并且并不实例运算 - 它们永远拷贝。
3.5.2 结构类型
3.5.2.1 数组类型
    数组类型的名字需符合它们使用的目的。该类型的名字必须加以前缀T。如果须声明
该数组类型的指针,那么该指针需加以前缀P而且应立即声明在该数组声明的前面。例如

        type
          PCycleArray = ^TCycleArray;
          TCycleArray = array[1…100] of integer;
    在实际应用中,数组的变量实例的名称应是其类型的名字去掉前缀T。
3.5.2.2 记录类型
    记录类型的名字应符合使用它们的目的。其类型的声明应加以前缀T。如果要声明该
记录类型的指针,就应加以前缀P并且应紧靠在类型声明的前面声明。例如:
        type
          PEmployee = ^TEmployee;
          TEmployee = record
            EmployeeName : string;
            EmployeeRate : Double;
          end;
3.6 语句
3.6.1 if 语句
    在if/then/else语句中最常发生的行为应放在then子句中,而其它发生可能性较小
的行为应放在else子句中。
    尽量避免使用嵌套的if语句,在这种情形下应用多个if语句来判断各种可能。
    不要使用if嵌套超过五级深度。应使代码编写得更加清晰、明了。
    不要在if语句中使用不必要的圆括号。
    如果在if语句中有多个条件需测试,这些条件应按计算强度由少到多的顺序从左到
右排列。这样做能使编译器在编译代码时获得布尔估算逻辑的捷径,从而使你的代码获
得最佳的优化。举例来说,如果条件1快过条件2,而条件2快过条件3,那么在if语句中
的排列应是:
         if 条件1 and 条件2 and 条件3 then
3.6.2 case 语句
3.6.2.1 一般性话题
    在一个case语句中的各个独立的单元应以数字或字母顺序排列。
    每一个case单元的动作行为应保持简单而不应该超过四到五行代码。如果所要执行
的动作过于复杂应采用独立的过程或函数。
    Case语句中的else子句只有当需要缺省行为或处理错误时才使用。
3.6.2.2 格式
    case语句应遵循其它结构的缩格和命名约定。
3.6.3 while 语句
    在一个while语句中不建议使用exit过程来跳出循环,尽量仅使用循环条件来跳出循
环。
    在一个while循环中所用的初始化代码应紧靠在进入while循环前面出现而不要被其
它不相关的语句隔开。
    任何结束后的处理应在循环之后立即进行。
3.6.4 for 语句
    for语句只有当循环次数已知的情况下才能取代while语句使用。
3.6.5 repeat 语句
    repeat语句的使用同while语句一样,并且遵循同样的通用方针。
3.6.6 with  语句
3.6.6.1 一般话题
    with语句应节省使用,并且带有大量的警告。避免过度使用with语句并且在with语
句中小心使用多个对象、记录等等。例如:
         with Record1, Record2 do
    这些事情会使程序员感到困惑并难以发现问题所在。
3.6.6.2 格式
    with 语句遵循本文档所说明的命名约定和缩格的格式规则。
3.7 结构异常处理
3.7.1 一般话题
    异常的处理大量地使用在错误纠正和资源保护方面。这就是说一旦资源被分配,一
个try…finally必需加以使用来保证该资源被正确的释放。这种异常的保护也是指在一
个单元的initializition/finalization或一个对象的constructor/destructor中进行资
源的分配和释放。
3.7.2 try…finally的使用
    任何情形下,每一次的分配都应跟随一个try…finally。举例来说,下面的代码会
造成可能的错误:
     SomeClass1 := TsomeClass.Create;
     SomeClass2 ;= TsomeClass.Create;
     try
       { do some code }
     finally
       SomeClass1.Free;
       SomeClass2.Free;
     end;
一个更安全更合适的分配过程应是:
     SomeClass1 := TSomeClass.Create;
     try
       SomeClass2 := TsomeClass.Create;
       try
         { do some code }
       finally
         SomeClass2.Free;
       end;
     finally
       SomeClass1.Free;
     end;
3.7.3 try…except的使用
    只有当在异常被触发而你想执行一些任务时才使用try…except。通常,你没有必要
为了只是简单地在屏幕上显示一个错误信息而使用try…except语句,因为这会被Appli
cation对象自动执行。如果你想在except子句中执行完一些任务之后调用缺省的异常处
理,使用raise来重新触发异常到下一个句柄。
3.7.4 try…except…else的使用
    try…except中的else子句不建议使用,因为它会打断所有的异常包括那些你没有准
备的异常。
3.8 类类型
3.8.1 命名和格式
    类类型的名称应符合使用它们的目的。类型名字应加以前缀T以表明这是一个类型的
定义 - 例如:
type
  Tcustomer = class(TObject)
    类型的实例通常是没有前缀T的类型的名字 - 例如:
var
  Customer :Tcustomer;
    注意:查阅“构件类型的命名标准”来获得更多有关构件命名的信息。
3.8.2 域
3.8.2.1 命名/格式
    类的域名遵循与变量标识符同样的约定除了它们应以F为前缀,来表明这是一个域的
名称。
3.8.2.2 可视化
    所有的域都必需是私有的。想在类的范围之外存取域得通过属性来使用。
3.8.3 方法
3.8.3.1 命名/格式
    方法的命名应遵循本文档中有关过程和函数的约定叙述。
3.8.3.2 使用静态的方法
    如果使用一个静态的方法,那么该方法就不能被该类的后代类所继承。
3.8.3.3 使用虚拟/动态的方法
    如果你打算该类的方法能被后代的类所继承就得使用虚拟的方法。只有在该方法有
多个继承时(直接的或间接的)才使用动态的方法。例如,一个类类型包含一个可继承
的方法,而100个后代类要继承这种方法,那么这个方法就会动态地产生为100个后代类
使用的内存。
3.8.3.4 使用抽象的方法
    如果在一个类中使用抽象的方法,该类就不能被创建。只有在那些永远不会被创建
的类中使用抽象的方法。
3.8.3.5 属性存取方法
    所有存取类的方法都只能出现在类的private或protected部分。属性存取方法的命
名应遵循过程和函数的约定规则。读取存取方法(方法读取器)必需以单词Get为前缀。
写入存取方法(方法写入器)必需以单词Set为前缀。方法写入器的参数的名字应为Val
ue,并且它的类型应是它所操作的属性的类型。例如:
 TSomeClass = class(TObject)
 private
   FsomeField : Integer;
 protected
   function GetSomeField : Integer;
   procedure SetSomeField(Value : Integer);
 public
   property SomeField : Integer read GetSomeField write SetSomeField;
 end;
3.8.4 属性
3.8.4.1 命名/格式
    属性如果是表示为一个私有域的存取器的话,那么它的名字应是它们所操作的域的
名字除去解释符F。
    属性的名字应是名词,不是动词。属性表示的是数据,而方法表示的是行为。
    数组类型的名称应为复数。一般情况下属性的名称应为单数。
3.8.4.2 使用存取的方法
    尽管没有要求,但还是建议尽量少地为一个表示私有域的属性而使用写入存取方法

■■■■■■■■■■■■■■■■■■■■■■■■
四、文件
■■■■■■■■■■■■■■■■■■■■■■■■
4.1 工程文件
4.1.1 命名
    工程文件应取个描述性的名字。例如,Delphi 4开发者指南错误管理器 的工程名字
是:DDGBugs.dpr。一个有关系统信息的程序的名字就应象 SysInfo.dpr。
4.2 窗体文件
4.2.1 命名
    一个窗体文件的取名应可以描述使用该窗体的目的,并加以后缀Frm。例如,一个“
关于”的窗体的文件名应是AboutFrm.dpr。主窗体的文件名应是MainFrm.dpr。
4.3 数据模板文件
4.3.1 命名
    数据模板的取名应能表示使用该数据模板的目的,它的名称应加以两个字符的后缀
DM。例如,自定义数据模板的文件名字应为CustomersDM.dfm。
4.4 远端数据模板文件
4.4.1 命名
    远端数据模板的取名应能表示使用该远端数据模板的目的,它的名称应加以三个字
符的后缀RDM。例如,自定义远端数据模板的文件名字应为CustomersRDM.dfm。
4.5 Unit文件
4.5.1 通用Unit结构
4.5.1.1 unit的名字
    Unit文件应取一个可描述性的名字。例如,包含应用程序主窗体的单元应叫做Main
Frm.pas。
4.5.1.2 uses子句
    在interface部分的uses子句应包含在interface部分中的代码所需要的单元。去掉
那些Delphi可以自动加入到程序中的单元。
    在implementation部分的uses子句应只包含在implementation部分中的代码所需要
的单元的名字。去掉不必要的单元。
4.5.1.3 interface部分
    interface部分应包含只那些其它单元所需要存取类型的定义、变量、过程/函数的
预定义等等。否则,就应放在implementation部分定义。
4.5.1.4 implementation部分
    implementation部分应包含那些只在本单元中私用的类型定义、变量、过程/函数定
义等等。
4.5.1.5 initialization部分
    不要在initialization 部分放入耗时长的代码,这将使程序的第一个界面出现得比
较缓慢。
4.5.1.6 finalization部分
    在这里要保证释放你在Initialization部分所分配的任何资源。
4.5.2 窗体单元
4.5.2.1 命名
    一个窗体的单元文件应拥有与它所对应的窗体文件同样的名称。例如,“关于”窗
体的单元名称应为 AboutFrm.pas,而主窗体的单元名称应为MainFrm.pas。
4.5.3 数据模板单元
4.5.3.1 命名
    一个数据模板的单元文件应拥有与它所对应的数据模板文件同样的名称。例如,一
个自定义数据模板单元的名称应为CustomersDM.pas。
4.5.4 一般目的单元
4.5.4.1 命名
    一般目的单元的取名应符合使用该单元的目的。例如,一个实用程序单元取名为Bu
gUtilities.pas。一个包含全局变量的单元取名为CustomerGlobals.pas。
    注意,该单元的名字不能与它的工程中所使用的所有包中的单元的名字相同。不赞
成使用一般的或通用的单元名字。
4.5.5 构件单元
4.5.5.1 命名
    构件单元应放在独立的目录,以将它们同定义构件组或构件集合的单元区分开来。
它们要永远同工程在不同的目录。单元名字应同它们的内容相符。
    注意:查阅“用户定义的构件”部分来获得更多有关构件命名标准的信息。
4.6 文件头
    建议在所有源文件、工程文件、单元等等中使用信息化文件头。一个良好的文件头
应包含以下信息:
{
 版权… 著作的年、月、日…
}
■■■■■■■■■■■■■■■■■■■■■■■■
五、窗体和数据模板
■■■■■■■■■■■■■■■■■■■■■■■■
5.1 窗体
5.1.1 窗体类型命名标准
    窗体类型的取名应能表达使用该窗体的目的。类型定义应加以前缀T。前缀后面跟随
着描述性的名字。最后,应加以Form后缀来描述名字。例如,一个“关于”的窗体的类
型的名字应为:
        TAboutFrom = class(TForm);
    主窗体的定义为:
        TMainForm = class(TForm);
    一个用户接入窗体的名字应象:
        TCustomerEntryForm = class(TForm);
5.1.2 窗体实例命名标准
    窗体实例应是没有带前缀T的相应类的名字。例如,对应于前面窗体类型而言,其实
例的名字应为:
     类型名称                   实例名称
   TAboutForm                AboutForm
   TMainForm                 MainForm
   TCustomerEntryForm      CustomerEntryForm
5.1.3 自动创建窗体
    只有主窗体可以是自动创建的除非有其它更好的理由不这样做。所有其它的窗体必
需从工程选项对话框中的自动创建列表中移走。查阅以下部分来获得更多的信息。
5.1.4 模式窗体实例化函数
    所有的窗体单元都应包含一个窗体实例化函数,该函数用来创建、设置、模式地显
示窗体,并释放窗体。该函数应返回窗体的模式结果。该函数要传递的参数应遵循本文
档指定的“参数传递”标准。通过这种方式封装的函数性有助于代码的再利用和维护。

    该窗体的变量要从单元中移走,并再窗体实例的函数中进行本地式地定义。注意,
这就意味着该窗体必需从工程/选项对话框中的自动创建列表中剔除。参考本文档后面的
“自动创建窗体”。
例如,下面的单元展示了再GetUserData窗体中的一个函数。
  unit UserDataFrm;
  interface
  uses windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dial
ogs, StdCtrls;
  type
    TUserDataForm = class(TForm)
      edtUserName : TEdit;
      edtUserID : TEdit;
    private
      { Private declarations }
    public
      { Public declarations }
    end;
  function GetUserData(var aUserName : String; var aUserID : Integer): Word
;
  implementation
  {$R *.DFM }
  function GetUserData(var aUserName : String; var aUserID : Integer): word;

  var
    UserDataForm : TuserDataForm;
  begin
    UserDataForm := TuserDataForm.Create(Application);
    try
      UserDataForm.Caption := ‘Getting User Data’;
      Result := UserDataForm.ShowModal;
      if (Result = mrOK) then
      begin
        aUserName := UserDataForm.edtUserName.Text;
        aUserID := StrToInt(UserDataForm.edtUserID.Text);
      end;
    finally
      UserDataForm.Free;
    end;
  end;
  end.
5.2 数据模板
5.2.1 数据模板命名标准
    数据模板的取名要符合使用该数据模板的目的。类型的定义应加以前缀T,后面紧接
着描述性的名字,最后要加以后缀单词“DataModule”。例如,一个自定义的数据模板
有时候应该象:
            TCustomerDataModule = class(TDataModule)
    一个命令式的数据模板的名字应象:
            TOrdersDataModule = class(TDataModule)
5.2.2 数据模板实例命名标准
    数据模板实例的名称应是对应不带前缀T的类型的名称。例如,对于前面的窗体类型
而言,其实例的名称应为:
           类型名称                      实例名称
          TCustomerDataModule      CustomerDataModule
          TOrdersDataModule        OrdersDataModule
■■■■■■■■■■■■■■■■■■■■■■■■
六、包
■■■■■■■■■■■■■■■■■■■■■■■■
6.1 使用运行包和设计包的比较
    运行时刻的包应只包含其它构件包所要求的单元或构件。另外,包含属性/构件编辑
器和其它只为设计的代码应放入到设计时刻包中。注册单元应放在设计包中。
6.2 文件命名标准
    包的名称应依照下面的例子:
“iiilibvv.pkg” - 设计时刻包
“iiistdvv.pkg” - 运行时刻包
    字符“iii”表示一个3字符标识前缀。这个前缀用来表明公司、个人或其它有标识
意义的实体。
    字符“vv”表示为该包想要对应Delphi某个版本的包的版本号。
    注意,包的名字中包含“lib”或“std”的意思是表明这是一个设计时刻包还是一
个运行时刻包。
    如果既是设计时刻包又是运行时刻包,该文件的命名是同上面一样的,例如,为De
lphi 4开发者指南做的包的名称应为:
    DdgLib40.pkg – 设计时刻包
    DdgStd40.pkg – 运行时刻包
■■■■■■■■■■■■■■■■■■■■■■■■
七、构件
■■■■■■■■■■■■■■■■■■■■■■■■
7.1 用户自定义构件
    在标准构件中命名出来的构件的名称同在“类类型”部分定义中的一样定义成一个
类类型,不同的是它们有一个3字符的指示前缀,这个前缀可以表示公司、个人或其它实
体。例如,一个为Delphi 4开发者指南编写的时钟构件的名称定义为:
      TddgClock = class(TComponent)
    注意,那三个前缀字符是小写的。
7.2 构件单元
    构件单元应只包含一个主要的构件,一个主要的构件是指出现在构件栏中的构件。
主要构件的辅助构件/对象应放入到同一个单元中。
7.3 使用注册单元
    构件的注册过程应从构件本身的单元中剔除,并放入到一个独立的单元中。这个注
册单元可以用来注册任何构件、属性编辑器、构件编辑器、专家器等。
    构件的注册只应在设计时刻包中进行,注册单元应包含在设计时刻包中而不应放在
运行时刻包中。
    推荐使用的注册单元的名称是:
XxxReg.pas
    上面的3个前缀字符“Xxx”用来表示一个公司、个人或任何其它的实体。例如,在
Delphi 4 开发者指南中的注册单元的名称应为 DdgReg.pas。
7.4 构件实例命名约定
    所有的构件都应取个描述性的名称。由Delphi创建的缺省名的构件不会被遗弃。在
设计构件类型时应设计一个小写的前缀。使用前缀而不使用后缀的原因是在搜寻时,在
对象检查器和代码探索器中搜寻构件的名字比搜寻构件的类型更容易实现。
7.5 构件的前缀
    以下构件的前缀可以用来设计Delphi 4中的标准构件。请在此列表中加入第三方构
件的前缀。
7.6 Standard页
前缀      构件
mm        TMainMenu
pm        TPopupMenu
mmi       TMainMenuItem
pmi       TPopupMenuItem
lbl       TLabel
edt       TEdit
mem       TMemo
btn       TButton
cb        TCheckBox
rb        TRadioBox
lb        TListBox
cb        TComboBox
scb       TScrollBar
gb        TGroupBox
rg        TRadioGroup
pnl       TPanel
cl        TCommandList
7.7 Additional页
前缀      构件
bbtn      TBitBtn
sb        TSpeedButton
me        TMaskEdit
sg        TStringGrid
dg        TDrawGrid
img       TImage
shp       TShape
bvl       TBevel
sbx       TScrollBox
clb       TCheckListbox
spl       TSplitter
stx       TStaticText
cht       TChart
7.8 Win32页
前缀      构件
tbc       TTabControl
pgc       TPageControl
il        TImageList
re        TRichEdit
thr       TTrackBar
prb       TProgressBar
ud        TUpDown
hk        THotKey
ani       TAnimate
dtp       TDateTimePicker
tv        TTreeView
lv        TListView
hdr       THeaderControl
stb       TStatusBar
tlb       TToolBar
clb       TCoolBar
7.9 System页
前缀      构件
tm        TTimer
pb        TPaintBox
mp        TMediaPlayer
olec      TOleContainer
ddcc      TDDEClientItem
ddci      TDDEClientItem
ddsc      TDDEServerConv
ddsi      TDDEServerItem
7.10 Internet页
前缀      构件
csk       TClientSocket
ssk       TServerSocket
wbd       TWebDispatcher
pp        TPageProducer
tp        TQueryTableProducer
dstp      TDataSetTableProducer
nmdt      TNMDayTime
nec       TNMEcho
nf        TNMFinger
nftp      TNMFtp
nhttp     TNMHttp
nMsg      TNMMsg
nmsg      TNMMSGServ
nntp      TNMNNTP
npop      TNMPop3
nuup      TNMUUProcessor
smtp      TNMSMTP
nst       TNMStrm
nsts      TNMStrmServ
ntm       TNMTime
nudp      TNMUdp
psk       TPowerSock
ngs       TNMGeneralServer
html      THtml
url       TNMUrl
sml       TSimpleMail
7.11 Data Access页
前缀      构件
ds        TDataSource
tbl       TTable
qry       TQuery
sp        TStoredProc
db        TDataBase
ssn       TSession
bm        TBatchMove
usql      TUpdateSQL
7.12 Data Controls页
前缀      构件
dbg       TDBGrid
dbn       TDBNavigator
dbt       TDBText
dbe       TDBEdit
dbm       TDBMemo
dbi       TDBImage
dblb      TDBListBox
dbcb      TDBComboBox
dbch      TDBCheckBox
dbrg      TDBRadioGroup
dbll      TDBLookupListBox
dblc      TDBLookupComboBox
dbre      TDBRichEdit
dbcg      TDBCtrlGrid
dbch      TDBChart
7.13 Decision Cube页
前缀      构件
dcb       TDecisionCube
dcq       TDecisionQuery
dcs       TDecisionSource
dcp       TDecisionPivot
dcg       TDecisionGrid
dcgr      TDecisionGraph
7.14 QReport页
前缀      构件
qr        TQuickReport
qrsd      TQRSubDetail
qrb       TQRBand
qrcb      TQRChildBand
qrg       TQRGroup
qrl       TQRLabel
qrt       TQRText
qre       TQRExpr
qrs       TQRSysData
qrm       TQRMemo
qrrt      TQRRichText
qrdr      TQRDBRichText
qrsh      TQRShape
qri       TQRImage
qrdi      TQRDBMImage
qrcr      TQRCompositeReport
qrp       TQRPreview
qrch      TQRChart
7.15 Dialogs页
    对话框构件是由构件封装的真正的窗体,因此,它们应遵循窗体的命名约定。类型
已由构件的名称定义。它的实例的名称是Delphi自动生成的类型实例名字去掉数字后缀
。举例如下:
      类型                    实例名字
    TOpenDialog             OpenDialog
    TSaveDialog             SaveDialog
    TOpenPictureDialog     OpenPictureDialog
    TSavePictureDialog     SavePictureDialog
    TFontDialog             FontDialog
    TColorDialog            ColorDialog
    TPrintSetupDialog      PrintSetupDialog
    TFindDialog             FindDialog
    TReplaceDialog         ReplaceDialog
7.16 Win3.1页
前缀      构件
dbll      TDBLookupList
dblc      TDBLookupCombo
ts        TTabSet
ol        TOutline
tnb       TTabbedNoteBook
nb        TNoteBook
hdr       THeader
flb       TFileListBox
dlb       TDirectoryListBox
dcb       TDriveComboBox
fcb       TFliterComboBox
7.17 Samples页
前缀      构件
gg        TGauge
cg        TColorGrid
spb       TSpinEdit
spe       TSpinEdit
dol       TDirectoryOutline
cal       TCalendar
ibea      TIBEventAlerter
7.18 ActiveX页
前缀      构件
cfx       TChartFX
vsp       TVSSpell
f1b       TF1Book
vtc       TVTChart
grp       TGraph
7.19 Midas页
前缀      构件
prv       TProvider
cds       TClientDataSet
qcds      TQueryClientDataSet
dcom      TDCOMConnection
olee      TOleEnterpriseConnection
sck       TSocketConnection
rms       TRemoteServer
mid       TMidasConnection
<完>

--
※ 来源:·日月光华站 bbs.fudan.edu.cn·[FROM: 61.170.136.227]


 
  

[返回上一页]

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

 

好的Delphi面向对象编程规则20条

规则一:为每一个类创建一个单元(One Class,One Unit)

  请始终牢记这一点:类的私有(private)和保护(protected)的部分只对于其他单元中的类和过程(procedure)才是隐藏的.因此,如果你想得到有效的封装性,你应该为每一个类使用一个不同的单元。对于一些简单的类,比如那些继承其他类的类,你可以使用一个共享的单元。不过共享同一个单元的类的数目是受到限制的:不要在一个简单的单元里放置超过20个复杂的类,虽然Borland公司的VCL代码曾经这样做过。
如果你使用窗体的时候,Delphi会默认的遵循“一个类使用一个单元”的规则,这对于程序员来说也是十分方便的。当你向你的项目中添加一个没有窗体的类时,Delphi也会创建一个新的独立的单元。

  规则二:为组件命名(Name Components)

  为每一个窗体和单元给出一个有意义的名字是十分重要的。窗体和单元的名字必须是不同的,不过我趋向于为他们两者使用相似的名字,如对于关于窗体和单元可以为他们使用AboutForm 和About.pas.
为组件使用带有描述性的名字同样十分重要。最常见的命名方式是使用类的小写字母开头,再加上组件的功能,如BtnAdd 或者editName。采用这样的命名方式为组件命名可能会有很多相似的名字,而且也没有一个最好的名字,到底应该选择那一个应该依据你的个人爱好而定。

  规则三:为事件命名(Name Events)

  对于事件处理方法给出合适的名字更加重要。如果你对于组件给出了一个合适的名字,那么系统默认的名字ButtonClick将变成BtnAddClick。虽然从这个名字中我们可以猜到这个事件处理程序的功能,但是我认为使用一个能够描述该方法的作用的名字,而不是采用Delphi附加的名字是一种更好的方式。例如,BtnAdd按钮的OnClick事件可以命名成AddToList。这会使得你的程序可读性更强,特别是当你在这个类的其他方法中调用这个事件处理程序时,而且这会帮助程序员为类似的事件或是不同的组件选用相同的方法。不过我必须声明,使用动作(Actions)是目前开发重要的程序时我最喜欢的方法。

  规则四:使用窗体方法(Use Form Methods)

  窗体都是一些类,因此窗体的代码是以方法组织的。你可以向窗体中添加事件处理程序,这些处理程序完成一些特别的功能,而且他们能被其他方法调用。除了事件处理方法外,你还可以向窗体添加完成动作的特别定义的方法以及访问窗体状态的方法。在窗体中添加一些公共的(Public)方法供其他窗体调用要比其他窗体直接操作他的组件要好。

规则5:添加窗体构造器(Add Form Constructors)

  在运行时创建的第二个窗体除了一个默认的构造器(从Tcomponent 类继承而来)外还会提供其他特殊的构造器。如果你不需要考虑和Delphi4以前的版本的兼容性问题,我建议你重载(Overload)Create方法,添加必要的初始化参数。具体代码可参见下面的代码:

Public
Constructor Create(Text:string): reintroduce ; overload;
Constructor TformDialog.Create(Text:string);
Begin
Inherited Create(Application);
Edit1.Text:=Text;
End;

  规则6:避免全局变量(Avoid Global Variables)

  应该避免使用全局变量(就是那些在单元的interface 部分定义的变量)。下面将会有一些建议帮助你如何去做。

  如果你需要为窗体存储额外的数据,你可以向窗体类中添加一些私有数据。这种情况下,每一个窗体实例都会有自己的数据副本。你可以使用单元变量(在单元的implementation部分定义的变量)声明那些供窗体类的多个实例共享的数据。

  如果你需要在不同类型的窗体之间共享数据,你可以把他们定义在主窗体里来实现共享,或者使用一个全局变量,使用方法或者是属性来获得数据。

  规则7:永远不要在Tform1类中使用Form1(Never Use Form1 in Tform1)

  你应该避免在类的方法中使用一个特定的对象名称,换句话说,你不应该在TForm1类的方法中直接使用Form1.如果你确实需要使用当前的对象,你可以使用Self关键字。请牢记:大多数时候你都没有必要直接使用当前对象的方法和数据。

  如果你不遵循这条规则,当你为一个窗体类创建多个实例的时候,你会陷入麻烦当中。

  规则8:尽量避免在其他的窗体中使用Form1(Seldom Use Form1 In Other Forms )

  即使在其他窗体的代码中,你也应该尽量避免直接使用全局变量,如Form1.定义一些局部变量或者私有域供其他窗体使用会比直接调用全局变量要好。

  例如,程序的主窗体能够为对话框定义一个私有域。很显然,如果你计划为一个派生窗体创建多个实例,这条规则将是十分有用。你可以在主窗体的代码范围内保持一份清单,也可以更简单地使用全局Sreen对象的窗体数组。

  规则9:移除Form1(Remove Form1)

  事实上,我的建议是在你的程序中移除Delphi自动创建的全局窗体对象。即使你禁止了窗体的自动添加功能,这也有可能是必要的,因为在Delphi随后仍然可能添加这样的窗体。我给你的建议是应该尽量避免使用全局窗体对象。

  我认为对于Delphi新手而言,移除全局窗体对象是十分有用的,这样他们不至于对类和全局对象两者的关系感到疑惑。事实上,
规则10:添加窗体属性(Add Form Properties)

  正如我已经提到过的,当你需要为你的窗体添加数据时,请添加一个私有域。如果你需要访问其他类的数据,可以为你的窗体添加属性。使用这种方法你就能够改变当前窗体的代码和数据(包含在它的用户界面中)而不必改变其他窗体或类的代码。

  你还应该使用属性或是方法来初始化派生窗体或是对话框,或是访问他们的最终状态。正如我前文所说的,你应该使用构造器来完成初始化工作

  规则11:显示组件属性(Expose Components Properties)

  当你需要访问其他窗体的状态时,你不应该直接访问它的组件。因为这样会将其他窗体或其它类的代码和用户界面结合在一起,而用户界面往往是一个应用程序中最容易发生改变的部分。最好的方法是,为你需要访问的组件属性定义一个窗体属性。要实现这一点,可以通过读取组件状态的Get方法和设置组件状态的Set方法实现。

  假如你现在需要改变用户界面,用另外一个组件替换现有的组件,那么你只需做的是修改与这个组件属性相关的Get方法和Set方法,而不必查找,修改所有引用这个组件的窗体和类的源码。详细实现方法请参见下面的代码:

private
function GetText:String;
procedure SetText(const Value:String);
public
property Text:String;
read GetText write SetText;
function TformDialog.GetText:String;
begin
Result:=Edit1.Text;
end;
procedure TformDialog.SetText(const Value:String);
begin
Edit1.Text;=Value;
end;

  规则12:属性数组(Array Properties)

  如果你需要处理窗体中的一系列变量,你可以定义一个属性数组。如果这些变量是一些对于窗体很重要的信息,你还可以把他们定义成窗体默认的属性数组,这样你就可以直接使用SpecialForm[3]来访问他们的值了。

  下面的代码显示了如何将一个listbox组件的项目定义成窗体默认的属性数组。

type
TformDialog =class(TForm)
private
listItems:TlistBox;
function GetItems(Index:Integer):String;
procedure SetItems(Index:Integer:const Value:String);
public
property Items[Index:Integer]:string;
end;
function TFormDialog.GetItems(Index:Integer):string;
begin
if Index >=ListItems.Items.Count then
raise Exception.Create(‘TformDialog:Out of Range’);
Result:=ListItems.Items[Index];
end;
procedure TformDialog.SetItems(Index:Integer;const alue:string);
begin
if Index >=ListItems.Items.Count then
raise Exception.Create(‘TformDialog:Out of Range’);
ListItems.Items[Index]:=Value;
end;

  规则13:使用属性的附加作用(Use Side-Effects In Properties)

  请记住:使用属性而不是访问全局变量(参见规则10、11、12)的好处之一就是当你设置或者读取属性的值时,你还可能有意想不到的收获。

  例如,你可以直接在窗体界面上拖拉组件,设置多个属性的值,调用特殊方法,立即改变多个组件的状态,或者撤销一个事件(如果需要的话)等等。

 

规则14:隐藏组件(Hide Components)

  我经常听见那些面向对象编程的狂热追求者抱怨Delphi窗体中包含一些在published部分声明的组件,这是和面向对象思想的封装性原理不相符合的。他们确实提出了一个重要的议题,但是他们中的大多数人都没有意识到解决方法其实就在他们手边,完全不用重写Delphi代码,也不用转向其他语言。

  Delphi向窗体中添加的组件参照可以被移到private部分,使得其他窗体不能访问他们。如果你这样做,你就有必要设置一些指向组件的窗体属性(请参见规则11),并且使用它们来访问组件的状态。

  Delphi将所有的这些组件都放在published部分,这是因为使用这种方式能够保证这些域一定是在.DFM文件中创建的组件。当你改变一个组件的名称时,VCL能够自动地将这个组件对象与它在窗体中的参照关联起来。因为delphi使用RTTI和Tobject方法来实现这种功能,所以如果想要使用这种自动实现功能,就必须把参照放置在published部分(这也正是为什么delphi将所有的组件都放在published部分的缘故)。

  如果你想知道的更详细一点,可以参看下面的代码:

procedure Tcomponent.SetReference(Enable:Boolean);
var
Field:^Tcomponent;
begin
If Fowner<> nil then begin
Field:=Fowner.FieldAddress(Fname);
If Field<>nil then
Field^:=Self
else
Field^:=nil;
end;
end;

  上面的代码是Tcomponent类的SetReference方法,这个方法可以被InserComponent,RemoveComponent和SetName等方法调用。

  当你理解了这一点后,你应该不难想到如果你将组件参照从published部分移到了private段,你将失去VCL的自动关联功能。为了解决这个问题,你可以通过在窗体的OnCreate事件中添加如下代码解决:

  Edit1:=FindComponent(‘Edit1’) as Tedit;

  你接下来应该做的就是在系统中注册这些组件类,当你为他们注册过后就能使RTTI包含在编译程序中并且能够被系统所使用。当你将这些类型的组件参照移到private部分时,对于每一个组件类,你只需为他们注册一次。即使为他们注册不是一定必要的时候,你也可以这样做,因为对于RegisterClasses的额外调用有益无害。通常你应该在单元中负责生成窗体的初始化部分添加以下的代码:

  RegisterClass([TEdit]);

  规则15:面向对象编程的窗体向导(The OOP Form Wizard)

  为每一个窗体的每一个组件重复上述两个操作不仅十分的烦人,而且相当的浪费时间。为了避免额外的负担,我已经为此写了一个简单的向导程序。这个程序将会生成一些可以完成以上两步工作的代码,你需要做的仅仅是做几次复制和粘贴就行了。

  遗憾的是这个向导程序不能自动将代码放置到单元中合适的地方,我目前正在修改这个向导程序,希望能实现这个功能。你可以到我的网站(www.marcocantu.com)查找更加完善的程序。

  规则16:可视化窗体继承(Visual Form Inheritance)

  如果应用得当,这将是一个强大的工具。根据我的经验,你所开发的项目越大,越能体现它的价值。在一个复杂的程序中,你可以使用窗体的不同等级关系来处理一组相关窗体的多态性(polymorphism)。

  可视化窗体继承允许你共享多个窗体的一些公共的动作:你可以使用共享的方法,公用的属性,甚至是事件处理程序,组件,组件属性,组件事件处理方法等等。

  规则17:限制保护域数据的使用(Limit Protected Data)

  当创建一些具有不同分级体系的类时,一些程序员趋向于主要使用保护域,因为私有数据不能被子类访问。我不能说这没有其合理性,但是这肯定是和封装性不相容和的。保护数据的实现能够被所有继承的窗体所共享,而且一旦这些数据的原始定义发生改变,你必须更改所有的相关部分。

  请注意,如果你遵循隐藏组件这样一条规则(Rule 14),继承窗体就不可能访问基类的私有组件。在一个继承窗体中,类似Edit1.Text:=’’的代码就不会被编译。虽然这是相当的不方便,但是至少在理论上这是值得肯定的事情,而不是否定的。如果你感觉到实现封装性是最主要,最需要的,就请将这些组件参照放在基类的私有段。

 

规则18:保护域中的访问方法(Protected Access Methods)

  在基类中将组件参照放置在私有域中,而为这些组件添加一些访问函数来得到他们的属性,这将是一种更好的方法。如果这些访问函数仅仅在这些类内部使用而且不是类接口的一部分,你应该在保护域声明他们。例如Rule 11中描述过的GetText和SetText方法就可以声明成protected,并且我们可以通过调用SetText(’’)来编辑文本。

  事实上,当一个方法被镜像到一个属性时,我们可以简单地采用如下代码就可以达到编辑文本地目的:

  Text:=’’;

  规则19:保护域中的虚拟方法(Protected Virtual Methods)

  实现一个灵活的分级制度的另一个关键点是定义一些你可以从外部类调用的虚拟方法来得到多态性。如果这个方法使用得当,将会很少出现其他公共的方法调用保护域中的虚拟方法的情况。这是一个重要的技巧,因为你可以定制派生类的虚拟方法,来修改对象的动作。

  规则20:用于属性的虚拟方法(Virtual Methods For Properties)

  即使是访问属性的方法也能定义成virtual,这样派生类就能改变属性的动作而不必重定义他们。虽然这种方法在VCL当中很少使用,但是它确实十分灵活、强大。为了实现这一点,仅仅需要将Rule 11当中的Get 和Set 方法定义成Virtual。基类的代码如下所示:

type
TformDialog = class ( TForm)
Procedure FormCreate(Sender:Tobject);
Private
Edit1:Tedit;
Protected
function GetText:String;virtual;
procedure SetText(const Value:String);virtual;
public
constructor Create(Text :String):reintroduce;overload;
property Text:String read GetText write SetText;
end; 

  在继承窗体中,你可以添加一些额外的动作来重载虚拟方法SetText:

procedure TformInherit.SetText(const Value:String);
begin
inherited SetText(Value);
if Value=’’ then
Button1.Enabled:=False;
end;

  小结

  要做到一个好的Delphi面向对象编程程序员远非我在上面提到的这些规则这么简单。上面的这20条规则中有一些可能需要足够的耐性和时间来实现,因此,我也不能强求你能遵循所有的这些规则。但是这些规则应该被合适的运用到你的程序中,而且当你开发的应用程序越大,参与的程序员越多,这些规则越重要。不过,即使是一些小程序,始终记住这些规则并在合适的地方使用他们也会对你有所帮助。

  当然,还有很多其他的经验规则我没有涉及到,特别是存储器处理和RTTI问题,因为他们十分的复杂,需要专门的说明。

  我的结论是要遵循我上面列出的规则会付出一定的代价,特别是额外的代码,但是这些代价会让你得到一个更加灵活强壮的程序。希望Delphi的后续版本能够帮组我们减少这些代价。

 

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

****************************************************************** 
*                    四、写代码的一些要素                        * 
****************************************************************** 
 
A. 尽可能不要在(对新手来说,是绝不要) 
 
        TMyForm=class(TForm) 
          ..... 
          ..... 
          ..... 
 
        end; 
 
   之外定义变量,尽量在Private段定义自己的变量和Procedure等。 
 
B. 任何情况下,不论多么艰难的调试情况,在begin回车之后,先打两个空 
 
   格再写程序代码。end一定要和相应的begin呼应在同一列上。 
 
C. Delphi是大小写不敏感的,但是多处引用时尽量保持相同的拼写。 
 
D. 不要自己去删Delphi自动生成的代码,解铃还需系铃人,如果不小心在哪 
 
   里Double Click了一下,Delphi生成的程序会在Save Project和Build时 
 
   自动删掉。(只要begin...end中间没写你自己的代码) 
 
E. FormCreat之前,它所包含的控件都还没有建立,是不能引用的。在Form1OnCreat 
 
   时,你不能用 
 
       Form1.ListBox1....... 
 
   但是你可以写: 
 
       ListBox1......... 
 
   这是Delphi的约定,所以不要问我为什么。 
 
F. Form1如果是MainForm, 在OnCreat时是不能去引用Form2的变量的,因为这 
 
   时Form2还不存在。 
 
G. Form2.ShowModal后,程序会在Form2返回后才执行后面的代码,而用Show 
 
   可不是这样。 
 
H. 任何一段消息回调函数的代码都不要执行过长时间,如果迫不得已,在大循 
 
   环的间隙,一定要调用 
 
    Application.ProcessMessages 
 
   要不,程序会象死机一样。 
 
 
****************************************************************** 
*                    五、Windows编程的重入问题                   * 
****************************************************************** 
 
TTimer是用于定时反复执行一些代码,可是千万记住如果一段代码执行时间 
 
过长时,下一次Timer触发会重入这段代码,就是说如果Timer1Timer中没有 
 
    Timer1.Enabled := False; 
 
的话,可能会有两个进程在执行这段代码,如果共同访问一个变量,一个有 
 
可能在改,一个有可能在读,那么就会出现意想不到的问题。 
 
类似的重入问题其它时候也会碰到,比如你在Show(而不是ShowModal)一个 
 
Form时,两个Visible的Form在共同访问同一变量,就会出现一些奇怪的现象。 
 
新手最好先避开这类问题,省得麻烦。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

一名Delphi程序员的开发习惯

作者: Musicwind?
有关开发习惯的一些想法,如鲠在喉,不吐不快。究其发贴动机,当然不排除有骗取参与分的可能,但另一方面,也希望能给同行(念Xing)者提供一些建议,或者参考(希望不是误人子弟)。同时,也希望各位能够就我的这些陋习,发表一点看法,给出批评和指正的意见。谢谢。
一.建立工程目录
       首先,第一步要做的,当然是给新项目建一个单独的目录(别笑)。目录名称与项目名称同名,或者另取一个也可,只要清楚、简练。然后,在此目录中创建以下各个目录:
       :用来存放该项目相关的开发文档(需求说明,概要设计,详细设计等等等等);
       :用来存放Delphi源程序中的”.Dpr”,”.Pas”,”.Dfm”等文件;
       :该目录中存放”.Dcu”文件,将’.Pas’与’.Dcu’文件分开存放只是为了让Source目录的内容更加清楚一些;
       :存放工程的输出文件,比如”.Exe”,”.Dll”或者”.Ocx”等等;
       :用来存放日志文件;通常在这个目录中我会放一个”<项目名称>程序员日志.Txt”文件。
       :当然是存放工程中用到的图片的目录了。一般情况下,这个目录是少不了的。假如还用到其他资源,那么也一样建立各自的目录,比如Wav,比如Avi等等。

二.设置工程选项
在Delphi中创建一个新的工程,将此工程保存到Source目录中,同时:
a.       选一个耐看的,与项目有些联系的图标作为这个工程的图标。当然,这个图标可能只是临时用用的,但是总要比Delphi默认的那个难看的要好才行,要不然,怎么对得起自己?
b.       将Project Options -> Directories/Conditionals页面中的Output Directory设置为Bin目录;
c.       将Unit output Directory设置为Dcu目录。

三.添加常量单元
       添加一个新的Unit,另存为“unt<工程名> Consts.Pas”,用来保存工程中用到的常量。

四.有关窗体(Form)及单元(Unit) 
按照匈牙利命名法则给Form命名,则一个用来登录的窗体可以命名为’FrmLogin’,而其单元名可以为’untLogin’。通常,两个对应的Form和Unit的名称在除去’Frm’或’unt’的缩写后应当保持一致。
在Unit的头部添加本单元的注释,注释的格式可以参照Delphi的源码,但是至少应当包含以下几项:功能描述;作者;版权;创建时间;最后修改时间;修改历史等等。
将新创建好的Form的Caption设置为该Form类的名称,而不是使用Delphi默认的。比如,将Form1更名为FrmLogin后,此时我们获得了TFrmLogin这个新的窗体类,并且Delphi自动将窗体的Caption更新为’FrmLogin’。依我看,该Caption应当为’TFrmLogin’才是,因为我们在设计的是一个窗体类TFrmLogin,而不是仅仅对FrmLogin进行操作。
向TFrmLogin这样功能明确的窗体类,许多人都有在设计期就将其Caption设置为诸如“操作员登录”这种名称的习惯。我的习惯是,象“操作员登录”这样的常量,通常存放在unt<工程名>Consts.Pas中,用ResourceString来定义,或者用Const来定义。至于窗体的Caption的命名,应当属于运行期的工作。所以,我往往在TForm.OnCreate事件触发之时才对Caption进行操作,比如:
procedure TFrmLogin.FormCreate(Sender: TObject);
begin
       Caption := csLoginTitle;
      ....
end;

五.关于Format函数的使用
       有iYear,iMonth,iDay三个数据,要显示诸如“生日:1976/3/18”这样的信息,你通常怎么做?使用s := ‘生日:’+IntToStr(iYear)+’.’+IntToStr(iMonth)+’.’+IntToStr(iDay); 吗?这样实在是太累了。我的习惯是,在unt<工程名>Consts.Pas中增加一个常量csBirthDayFormat = ‘生日:%d/%d/%d’来保存显示格式,然后使用s := Format(csBirthDayFormat, [iYear, iMonth, iDay]);这样的语句完成数据的拼装。这么做的好处显而易见,那就是你只需在一个地方维护数据的显示格式。
       Format函数功能强大,我对它很是推崇,你呢?

六.关于注册表或者Ini文件的存储
原先访问注册表我通常使用TRegistry,而访问Ini文件通常使用TIniFile。这两个类的使用方法各不相同,因此想要使用相同的代码既能访问注册表又能访问Ini文件几乎是不可能的。真头疼啊!
终于我发现了救星!那就是TRegistryIniFile类。查看Registry单元,我们发现,TRegistryIniFile继承自TCusomIniFile。而TIniFile也是继承于TCusomIniFile。因此,使用抽象类TCusomIniFile来实现对注册表或者Ini文件的访问便是一举两得了。比如:
var
  csmIniFile: TCusomIniFile;
begin
  if blUseIniFile then//如果使用Ini文件
    csmIniFile:= TIniFile.Create(csRootKey)
  else
    csmIniFile:= TRegistryIniFile.Create(csRootKey);
  //接着就可以使用csmIniFile对Ini文件进行访问,
//或者用类似访问Ini文件的方式访问注册表。

七.关于TStream流以及TFileStream,TMemoryStream等等
       TFileStream和TMemoryStream都继承自抽象类TStream,这意味着我们可以使用一套代码完成对文件和内存的存取操作。因此,定义一些接口的时候,我往往倾向于将参数的类型定义为抽象类,而不是具体类。比如,要完成保存功能的一个函数,定义成
function Save(AStream: TStream): Boolean;
就比定义成
function Save(AStream: TFileStream): Boolean;
要灵活的多。
前一个定义是具有前瞻性的,因为它可以适用于以后可能出现的新型态的流。而后一个定义只适用于TFileStream这种流(当然包括TFileStream的子类),呆板多了。
我的习惯:如果存在抽象类,那么尽量将参数定义为抽象类的类型,毕竟,我们无法预见未来。

八.多使用TAction
       Delphi 4以后引入了Action的概念,并且在Standard组件栏中增加TActionList组件。使用Action的好处是,控件状态同步的烦恼从此一扫而空!

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

DELPHI编程技巧集锦(1

董占山

(中国农科院棉花研究所,河南安阳,455112)

美国著名的《Delphi开发者杂志(Delphi Developer's Journal)》是世界上众多Delphi程序员必读的专业杂志,在国内我们很少有机会读到这份优秀的专业刊物,但是我们可以在Inprise公司(http://www.inprise.com)的网页上看到该杂志刊登的一些优秀文章。同时,还可以通过电子邮件订阅该杂志免费提供的Delphi使用技巧,订阅网址为http://www.zdtips.com/ddj/bor-f.htm。笔者从中筛选出一些十分有用的Delphi使用技巧和文章,编译出来,与广大Delphi爱好者分享。有什么意见和建议可以直接给笔者发电子邮件(dzs@126.com)。读者请注意,本文中的内容多以Delphi 4为例进行介绍,请使用其他版本的读者根据实际情况灵活运用。

一、Delphi集成环境与代码调试

修改Delphi的系统信息

默认的Delphi消息、警告和例外描述都是英文的,将这些内容翻译成另一种语言或修改它们使其适合你的需要的最简单方法是编辑资源文件并改变相应的字符串,这些文件位于BIN目录。主要资源文件有:SysUtils单元的信息(文件没有找到、转换错误信息等)在sysutils.res中,数据库错误信息在dbconsts.res中,VCL信息在consts.res中。注意一些字符串使用格式字符,如%s%d,来产生最终的字符串,在这种情况下,应将这些字符保留在适当的位置。

如何清除无用代码

Delphi提供了自动清除源代码中无用代码的强大功能,一般来说,当你保存文件时,Delphi自动将源代码中空的类方法删除,保证了源代码的清洁。在没有编译和保存文件的前提下,也可以清除无用代码,方法是:在Delphi 3/4中单击“File*Save As...”菜单命令(在Delphi 1/2中单击“File*Save File As...”菜单命令),打开“Save As...”对话窗口,单击“取消”按钮即可。

Delphi 4集成环境中不使用浮动功能

你无疑知道Delphi 4集成环境支持大多数窗口的浮动功能。但是,有时你不想让一个窗口具有浮动功能。浮动窗口在需要时,十分有用,但在不需要时,也十分恼人。有两种方法可以改变一个窗口的浮动属性。

第一种方法是:每个可浮动窗口具有一个本地菜单项目---Dockable,如果你不希望一个特定的窗口具有浮动功能,简单地用鼠标右键单击窗口,选空Dockable菜单项目。这个窗口的浮动功能就关闭了,直到你再选中Dockable项目为止。

这一技术可以防止特定的窗口可停靠。但有时,你仅仅希望暂时关闭浮动功能,这时,只需要按下<Ctrl>键,再拖动窗口。

在工具菜单中添加项目

Delphi集成环境中按F1键可以打开多数Delphi帮助标题,这种方法可以快速打开相关标题的帮助窗口。但是这种快速方法对第3方工具和常问问题(FAQs)是不可用的,Delphi提供了一个变通的方法,使在集成环境下快速打开这些工具成为可能。

在工具菜单添加用户项目的方法是:单击“Tools*Configure Tools”命令,打开一个包含所有可用工具列表的对话窗口,单击“Add”按钮,打开“Tool Properties”对话窗口,分别设置4个编辑框,然后单击“Ok”按钮,再单击“Close”按钮,完成设置。

设置条件断点

一般来说,大家都会使用断点来调试程序,但是如何使用条件断点来调试程序呢?条件断点,顾名思义,就是指需要满足一定条件时的断点。这种断点在调试很长的ForWhile循环时十分有用,当你只希望看一看一个特定循环的执行情况而非所有循环时,就需要在循环中设定一个条件断点,当设定的条件满足时,Delphi停止应用程序的执行。

设置条件断点的方法是:按常规的方法建立断点,单击“View*Debug Windows*Breakpoints”命令,弹出一个断点列表窗口,用鼠标右键单击欲设置为条件断点的断点,在快捷菜单中单击“Properties”命令,打开一个断点编辑窗口,在这个窗口的条件域中输入一个逻辑表达式即可。在调试程序时,Delphi判断这个逻辑表达式,当逻辑表达式为真时,就中断程序运行,返回代码窗口。

不要让集成调试器打断调试过程

在调试程序时,Delphi的集成调试器监视一切运行时错误。当调试器发现一个运行时错误时,Delphi中断应用程序并返回到设计状态,并显示一个错误信息窗口。当关闭错误信息窗口后,需要按<Ctrl-F2>重新开始启动程序,或者按<F9>继续运行程序。无疑,Delphi集成调试器是十分有用的,但有时也让人烦恼。能否暂时关闭集成调试器呢?可以。使用下面的方法可防止集成调试器中断应用程序:

单击“Tools*Environment Options...”菜单命令;

单击“Preferences”对话页标签;

选空“Integrated debugging option”复选框;

单击“Ok”完成操作。

这样当你在集成环境下调试应用程序时,Delphi的集成调试器探测到运行时错误时,就不再切换到设计状态并显示错误信息了。

调试Delphi 3/4集成环境的插件

Delphi 1, 要调试集成环境的插件/专家是十分困难的。Delphi 3/4提供了调试DLL的能力,从而简化了这项工作。

第一步,保证插件/专家没有包括在Windows注册表的插件/专家列表中,然后,启动Delphi 3/4并装载需要调试的专家DLL,修改注册表,使Delphi 3/4能够调用这个DLL

第二步,单击“Run*Parameters”菜单命令,打开“Run Parameters”对话窗口,单击“Local”对话页上的“Host Application”编辑框右边的“Browse”按钮,查找“Delphi32.exe”程序的位置(本例为C:/Program Files/Borland/Delphi4/Bin/delphi32.exe);

第三步,运行待调试的DLL,将启动Delphi的第二个实例,并装载要调试的DLL,允许对其进行调试。

二、窗体设计的相关技巧

透明象素点

当将一个image图象,一般为BMP文件,放到一个TBitBtn上时,图片左下角的一个象素点决定图片中的哪种颜色为透明色。图片上任何具有这种颜色的象素点,在按钮上都是透明的。假如不希望图片上的任何象素点是透明的,就需要将图片左下角的这个象素点的颜色设置为不同于图片上任何象素点的颜色。

自动调整窗体的分辨率

创建应用程序时,总是依监视器的分辨率进行的,其缺点是:假如在较高分辨率下设计应用程序,它可能大于用户的有效屏幕大小,在用户使用程序时,就不能显示出全部窗体内容,给用户带来不便。一种简单的解决办法是:在程序运行时,让Delphi自动添加滚动条来解决这个问题。

但是,使用Delphi的自动调整比例过程将产生更加专业的结果。在运行时,Delphi获得系统的屏幕分辨率,并将结果保存在应用程序的Screen对象的PixelsPerInch属性中,然后,使用这个属性的值将窗体调整到当前分辨率。

记住,为了有效地使用这项技术,需要设置窗体的Scaled属性为真,并且只用TrueType字体,如果开发程序时,使用了Windows的小字体,应将窗体的AutoScroll属性设置为假(FALSE)。

为控制设置一种自定义颜色

窗体和各种控制都具有一个Color属性,当你选择它们的Color属性时,可以在列表框中选择一种Windows系统默认的各种颜色,也可以建立一种自定义颜色,使它们显得与众不同。为窗体或控制设定自定义颜色的步骤如下:

双击组件的Color属性,弹出颜色对话窗口;

选择一种最接近你想要的基色;

单击“Define Custom Colors>>”按钮,颜色对话窗口将扩展,显示出一个色谱区域;

使用十字光标在这个色谱区域选择你想要的颜色,然后单击“Add to Custom Colors”按钮;这样你选定的特定颜色就被添加到颜色对话窗口中了;

单击“Ok”按钮,就将刚定义的颜色应用到选定的控件了。

缩小步长

大多数程序员在设计窗体时喜爱“(靠到格线)Snap to grid”功能,可以节省安置组件的时间,但是,有时你还需要微调其位置和大小。

其一:将组件在窗体上一次移动一个象素点。首先,选中你想移动的组件,然后,按下<Ctrl>键不放,按光标键,选中的控制将一次移动一个象素点,方向与光标键所指方向相同。

其二:每次按一个象素点调整控制的大小。选中控制,按下<Shift>键不放,按光标键,根据光标键所指方向不同,选中的控制每次放大或缩小一个象素点。

控制滚动条的有效方法

TFormHorzScrollBarVertScrollBar属性使用Tracking子属性来管理窗体的显示,Tracking属性是一个布尔型属性。若此属性设置为真,窗体随用户拖动滚动条而移动;若此属性设置为假,窗体不随用户拖动滚动块而移动,只有用户释放滚动块时才移动。这种差别对查看列表和图象的用户十分重要。如果要平滑地显示列表和图象,将Tracking属性设置为真,但当图象或列表信息特别复杂时,窗口的滚动特别地缓慢。如果要快速显示列表和图象信息,将Tracking属性设置为假,这样窗口的滚动就会加快,但是由于不能看到实际位置,所以使用时难以掌握。除了TForm以外,TScrollBox组件也使用Tracking属性来管理其显示内容。

选择合适的组合框

Delphi提供了5类组合框,它们具有相同的特性,但是也有不同的特点。了解其间的差别,可帮助程序员根据需要选择合适的组合框类型。

所有的组合框都是一个列表框和编辑框的组合,用户可以在列表框中选择或在编辑框中直接输入值。当用户从列表框中选择时,这个条目将显示在编辑框中。5类组合框的不同特性决定了它们的显示和与用户交互的方式。下表列出了5种类型组合框的的独有特征。

格式描述

格式

说明

Simple

这种格式就是列表框上显示一个编辑框,用户可以从列表框中选取条目,也可以直接在编辑框中输入文本

Drop-down

除了列表框开始不显示外,其他特性均类似于simple格式。在编辑框的左边有一个下拉按钮,单击可以打开列表框,从中选取条目;也可在编辑框中直接输入项目。

Drop-down list

这是组合框中限制条件最多的一种,显示格式类似于drop-down,开始时列表框不显示。用户单击下拉按钮打开列表框并从中选取条目,但是不能在编辑框中直接输入文本。

OwnerDrawFixed

这种组合框类似于Simple类,不同的是其列表框中的条目高度是根据用户在ItemHeight定义的值而设置的。

OwnerDrawVariable

这种组合框类似于OwnerDrawFixed类,特点是列表条目的高度是可变的。

当窗体上有足够的空间和列表很短时,使用Simple格式的组合框较为合适。否则,使用Drop-down格式的组合框。当想让用户只能从预定义项目中选取条目时,用Drop-down list格式的组合框。需要可变高度列表项时,使用后两种。

使非可视组件易于辨认

非可视组件没有标题属性,一个窗体中多个同类非可视组件时,由于它们看起来一模一样,故难以辨认。DELPHI提供了一种变通的方法,就是将非可视组件的名称放置在组件图标之下,使它们易于辨认。设置方法如下:

单击“Tools*Environment Option”,弹出一个对话窗口;

单击“Preferences”标签,切换到Preferences对话页;

选中“Show component captions”复选框;

单击“Ok”完成。

这时,在当前的设计窗体上,就可以看到每个非可视组件下显示出一个标签。这个选项设置之后,对所有窗体都是有效的。

标签的加速键

对含有Caption属性的组件,添加快捷键是比较容易的,只需在Caption属性中特定字符前加上“&”符号即可。那么,怎样给没有Caption属性的控制添加快捷键呢?现以给一个TMemo

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述
  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值