第二十章-开发Delphi对象式数据管理功能(一)-(2)

20.1.1.2 TStream的实现原理

TStream对象是Stream对象的基础类,这是Stream对象的基础。为了能在不同媒介上的存储数据对象,后继的Stream对象主要是在Read和Write方法上做了改进,。因此,了解TStream是掌握Stream对象管理的核心。Borland公司虽然提供了Stream对象的接口说明文档,但对于其实现和应用方法却没有提及,笔者是从Borland Delphi 2.0 Client/Server Suite 提供的源代码和部分例子程序中掌握了流式对象技术。

下面就从TStream的属性和方法的实现开始。

1. TStream属性的实现

前面介绍过,TStream具有Position和Size两个属性,作为抽象数据类型,它抽象了在各种存储媒介中读写数据所需要经常访问的域。那么它们是怎样实现的呢?

在自定义部件编写这一章中介绍过部件属性定义中的读写控制。Position和Size也作了读写控制。定义如下:

property Position: Longint read GetPosition write SetPosition;

property Size: Longint read GetSize;

由上可知,Position是可读写属性,而Size是只读的。

Position属性的实现就体现在GetPosition和SetPosition。当在程序运行过程中,任何读取Position的值和给Position赋值的操作都会自动触发私有方法GetPosition和SetPosition。两个方法的声明如下:

function TStream.GetPosition: Longint;

begin

Result := Seek(0, 1);

end;

procedure TStream.SetPosition(Pos: Longint);

begin

Seek(Pos, 0);

end;

在设置位置时,Delphi编译机制会自动将Position传为Pos。

前面介绍过Seek的使用方法,第一参数是移动偏移量,第二个参数是移动的起点,返回值是移动后的指针位置。

Size属性的实现只有读控制,完全屏蔽了写操作。读控制方法GetSize实现如下:

function TStream.GetSize: Longint;

var

Pos: Longint;

begin

Pos := Seek(0, 1);

Result := Seek(0, 2);

Seek(Pos, 0);

end;

2. TStream方法的实现

⑴ CopyFrom方法

CopyFrom是Stream对象中很有用的方法,它用于在不同存储媒介中拷贝数据。例如,内存与外部文件之间、内存与数据库字段之间等。它简化了许多内存分配、文件打开和读写等的细节,将所有拷贝操作都统一到Stream对象上。

前面曾介绍:CopyFrom方法带Source和Count两个参数并返回长整型。该方法将Count个字节的内容从Source拷贝到当前流中,如果Count值为0则拷贝所有数据。

function TStream.CopyFrom(Source: TStream; Count: Longint): Longint;

const

MaxBufSize = $F000;

var

BufSize, N: Integer;

Buffer: PChar;

begin

if Count = 0 then

begin

Source.Position := 0;

CouNG="ZH-CN">资源文件中的部件时调用,通常程序员不需自己调用。如果读取的不是资源文件ReadResHeader,将触发异常事件。

procedure TStream.ReadResHeader;

var

ReadCount: Longint;

Header: array[0..79] of Char;

begin

FillChar(Header, SizeOf(Header), 0);

ReadCount := Read(Header, SizeOf(Header) - 1);

if (Byte((@Header[0])^) = $FF) and (Word((@Header[1])^) = 10) then

Seek(StrLen(Header + 3) + 10 - ReadCount, 1)

else

raise EInvalidImage.CreateRes(SInvalidImage);

end;

ReadComponentRes在Windows资源文件中读取部件,为了判断是否是资源文件,它首先调用ReadResHeader方法,然后调用ReadComponent方法读取Instance指定的部件。下面是它的实现:

function TStream.ReadComponentRes(Instance: TComponent): TComponent;

begin

ReadResHeader;

Result := ReadComponent(Instance);

end;

与ReadComponentRes相应的写方法是WriteComponentRes,Delphi 调用这两个方法读写窗体文件(DFM文件),在后面书中会举用这两个方法读取DFM文件的例子。

⑷ WriteComponent和WriteDescendant方法

Stream对象的WriteDescendant方法在实现过程中,创建了TWriter对象,然后利用TWriter的WriteDescendant方法将Instance写入流。而WriteComponent方法只是简单地调用WriteDescendant方法将Instance写入流。它们的实现如下:

procedure TStream.WriteComponent(Instance: TComponent);

begin

WriteDescendent(Instance, nil);

end;

procedure TStream.WriteDescendent(Instance, Ancestor: TComponent);

var

Writer: TWriter;

begin

Writer := TWriter.Create(Self, 4096);

try

Writer.WriteDescendent(Instance, Ancestor);

finally

Writer.Free;

end;

end;

⑸ WriteDescendantRes和WriteComponentRes方法

WriteDescendantRes方法用于将部件写入Windows资源文件;而WriteComponentRes 方法只是简单地调用WriteDescendantRes方法,它们的实现如下:

procedure TStream.WriteComponentRes(const ResName: string; Instance:

TComponent);

begin

WriteDescendentRes(ResName, Instance, nil);

end;

procedure TStream.WriteDescendentRes(const ResName: string; Instance,

Ancestor: TComponent);

var

HeaderSize: Integer;

Origin, ImageSize: Longint;

Header: array[0..79] of Char;

begin

Byte((@Header[0])^) := $FF;

Word((@Header[1])^) := 10;

HeaderSize := StrLen(StrUpper(StrPLCopy(@Header[3], ResName, 63))) + 10;

Word((@Header[HeaderSize - 6])^) := $1030;

Longint((@Header[HeaderSize - 4])^) := 0;

WriteBuffer(Header, HeaderSize);

Origin := Position;

WriteDescendent(Instance, Ancestor);

ImageSize := Position - Origin;

Position := Origin - 4;

WriteBuffer(ImageSize, SizeOf(Longint));

Position := Origin + ImageSize;

end;

WriteCompnentRes是与ReadComponentRes相应的对象写方法,这两个方法相互配合可读取Delphi的DFM文件,从而利用Delphi系统的功能。

时间: 2024-11-03 21:04:24

第二十章-开发Delphi对象式数据管理功能(一)-(2)的相关文章

第二十章-开发Delphi对象式数据管理功能(四)(6)

7. SetName方法和OnSetName事件 因为在OnSetName事件中,Name参数是var型的,所以可以用OnSetName事件处理过程修改所读部件的名字.而OnSetName事件处理过程是在SetName方法中实现的. procedure TReader.SetName(Component: TComponent; var Name: string); begin if Assigned(FOnSetName) then FOnSetName(Self, Component, Na

第二十章-开发Delphi对象式数据管理功能(一)-(1)

面向对象技术是九十年代的主流技术,各类应用软件如果以面向对象的方法构造并且渗透面向对象的风格将使软件具有更高的品质.在面向对象程序设计中,对象式数据管理占有很重要的地位.在Delphi中,对对象式数据管理的支持方式是其一大特色. Delphi是一个面向对象的可视化设计与面向对象的语言相结合的集成开发环境.Delphi的核心是部件.部件是对象的一种.Delphi应用程序完全是由部件来构造的,因此开发高性能的Delphi应用程序必然会涉及对象式数据管理技术. 对象式数据管理包括两方面的内容: ● 用

第二十章-开发Delphi对象式数据管理功能(二)(2)

4. 析构方法Destroy 该方法产生给资源解锁,然后释放该资源,最后调用继承的Destroy方法释放ResourceStream.其实现如下: destructor TResourceStream.Destroy; begin UnlockResource(HGlobal); FreeResource(HResInfo); inherited Destroy; end; 回顾Initialize方法,我们不难发现: ● ResourceStream没有额外地给资源重新分配内存,而是直接使用H

第二十章-开发Delphi对象式数据管理功能(五)(6)

20.3.2.4 BLOB字段与Stream对象 因为Delphi中,BLOB字段是通过BLOB流来访问的,所以可以很容易地在BLOB字段和Stream对象之间传递数据.为此,TBlobField对象提供了LoadFromStream和SaveToStream方法. procedure TBlobField.LoadFromStream(Stream: TStream); var BlobStream: TBlobStream; begin BlobStream := TBlobStream.C

第二十章-开发Delphi对象式数据管理功能(五)(4)

3. 动态DFM文件应用之二:超媒体系统脚本语言设计 超媒体脚本语言设计是超媒体系统设计的重要内容.脚本语言必须能够表达卡片中的多种媒体对象,必须是可编程,可理解的,必须是可执行的,应该可以由脚本语言生成超媒体系统中的卡片和链. DFM文件可以看作是超媒体系统的卡片,DFM脚本能够表达DFM文件中的多种控制,也就是说能够表达卡片中的多种媒体对象,再加上DFM脚本的对象式表达,可编辑性,可转换为DFM文件,因此用作超媒体系统脚本语言较好的形式. ObjectBinaryToText和ObjectT

第二十章-开发Delphi对象式数据管理功能(四)(1)

20.2.3 TReader对象 TReader对象是可实例化的用于从相联系的流中读取数据的Filer对象.TReader对象从TFiler继承下来,除了从TFiler继承的属性和方法外,TReader声明了不少属性.方法和事件. Owner和Parent属性用于表示从Reader对象的流中读取的部件的拥有者和双亲结点.OnError,OnFindMethod和OnSetName事件使应用程序在运行中读数据时能定制响应方式.除了覆盖了一些从TFiler对象中继承的方法外,TReader对象还定义

第二十章-开发Delphi对象式数据管理功能(二)(5)

4. Truncate方法 该方法是通过调用BDE API函数实现的.其实现如下: procedure TBlobStream.Truncate; begin if FOpened then begin Check(DbiTruncateBlob(FDataSet.Handle, FRecord, FFieldNo, FPosition)); FModified := True; end; end; 该方法从BLOB流的当前位置起删除所有数据,并设置修改标志FModified为True.在Del

第二十章-开发Delphi对象式数据管理功能(五)(5)

20.3.2 数据库BLOB字段应用 Delphi VCL提供了TBlobStream对象支持对数据库BLOB字段的存取.Delphi 的TBlobStream对象的作用在于一方面可以使Delphi应用程序充分利用多媒体数据库的数据管理能力.另一方面又能利用Delphi Object Pascal的程序设计能力给关系型多媒体数据库提供底层控制能力和全方位的功能扩展余地. 20.3.2.1 TBlobStream的使用 TBlobStream对象用一个TBlobField类型的对象作为参数来创建与

第二十章-开发Delphi对象式数据管理功能(五)(3)

20.3.1.5 动态DFM文件应用揭秘 1. 动态DFM文件概述 动态DFM文件是相对于静态DFM文件而言.所谓静态DFM文件是指在Delphi开发环境中设计的窗体文件.窗体的设计过程就是程序的编制过程.因此,动态DFM文件就是指在程序运行过程生成或存取的DFM文件. 动态DFM文件的创建和使用分别如下两种情况: ● 在程序运行过程中,由Create方法动态生成窗体或部件,然后动态生成其它部件插入其中生成DFM文件 ● 在Delphi开发环境中,设计生成DFM文件,然后用DFM 文件存取函数,