2006-12-3 21:54
蓝色虫
delphi控件的安装
作者 : picses_y
标题 : delphi控件的安装
[b]delphi 7中的安装方法[/b]
1. 把 EhLib 中的 common 和 DataService 文件拷贝到 Delphi7 目录中.
2.在 TOOLS->Environment Options->Library->Library Path 中添入EHLIB路径。
3.打开新建文件夹中的 EHLIB70.DPK ,编译一下,但不要安装。
4.打开Ehlib中的DclEhLib70.DPK,编译,安装
5. 在Delphi 7中打开DclEhLib70.dpk,编译并安装。
6. 组件面板中出现一个EhLib的组件页。
7. 打开附带的DEMOS,编译并运行,测试安装成功。
[b]1、带源码的安装:[/b]
要识别是否属于带源码的控件,最容易识别的方法是看是否含有PAS文件,而不含有dpk文件,如果发现dpk文件就按不带源码处理。面对这些pas文件,我们有如下方法安装:
增加控件:点菜单component/install component,选into new package,在unit file name处按browse,把该控件的pas文件全加进来,在package description处写一个存放的文件名称,按OK后就创建了一个自己的控件包。你会看到一个Package窗体,这时再按Compile安装选择的控件。
删除该控件:点菜单component/install packages,按remove,找到你增加下去的Pas文件,按ok删除。
[b]2、不带源码
[/b]
这种一般比较容易安装,可以直接运行控件包的dpk文件,如果成功那么将会在控件栏中出现该控件。这些控件包一般都经过编译,所以不含有pas文件,是不可以修改的。
不过有很多控件都不是这么简单的。有些控件包是编写不完整,错误百出,有些控件包提供不完全,会漏了一些dcu文件,也有些是delphi本身遗漏某个类,控件编译通不过,从而导致无法安装。遇到这些问题时就需要你灵活变通或者自己修改才行了。
[b]基本安装
[/b]
1、对于单个控件,Componet-->install component..-->PAS或DCU文件-->install;
2、对于带*.dpk文件的控件包,File-->Open(下拉列表框中选*.dpk)-->install即可;
3、对于带*.bpl文件的控件包,Install Packages-->Add-->bpl文件名即可;
4、如果以上Install按钮为失效的话,试试Compile按钮;
5、是run time lib则在option下的packages下的runtimepackes加之。
如果编译时提示文件找不到的话,一般是控件的安装目录不在Delphi的Lib目录中,有两种方法可以解决:
1、反安装的源文件拷入到Delphi的Lib目录下;
2、或者Tools-->Environment Options中把控件源代码路径加入到Delphi的Lib目录中即可。
注意:所安装的控件是否与你所用的Delphi版本相适应。
[b]RxLib的安装[/b]
首先在Delphi 5 的 IDE 中将以前版本的 Rxlib 反安装掉,删除 RXCTL5.BPL、RXDB5.BPL、 RXBDE5.BPL、DCLRX5.BPL、 DCLRXDB5.BPL 和DCLRXBD5.BPL。
打开 Rx 的运行包 RXCTL5.DPK,在 Package 窗口中按 Compile 按钮编译 RXCTL5.DPK ,然后用同样方法编译另两个运行包RXDB5.DPK 和 RXBDE5.DPK ,将编译后的三个 BPL 文件放到搜索路径中,如 WINDOWS\SYSTEM等。
在编译完运行包后你必须将 RX 的设计期包安装到 IDE 环境中。
打开 Rx 的设计期包 DCLRX5.DPK,在 Package 窗口中按 Compile 按钮编译,然后按 Install按钮将设计期包注册到组件面板中。用同样的方法安装 DCLRXDB5.DPK 和 DCLRXBD5.DPK。
注意:不要在 Delphi IDE 中保存包资源(package sources)!
[b]控件删除
[/b]
在Component/Install Packages中删除。
选Component/configure Palette…
有pages和components两个区域
双击components区域,选中要删除得控件,下面有得Delete按钮
但系统提供的控件只能Hide,不能delete。
打开控件所在的包文件(*.dpk),从中删除控件那个文件,再重新编译该包即可
如果是整个控件包都要删除的话,project->Option->Packages,删掉那个packages,That would be ok~
2006-12-3 21:59
蓝色虫
DELPHI的原子世界Delphi控件杂项
关键词:Delphi控件杂项
在使用DELPHI开发软件的过程中,我们就像草原上一群快乐牛羊,无忧无虑地享受着Object Pascal语言为我们带来的阳光和各种VCL控件提供的丰富的水草。抬头望望无边无际蔚蓝的天空,低头品尝大地上茂密的青草,谁会去想宇宙有多大,比分子和原子更小的东西是什么?那是哲学家的事。而哲学家此时正坐在高高的山顶上,仰望宇宙星云变换,凝视地上小虫的爬行,蓦然回头,对我们这群吃草的牛羊点头微笑。随手扯起一根小草,轻轻地含在嘴里,闭上眼睛细细品尝,不知道这根青草在哲学家的嘴里是什么味道?只是,他的脸上一直带着满意的微笑。
认识和了解DELPHI微观的原子世界,可以使我们彻底理解DELPHI的宏观应用程序结构,从而在更广阔的思想空间中开发我们的软件。这就好像,牛顿发现了宏观物体的运动,却因为搞不清物体为什么会这样运动而苦恼,相反,爱因斯坦却在基本粒子规律和宏观物体运动之间体验着相对论的快乐生活!
第一节 TObject原子
TObject是什么?
是Object Pascal语言体系结构的基本核心,也是各种VCL控件的起源。我们可以认为,TObject是构成DELPHI应用程序的原子之一,当然,他们又是由基本Pascal语法元素等更细微的粒子构成。
说TObject是DELPHI程序的原子,是因为TObject是DELPHI编译器内部支持的。所有的对象类都是从TObject派生的,即使你并未指定TObject为祖先类。TObject被定义在System单元,它是系统的一部分。在System.pas单元的开头,有这样的注释文本:
{ Predefined constants, types, procedures, }
{ and functions (such as True, Integer, or }
{ Writeln) do not have actual declarations.}
{ Instead they are built into the compiler }
{ and are treated as if they were declared }
{ at the beginning of the System unit. }
它的意思说,这一单元包含预定义的常量、类型、过程和函数(诸如:Ture、Integer或Writeln),它们并没有实际的声明,而是编译器内置的,并在编译的开始就被认为是已经声明的定义。你可以将Classes.pas或Windows.pas等其他源程序文件加入你的项目文件中进行编译和调试其源代码,但你绝对无法将System.pas源程序文件加入到你的项目文件中进行编译!DELPHI将报告重复定义System的编译错误!
因此,TObject是编译器内部提供的定义,对于我们使用DELPHI开发程序的人来说,TObject是原子性的东西。
TObject在System单元中的定义是这样的:
TObject = class
constructor Create;
procedure Free;
class function InitInstance(Instance: Pointer): TObject;
procedure CleanupInstance;
function ClassType: TClass;
class function ClassName: ShortString;
class function ClassNameIs(const Name: string): Boolean;
class function ClassParent: TClass;
class function ClassInfo: Pointer;
class function InstanceSize: Longint;
class function InheritsFrom(AClass: TClass): Boolean;
class function MethodAddress(const Name: ShortString): Pointer;
class function MethodName(Address: Pointer): ShortString;
function FieldAddress(const Name: ShortString): Pointer;
function GetInterface(const IID: TGUID; out Obj): Boolean;
class function GetInterfaceEntry(const IID: TGUID): PInterfaceEntry;
class function GetInterfaceTable: PInterfaceTable;
function SafeCallException(ExceptObject: TObject;
ExceptAddr: Pointer): HResult; virtual;
procedure AfterConstruction; virtual;
procedure BeforeDestruction; virtual;
procedure Dispatch(var Message); virtual;
procedure DefaultHandler(var Message); virtual;
class function NewInstance: TObject; virtual;
procedure FreeInstance; virtual;
destructor Destroy; virtual;
end;
下面,我们将逐步敲开TObject原子的大门,看看里面到底是什么结构。
我们知道,TObject是所有对象的基本类,那么,一个对象到底是什么?
DELPHI中的任何对象都是一个指针,这个指针指明该对象在内存中所占据的一块空间!虽然,对象是一个指针,可是我们引用对象的成员时却不用写成这样的代码MyObject^.GetName,而只能写成MyObject.GetName,这是Object Pascal语言扩充的语法,是由编译器支持的。使用C++ Builder的朋友就很清楚对象与指针的关系,因为在C++ Builder的对象都要定义为指针。对象指针指向的地方就是对象存储数据的对象空间,我们来分析一下对象指针指向的内存空间的数据结构。
对象空间的头4个字节是指向该对象类的虚方法地址表(VMT – Vritual Method Table)。接下来的空间就是存储对象本身成员数据的空间,并按从该对象最原始祖先类的数据成员到该对象类的数据成员的总顺序,和每一级类中数据成员的定义顺序存储。
类的虚方法地址表(VMT)保存从该类的原始祖先类派生到该类的所有类的虚方法的过程地址。类的虚方法,就是用保留字vritual声明的方法,虚方法是实现对象多态性的基本机制。虽然,用保留字dynamic声明的动态方法也可实现对象的多态性,但这样的方法不保存在虚方法地址表(VMT)中,它只是Object Pascal提供的另一种可节约类存储空间的多态实现机制,但却是以牺牲调用速度为代价的。
即使,我们自己并未定义任何类的虚方法,但该类的对象仍然存在指向虚方法地址表的指针,只是地址项的长度为零。可是,在TObject中定义的那些虚方法,如Destroy、FreeInstance等等,又存储在什么地方呢?原来,他们的方法地址存储在相对VMT指针负方向偏移的空间中。其实,在VMT表的负方向偏移76个字节的数据空间是对象类的系统数据结构,这些数据结构是与编译器相关的,并且在将来的DELPHI版本中有可能被改变。
因此,你可以认为,VMT是一个从负偏移地址空间开始的数据结构,负偏移数据区是VMT的系统数据区,VMT的正偏移数据是用户数据区(自定义的虚方法地址表)。TObject中定义的有关类信息或对象运行时刻信息的函数和过程,一般都与VMT的系统数据有关。
一个VMT数据就代表一个类,其实VMT就是类!在Object Pascal中我们用TObject、TComponent等等标识符表示类,它们在DELPHI的内部实现为各自的VMT数据。而用class of保留字定义的类的类型,实际就是指向相关VMT数据的指针。
对我们的应用程序来说,VMT数据是静态的数据,当编译器编译完成我们的应用程序之后,这些数据信息已经确定并已初始化。我们编写的程序语句可访问VMT相关的信息,获得诸如对象的尺寸、类名或运行时刻的属性资料等等信息,或者调用虚方法或读取方法的名称与地址等等操作。
当一个对象产生时,系统会为该对象分配一块内存空间,并将该对象与相关的类联系起来,于是,在为对象分配的数据空间中的头4个字节,就成为指向类VMT数据的指针。
我们再来看看对象是怎样诞生和灭亡的。看着我三岁的儿子在草地上活蹦乱跳,正是由于亲眼目睹过生命的诞生过程,我才能真真体会到生命的意义和伟大。也只有那些经历过死别的人,才会更加理解和珍惜生命。那么,就让我们理解一下对象的产生和消亡的过程吧!
我们都知道,用下面的语句可以构造一个最简单对象:
AnObject := TObject.Create;
编译器将其编译实现为:
用TObject对应的VMT为依据,调用TObject的Create构造函数。而在Create构造函数调用了系统的ClassCreate过程,系统的ClassCreate过程又通过存储在类VMT调用NewInstance虚方法。调用NewInstance方法的目的是要建立对象的实例空间,因为我们没有重载该方法,所以,它就是TObject类的NewInstance。TObjec类的NewInstance方法将根据编译器在VMT表中初始化的对象实例尺寸(InstanceSize),调用GetMem过程为该对象分配内存,然后调用InitInstance方法将分配的空间初始化。InitInstance方法首先将对象空间的头4个字节初始化为指向对象类对应VMT的指针,然后将其余的空间清零。建立对象实例之后,还调用了一个虚方法AfterConstruction。最后,将对象实例数据的地址指针保存到AnObject变量中,这样,AnObject对象就诞生了。
同样,用下面的语句可以消灭一个对象:
AnObject.Destroy;
TObject的析构函数Destroy被声明为虚方法,它也是系统固有的虚方法之一。Destory方法首先调用了BeforeDestruction虚方法,然后调用系统的ClassDestroy过程。ClassDestory过程又通过类VMT调用FreeInstance虚方法,由FreeInstance方法调用FreeMem过程释放对象的内存空间。就这样,一个对象就在系统中消失。
对象的析构过程比对象的构造过程简单,就好像生命的诞生是一个漫长的孕育过程,而死亡却相对的短暂,这似乎是一种必然的规律。
在对象的构造和析构过程中,调用了NewInstance和FreeInstance两个虚函数,来创建和释放对象实例的内存空间。之所以将这两个函数声明为虚函数,是为了能让用户在编写需要用户自己管理内存的特殊对象类时(如在一些特殊的工业控制程序中),有扩展的空间。
而将AfterConstruction和BeforeDestruction声明为虚函数,也是为了将来派生的类在产生对象之后,有机会让新诞生的对象呼吸第一口新鲜空气,而在对象消亡之前可以允许对象完成善后事宜,这都是合情合理的事。其实,TForm对象和TDataModule对象的OnCreate事件和OnDestroy事件,就是在TForm和TDataModule重载的这两个虚函数过程分别触发的。
此外,TObjec还提供了一个Free方法,它不是虚方法,它是为了那些搞不清对象是否为空(nil)的情况下能安全释放对象而专门提供的。其实,搞不清对象是否为空,本身就有程序逻辑不清晰的问题。不过,任何人都不是完美的,都可能犯错,使用Free能避免偶然的错误也是件好事。然而,编写正确的程序不能一味依靠这样的解决方法,还是应该以保证程序的逻辑正确性为编程的第一目标!
有兴趣的朋友可以读一读System单元的原代码,其中,大量的代码是用汇编语言书写的。细心的朋友可以发现,TObject的构造函数Create和析构函数Destory竟然没有写任何代码,其实,在调试状态下通过Debug的CPU窗口,可清楚地反映出Create和Destory的汇编代码。因为,缔造DELPHI的大师门不想将过多复杂的东西提供给用户,他们希望用户在简单的概念上编写应用程序,将复杂的工作隐藏在系统的内部由他们承担。所以,在发布System.pas单元时特别将这两个函数的代码去掉,让用户认为TObject是万物之源,用户派生的类完全从虚无中开始,这本身并没有错。虽然,阅读DELPHI的这些最本质的代码需要少量的汇编语言知识,但阅读这样的代码,可以让我们更深刻认识DELPHI世界的起源和发展的基本规律。即使看不太懂,能起码了解一些基本东西,对我们编写DELPHI程序也是大有帮助。
第二节 TClass原子
在System.pas单元中,TClass是这样定义的:
TClass = class of TObject;
它的意思是说,TClass是TObject的类。因为TObject本身就是一个类,所以TClass就是所谓的类的类。
从概念上说,TClass是类的类型,即,类之类。但是,我们知道DELPHI的一个类,代表着一项VMT数据。因此,类之类可以认为是为VMT数据项定义的类型,其实,它就是一个指向VMT数据的指针类型!
在以前传统的C++语言中,是不能定义类的类型的。对象一旦编译就固定下来,类的结构信息已经转化为绝对的机器代码,在内存中将不存在完整的类信息。一些较高级的面向对象语言才可支持对类信息的动态访问和调用,但往往需要一套复杂的内部解释机制和较多的系统资源。而DELPHI的Object Pascal语言吸收了一些高级面向对象语言的优秀特征,又保留可将程序直接编译成机器代码的传统优点,比较完美地解决了高级功能与程序效率的问题。
正是由于DELPHI在应用程序中保留了完整的类信息,才能提供诸如as和is等在运行时刻转换和判别类的高级面向对象功能,而类的VMT数据在其中起了关键性的核心作用。有兴趣的朋友可以读一读System单元的AsClass和IsClass两个汇编过程,他们是as和is操作符的实现代码,以加深对类和VMT数据的理解。
第二节 TClass原子
在System.pas单元中,TClass是这样定义的:
TClass = class of TObject;
它的意思是说,TClass是TObject的类。因为TObject本身就是一个类,所以TClass就是所谓的类的类。
从概念上说,TClass是类的类型,即,类之类。但是,我们知道DELPHI的一个类,代表着一项VMT数据。因此,类之类可以认为是为VMT数据项定义的类型,其实,它就是一个指向VMT数据的指针类型!
在以前传统的C++语言中,是不能定义类的类型的。对象一旦编译就固定下来,类的结构信息已经转化为绝对的机器代码,在内存中将不存在完整的类信息。一些较高级的面向对象语言才可支持对类信息的动态访问和调用,但往往需要一套复杂的内部解释机制和较多的系统资源。而DELPHI的Object Pascal语言吸收了一些高级面向对象语言的优秀特征,又保留可将程序直接编译成机器代码的传统优点,比较完美地解决了高级功能与程序效率的问题。
正是由于DELPHI在应用程序中保留了完整的类信息,才能提供诸如as和is等在运行时刻转换和判别类的高级面向对象功能,而类的VMT数据在其中起了关键性的核心作用。有兴趣的朋友可以读一读System单元的AsClass和IsClass两个汇编过程,他们是as和is操作符的实现代码,以加深对类和VMT数据的理解。
有了`类的类型,就可以将类作为变量来使用。可以将类的变量理解为一种特殊的对象,你可以象访问对象那样访问类变量的方法。例如:我们来看看下面的程序片段:
type
TSampleClass = class of TSampleObject;
TSampleObject = class( TObject )
public
constructor Create;
destructor Destroy; override;
class function GetSampleObjectCount:Integer;
procedure GetObjectIndex:Integer;
end;
var
aSampleClass : TSampleClass;
aClass : TClass;
在这段代码中,我们定义了一个类TSampleObject及其相关的类类型TSampleClass,还包括两个类变量aSampleClass和aClass。此外,我们还为TSampleObject类定义了构造函数、析构函数、一个类方法GetSampleObjectCount和一个对象方法GetObjectIndex。
首先,我们来理解一下类变量aSampleClass和aClass的含义。
显然,你可以将TSampleObject和TObject当作常量值,并可将它们赋值给aClass变量,就好象将123常量值赋值给整数变量i一样。所以,类类型、类和类变量的关系就是类型、常量和变量的关系,只不过是在类的这个层次上而不是对象层次上的关系。当然,直接将TObject赋值给aSampleClass是不合法的,因为aSampleClass是TObject派生类TSampleObject的类变量,而TObject并不包含与TSampleClass类型兼容的所有定义。相反,将TSampleObject赋值给aClass变量却是合法的,因为TSampleObject是TObject的派生类,是和TClass类型兼容的。这与对象变量的赋值和类型匹配关系完全相似。
然后,我们再来看看什么是类方法。
所谓类方法,就是指在类的层次上调用的方法,如上面所定义的GetSampleObjectCount方法,它是用保留字class声明的方法。类方法是不同于在对象层次上调用的对象方法的,对象方法已经为我们所熟悉,而类方法总是在访问和控制所有类对象的共同特性和集中管理对象这一个层次上使用的。在TObject的定义中,我们可以发现大量的类方法,如ClassName、ClassInfo和NewInstance等等。其中,NewInstance还被定义为virtual的,即虚的类方法。这意味作你可以在派生的子类中重新编写NewInstance的实现方法,以便用特殊的方式构造该类的对象实例。
在类方法中你也可使用self这一标识符,不过其所代表的含义与对象方法中的self是不同的。类方法中的self表示的是自身的类,即指向VMT的指针,而对象方法中的self表示的是对象本身,即指向对象数据空间的指针。虽然,类方法只能在类层次上使用,但你仍可通过一个对象去调用类方法。例如,可以通过语句aObject.ClassName调用对象TObject的类方法ClassName,因为对象指针所指向的对象数据空间中的头4个字节又是指向类VMT的指针。相反,你不可能在类层次上调用对象方法,象TObject.Free的语句一定是非法的。
值得注意的是,构造函数是类方法,而析构函数是对象方法!
什么?构造函数是类方法,析构函数是对象方法!有没有搞错?
你看看,当你创建对象时分明使用的是类似于下面的语句:
aObject := TObject.Create;
分明是调用类TObject的Create方法。而删除对象时却用的下面的语句:
aObject.Destroy;
即使使用Free方法释放对象,也是间接调用了对象的Destroy方法。
原因很简单,在构造对象之前,对象还不存在,只存在类,创建对象只能用类方法。相反,删除对象一定是删除已经存在的对象,是对象被释放,而不是类被释放。
最后,顺便讨论一下虚构造函数的问题。
在传统的C++语言中,可以实现虚析构函数,但实现虚构造函数却是一个难题。因为,在传统的C++语言中,没有类的类型。全局对象的实例是在编译时就存在于全局数据空间中,函数的局部对象也是编译时就在堆栈空间中映射的实例,即使是动态创建的对象,也是用new操作符按固定的类结构在堆空间中分配的实例,而构造函数只是一个对已产生的对象实例进行初始化的对象方法而已。传统C++语言没有真正的类方法,即使可以定义所谓静态的基于类的方法,其最终也被实现为一种特殊的全局函数,更不用说虚拟的类方法,虚方法只能针对具体的对象实例有效。因此,传统的C++语言认为,在具体的对象实例产生之前,却要根据即将产生的对象构造对象本身,这是不可能的。的确不可能,因为这会在逻辑上产生自相矛盾的悖论!
然而,正是由于在DELPHI中有动态的类的类型信息,有真正虚拟的类方法,以及构造函数是基于类实现的等等这些关键概念,才可实现虚拟的构造函数。对象是由类产生的,对象就好象成长中的婴儿,而类就是它的母亲,婴儿自己的确不知道自己将来会成为什么样的人,可是母亲们却用各自的教育方法培养出不同的人,道理是相通的。
正是在TComponent类的定义中,构造函数Create被定义为虚拟的,才能使不同类型的控件实现各自的构造方法。这就是TClass创造的类之类概念的伟大,也是DELPHI的伟大。
......................................
第三章 WIN32的时空观
我的老父亲看着地上玩玩具的小孙子,然后对我说:“这孩子和小时的你一样,喜欢把东西拆开,看过究竟才罢手”。想想我小时侯,经常将玩具车、小闹钟、音乐盒,等等,拆得一塌糊涂,常常被母亲训斥。
我第一次理解计算机的基本原理,与我拆过的音乐盒有关。那是在念高中时的一本漫画书上,一位白胡子老头在讲解智能机的理论,一位留八字胡的叔叔在说计算机和音乐盒。他们说,计算机的中央处理器就是音乐盒中用来发音的那一排音乐簧片,计算机程序就是音乐盒中那个小圆筒上密布的凸点,小圆筒的转动相当于中央处理器的指令指针的自然移动,而小圆筒上代表音乐的凸点控制音乐簧片振动发音相当于中央处理器执行程序的指令。音乐盒发出美妙的旋律,是按工匠早已刻在小圆筒上的音乐谱演奏的,计算机完成复杂的处理,是根据程序员预先编制好的程序实现的。上大学之后,我才知道那个白胡子老头就是科学巨匠图灵,他的有限自动机理论推动了整个信息革命的发展,而那个留八字胡的叔叔就是计算机之父冯.诺依曼,冯氏计算机体系结构至今仍然是计算机的主要体系机构。音乐盒没白拆,母亲可以宽心。
有深入浅出的理解,才能有高深而又简洁的创造。
这一章我们将讨论Windows的32位操作系统中与我们编程有关的基本概念,建立WIN32中正确的时空观。希望阅读完本章之后,我们能更加深入地理解程序、进程和线程,理解执行文件、动态连接库和运行包的原理,看清全局数据、局部数据和参数在内存中的真相。
第一节 理解进程
由于历史的原因,Windows是起源于DOS。而在DOS时代,我们一直只有程序的概念,而没有进程的概念。那时侯,只有操作系统的正规军,如UNIX和VMS等等,才有进程的概念,而且多进程就意味着小型机、终端和多用户,也意味着金钱。我绝大多数的时间只能使用相对廉价的微机和DOS系统,只是在学操作系统这门课程时才开始接触进程和小型机。
在Windows 3.X之后,Microsoft才在图形界面的操作系统站住脚跟,而我也是在这时开始正式面对多任务和进程的概念。以前在DOS下,同一时间只能执行一个程序,而在Windows下同一时间可执行多个程序,这就是多任务。在DOS下运行一个程序的同时,不能执行相同的程序,而在Windows下,同一程序可以同时有两个以上的副本在运行,每一个运行的程序副本就是一个进程。更确切地说,任何程序的一次运行就产生一个任务,而每个任务就是一个进程。
当将程序和进程放到一起理解时,可以认为程序一词说的是静态的东西,一个典型的程序是由一个EXE文件或一个EXE文件加上若干DLL文件组成的静态代码和数据。而进程是程序的一次运行,是在内存中动态运行的代码和动态变化的数据。当静态的程序要求运行时,操作系统将为本次运行提供一定的内存空间,把静态的程序代码和数据调入这些内存空间,将程序的代码和数据进行重定位映射之后,就在该空间内执行程序,这样就产生了动态的进程。
同一个程序同时运行着的两个副本,意味着在系统内存中有两个进程空间,只不过它们的程序功能是一样的,但处于不同的动态变化的状态之中。
从进程运行的时间上来说,各进程是同时执行的,专业术语称为并行执行或并发执行。但这主要是操作系统给我们的表面感觉,实际上各进程是分时执行的,也就是各进程轮流占用CPU的时间来执行进程的程序指令。对于一个CPU来说,同一时间只有一个进程的指令在执行。操作系统是调度进程运行的幕后操纵者,它不断保存和切换各进程在CPU中执行的当前状态,使得每一个被调度的进程都认为自己是完整和连续地运行着。由于进程分时调度的速度非常快,所以给我们的感觉就是进程都是同时运行的。其实,真正意义上的同时运行只有在多CPU的硬件环境中才有。稍后在讲述线程一节时,我们将发现,真正推动进程运转的是线程,进程更重要的是提供了进程空间。
从进程占据的空间上来说,各进程空间是相对独立的,每一个进程在自己独立的空间中运行。一个程序既包括代码空间又包括数据空间,代码和数据都要占据进程空间。Windows为每一进程所需的数据空间分配实际的内存,而对代码空间一般都采用共享手段,将一个程序的一份代码映射给该程序的多个进程。这意味着,如果一个程序有100K的代码并需要100K的数据空间,也就是总共需要200K的进程空间,则第一次运行程序时操作系统将分配200K的进程空间,而运行程序的第二个进程时,操作系统只分配100K的数据空间,而代码空间则共享前一个进程的空间。
上面所说的是Windows操作系统中进程的基本时空观,其实Windows的16位和32位操作系统在进程的时空观上有很大的差异。
从时间上来说,16位的Windows操作系统,如Windows 3.x等,进程管理是非常简单的,它实际上只是一个多任务管理操作系统。而且,操作系统对任务的调度是被动的,如果一个任务不自己放弃对消息的处理,操作系统就必须等待。由于16位Windows系统在管理进程方面的缺陷,一个进程运行时,完全占有着CPU的资源。在那个年代,为了16位Windows可以有机会调度别的任务,微软公司大力赞扬开发Windows应用程序的开发者是心胸宽阔的程序员,以使得他们乐意多编写几行恩赐给操作系统的代码。相反,WIN32的操作系统,如Windows 95和NT等,才是具备了真正的多进程和多任务操作系统的能力。WIN32中的进程完全由操作系统调度,一旦进程运行的时间片结束,不管进程是否还在处理数据,操作系统将主动切换到下一进程。严格地说,16位的Windows操作系统不能算是完整的操作系统,而32位的WIN32操作系统才是真正意义上的操作系统。当然,微软公司不会说WIN32弥补了16位Windows的缺陷,而是宣称WIN32实现了一种称为“抢占式多任务”的先进技术,这是商业手段。
从空间上看,16位的Windows操作系统中的进程空间虽然相对独立,但进程之间可已很容易地互相访问对方的数据空间。因为,这些进程实际是在相同的物理空间中的不同的数据段而已,而且不当的地址操作很容易造成错误的空间读写,并使操作系统崩溃。然而,在WIN32操作系统中,各进程空间完全是独立的。WIN32为每一个进程提供一个可达4G的虚拟的,并且是连续的地址空间。所谓连续的地址空间,是指每一个进程都拥有从$00000000到$FFFFFFFF的地址空间,而不是向16位Windows的分段式空间。在WIN32中,你完全不必担心自己的读写操作会无意地影响到其他进程空间中的数据,也不用担心别的进程会来骚扰你的工作。同时,WIN32为你的进程提供的连续的4G虚拟空间,是操作系统在硬件的支持下将物理内存映射给你的,你虽然拥有如此广阔的虚拟空间,但系统决不会浪费一个字节的物理内存。
第二节 进程空间
在我们用DELPHI编写WIN32的应用程序时,很少去关心进程在运行时的内部世界。因为WIN32为我们的进程提供了4G的连续虚拟进程空间,可能目前世界上最庞大的应用程序也只用到了其中的部分空间。似乎进程空间是无限的,但4G的进程空间是虚拟的,而你机器的实际内存可能与此相差甚远。虽然,进程拥有如此广阔的空间,但有些复杂算法的程序还是会因为堆栈溢出而无法运行,特别是含有大量递归算法的程序。
因此,深入地认识和了解这4G的进程空间的结构,以及它与物理内存的关系等等,将有助于我们更清楚地认识WIN32的时空世界,从而可在实际的开发工作中运用正确的世界观和方法论解决各种难题。
下面,我们将通过简单的实验,来了解WIN32的进程空间的内部世界。这可能需要一些对CUP寄存器和汇编语言的知识,但我尽量用简单的语言来说明。
当启动DELPHI时,将自动产生一个Project1的项目,我们就拿它开刀。在Project1.dpr原程序的任意位置设一断点,比如,就在begin一句处设一断点。然后运行程序,当程序运行到断点时会自动停下来。这时,我们就可以打开调试工具中的CPU窗口来观察进程空间的内部结构了。
当前的指令指针寄存器EIP是停在$0043E4B8,从程序指令所在地址的最高两位16进制数都是零,可以看出当前的程序处在4G进程空间相当底端的地址位置,其占据$00000000到$FFFFFFFF的相当少的地址空间。
在CPU窗口中的指令框中,你可以向上查看进程空间中的内容。当查看小于$00400000的空间内容时,你会发现小于$00400000的内容出现一串串的问号“????”,那是因为该地址空间还未映射到实际物理空间的缘故。如果在这时,你查看一下全局变量HInstance的16进制值就会发现它也是$00400000。虽然HInstance反映的是进程实例的句柄,其实,它就是程序被加载到内存中的起始地址值,在16位Windows中也是如此。因此,我们可以认为进程的程序是从$00400000开始加载的,也就是从4G虚拟空间中的4M以后的空间开始是程序加载的空间。
从$00400000往后,到$0044D000之前,主要是程序代码和全局数据的地址空间。在CPU窗口中的堆栈框中,可以查看到当前堆栈的地址。同样,你会发现当前堆栈的地址空间是从$0067B000到$00680000的,长度为$5000。其实,进程最小的堆栈空间大小就是$5000,它是根据编译DELPHI程序时在Project\Options中Linker页中设置的Min stack size值,加上$1000而得到的。堆栈是由高端地址向底端增长的,当程序运行的堆栈不够时,系统将自动向地端地址方向增加堆栈空间的大小,这一过程将把更多的实际内存映射到进程空间。可在编译DELPHI程序时,通过设置Project\Options中Linker页中Max stack size的值,控制可增加的最大堆栈空间。特别是在含有深层次的子程序调用关系或运用递归算法的程序中,一定要合理地设置Max stack size的值。因为,调用子程序是需要耗用堆栈空间,而堆栈耗尽之后,系统就会抛出“Stack overflow”的错误。
似乎,从堆栈空间之后的进程空间就应该是自由的空间了吧。其实不然,WIN32的有关资料说,$80000000之后的2G空间是系统使用的空间。看来,进程能够真正拥有的只有2G空间。其实,进程能真正拥有的空间连2G都不够,因为从$00000000到$00400000的这4M空间也是禁区。
但不管怎样,我们的进程可以使用的地址还是非常广阔的。特别是堆栈空间之后到$80000000之间,是进程空间的主战场。进程从系统分配的内存空间将被映射到这块空间,进程加载的动态连接库将被映射到这块空间,新建线程的线程堆栈空间也将映射到这块空间,几乎所有涉及分配内存的操作都将映射到这块空间。请注意,这里所说的映射,意味着实际内存与这块虚拟空间的对应,没有映射为实际内存的进程空间是无法使用的,就象调试时CPU窗口指令框中的那一串串的“????”。
2006-12-3 22:02
蓝色虫
Delphi第三方控件大比拼
众所周知,Delphi提供了大量的组件,使用这些组件基本上已能满足我们的编程需求。但是在对于有特定要求的程序,仅仅使用Delphi自带的组件就无法适应了。例如,Delphi没有提供串口通信组件(反正我是没有找到),编写有关串口通信的程序就需要使用API函数来实现串口通信,比较麻烦。另外,Delphi自带的一些组件功能比较简单,很难满足我们一些特定的要求。值得庆幸的是,现在有很多的第三方组件,这些组件功能强劲,而且覆盖了编程的方方面面,极大的方便了我们。使用这些第三方组件往往达到事半功倍的效果,大大提高编程的效率。同时还能使我们的程序更漂亮、更专业、更强大。所以第三组件是我们使用Delphi编程一大法宝。
第三方组件往往是Delphi自带组件的扩展,是在Delphi自带组件的基础上加强功能,并进行功能细化和专业化。例如,有些第三方组件把按钮、标签细化为很多种,每一种实现一种特定的功能。另外一些第三组件是Delphi中没有的,这些组件往往是根据编程时常遇到的需求,将一些常用的方法、函数以及API集成到这些组件中,编程时就不需要编写这些程序了。如TrayIcon、Specomm等。这些组件往往都特别有用。
第三组件从组成上分可分为单个组件和组件包。单个组件只有一个组件,这些组件一般都比较专业,往往功能也比较强大,如Specomm。组件包由多个组件组成,组件包又可分两种:一种是整套组件,它包含了各种各样的组件(可能有上百个),一般覆盖了Delphi编程的大部分领域,如AHM、Rxlib、ABC等,这些组件一般不会太专业,功能上主要是Delphi自带组件的扩展,不会太强大;另一种组件包组件较少,一般只有6、7个,往往只涉及一个方面,但是这些组件往往都很有特点,功能非常强大,在编程过程中十分有用,如CoolMenu、DragDrop、XlGrid等等。
从组件的使用领域来划分,第三方组件可分为:界面增强类、图形图像类、多媒体类、系统类、数据库类、网络类等等。
第三方组件一部分是个人编制的,这些组件往往是单个组件或小的组件包,它们的优良与编制者的水平密切相关。有些个人组件就非常好,很专业,有些就不是太强大。个人组件一般是共享的,而且是免费的。另一部分的组件,特别是组件包是由专门的组件商提供的,这些组件往往比较专业,性能比较稳定,这些组件有些是免费共享的,有些则是需要注册交费的。一般说来需要付费的组件(包)是企业级别的,功能特别强大。免费组件与之相比是有等级差别的。但是对于我们来说,这些免费组件(包)已是够用了。而且,我们还可以在网上找到付费的组件(包)的注册码或破解文件。
现在国内编制Delphi组件的个人或组织(开发商)较少,绝大部分的第三方组件(包)都是有国外提供的。但我们不需到这些国外站点去下载,国内有很多的Delphi站点都提供有Delphi组件下载。这里可以推荐几个:
Delphi大学(http://go.163.com/~xuguohua/index.html)
Delphi大师(http://go.163.com/~delphi6/)
崔卫的世界(http://go.163.com/~mycwcgr/)
现在的第三方组件很多,比较出名有:Rxlib2.75、AHM2000 for Delphi5、ABC5D、XlGrid1.62、CoolMenu1.5、DragDrog3.7等等。我们将后面对这些典型组件(包)进行介绍。
第三方组件都需要安装才能在Delphi中使用,各种组件的安装可能有较大的差异,有些很麻烦,有些却是全自动的。对于初学者,第三方组件的安装是一个很现实的问题,我们将在后面对第三方组件的安装进行详细的说明。
下面这篇文章是一位网友对多种第三方组(控)件的看法,英雄所见所略同,他的见解还是颇有见地的。但所谓智者见智,仁者见者,下面的红字是我的个人看法。
古人云∶“工欲善其事,必先利其器。” 这句话,我想凡是用Delphi的朋友,应该都有很深切的体会吧。的确,如果Delphi没有了控件的支持,那么人气度一定会大大的降低,不会有现在这样多的Fan了,俺也就改行用 BCB或VC了,呵呵。 但是,现在控件满天飞,不要说DSP(Delphi Super Page)了,光一个深度历险上面的控件就已经洋洋洒洒上万数了,而且每天还在更新,多恐怖啊∶) 然而,选择多了以后,烦恼也就随之而来了(呵呵,如果MM也能有那么多让我挑就好了),因为无法一个个的都去试过,所以有许多的优秀控件还不是为人所知,因此我就写下了这篇文章,希望能为大家当个向导,起到一个抛砖引玉的作用吧。好了,现在转入正题。
首先来大体上为控件分一下类,以方便我们后面的讨论。 但因为控件的种类太多,所以就粗略的分为如下几个类别∶
---界面风格类
---Shell外观类
---Editor类
---Grid类
---DB类
---Report类
---图形类
---综合类
(这里的分类不是很准确,也不够全面)
约定的前提是∶All FreeWare,All source.至于那些要花钱购买的商业控件,我将在后面另外进行讨论。对于文中我们所讨论的每一个控件,都会给出一个品质得分,商业控件和免费控件一视同仁,不以价格论高低,而以质量分高下。大体的评分标准如下:
一级棒的超cool控件: ★★★★★
也很不错的控件: ★★★★
虽一般但有特色的控件: ★★★
三颗星以下的控件就不在本文的讨论范围之内了。(☆表示★的效力减半)
◆首先,我们先来讨论一下免费的第三方控件(有源代码):
㈠界面风格类
一个优秀的软件应该具有一个优秀的操作界面,我想这应该是不容置疑的。但是用过C/C++写程序的朋友一定会有这样的感叹,作一个美观而又容易上手的界面实在太累了(除了BCB外)。但自从Delphi横空出世之后,这一切就豁然改观了。 这里我先为大家推荐四套优秀的界面制作控件包。
1.FlatStyle2.1 品质:★★★★★
评测: 非常非常棒的界面控件包,什么叫Cool?用过了FaltStyle后,你就知道了:)在最新的2.1版中,FlatStyle作了很大的改动,不但新增了好几个控件,还对源码作了很大幅度的修改,更加有条理了.不过,还是有几个小bug,呵呵,但无伤大雅.AWater自己又在这个基础上,修订了一下,并增添了几个控件,使用的感觉只有一个字可以形容,呵呵,爽呀!强烈推荐!
(FlatStyle2.1确实是不错的一套不错的组件,顾名思义,它的一大特点是Flat效果,但要评为5星级组件似乎还差一点点,我在编程中用它就用得不多)
2.JLAqua1.0 品质:★★★★
评测: 这是一个类Mac OS界面的控件包,如果你对苹果那可人的界面情有独钟的话,这个东东是你最好的选择.绝对的抢眼.但由于是1.0版,AWater用了后觉的还是意犹未尽,好象还是少了点什么.不过已经很不错了呢,向您推荐.
3.Platinum Controls 品质:★★★☆
评测: 又是一个类Mac OS界面的控件包,和上面的JLAqua相比较的话,主要的不同点在于这个控件包所模拟的是一种较为经典的老式的Mac OS风格界面,而JLAqua则比较新潮一些,同时这个控件包所提供的控件种类也比较少,功能也较为单一。但是,还是颇有点特色的,值得推荐。
4.CoolForm 品质:★★★
评测: 第一次用这个家伙的时候,还真被它的名字给唬住了,后来仔细一看它的源码,才发现不过如此,其实就是一个作古里古怪的Form的东东而已,不过写得很简洁,功能也不俗,特别是他内带的属性编辑器,写得很有意思,可以根据你所提供的图片而自动的生成Mask图像。呵呵,还算不错的一个控件,用不用随你。
㈡Shell外观类
相信很多朋友在写程序时,并不满足Delphi提供的OpenDialog和SaveDialog吧,有时需要作一个类似资源管理器(Explorer)的东东,而Delphi提供的FileListBox和DirectoryListBox的却又太难看,太简陋。虽然Delphi提供了ShellApi.pas,但自己再从头写一个这样的Component却又太麻烦时,下面的这几个东东可以让你从多余的重复劳动中解放出来。
1.DFS TSystemTreeView v0.95 Beta 品质:★★★★☆
评测: 说起DFS,相信凡是用Delphi的老鸟,一定不会陌生。这个控件可以算得上是精品了,AWater也就不多嚼舌了,但由于是Beta版的缘故吧,还是有些不太稳定,偶尔会出错。所以就只打了四颗星,有点委屈它了呢,呵呵。向您推荐!
2.LsFileExplorer 2.7 品质:★★★☆
评测: 挺不错的一个控件包,唯一可惜的地方是其中的TLsDirTreeCombo部分有一个bug,就是当把TLsDirTreeCombo放在TCoolBar或TControlBar之上时,一旦width有变化,你就会发现TLsDirTreeCombo的ClickButton位置会有严重的错位。呵呵,本来AWater想给它打★★★★☆的,结果就一落千丈啦,满可惜的。如果这个bug能够修正的话,那就很不错了,不过话又说回来,毕竟是免费的吗。还是值得向您推荐。
㈢Editor类
有没有这样的感觉呢?Memo太简单,RichEdit不好用,版本也太乱,容易出问题。想不想拥有一个象Delphi自带的Editor一样的支持语法高亮,功能又强大的编辑控件呢?请看下面两个东东吧。
1.mwEdit 0.92a 品质:★★★★★
评测: 这个东东可是目前免费控件中的顶级之作,拥有商业控件般的强大功能,同时又开放源代码,可是广大的Delphi程序员的福气呦!有了它,您也能够轻松的写出像Delphi自带的Editor一样的编辑器来,它除了支持Pascal语法的特殊高亮显示之外,还能够支持其它十多种的语法高亮显示。最妙的是,mwEdit居然还能够和数据库连接起来, 呵呵。实在是太强大了,向您强烈推荐!
2.unicode edit 1.0 品质:★★★★☆
评测: 这个控件是著名的JEDI项目之一,大体上和mwEdit相似,不过功能还没有它那么强大,但也已经很不错了。特点是内建了超过一百个unicode(WideString)的函数,是不是很恐怖呀?呵呵,向您推荐!
㈣Grid类
在现实中的很多数据组织方式非常适合用Grid来表示,尤其是在一个数据量大,信息繁杂的系统中,如果没有Grid control,那将是无法想像的。然而Delphi自带的Grid,不管是StringGrid,还是DrawGrid,或DBGrid,都还嫌不够强大。下面的几个Grid控件也许会让你感到兴奋的。
1.TStringAlignGrid 2.0 品质:★★★★
评测: 这个控件虽然是个免费的东东,但是可以看出作者还是很用心的。功能不能说非常强大,但却够用,只要你不是做什么特别的东西,这个控件绝对是你最好的选择。而且附带了一份详细的help文件,值得推荐。
㈤DB类
这方面好像没有什么特别突出的免费控件,挑来捡去的,就只找到这一个,呵呵。
1.TkbmMEMTABLE v. 2.33 品质:★★★★
评测: 一个不错的内存表控件。如果你正急需这方面的控件的话,就试试吧。值得推荐。
㈥Report类
说到报表,许多朋友的心里一定会翻涌起种莫名的滋味吧。在品尝过QuickReport带来的尴尬之后,寻找一个优秀的,功能出众的报表控件就一直是我们孜孜以求的,下面为大家推荐两个非常优秀的报表控件,而且还都是我们国人自己开发的,呵呵,掌声欢迎:
1.eReport 品质:★★★★☆
评测: 非常优秀的报表控件,完全为了中国的报表格式所设计,同时内带一个报表编辑器,工作模式类似于套打,本来用QuickReport需要干一个月的活,用eReport三天就可以搞定了,呵呵。不过,需要指出的是,eReport现在还不能支持报表嵌套,这不能不说是一种遗憾。(居作者王寒松自己说,报表嵌套的部分本来是已经写好了的,可惜不当心给搞丢了,后来也就一直没有写下去了。呜呜呜呜......)
2.rmachine 品质:★★★★
评测: 说起这个东东,可能知道的人并不是很多。但说起FastReport,相信大家应该都有所耳闻吧。这个控件就是在著名的FastReport的基础上发展起来的,修正了一些Bug,增强了许多功能。挺不错的,呵呵。推荐!
㈦图形类 -------- 应该说图形类控件范围太大,从一般的Image到Chart,还有各种各样的Effect.内容实在太多太广,我就简单的挑几个最有特色的介绍个大家吧。
1.FastLib 品质:★★★★★
评测: 非常非常优秀的图形库,提供了大量的图形处理函数,功能之强大甚至连一些商业控件都自愧不如。用它作出的各种的图形特效,呵呵,只能说一个绝字。向您强烈推荐!
2.GLScene(OpenGL Component) 品质:★★★★☆
评测: 有没有试过这样写OpenGL程序:选一个模型,然后为它添加灯光,纹理。实时调整大小,位置。不满意?就换一个模型,重来一次。一切好像不是在写程序,而好像在3DSMax中现场编辑的感觉一样。怎么样,奇妙吧,还不快去试试。呵呵,向您强烈推荐!
3.TPicShow v2.3 品质:★★★★☆
评测: 这个小东东,提供了一百二十二种的图形特效,而且效率也不错。剩去了你的大量查书,编码的时间,快来试试吧,给你的程序里的图形加上些切换特效,让你的用户啧啧称赞你的程序界面。呵呵,向您强烈推荐!
(最适合于初学者的图像组件)
㈧综合类
综合类的控件包,就是指那些囊括了各种类型的控件的大杂烩,下面为大家列举几个免费控件中优秀的综合类控件包:
1.RxLib 2.75 品质:★★★★☆
评测: 说起这个家伙,大家应该早巳如雷贯耳了吧?呵呵,所以AWater就不多说了,可别告诉我说你还不知道,向您强烈推荐!
(将RxLib评为5星级亦不为过)
2.RALib 1.52a 品质:★★★★★
评测: 这个东东和RxLib虽然名字差了一个字,但功能却比RxLib还要强,只不过在国内的知名度没有RxLib那么响罢了,去试试吧,保证你会惊喜万分的。向您强烈推荐!
3.DevExpress Forum Library 2.0 品质:★★★★☆
这个控件包是著名的Delphi控件厂商Developer Express出品的一套免费且有源代码的扩件包。秉承Developer Express的一贯风格,这个控件包处处透露出一股“贵族”的味道,其中包含了许多的优秀控件,给人的感觉可一点都不像是免费的控件,如果你看一下它的源码,更有这种感觉,条理清晰,结构合理。不愧是名家出手。呵呵。不过 ,这么好的东东也不是随便就能得到的,首先得参加Developer Express的Forum,在他们那儿注册之后(当然是免费的),才可以得到。快去注册吧。强烈推荐!
下一节将介绍商业控件的情况。
好了,看过了上一节的一些免费的第三方控件之后,下面让我们来看一下商业控件的情形吧,我们同样也把商业控件分成8个类别,进行一下评测,来和前面推荐的免费的控件来比一比看,到底是谁利害,商业控件可不一定能全占优呢! 商业控件(可是要花钱去买的哟):
㈠界面风格类
1.DevExpress Bars 3.1 品质:★★★★★
评测: 是由著名的Delphi控件厂商Developer Express出品的类Word2000界面的控件组。功能之强大,界面之华丽,呵呵,简直是一言难尽呀。我甚至都有些怀疑Dephi的菜单和工具栏就是用这个东东作的。实在太cool了,相比之下,免费的ToolBar97,简直就成了鸡胁,食之无味啊。呵呵,如果你想作出一个精美的流行界面,这是你最好的选择, 而且也能剩下你的大量重复劳动时间。强烈推荐!!!
(DevExpress Bars 3.1确实是一套很Cool的组件)
2.ExtarPack 1.5 品质:★★★★★
评测: 如果你想把自已的程序界面作很另类的话,这个东东就是最好的选择了,呵呵。可以把你的程序武装到牙齿,如果别人不知到的话,肯定以为你再用一个什么的新式操作系统呢。呵呵,想给别人一个惊喜吗,就用ExtarPack吧。会让你满意的很。不过,我可要事先提醒你,这个东东的耗费系统资源量也不小哟。强烈推荐!
3.FormContainer 1.5 品质:★★★★★
评测:你不会没用过Delphi自带的TeeChart吧,这个东东就是出TeeChart的那个公司的两个程序员写的,质量吗,呵呵,一级棒的呢。绝对不给TeeChart丢脸。知道一个人为什么会在电脑面前傻傻的发呆吗?多半是看到了用FormContainer写的程序了。呵呵。真的绝了,绝对经典的界面风格,让你意想不到的一种惊喜。AWater很配服能写出这个控件的程序员,非常了不起。可惜搞不到源码,不然一定要好好研究一下。向您强烈推荐!!
㈡Shell外观类
1.Shell Control Pack VCL v1.5 品质:★★★★★
评测: 关于这个控件,AWater也就不想多费话了。只想说一句:用着的感觉就好像在用资源管理器(Explorer)一样。呵呵,非常非常的棒。向您强烈推荐!!
㈢Editor类
1.Dream Memo 3.1 品质:★★★★☆
评测: 著名的Delphi控件厂商“梦之队”Dream Company出品的强大的编辑控件。应该说各方面都非常优秀。至少在AWater没有使用mwEdit之前一至认为它是最好的,现在吗,嘿嘿,最好的当然就论不到它了。不过,的确非常强大,可惜这个东东写的太庞杂。所以吗,Bug也比较多。但还是值得向您推荐的。
2.PlusMemo 5.2 品质:★★★★☆
评测: 这个控件可是元老了,功能强大。很有特色。很有自已的风格,也支持数据感应。而且作的也很小巧。非常不错。向您强烈推荐!!
㈣Grid类
1.DevExpress ExpressQuantumGrid 2.1 品质:★★★★★
评测: 又是由著名的Delphi控件厂商Developer Express出品的超级Grid控件。主要应用于数据库的操作使用方面。功能强悍,有许多的“独门武功”。呵呵,如果借用围棋的段位来评分的话,这个控件的水平恐怕还在九段之上。堪称超一流。就算是同样的商业控件中,在操作数据库方面,比ExpressQuantumGrid强的恐怕还没生出来。如果再配上同门所出的dxTreeList,dxPrintSystem,可真的是打遍天下无敌手了。而且是百分之一百的纯VCL写成的。是不是COOL呆了,呵呵。向您强烈推荐!!!!!
2.TopGrid 2.01 品质:★★★★★
评测: 这个控件虽然在操作数据库功能方面没有像前面的DevExpress ExpressQuantumGrid那样犀利。但它却适应面很广,可以胜任StringGrid,DrawGrid,DBGrid的所有工作,不像ExpressQuantumGrid只适用于数据库操作。而且TopGrid的界面非常的Cool,有点像PowerBuild里的DataWindow的感觉,而且是更加美观。功能十分灵活,可以非常方便的操作Grid中的每一个Cell,唯一的缺点是编译出来的EXE文件大了点,不过用ASPack压一下就可以两全了,呵呵。向您强烈推荐!!!
3.XLGrid 1.62 品质:★★★★★
评测: 用这个控件让我想起了MS的Excel,呵呵。强大,强大,还是强大。可惜不支持数据库操作。在它的主页上有预发布2.0的实现功能计划书,AWater看了后,大流口水,太Cool了,可惜还没发布。不过这个1.62版的,巳经很爽了。向您强烈推荐!!!
(XlGrid组件实在是太Cool了,我正在用它,的确很好,现在的新版本是1.63)
㈤DB类
实在太多太多了,从高端的ASTA到性能全面的DBISAM,从DAO到Topaz,还有大名鼎鼎的InfoPower,实在是太多了,而且个个都是五星级的。AWater就不写了,反正这方面,是商业控件全面胜出。呵呵。
(Delphi最大的特点是它强大的数据功能,所以第三组件(特别是商业组件)中最为突出的也是要数据库类)
㈥Report类
1.ReportBuilder 5.0 品质:★★★★★
评测: 非常非常强大的报表控件,不要问我它到底强大到如何程度,因为这估计得整整写上五六千字才能向你介绍清楚。如果你正在为手头缺少一个功能强大,适用面广报表控件时,那么就只有它了,这是你最好的选择。可以说,只要你想得到,它基本都作到的。向您强烈推荐!!!
2.HTMLReport 品质:★★★★☆
评测: 放上这个东东,可能有凑数之嫌。不能说功能非常非常强大。但你看它的名字,里面有个非常时兴的字眼:HTML。呵呵,对了,它就是作这个用的。如果你有这方面的需要,找它就没错了。总体性能也很不错。当然还没有强大到像上面那个REportBuilder一样恐怖。向您强烈推荐!!
㈦图形类
1.Pegasus公司的系列图形控件 品质:★★★★★
评测: Pegasus 公司出品过许多知名的图形控件,比如像FXTools,ImagN'之类大家都早巳有所耳闻的超级控件。如果你对图形处理方面有较为高的要求,则应该考虑一下Pegasus 公司出品的这些一流的控件。可不是一般的免费控件可以替代的哟。向您强烈推荐!!
㈧综合类
综合类的我就不写测评了,反正无论是恐龙级的LMD,AHM2000,还是RZLIB,或是精致的1stClass。强大的功能和繁多的控件,都不是免费的控件包可以相提并论的,用的时侯,唯一让我担心的,就是我倒底该用哪一个好呢?呵呵,这岂不也是一种烦恼吗?
(这实在是一种烦恼,我有时陷入这些超Cool组件包的包围之中,但不管你爱几个mm,你最终只能选择一个,呵呵)
比较之下,我想大家心里都有了一个底了吧。在以上免费控件和商业控件的共八个大类的评测下,应该说商业控件占了绝对的优势,只除了一个Editor类,免费控件可以和商业控件一较高下之外,其余的都是有一定的差距。特别是在DB类方面,免费控件一方死的最惨,呵呵。
不过话说回来,天下到底没有白吃的午餐,好东西总还是要花钱去买的吗。但是,最后我们可以得出这样一个结论,虽然商业控件功能强大,品质优秀。但是,在你没有哪么多的资金去购买,或你对程序的某方面性能要求并不是非常苛刻时,你完全可以考虑使用一些优秀的第三方免费控件,或以之为蓝本在这个基础上进行二次开发,来达到你的设计要求,这也是一个非常不错,而且也很省钱的方案吧。
从上面的论述中,大家应该可以了解到了一些关于delphi的第三方控件的资料了,不过AWater在这里要提醒大家的是,控件虽好,但也不能滥用。更不能什么都依靠控件,一个好的程序员,不但要会用,更要会自己写。有空多研究一下优秀控件的源码,对水平的提高是大有帮助的,也能更加深入的理解面向对象编程的机制。希望有朝一日,我们中国人也能写出像delphi的优秀程序来,让满世界的老外为我们来开发第三方的控件,呵呵呵..... 。
(路漫漫其修远兮,吾将上下而求索,大家都努力呀,呵呵)
[[i] 本帖最后由 蓝色虫 于 2006-12-3 22:04 编辑 [/i]]
2006-12-3 22:18
蓝色虫
在Delphi中编写控件的基本方法
文档提供者:newebug
作为Delphi程序员,要想进一步提高编程水平就必须掌握控件的编写方法,本篇文章将通过一个简单的例子来为初学者介绍编写控件的一些基本方法和模式。
这个例子控件叫TLeiLabel,是在TLabel的基础上增加两个实用的功能:一是使文字具有立体形状,二是使文字具有超链接属性。下面就让我们一步步来实现这些功能。
一、使文字具有立体形状
首先定义类型T3DEffect和属性Style3D分别如下:
T3DEffect=(Normal,Raised,Lowered, Shadowed);
property Style3D:T3DEffect read FStyle3D write SetStyle3D default Normal;
再在private中定义变量:“FStyle3D:T3DEffect;”,并设置SetStyle3D()方法如下,这也是写方法的一般格式:
procedure TLeiLabel.SetStyle3D(Value: T3DEffect);
begin
if FStyle3D <> value then
begin
FStyle3D := value;
invalidate; //表示控件将重画
end;
end;
另外对于带阴影的文字还要定义阴影的偏移量ShadeXOffSet和ShadeYOffSet:
property ShadowXOffSet: integer read FXOffSet write SetFXOffSet default 5;
property ShadowYOffSet: integer read FYOffSet write SetFYOffSet default -5;
写方法SetFXOffSet()、SetFYOffSet()和上面的SetStyle3D()类似。
要重画控件一般要重载Paint方法,此处只是重画文字,我们只需重载DoDrawText方法。
DoDrawText的声明放在Protected中:
procedure DoDrawText(var Rect: TRect; Flags: Longint); override;
此处DoDrawText()根据四种类型(正常、凸起、凹进和阴影)分别画出不同的文字。
二、使文字具有超链接属性
定义一个属性URL表示要链接的网址或Email地址。
Property URL : String read FURL write SetURL;
写方法SetURL如下:
procedure TLeiLabel.SetURL(Value: String);
Begin
if FURL <> Value then FURL := Value ;
if FURL <> '' then
Cursor := crHandPoint;
end;
当点击此Label时要打开浏览器或收发邮件工具,这便要重载Click方法。
Procedure Click; Override;
procedure TLeiLabel.Click;
var s: string;
Begin
Inherited Click;
if FURL = '' then exit;
if LowerCase(Copy(FURL,1,7)) = 'http://' then
s := FURL
else if Pos('@',FURL) <> 0 Then
s := 'mailto:' + FURL
else
s := 'http://' + FURL;
ShellExecute(Application.Handle, 'open', PChar(s), NIL, NIL, SW_SHOWNORMAL);
end;
一般的超链接当鼠标移入时文字的颜色发生变化。为此加上属性HoverColor,表示鼠标移入时文字的颜色。
Property HoverColor : TColor Read FHoverColor Write SetHoverColor default clRed;
还要定义两个接收Windows消息CM_MOUSEENTER和CM_MOUSELEAVE(鼠标移进和移出)的过程:
Procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
Procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
Procedure TLeiLabel.CMMouseEnter (Var Message: TMessage);
begin
If Enabled and Visible and getParentForm(Self).Active then
begin
FFontColor := Font.Color;
//将文字的颜色保存起来
Font.Color := FHoverColor;
//改变文字颜色
End;
end;
Procedure TLeiLabel.CMMouseLeave (Var Message: TMessage);
begin
Font.Color:=FFontColor;
//恢复文字原来的颜色
end;
为设置属性的默认值,我们还需要重载构造Create(),注意,重载构造时必须首先调用祖先类的构造。重载构造Create()的程序如下:
constructor TLeiLabel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
//必须首先调用祖先类的构造
FStyle3D := Normal;
FXOffSet := 5;
FYOffSet := -5;
FHoverColor := clRed;
end;
最后,还必须为这个控件加上图标。我们可以用Delphi中的Image Editor来创建一个24×24的Bitmap位图,保存为一个DCR文件,文件名必须与控件的Pas文件名相同,位图名必须与控件名相同且全部大写。