第二十章 开发Delphi对象式数据管理功能(五)_第1页
第二十章 开发Delphi对象式数据管理功能(五)_第2页
第二十章 开发Delphi对象式数据管理功能(五)_第3页
第二十章 开发Delphi对象式数据管理功能(五)_第4页
第二十章 开发Delphi对象式数据管理功能(五)_第5页
已阅读5页,还剩36页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、写 DFM 文件的过程:WriteComponentResFie该过程带有两个参数 FileName 和 Instance 。 FileName 参数指定要写入的 DFM 文件 名, Instance 参数是 TComponent 类型的,它指定要写入的部件名,一般是 TForm 对象的 子类。该过程将 Instance 部件和其拥有的所有部件写入 DFM 文件。这个过程的意义在于,可以在程序运行过程中产生 Delphi 的窗体部件和在窗体中插入 部件,并由该函数将窗体写入 DFM 文件,支持了动态 DFM 文件的重用性。该过程的程序是这样的:procedure WriteCo

2、mponentResFile(const FileName: string; Instance: TComponent; varStream: TStream;beginStream := TFileStream.Create(FileName, fmCreate;tryStream.WriteComponentRes(Instance.ClassName, Instance;finallyStream.Free;end;end;函数中,用 FileStream 创建文件,用 Stream 对象的 WriteComponetRes 方法将 Inst ance 写入流中。 读 D

3、FM 文件的函数:ReadComponentResFileReadComponentResFile 函数带有两个参数 FileName 和 Instance 。 FileName 参数指定要 读 DFM 文件名, Instance 参数指定从 DFM 文件中要读的部件。该函数从 DFM 文件中将 I nstance 和它拥有的所有部件,并返回该部件。这个函数的意义在于,配合 WriteComponentResFile 过程的使用支持 DFM 文件的重 用性。该函数的程序是这样的:function ReadComponentResFile(const FileName: string; Inst

4、ance: TComponent: TComponent;varStream: TStream;beginStream := TFileStream.Create(FileName, fmOpenRead;tryResult := Stream.ReadComponentRes(Instance;finallyStream.Free;end;end;程序中使用 FileStream 对象打开由 FileName 指定的 DFM 文件,然后用 Stream 对象 的 ReadComponentRes 方法读出 Instance ,并将读的结果作为函数的返回值。 读取 Delphi

5、 应用程序资源中的部件函数 InternalReadComponentRes 可以读取 Delphi 应用程序资源中的部件。 Delphi 的 DFM 文件在程序经过编译链接后被嵌入应用程序的资源中,而且格式发生了改变,即少 了资源文件头。在第一节中曾经介绍过 TResourceStream 对象,该对象是操作资源媒介上的数据的。函数 InternalReadComponentRes 用了 TResourceStream 。程序是这样的:function InternalReadComponentRes(const ResName: string;var Instance: TComponen

6、t: Boolean;varHRsrc: THandle;begin 避免“ EResNotFound ”异常事件的出现 HRsrc := FindResource(HInstance, PChar(ResName, RT_RCDATA;Result := HRsrc <> 0;if not Result then Exit;FreeResource(HRsrc;with TResourceStream.Create(HInstance, ResName, RT_RCDATA dotryInstance := ReadComponent(Instance;finallyFree;e

7、nd;Result := True;end;HInstance 是一个 Delphi VCL 定义的全局变量,代表当前应用程序的句柄。函数用了 资源访问 API 函数 FindResource 来测定是否存在 ResName 所描述资源。因为在 TResou rceStream 的创建过程还有 FindResource 等操作,所以函数中调用了 FreeResource 。最 后函数调用了 Stream 对象的 ReadComponent 方法读出部件。 因为函数的 Instance 是 var 类型的参数,所以可以访问 Instance ,得到读出的部件。 DFM 文件与标准

8、文本文件 (TXT文件 的相互转换在 Delphi 可视化设计环境中,允许程序员在代码编辑器中以文本的方式浏览和修改 D FM 文件内容。当用 File/Open命令直接打开 DFM 文件或者选择窗体设计窗口的弹出式菜 单上的 View as Text 命令时,就会在编辑器中出现文本形式的信息。我们姑且将这种文本 形式称之为窗体设计脚本。 Delphi 提供的这种脚本编辑功能是对 Delphi 可视化设计的一大 补充。 当然这个脚本编辑能力是有限制的, 比方说不能在脚本任意地添加和删除部件, 因为 代码和 DFM 脚本是紧密相连的,任意添加和修改会导致不一致性。然而在动态生成的 DF M 文件

9、中,就不存在这一限制,后面会介绍 DFM 动态生成技术的应用。实际上, DFM 文件内容是二进制数据,它的脚本是经过 Delphi 开发环境自动转化的, 而且 Delphi VCL 中的 Classes 库单元中提供了在二进制流中的文件 DFM 和它的脚本之相 互转化的过程。它们是 ObjectBinaryToText 和 ObjectTextBinary 、 ObjectResourceToText 和 ObjectTextToResource 。ObjectBinaryToText 过程将二进制流中存储的部件转化为基于文本的表现形式,这样就可 以用文本处理函数进行处理, 还可以用文本编辑器

10、进行查找和替代操作, 最后可以将文本再 转化成二进制流中的部件。ObjectBinaryToText 过程的主程序是这样的:procedure ObjectBinaryToText(Input, Output: TStream;varNestingLevel: Integer;SaveSeparator: Char;Reader: TReader;Writer: TWriter;procedure WriteIndent;constBlanks: array0.1 of Char = ' 'varI: Integer;beginfor I := 1 to NestingLeve

11、l do Writer.Write(Blanks, SizeOf(Blanks; end;procedure WriteStr(const S: string;beginWriter.Write(S1, Length(S;end;procedure NewLine;beginWriteStr(#13#10;WriteIndent;end;procedure ConvertHeader;beginend;procedure ConvertBinary; beginend;procedure ConvertValue; beginend;procedure ConvertProperty; beg

12、inend;procedure ConvertObject; beginend;beginReader := TReader.Create(Input, 4096;SaveSeparator := DecimalSeparator;DecimalSeparator := '.'tryWriter := TWriter.Create(Output, 4096;tryReader.ReadSignature;ConvertObject;finallyWriter.Free;end;finallyDecimalSeparator := SaveSeparator;Reader.Fre

13、e;end;end;过程中调用的 ConvertObject 过程是个递归过程,用于将 DFM 文件中的每一个部件转 化为文本形式。因为由于部件的拥有关系,所以部件成嵌套结构,采用递归是最好的方式:procedure ConvertObject;beginConvertHeader;while not Reader.EndOfList do ConvertProperty;Reader.ReadListEnd;while not Reader.EndOfList do ConvertObject;Reader.ReadListEnd;Dec(NestingLevel;WriteIndent;W

14、riteStr('end'#13#10;end;NestStingLevel 变量表示部件的嵌套层次。 WriteIndent 是写入每一行起始字符前的空 格, ConvertHeader 过程是处理部件的继承标志信息。转换成的头信息文本有两种形式。Inherited TestForm1: TTestForm2或者:Object TestForm1: TTestForm前者是 ffInherited 和 ffChildPos 置位,后面是都没置位。ConvertProperty 过程用于转化属性。procedure ConvertProperty;beginWriteInden

15、t;WriteStr(Reader.ReadStr;WriteStr(' = 'ConvertValue;WriteStr(#13#10;end;WriteIndent 语句写入属性名前的空格, WriteStr(Reader.ReadStr语句写入属性名 Co nvertValue 过程根据属性的类型将属性值转化为字符串,然后写入流中。ObjectTextToBinary 过程执行的功能与 ObjectBinaryToText 相反, 将 TXT 文件转换为 二进制流中的部件,而且只要 TXT 文件内容的书写符合 DFM 脚本语法, ObjectTextToBin ary 可

16、将任何程序生成的 TXT 文件转换为部件, 这一功能也为 DFM 文件的动态生成和编辑 奠定了基础。 ObjectTextToBinary 过程的主程序如下:procedure ObjectTextToBinary(Input, Output: TStream;varSaveSeparator: Char;Parser: TParser;Writer: TWriter;beginParser := TParser.Create(Input;SaveSeparator := DecimalSeparator;DecimalSeparator := '.'tryWriter :=

17、TWriter.Create(Output, 4096;tryWriter.WriteSignature;ConvertObject;finallyWriter.Free;end;finallyDecimalSeparator := SaveSeparator;Parser.Free;end;end;在程序流程和结构上与 ObjectBinaryToText 差不多。 ConvertObject 也是个递归过程:procedure ConvertObject;varInheritedObject: Boolean;beginInheritedObject := False;if Parser.

18、TokenSymbolIs('INHERITED' thenInheritedObject := TrueelseParser.CheckTokenSymbol('OBJECT'Parser.NextToken;ConvertHeader(InheritedObject;while not Parser.TokenSymbolIs('END' andnot Parser.TokenSymbolIs('OBJECT' andnot Parser.TokenSymbolIs('INHERITED' do Convert

19、Property;Writer.WriteListEnd;while not Parser.TokenSymbolIs('END' do ConvertObject;Writer.WriteListEnd;Parser.NextToken;end;DFM 文件与 DFM 脚本语言之间相互转换的任务由 ObjectResourceToText 和 ObjextT extToResource 两个过程完成。procedure ObjectResourceToText(Input, Output: TStream;beginInput.ReadResHeader;ObjectBina

20、ryToText(Input, Output;end;ObjectTextToResource 过程就比较复杂,因为 DFM 文件资源头中要包含继承标志信息, 因此在调用 ObjectTextToBinary 后,就读取标志信息,然后写入资源头。procedure ObjectTextToResource(Input, Output: TStream;Len: Byte;Tmp: Longint;MemoryStream: TMemoryStream;MemorySize: Longint;Header: array0.79 of Char;beginMemoryStream := TMemo

21、ryStream.Create;tryObjectTextToBinary(Input, MemoryStream;MemorySize := MemoryStream.Size;FillChar(Header, SizeOf(Header, 0; MemoryStream.Position := SizeOf(Longint; Skip header MemoryStream.Read(Len, 1;if Len and $F0 = $F0 thenbeginif ffChildPos in TFilerFlags(Len and $F0 thenbeginMemoryStream.Read

22、(Len, 1;case TValueType(Len ofvaInt8: Len := 1;vaInt16: Len := 2;vaInt32: Len := 4;MemoryStream.Read(Tmp, Len;end;MemoryStream.Read(Len, 1;end;MemoryStream.Read(Header3, Len;StrUpper(Header3;Byte(Header0 := $FF;Word(Header1 := 10;Word(HeaderLen + 4 := $1030;Longint(HeaderLen + 6 := MemorySize;Output

23、.Write(Header, Len + 10;Output.Write(MemoryStream.Memory, MemorySize;finallyMemoryStream.Free;end;end; 动态 DFM 文件应用揭秘1. 动态 DFM 文件概述动态 DFM 文件是相对于静态 DFM 文件而言。所谓静态 DFM 文件是指在 Delphi 开发环境 中设计的窗体文件。窗体的设计过程就是程序的编制过程。因此,动态 DFM 文件就是指在 程序运行过程生成或存取的 DFM 文件。动态 DFM 文件的创建和使用分别如下两种情况: 在程序运行过程中, 由 Create 方法动

24、态生成窗体或部件, 然后动态生成其它部件插 入其中生成 DFM 文件 在 Delphi 开发环境中,设计生成 DFM 文件,然后用 DFM 文件存取函数,或者用 Stream 对象和 Filer 对象的方法,将 DFM 文件读入内存,进行处理,最后又存入磁盘中由 Delphi 的窗体设计的常规方法生成的 DFM 文件在程序运行一开始就规定了部件的结 构。 因为在窗体设计过程中, 窗体中的每个部件都在程序的对象声明中定义了部件变量。 这 种固定的结构虽然能方便应用,但以牺牲灵活性为代价。在 Delphi 应用程序中有时需要在运行过程中创建控制,然后将该控制插入另一个部件 中。例如:procedu

25、re TForm1.Button1Click(Sender: Tobject;varCtrl: TControlbeginCtrl := TEdit.Create(Self;Ctrl.Top := 100;Ctrl.Left := 100;Ctrl.Width := 150;Ctrl.Height := 20;InsertControl(Ctrl;end;动态插入控制的优点是可以在任何时刻、 任意位置插入任意数量的任何类型的控制。 因 为应用程序需求在很多情况下是在程序运行中才知道的,所以动态插入控制就显得很重要。而且在很多情况下, 需要保存这些界面元素, 留待程序再次调用。 例如应用程序界面

26、的定制、 系统状态的保存、对话框的保存等。这时生成动态 DFM 文件是最佳选择。动态插入控制的不足之处是在插入控制前, 无法直观地看到控制的大小、 风格、 位置等, 也就是动态插入控制的过程是非可视化的。但可以借助于静态 DFM 文件的可视化设计。这 就是生成和使用动态 DFM 文件的第二种方法。 也就是在应用程序运行前, 在 Delphi 开发环 境中,使用可视化开发工具设计所需窗口或部件的样式,以 DFM 文件保存。然后在应用程 序运行过程中,将 DFM 文件读入内存。 Delphi 的 Stream 对象和 Filer 对象在读取 DFM 文 件时,会根据 DFM 文件的内容自动创建部件

27、及其拥有的所有部件。在使用动态 DFM 文件时有两点需要注意。 每一个动态插入的控制或部件必须在程序中调用 RegisterClass 进行注册 读入 DFM 文件自动创建部件后, 如果调用了 InsertControl 方法, 则在关闭窗口时 要调用 RemoveControl 方法移去该控制,否则会产生异常事件2. 动态 DFM 文件应用之一:超媒体系统的卡片设计Delphi 多种类型的可视部件,如文本部件、编辑部件、图形图像部件、数据库部件、 媒体媒放部件和 OLE 部件等,每一种部件在屏幕中占据一定的区域,具有相当丰富的表现 能力, 可以作为卡片中的一种媒体, 因此可以利用这些可视部件

28、进行超媒体系统的卡片设计。超媒体卡片设计要求卡片中的媒体数目和媒体种类是不受限制的, 而且必须能够修改和 存取卡片,因此,采用动态 DFM 文件是比较合适的。而且如果利用 Stream 对象,将卡片 存储在数据库 BLOB 字段中,就为把超文本与关系数据库技术结合起来创造了契机。下面是超媒体卡片设计子系统中的部分源程序, 它演示了如何创建对象、 插入对象和存 取动态 DFM 文件。 在应用程序中注册对象procedure TMainForm.FormCreate(Sender: TObject;beginRegisterClass(TLabel;RegisterClass(TEdit;Regi

29、sterClass(TMemo;RegisterClass(TButton;RegisterClass(TPanel;RegisterClass(TPanelP;RegisterClass(TBitBtn;end; 创建和插入对象procedure TMDIChild.FormClick(Sender: TObject; varCtrl : TControl;Point: TPoint;beginGetCursorPos(Point;Point := BackGround.ScreenToClient(Point; case CurToolIndex of1 : beginCtrl := TL

30、abel.Create(self;TLabel(Ctrl.AutoSize := False; TLabel(ctrl.Caption := 'Label'+S; TLabel(ctrl.Name := 'Label 1'TLabel(ctrl.Top := Point.Y;TLabel(ctrl.Left := Point.X;TLabel(Ctrl.Height := Round(100*Res/1000/Ratio; TLabel(Ctrl.Width := Round(600*Res/1000/Ratio; TLabel(Ctrl.Color := cl

31、White; TLabel(Ctrl.Font.Color := clBlack; TLabel(Ctrl.Font.Name := 'Roman' TLabel(Ctrl.Font.Height := -TLabel(Ctrl.Height; TLabel(Ctrl.Font.Pitch := fpFixed; TLabel(Ctrl.Enabled := False; TLabel(Ctrl.OnClick := LabelClick; TLabel(Ctrl.OnMouseMove := ReportPos; BackGround.InsertControl(Ctrl;C

32、urTool.Down := False;CurTool := nil;end;2: beginCtrl := TEdit.Create(self;TEdit(ctrl.AutoSize := True;TEdit(ctrl.Top := Point.Y;TEdit(ctrl.Left := Point.X;TEdit(Ctrl.Height := 20; BackGround.InsertControl(Ctrl;end;3:end;end; 存取动态 DFM 文件procedure TMainForm.FileOpen(Sender: TObject;beginif OpenDialog.

33、Execute thenbeginDesignWin := TMDIChild.Create(Application; ReadComponentResFile(OpenDialog.FileName, DesignWin;DesignWin.Init;FileName := OpenDialog.FileName;DesignWin.Caption := FFileName;end;end;DesignWin 是在 TMainForm 中定义的 TMDIChild 类型的窗体部件,是卡片设计平台; FFileName 是私有变量,用来保存当前编辑的卡片文件名。 DesignWin 的 Ini

34、t 方法实现如 下:procedure TMDIChild.Init;varI: Integer;Ctrl: TControl;beginBackGround.BringToFront;with BackGround dofor I:= 0 to ControlCount - 1 doif ControlsI.Name <> ''thenObjectIns.ObjectList.Items.AddObject(ControlsI.Name, ControlsI;end;BackGround 是 TPanel 类型的部件,所有的动态创建对象都插入到 BackGroun

35、d 中, 所以,后面调用 BackGround.InsertControl(Ctrl; ObjectIns 是个仿 Delphi 的媒体属性编 辑器。动态 DFM 文件的存储过程是这样的:procedure TMainForm.FileSave(Sender: TObject;beginif DesignWin.CurControl <> nil thenDesignWin.CurControl.Enabled := True;WriteComponentResFile(FFilename, DesignWin;DesignWin.Caption := FileName;end;e

36、nd;因为在 DesignWin 的 Init 方法中调用了 InsertControl 方法, 所以在关闭 DesignWin 窗 口时要相应地调用 RemoveControl ,否则在关闭 DesignWin 窗口时会产生内存错误。procedure TMDIChild.FormCloseQuery(Sender: TObject; var CanClose: Boolean; varI: Integer;Ctrl: TControl;Removed: Boolean;beginif Modified = True thenif MessageDlg('Close the form

37、?', mtConfirmation,mbOk, mbCancel, 0 = mrCancel thenCanClose := False;if CanClose = True thenbeginrepeatremoved := False;I := 0;repeatif BackGround.ControlsI.Name <> '' thenbeginBackGround.RemoveControl(BackGround.ControlsI;Removed := True;end;I := I + 1until (I >= BackGround.Co

38、ntrolCount or (Removed = True;until (Removed = False;SendMessage(ObjectIns.Handle, WM_MDICHILDCLOSED, 0, 0;end;end;3. 动态 DFM 文件应用之二:超媒体系统脚本语言设计超媒体脚本语言设计是超媒体系统设计的重要内容。 脚本语言必须能够表达卡片中的多 种媒体对象,必须是可编程,可理解的, 必须是可执行的,应该可以由脚本语言生成超媒体 系统中的卡片和链。DFM 文件可以看作是超媒体系统的卡片, DFM 脚本能够表达 DFM 文件中的多种控制, 也就是说能够表达卡片中的多种媒体对象,再

39、加上 DFM 脚本的对象式表达,可编辑性,可 转换为 DFM 文件,因此用作超媒体系统脚本语言较好的形式。ObjectBinaryToText 和 ObjectTextToBinary 过程提供了在部件和 DFM 脚本之间相互 转化的功能, ObjectResourceToText 和 ObjectTextToResoure 过程提供了 DFM 文件和 D FM 脚本之间相互转化的功能。 这样就可以在应用程序中自如实现超媒体卡片和超媒体脚本 语言相互转化。下面是卡片和脚本语言相互转化的程序:procedure TMDIChild.CardToScript;varIn, Out: TStream

40、;beginIn := TMemoryStream.Create;Out := TMemoryStream.Create;tryIn.WriteComponentRes(Self.ClassName, Self; ObjectResourceToText(In, out; ScriptForm.ScriptEdit.Lines.LoadFromStream(Out;finallyIn.Free;Out.Free;end;end;ScriptEdit 是个文本编辑器,它的 Lines 属性是 TStrings 类型的对象。procedure TScriptForm.ScriptToCard;va

41、rIn, Out: TStream;beginIn := TMemoryStream.Create;Out := TMemoryStream.Create;tryScriptForm.ScriptEdit.Lines.SaveToFromStream(In;ObjectTextToResource(In, out;In.ReadComponentRes(DesignWin;finallyIn.Free;Out.Free;end;end;这两段程序是对整个卡片,即窗体级,进行转换的。 ObjectBinaryToText 和 ObjectTe xtToBinary 过程可以细化到部件级的转换。

42、因此超媒体脚本语言的编辑可以细化到媒体对象 级。4. 超媒体编辑和表现系统与动态 DFM 文件的扩展超媒体系统的媒体编辑与卡片管理有其特殊的需求, 比如链接需求。 这时采用已有的窗 体部件和媒体部件并按常规的 DFM 文件处理就显得力不从心了。 解决这个矛盾有两套方案: 利用 Delphi 部件开发技术,继承和开发新的部件增加新的超媒体特有的属性和处理 方法 扩展 DFM 文件结构,使之能按自己的需要任意地存取和转换部件和 DFM 文件前者是充分利用 Delphi 的面向对象部件开发技术,在存取和转换等处理上仍旧与常规 DFM 文件相同。而后者需要 DFM 的存取和转换上作比较大的改动。下文介

43、绍扩展 DFM 文 件的思路。扩展动态 DFM 文件的总体思路是降低处理操作的数据的颗粒度,即从原先窗体级降低 到部件级。下面是存取操作的扩展示范:varFileStream: TStream;I: Integer;beginFileStream := TFileStream.Create('OverView.Crd', fmOpenWrite; With TWriter.Create(FileStream, 4096 dotryfor I := 0 to DesignWin.ControlCount - 1 dobeginWriteInteger(MMIDi; WriteRo

44、otComponent(DesignWin.Controlsi; 写相应媒体扩展信息 end;WriteListEnd;finally.Free;end;FileStream.Free;end;WriteInteger(MMIDi语句是写入媒体标识。下面是相应的读扩展 DFM 的程序:varPropInfo: PPropInfo;Method : TMethod;FileStream: TStream;I: Integer;beginFileStream := TFileStream.Create('OverView.Crd', fmOpenRead; With TReader

45、.Create(FileStream, 4096 dotrywhile not EndOfList dobegincase ReadInteger ofIDText: beginCtrl := TControl(ReadRootComponent(nil;PropInfo := GetPropInfo(Ctrl.ClassInfo, 'OnClick'Method.Code:= Self.MethodAddress(MethodName;Method.Data := Self;if Method.Code <> nil thenSetMethodProp(Ctrl,

46、 PropInfo, Method; DesignWin.InsertControl(Ctrl;end;IDImage:end;WriteListEnd;end;finally.Free;end;FileStream.Free;end;SetMethodProp 过程是用于重新联接控制和它的事件处理过程。 类似的功能还可以用 T Reader 对象的 OnFindMethod 事件的处理过程来实现。实现脚本语言扩展的基本方法与存取扩展类似,但它还要加扩展媒体信息转换为文本, 并插入到部件的脚本描述中。20.3.2 数据库 BLOB 字段应用Delphi VCL 提供了 TBlobStream

47、对象支持对数据库 BLOB 字段的存取。 Delphi 的 T BlobStream 对象的作用在于一方面可以使 Delphi 应用程序充分利用多媒体数据库的数据管 理能力。另一方面又能利用 Delphi Object Pascal 的程序设计能力给关系型多媒体数据库 提供底层控制能力和全方位的功能扩展余地。 TBlobStream 的使用TBlobStream 对象用一个 TBlobField 类型的对象作为参数来创建与 BLOB 字段相联的 BLOB 流,接着就可用流的存取方法在 BLOB 字段中存取数据。varBlobStream: TBlobStream;I: Inte

48、ger;beginBlobStream := TBlobStream.Create(TBlobField(CardTable.Fields10, bmWrite;With TWriter.Create(BlobStream, 4096 dotryfor I := 0 to DesignWin.ControlCount - 1 dobeginWriteInteger(MMIDi;WriteRootComponent(DesignWin.Controlsi; 写相应媒体扩展信息 end;WriteListEnd;finally.Free;end;BlobStream.Free;CardTable.

49、Post;end;Fields 变量是表示数据库记录的字段数组, Fields10正是数据库的 BLOB 字段。 Car dTable 的 Post 方法将数据库的修改反馈到数据库的物理存储上。上面这段程序是超媒体卡片存储的部分源程序,我们就是将卡片保存在数据库 BLOB 字段中,实现将超文本和关系数据库两种数据管理方式结合起来。读卡片的程序如下:varPropInfo: PPropInfo;Method: TMethod;Blobtream: TStream;I: Integer;beginBlobStream := TBlobStream.Create(TBlobField(CardTab

50、le.Fields10, bmRead; With TReader.Create(BlobStream, 4096 dotrywhile not EndOfList dobegincase ReadInteger ofIDText: beginCtrl := TControl(ReadRootComponent(nil;PropInfo := GetPropInfo(Ctrl.ClassInfo, 'OnClick'Method.Code:= Self.MethodAddress(MethodName;Method.Data := Self;if Method.Code <

51、;> nil thenSetMethodProp(Ctrl, PropInfo, Method;DesignWin.InsertControl(Ctrl;end;IDImage:end;WriteListEnd;end;finally.Free;end;FileStream.Free;end; BLOB 字段与图形图像在多媒体数据库中处理得比较多的是图形图像, 因此早期的多媒体数据库在扩展关系数 据库时往往是增加一个图像字段。 BLOB 字段是以二进制数据存储方式, 因此它完全可以表 达图形图像数据。在 TBlobField 对象中提供了 LoadFromBitMap 和

52、 SaveToBitMap 方法存取位图数据。 它们在实现上都是使用 BlobStream 对象。procedure TBlobField.LoadFromBitmap(Bitmap: TBitmap;varBlobStream: TBlobStream;Header: TGraphicHeader;beginBlobStream := TBlobStream.Create(Self, bmWrite;tryif (DataType = ftGraphic or (DataType = ftTypedBinary then beginHeader.Count := 1;Header.HType

53、 := $0100;Header.Size := 0;BlobStream.Write(Header, SizeOf(Header; Bitmap.SaveToStream(BlobStream;Header.Size := BlobStream.Position - SizeOf(Header; BlobStream.Position := 0;BlobStream.Write(Header, SizeOf(Header;end elseBitmap.SaveToStream(BlobStream;finallyBlobStream.Free;end;end;procedure TBlobF

54、ield.SaveToBitmap(Bitmap: TBitmap;varBlobStream: TBlobStream;Size: Longint;Header: TGraphicHeader;beginBlobStream := TBlobStream.Create(Self, bmRead;trySize := BlobStream.Size;if Size >= SizeOf(TGraphicHeader thenbeginBlobStream.Read(Header, SizeOf(Header;if (Header.Count <> 1 or (Header.HT

55、ype <> $0100 or(Header.Size <> Size - SizeOf(Header thenBlobStream.Position := 0;end;Bitmap.LoadFromStream(BlobStream;finallyBlobStream.Free;end;end;程序中按两种方式存取数据,对于位图数据, 数据的起点是流的 Potition 为 0处, 对于图形 或其它类型的 Blob 数据,则以流的 Position 为 SizeOf(Header + 1处开始, 即多了个头 信息。 BLOB 字段与文本Delphi B

56、LOB 字段中增加了大型文本的处理能力。可以在 TBlobField 和 Strings 中自 由地交换数据。procedure TBlobField.LoadFromStrings(Strings: TStrings;varBlobStream: TBlobStream;beginBlobStream := TBlobStream.Create(Self, bmWrite;tryStrings.SaveToStream(BlobStream;finallyBlobStream.Free;end;end;procedure TBlobField.SaveToStrings(Strings: TStrings;varBlobStream: TBlobStream;beginBlobStream := TBlobStream.Create(Self, bmRead;tryStrings.LoadFromStream(BlobStream;finallyBlobStream.Free;end;end; BLOB字段与 S

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论