Delphi程序设计之--惯用法[1]

[入库:2005年8月18日] [更新:2007年3月25日]

本文简介:选择自 l_xiaofeng 的 blog

delphi --技巧探索:  
{ no. 1 }
创建模式窗体的句子:
class procedure tmyform.runform(aobj1, aobj2: tobject);
var
vform: tmyform;
begin
vform := tmyform.create(application);
with vform do
try
 initform(aobj1, aobj2);
 showmodal;
finally
 free;
end;
end;
//*说明:
通过class声明的函数,类似与vc中的静态函数;使用语句:tmyform.runform(vobj1, vobj2);
其他具体的,参考:delphi 帮助中的,class 类说明。
强调这个惯用法,就是为了:
1、如果此窗体在多处被使用,那么可以保证统一都调用此段代码;
2、如果功能上有所修改,比如:根据showmodal的返回值不同进行处理,那么只修改此函数就行了。
3、程序封装性好,易于维护和工作交接。*//

{ no. 2 }//tag 的使用
窗体工具栏按钮事件的响应
procedure tmyform.runoperate(atag: integer);
begin
 case atag of
 1: mybutton.color := clred;
 2: mybutton.color := clgreen;
 3: mybutton.color := clblack;
 end;
end;

procedure tmyform.toolbtnclick(sender: tobject);
begin
 runoperate(tcontrol(sender).tag);
end;

如果你在某下拉菜单中,也需要执行类似功能则
procedure tmyform.menuitemclick(sender: tobject);
begin
 runoperate(tmenuitem(sender).tag);
end;

//*说明:
1、结构清晰
2、相关的信息集中,比较容易查错、修改和维护
3、提高程序的适应、扩展能力;比如现在要求不在工具栏按钮中实现,而要求在不同按钮中实现,则修改容易。
建议:每个分类后面只跟一行或不多的几行代码,如果代码比较多,使用过程函数替代。
比较有意思的是,我经常如下写:
case btnmybutton.visible of
{ 显示 } true: ...
{不显示} false: ...
end;    *//

 

{ no. 3 }//事件指针做参数
//对于列表等的读取使用事件指针的方式
type
 tdatasetevent = procedure (dataset: tdataset; aindex, acount: integer) of object;
//从 tadoquery派生而来的类
procedure tmyadoquery.enumrecord(awherestr: string; apro: tdatasetevent);
begin
 close;
 sql.clear;
 sql.add('select * from table1');
 if awherestr <> '' then
   sql.add('where ' + awherestr);
 open;
 while not eof do
 begin
   if assigned(apro) then apro(self, recno, recordcount);
   next;
 end;  
 close;
end;

//*说明:
此方法来自与window中,枚举当前所有子窗体的api函数,enumchildwindow
1、原则:尽量将数据读取与数据显示、数据处理等分离;如:mvc等都是此目的。
2、程序扩展性增强,如果您原来希望在列表中显示或处理某列信息,后来改为用combobox,则在修改程序时,不在阅读数据读取部分,只需要修改信息显示等即可。又比如,现在要求您在读取记录时,用进度条显示读取进度等。
*//

 

{ no. 4 }//常量数组

{ 在 no.2 中,实现了如下的内容
procedure tmyform.runoperate(atag: integer);
begin
case atag of
1: mybutton.color := clred;
2: mybutton.color := clgreen;
3: mybutton.color := clblack;
end;
end;
}
//那么用数组方式实现,则就比较理想了
procedure tmyform.runoperate(atag: integer);
const
 mybuttoncolormax := 3;
 mybuttoncolor: array [1..mybuttoncolormax] of tcolor = (clred, clgreen, clblack);
begin
case atag of
1..mybuttoncolormax:  mybutton.color := mybuttoncolor[atag];
101:....
end;
end;

//*说明:
对于数组方式使用,只要注意数组的上限或下限使用常量来实现,然后在以后使用中都尽量使用此常量进行数组循环读取就行了。
*//

 

{ no. 5 }消息机制 减少类公共函数
//如何让一个窗体中,尽量减少公共函数的定义;
{ 比如:要实现一个当前窗体控件的属性列表窗体,当需要刷新属性窗体;改变某属性值;添加新的属性等;会有很多需要交互的信息。如果我们使用类公共函数,则需要定义很多的公共函数。同时,如果需要进行窗体类型转换,转换为目标窗体类型才可以使用公共函数。所以,会遇到两个单元需要互相包含的情况 }
//解决方案:
tfrmmyform = class(tform)
 ffrmproperty: tform;
end;

...
 ffrmproperty := tfrmproperty.mycreate(application, self);
...

//当需要刷新属性窗体时
 ffrmproperty.perform(wd_refreshpropertylist, 0, 0);

tfrmproperty = class(tform)
private
 fmyform: tform;
 procedure wdrefreshpropertylist(var message: tmessage); message wd_refreshpropertylist;
public
 constructor mycreate(owner: tcomponent; aform: tform);
end;

constructor tfrmproperty.mycreate(owner: tcomponent; aform: tform);
begin
 inherited create(owner);
 fmyform := aform;
end;

//* 对于使用消息的方式,可以减少窗体公共函数的定义。同时,提高程序的可扩充性。如果,使用他的窗体替代时,则可以比较轻松的转换,因为如果最多也就是您的窗体,对当前的消息没有进行处理而已 *)// 

 

 

{ no. 6 }使用注册列表管理可能扩充的模块
//项目:要求你对一个数据集支持多种输出显示方式

...例子,以后给出

//* 说明:
1、“多种输出方式”,说明输出方式在今后的应用中可能会经常扩充,因此要在程序设计时考虑到输出方式的易扩充性。
2、参考vcl中,控件注册(registercomponents)的机制,可以发现vcl中大量的使用到了注册机制;其中比较经典的就是控件属性编辑器的注册了。
*//

{ no. 7 }使用预定义控制程序版本

//如果您做的是一个二次开发平台的程序,则必须涉及到产品版本控制和项目版本控制问题
//通常使用预定义的方式控制

//语句比较简单了就是:
{$define joyyuan97}
{$ifdef joyyuan97} {else} {endif}
{$undef joyyuan97}

*说明:
1、将预定义划分在多个单独的文件中。
2、在每个单元的最前头但在unit 后,使用{$i ...} 将文件包含(include)进当前单元
3、根据预定义情况控制当前单元所能包含的单元文件
4、尽量单独划分一个针对项目的预定义文件在包含所有预定义文件后,包含此文件,则在此文件中,可以针对项目的需要,将取消部分预定义{$undef joyyuan97}

本文关键:经验,技巧
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top