汇编 | Java | C# | Delphi | C/C++ |

DELPHI基础教程 第二十章 开发Delphi对象式数据管理功能(五)

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

织梦好,好织梦

20.3.1.1DFM文件的过程:WriteComponentResFie 织梦内容管理系统

   该过程带有两个参数FileNameInstanceFileName参数指定要写入的DFM文件名,Instance参数是TComponent类型的,它指定要写入的部件名,一般是TForm对象的子类。该过程将Instance部件和其拥有的所有部件写入DFM文件。 织梦好,好织梦

  这个过程的意义在于,可以在程序运行过程中产生Delphi的窗体部件和在窗体中插入部件,并由该函数将窗体写入DFM文件,支持了动态DFM文件的重用性。 内容来自dedecms

  该过程的程序是这样的: 织梦内容管理系统

  copyright dedecms

procedure WriteComponentResFile(const FileName: string; Instance: TComponent); 织梦内容管理系统

var 织梦好,好织梦

Stream: TStream; 内容来自dedecms

begin

dedecms.com

Stream := TFileStream.Create(FileName, fmCreate);

本文来自织梦

try dedecms.com

Stream.WriteComponentRes(Instance.ClassName, Instance);

织梦内容管理系统

finally 织梦好,好织梦

Stream.Free;

织梦内容管理系统

end;

织梦内容管理系统

end; 织梦好,好织梦

 

织梦好,好织梦

  函数中,用FileStream创建文件,用Stream对象的WriteComponetRes方法将Instance写入流中。 dedecms.com

 

本文来自织梦

20.3.1.2 DFM文件的函数:ReadComponentResFile

织梦好,好织梦

 

copyright dedecms

ReadComponentResFile函数带有两个参数FileNameInstanceFileName参数指定要读DFM文件名,Instance参数指定从DFM文件中要读的部件。该函数从DFM文件中将Instance和它拥有的所有部件,并返回该部件。 copyright dedecms

  这个函数的意义在于,配合WriteComponentResFile过程的使用支持DFM文件的重用性。

内容来自dedecms

  该函数的程序是这样的:

dedecms.com

  copyright dedecms

function ReadComponentResFile(const FileName: string; Instance: TComponent):

copyright dedecms

TComponent;

copyright dedecms

var

织梦内容管理系统

Stream: TStream;

dedecms.com

begin

织梦内容管理系统

Stream := TFileStream.Create(FileName, fmOpenRead);

织梦好,好织梦

try dedecms.com

Result := Stream.ReadComponentRes(Instance);

copyright dedecms

finally

织梦内容管理系统

Stream.Free;

织梦内容管理系统

end; 织梦内容管理系统

end; 内容来自dedecms

 

内容来自dedecms

  程序中使用FileStream对象打开由FileName指定的DFM文件,然后用Stream对象的ReadComponentRes方法读出Instance,并将读的结果作为函数的返回值。

dedecms.com

 

织梦好,好织梦

20.3.1.3 读取Delphi应用程序资源中的部件 copyright dedecms

  copyright dedecms

  函数InternalReadComponentRes可以读取Delphi应用程序资源中的部件。Delphi DFM文件在程序经过编译链接后被嵌入应用程序的资源中,而且格式发生了改变,即少了资源文件头。 copyright dedecms

在第一节中曾经介绍过TResourceStream对象,该对象是操作资源媒介上的数据的。函数InternalReadComponentRes用了TResourceStream。程序是这样的: dedecms.com

  dedecms.com

function InternalReadComponentRes(const ResName: string;

本文来自织梦

var Instance: TComponent): Boolean; 本文来自织梦

var

copyright dedecms

HRsrc: THandle;

内容来自dedecms

begin { 避免“EResNotFound”异常事件的出现 } 本文来自织梦

HRsrc := FindResource(HInstance, PChar(ResName), RT_RCDATA);

copyright dedecms

Result := HRsrc <> 0;

dedecms.com

if not Result then Exit; 本文来自织梦

FreeResource(HRsrc);

dedecms.com

with TResourceStream.Create(HInstance, ResName, RT_RCDATA) do

织梦好,好织梦

try 本文来自织梦

Instance := ReadComponent(Instance); 本文来自织梦

finally 织梦内容管理系统

Free;

织梦好,好织梦

end; 织梦内容管理系统

Result := True;

织梦内容管理系统

end; 织梦好,好织梦

  织梦内容管理系统

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

本文来自织梦

  织梦好,好织梦

20.3.1.4 DFM文件与标准文本文件(TXT文件)的相互转换 本文来自织梦

 

内容来自dedecms

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

本文来自织梦

  实际上,DFM文件内容是二进制数据,它的脚本是经过Delphi开发环境自动转化的,而且Delphi VCL中的Classes库单元中提供了在二进制流中的文件DFM和它的脚本之相互转化的过程。它们是ObjectBinaryToTextObjectTextBinaryObjectResourceToTextObjectTextToResource

本文来自织梦

ObjectBinaryToText过程将二进制流中存储的部件转化为基于文本的表现形式,这样就可以用文本处理函数进行处理,还可以用文本编辑器进行查找和替代操作,最后可以将文本再转化成二进制流中的部件。 织梦内容管理系统

  ObjectBinaryToText过程的主程序是这样的: 织梦内容管理系统

 

dedecms.com

procedure ObjectBinaryToText(Input, Output: TStream); 织梦内容管理系统

var

dedecms.com

NestingLevel: Integer;

dedecms.com

SaveSeparator: Char;

织梦好,好织梦

Reader: TReader; 织梦好,好织梦

Writer: TWriter;

copyright dedecms

 

copyright dedecms

procedure WriteIndent;

内容来自dedecms

const 内容来自dedecms

Blanks: array[0..1] of Char = ' '; dedecms.com

var

内容来自dedecms

I: Integer;

dedecms.com

begin dedecms.com

for I := 1 to NestingLevel do Writer.Write(Blanks, SizeOf(Blanks)); dedecms.com

end;

织梦好,好织梦

 

dedecms.com

procedure WriteStr(const S: string); 本文来自织梦

begin dedecms.com

Writer.Write(S[1], Length(S));

dedecms.com

end;

copyright dedecms

  内容来自dedecms

procedure NewLine; 本文来自织梦

begin

织梦内容管理系统

WriteStr(#13#10);

织梦好,好织梦

WriteIndent;

copyright dedecms

end; dedecms.com

 

copyright dedecms

procedure ConvertHeader; 织梦内容管理系统

begin 本文来自织梦

织梦好,好织梦

end;

内容来自dedecms

 

copyright dedecms

procedure ConvertBinary;

本文来自织梦

begin

dedecms.com

织梦内容管理系统

end; 内容来自dedecms

  dedecms.com

procedure ConvertValue;

本文来自织梦

begin 内容来自dedecms

织梦好,好织梦

end; 织梦内容管理系统

 

织梦内容管理系统

procedure ConvertProperty; dedecms.com

begin 内容来自dedecms

织梦内容管理系统

end; copyright dedecms

  织梦好,好织梦

procedure ConvertObject; 织梦好,好织梦

begin dedecms.com

内容来自dedecms

end;

copyright dedecms

  织梦内容管理系统

begin dedecms.com

NestingLevel := 0;

织梦好,好织梦

Reader := TReader.Create(Input, 4096); 织梦内容管理系统

SaveSeparator := DecimalSeparator;

织梦好,好织梦

DecimalSeparator := '.';

本文来自织梦

try 织梦内容管理系统

Writer := TWriter.Create(Output, 4096); 织梦好,好织梦

try 内容来自dedecms

Reader.ReadSignature;

dedecms.com

ConvertObject; 内容来自dedecms

finally

织梦内容管理系统

Writer.Free;

dedecms.com

end;

织梦内容管理系统

finally

copyright dedecms

DecimalSeparator := SaveSeparator; 织梦好,好织梦

Reader.Free; 织梦内容管理系统

end; copyright dedecms

end;

内容来自dedecms

  dedecms.com

  过程中调用的ConvertObject过程是个递归过程,用于将DFM文件中的每一个部件转化为文本形式。因为由于部件的拥有关系,所以部件成嵌套结构,采用递归是最好的方式:

织梦内容管理系统

  dedecms.com

procedure ConvertObject; copyright dedecms

begin

内容来自dedecms

ConvertHeader;

织梦好,好织梦

Inc(NestingLevel);

内容来自dedecms

while not Reader.EndOfList do ConvertProperty; 内容来自dedecms

Reader.ReadListEnd; 织梦内容管理系统

while not Reader.EndOfList do ConvertObject; 织梦内容管理系统

Reader.ReadListEnd;

织梦好,好织梦

Dec(NestingLevel);

织梦内容管理系统

WriteIndent; copyright dedecms

WriteStr('end'#13#10); 本文来自织梦

end; dedecms.com

 

织梦内容管理系统

  NestStingLevel变量表示部件的嵌套层次。WriteIndent是写入每一行起始字符前的空格,ConvertHeader过程是处理部件的继承标志信息。转换成的头信息文本有两种形式。

织梦内容管理系统

  Inherited TestForm1: TTestForm[2] 织梦好,好织梦

  或者: copyright dedecms

Object TestForm1: TTestForm

织梦好,好织梦

  织梦内容管理系统

前者是ffInheritedffChildPos置位,后面是都没置位。

织梦内容管理系统

  ConvertProperty过程用于转化属性。

dedecms.com

  copyright dedecms

procedure ConvertProperty; 本文来自织梦

begin dedecms.com

WriteIndent; 织梦好,好织梦

WriteStr(Reader.ReadStr); 织梦好,好织梦

WriteStr(' = '); 织梦好,好织梦

ConvertValue;

内容来自dedecms

WriteStr(#13#10); 内容来自dedecms

end; 织梦内容管理系统

 

内容来自dedecms

  WriteIndent语句写入属性名前的空格,WriteStr(Reader.ReadStr)语句写入属性名ConvertValue过程根据属性的类型将属性值转化为字符串,然后写入流中。 内容来自dedecms

  ObjectTextToBinary过程执行的功能与ObjectBinaryToText相反,将TXT文件转换为二进制流中的部件,而且只要TXT文件内容的书写符合DFM脚本语法,ObjectTextToBinary可将任何程序生成的TXT文件转换为部件,这一功能也为DFM 文件的动态生成和编辑奠定了基础。ObjectTextToBinary过程的主程序如下:

dedecms.com

 

织梦好,好织梦

procedure ObjectTextToBinary(Input, Output: TStream); dedecms.com

var 织梦好,好织梦

SaveSeparator: Char; dedecms.com

Parser: TParser; copyright dedecms

Writer: TWriter;

本文来自织梦

  本文来自织梦

  本文来自织梦

   本文来自织梦

begin

dedecms.com

Parser := TParser.Create(Input); dedecms.com

SaveSeparator := DecimalSeparator;

织梦好,好织梦

DecimalSeparator := '.'; 织梦内容管理系统

try copyright dedecms

Writer := TWriter.Create(Output, 4096); copyright dedecms

try 内容来自dedecms

Writer.WriteSignature;

copyright dedecms

ConvertObject;

织梦好,好织梦

finally

内容来自dedecms

Writer.Free; dedecms.com

end; 织梦内容管理系统

finally 内容来自dedecms

DecimalSeparator := SaveSeparator; dedecms.com

Parser.Free; 织梦内容管理系统

end; copyright dedecms

end; 本文来自织梦

  织梦内容管理系统

  在程序流程和结构上与ObjectBinaryToText差不多。ConvertObject也是个递归过程: dedecms.com

  dedecms.com

procedure ConvertObject;

copyright dedecms

var 织梦好,好织梦

InheritedObject: Boolean; 织梦内容管理系统

begin

织梦好,好织梦

InheritedObject := False; dedecms.com

if Parser.TokenSymbolIs('INHERITED') then dedecms.com

InheritedObject := True

织梦好,好织梦

else copyright dedecms

Parser.CheckTokenSymbol('OBJECT');

织梦好,好织梦

Parser.NextToken; 织梦内容管理系统

ConvertHeader(InheritedObject); 本文来自织梦

while not Parser.TokenSymbolIs('END') and

织梦内容管理系统

not Parser.TokenSymbolIs('OBJECT') and

copyright dedecms

not Parser.TokenSymbolIs('INHERITED') do ConvertProperty; 织梦内容管理系统

Writer.WriteListEnd; 本文来自织梦

while not Parser.TokenSymbolIs('END') do ConvertObject;

本文来自织梦

Writer.WriteListEnd;

织梦好,好织梦

Parser.NextToken;

织梦内容管理系统

end;

织梦好,好织梦

  织梦好,好织梦

  DFM文件与DFM脚本语言之间相互转换的任务由ObjectResourceToTextObjextTextToResource两个过程完成。 本文来自织梦

 

织梦内容管理系统

procedure ObjectResourceToText(Input, Output: TStream);

本文来自织梦

begin

dedecms.com

Input.ReadResHeader; 内容来自dedecms

ObjectBinaryToText(Input, Output);

织梦好,好织梦

end; 织梦好,好织梦

 

织梦内容管理系统

ObjectTextToResource过程就比较复杂,因为DFM文件资源头中要包含继承标志信息,因此在调用ObjectTextToBinary后,就读取标志信息,然后写入资源头。

织梦内容管理系统

 

copyright dedecms

procedure ObjectTextToResource(Input, Output: TStream); copyright dedecms

var

织梦内容管理系统

Len: Byte; dedecms.com

Tmp: Longint; dedecms.com

MemoryStream: TMemoryStream; dedecms.com

MemorySize: Longint;

本文来自织梦

Header: array[0..79] of Char; 本文来自织梦

begin 本文来自织梦

MemoryStream := TMemoryStream.Create; 内容来自dedecms

try 织梦好,好织梦

ObjectTextToBinary(Input, MemoryStream);

内容来自dedecms

MemorySize := MemoryStream.Size;

织梦好,好织梦

FillChar(Header, SizeOf(Header), 0); dedecms.com

MemoryStream.Position := SizeOf(Longint); { Skip header } 内容来自dedecms

MemoryStream.Read(Len, 1);

织梦好,好织梦

if Len and $F0 = $F0 then dedecms.com

begin dedecms.com

if ffChildPos in TFilerFlags((Len and $F0)) then 内容来自dedecms

begin

内容来自dedecms

MemoryStream.Read(Len, 1);

dedecms.com

case TValueType(Len) of

织梦内容管理系统

vaInt8: Len := 1; copyright dedecms

vaInt16: Len := 2;

内容来自dedecms

vaInt32: Len := 4; copyright dedecms

end;

copyright dedecms

MemoryStream.Read(Tmp, Len);

copyright dedecms

end; 本文来自织梦

MemoryStream.Read(Len, 1);

织梦好,好织梦

end; 内容来自dedecms

MemoryStream.Read(Header[3], Len);

织梦内容管理系统

StrUpper(@Header[3]);

织梦内容管理系统

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

内容来自dedecms

Word((@Header[1])^) := 10; 织梦内容管理系统

Word((@Header[Len + 4])^) := $1030;

织梦内容管理系统

Longint((@Header[Len + 6])^) := MemorySize; copyright dedecms

Output.Write(Header, Len + 10); copyright dedecms

Output.Write(MemoryStream.Memory^, MemorySize);

织梦好,好织梦

finally 内容来自dedecms

MemoryStream.Free;

织梦内容管理系统

end; dedecms.com

end; 织梦好,好织梦

 

dedecms.com

20.3.1.5 动态DFM文件应用揭秘

织梦内容管理系统

 

织梦内容管理系统

  1. 动态DFM文件概述

本文来自织梦

动态DFM文件是相对于静态DFM文件而言。所谓静态DFM文件是指在Delphi开发环境中设计的窗体文件。窗体的设计过程就是程序的编制过程。因此,动态DFM文件就是指在程序运行过程生成或存取的DFM文件。

dedecms.com

  动态DFM文件的创建和使用分别如下两种情况: 内容来自dedecms

  ● 在程序运行过程中,由Create方法动态生成窗体或部件,然后动态生成其它部件插入其中生成DFM文件 织梦好,好织梦

  ● Delphi开发环境中,设计生成DFM文件,然后用DFM 文件存取函数,或者用Stream对象和Filer对象的方法,将DFM文件读入内存,进行处理,最后又存入磁盘中 本文来自织梦

 

内容来自dedecms

  由Delphi的窗体设计的常规方法生成的DFM文件在程序运行一开始就规定了部件的结构。因为在窗体设计过程中,窗体中的每个部件都在程序的对象声明中定义了部件变量。这种固定的结构虽然能方便应用,但以牺牲灵活性为代价。 内容来自dedecms

  在Delphi应用程序中有时需要在运行过程中创建控制,然后将该控制插入另一个部件中。例如: 织梦内容管理系统

 

copyright dedecms

procedure TForm1.Button1Click(Sender: Tobject);

dedecms.com

var

dedecms.com

Ctrl: TControl copyright dedecms

begin dedecms.com

Ctrl := TEdit.Create(Self);

本文来自织梦

Ctrl.Top := 100;

织梦内容管理系统

Ctrl.Left := 100;

织梦内容管理系统

Ctrl.Width := 150; 织梦内容管理系统

Ctrl.Height := 20; dedecms.com

InsertControl(Ctrl);

织梦内容管理系统

end; 织梦好,好织梦

  本文来自织梦

  动态插入控制的优点是可以在任何时刻、任意位置插入任意数量的任何类型的控制。因为应用程序需求在很多情况下是在程序运行中才知道的,所以动态插入控制就显得很重要。而且在很多情况下,需要保存这些界面元素,留待程序再次调用。例如应用程序界面的定制、系统状态的保存、对话框的保存等。这时生成动态DFM文件是最佳选择。

copyright dedecms

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

dedecms.com

  在使用动态DFM文件时有两点需要注意。

织梦好,好织梦

 ● 每一个动态插入的控制或部件必须在程序中调用RegisterClass进行注册 copyright dedecms

  ● 读入DFM文件自动创建部件后,如果调用了InsertControl方法, 则在关闭窗口时要调用RemoveControl方法移去该控制,否则会产生异常事件 织梦内容管理系统

  织梦内容管理系统

  2. 动态DFM文件应用之一:超媒体系统的卡片设计

织梦内容管理系统

  Delphi多种类型的可视部件,如文本部件、编辑部件、图形图像部件、数据库部件、媒体媒放部件和OLE部件等,每一种部件在屏幕中占据一定的区域,具有相当丰富的表现能力,可以作为卡片中的一种媒体,因此可以利用这些可视部件进行超媒体系统的卡片设计。 内容来自dedecms

  超媒体卡片设计要求卡片中的媒体数目和媒体种类是不受限制的,而且必须能够修改和存取卡片,因此,采用动态DFM文件是比较合适的。而且如果利用Stream对象,将卡片存储在数据库BLOB字段中,就为把超文本与关系数据库技术结合起来创造了契机。 dedecms.com

  下面是超媒体卡片设计子系统中的部分源程序,它演示了如何创建对象、插入对象和存取动态DFM文件。

内容来自dedecms

  ⑴ 在应用程序中注册对象

织梦好,好织梦

  copyright dedecms

procedure TMainForm.FormCreate(Sender: TObject); 织梦内容管理系统

begin 织梦内容管理系统

RegisterClass(TLabel); 织梦内容管理系统

RegisterClass(TEdit);

织梦好,好织梦

RegisterClass(TMemo); 织梦好,好织梦

RegisterClass(TButton);

织梦内容管理系统

RegisterClass(TPanel);

织梦好,好织梦

RegisterClass(TPanelP);

织梦内容管理系统

RegisterClass(TBitBtn);

dedecms.com

内容来自dedecms

end; 织梦内容管理系统

  织梦内容管理系统

创建和插入对象

dedecms.com

  copyright dedecms

procedure TMDIChild.FormClick(Sender: TObject); 内容来自dedecms

var dedecms.com

Ctrl : TControl;

copyright dedecms

Point: TPoint; 织梦好,好织梦

begin

内容来自dedecms

GetCursorPos(Point);

内容来自dedecms

Point := BackGround.ScreenToClient(Point); 织梦内容管理系统

case CurToolIndex of 本文来自织梦

1 : begin

织梦内容管理系统

Ctrl := TLabel.Create(self); copyright dedecms

TLabel(Ctrl).AutoSize := False; copyright dedecms

TLabel(ctrl).Caption := 'Label'+S;

内容来自dedecms

TLabel(ctrl).Name := 'Label 1'; 内容来自dedecms

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 := clWhite; 内容来自dedecms

TLabel(Ctrl).Font.Color := clBlack;

织梦内容管理系统

TLabel(Ctrl).Font.Name := 'Roman'; copyright dedecms

TLabel(Ctrl).Font.Height := -TLabel(Ctrl).Height; 内容来自dedecms

TLabel(Ctrl).Font.Pitch := fpFixed;

织梦好,好织梦

TLabel(Ctrl).Enabled := False; dedecms.com

TLabel(Ctrl).OnClick := LabelClick; 本文来自织梦

TLabel(Ctrl).OnMouseMove := ReportPos;

内容来自dedecms

BackGround.InsertControl(Ctrl);

dedecms.com

CurTool.Down := False;

本文来自织梦

CurTool := nil; 本文来自织梦

本文来自织梦

end; 织梦内容管理系统

2: begin

本文来自织梦

Ctrl := TEdit.Create(self); 织梦内容管理系统

TEdit(ctrl).AutoSize := True; copyright dedecms

TEdit(ctrl).Top := Point.Y;

织梦好,好织梦

TEdit(ctrl).Left := Point.X;

织梦好,好织梦

TEdit(Ctrl).Height := 20;

本文来自织梦

BackGround.InsertControl(Ctrl);

本文来自织梦

织梦内容管理系统

end;

内容来自dedecms

3:

内容来自dedecms

copyright dedecms

end;

copyright dedecms

end; 织梦好,好织梦

  

本文来自织梦

  ⑵ 存取动态DFM文件 织梦好,好织梦

  本文来自织梦

procedure TMainForm.FileOpen(Sender: TObject);

本文来自织梦

begin

织梦好,好织梦

if OpenDialog.Execute then 织梦内容管理系统

begin

本文来自织梦

DesignWin := TMDIChild.Create(Application);

织梦好,好织梦

ReadComponentResFile(OpenDialog.FileName, DesignWin); copyright dedecms

DesignWin.Init; 本文来自织梦

FileName := OpenDialog.FileName;

本文来自织梦

DesignWin.Caption := FFileName; 本文来自织梦

end; 内容来自dedecms

end; 织梦内容管理系统

 

织梦好,好织梦

  DesignWin是在TMainForm中定义的TMDIChild类型的窗体部件,是卡片设计平台;FFileName是私有变量,用来保存当前编辑的卡片文件名。DesignWinInit方法实现如下: 本文来自织梦

 

内容来自dedecms

procedure TMDIChild.Init;

本文来自织梦

var

dedecms.com

I: Integer; 织梦好,好织梦

Ctrl: TControl; 本文来自织梦

begin 织梦好,好织梦

BackGround.BringToFront;

dedecms.com

with BackGround do

dedecms.com

for I:= 0 to ControlCount - 1 do

织梦内容管理系统

if Controls[I].Name <> ''then 织梦好,好织梦

ObjectIns.ObjectList.Items.AddObject(Controls[I].Name, Controls[I]); dedecms.com

end; dedecms.com

 

内容来自dedecms

  BackGroundTPanel类型的部件,所有的动态创建对象都插入到BackGround中,所以,后面调用BackGround.InsertControl(Ctrl)ObjectIns是个仿Delphi 的媒体属性编辑器。

本文来自织梦

  动态DFM文件的存储过程是这样的:

本文来自织梦

  本文来自织梦

procedure TMainForm.FileSave(Sender: TObject); 织梦内容管理系统

begin

内容来自dedecms

if DesignWin.CurControl <> nil then

本文来自织梦

DesignWin.CurControl.Enabled := True; 织梦内容管理系统

WriteComponentResFile(FFilename, DesignWin);

本文来自织梦

DesignWin.Caption := FileName;

织梦内容管理系统

end;

内容来自dedecms

end;

本文来自织梦

 

织梦好,好织梦

  因为在DesignWinInit方法中调用了InsertControl方法,所以在关闭DesignWin窗口时要相应地调用RemoveControl,否则在关闭DesignWin窗口时会产生内存错误。

copyright dedecms

 

织梦内容管理系统

procedure TMDIChild.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 织梦好,好织梦

var

织梦好,好织梦

I: Integer; 本文来自织梦

Ctrl: TControl; 内容来自dedecms

Removed: Boolean;

dedecms.com

begin dedecms.com

if Modified = True then

dedecms.com

if MessageDlg('Close the form?', mtConfirmation, copyright dedecms

[mbOk, mbCancel], 0) = mrCancel then copyright dedecms

CanClose := False;

内容来自dedecms

if CanClose = True then copyright dedecms

begin 内容来自dedecms

repeat 内容来自dedecms

removed := False; 织梦内容管理系统

I := 0; 内容来自dedecms

repeat

copyright dedecms

if BackGround.Controls[I].Name <> '' then 织梦内容管理系统

begin

copyright dedecms

BackGround.RemoveControl(BackGround.Controls[I]);

内容来自dedecms

Removed := True; dedecms.com

end;

dedecms.com

I := I + 1 copyright dedecms

until (I >= BackGround.ControlCount) or (Removed = True);

内容来自dedecms

until (Removed = False);

dedecms.com

SendMessage(ObjectIns.Handle, WM_MDICHILDCLOSED, 0, 0);

织梦好,好织梦

end;

织梦内容管理系统

end; copyright dedecms

  copyright dedecms

  3. 动态DFM文件应用之二:超媒体系统脚本语言设计

dedecms.com

  超媒体脚本语言设计是超媒体系统设计的重要内容。脚本语言必须能够表达卡片中的多种媒体对象,必须是可编程,可理解的,必须是可执行的,应该可以由脚本语言生成超媒体系统中的卡片和链。

内容来自dedecms

  DFM文件可以看作是超媒体系统的卡片,DFM脚本能够表达DFM文件中的多种控制,也就是说能够表达卡片中的多种媒体对象,再加上DFM脚本的对象式表达,可编辑性,可转换为DFM文件,因此用作超媒体系统脚本语言较好的形式。 本文来自织梦

  ObjectBinaryToTextObjectTextToBinary过程提供了在部件和DFM脚本之间相互转化的功能,ObjectResourceToTextObjectTextToResoure过程提供了DFM文件和DFM脚本之间相互转化的功能。这样就可以在应用程序中自如实现超媒体卡片和超媒体脚本语言相互转化。 织梦内容管理系统

  织梦内容管理系统

  下面是卡片和脚本语言相互转化的程序: 内容来自dedecms

  dedecms.com

procedure TMDIChild.CardToScript;

dedecms.com

var 织梦好,好织梦

In, Out: TStream; copyright dedecms

begin 本文来自织梦

In := TMemoryStream.Create; 织梦内容管理系统

Out := TMemoryStream.Create; dedecms.com

try

织梦好,好织梦

In.WriteComponentRes(Self.ClassName, Self);

dedecms.com

ObjectResourceToText(In, out); 织梦好,好织梦

ScriptForm.ScriptEdit.Lines.LoadFromStream(Out); 内容来自dedecms

finally

dedecms.com

In.Free;

copyright dedecms

Out.Free;

织梦好,好织梦

end;

织梦内容管理系统

end;

dedecms.com

  内容来自dedecms

  ScriptEdit是个文本编辑器,它的Lines属性是TStrings类型的对象。 内容来自dedecms

  内容来自dedecms

procedure TScriptForm.ScriptToCard;

本文来自织梦

var 本文来自织梦

In, Out: TStream;

织梦好,好织梦

begin

织梦内容管理系统

In := TMemoryStream.Create; copyright dedecms

Out := TMemoryStream.Create; 本文来自织梦

try

织梦好,好织梦

ScriptForm.ScriptEdit.Lines.SaveToFromStream(In);

copyright dedecms

ObjectTextToResource(In, out); copyright dedecms

In.ReadComponentRes(DesignWin);

内容来自dedecms

finally copyright dedecms

In.Free; 织梦好,好织梦

Out.Free; copyright dedecms

end;

copyright dedecms

end; copyright dedecms

  dedecms.com

  这两段程序是对整个卡片,即窗体级,进行转换的。ObjectBinaryToTextObjectTextToBinary过程可以细化到部件级的转换。因此超媒体脚本语言的编辑可以细化到媒体对象级。 本文来自织梦

  4. 超媒体编辑和表现系统与动态DFM文件的扩展 dedecms.com

  超媒体系统的媒体编辑与卡片管理有其特殊的需求,比如链接需求。这时采用已有的窗体部件和媒体部件并按常规的DFM文件处理就显得力不从心了。解决这个矛盾有两套方案: 织梦好,好织梦

  利用Delphi部件开发技术,继承和开发新的部件增加新的超媒体特有的属性和处理方法

织梦内容管理系统

  ● 扩展DFM文件结构,使之能按自己的需要任意地存取和转换部件和DFM文件

织梦好,好织梦

  织梦内容管理系统

  前者是充分利用Delphi的面向对象部件开发技术,在存取和转换等处理上仍旧与常规DFM文件相同。而后者需要DFM的存取和转换上作比较大的改动。下文介绍扩展DFM文件的思路。

本文来自织梦

  扩展动态DFM文件的总体思路是降低处理操作的数据的颗粒度,即从原先窗体级降低到部件级。 织梦好,好织梦

  下面是存取操作的扩展示范:

copyright dedecms

 

本文来自织梦

  var dedecms.com

FileStream: TStream;

织梦好,好织梦

I: Integer;

copyright dedecms

begin 本文来自织梦

FileStream := TFileStream.Create('OverView.Crd', fmOpenWrite);

copyright dedecms

With TWriter.Create(FileStream, 4096) do copyright dedecms

try copyright dedecms

for I := 0 to DesignWin.ControlCount - 1 do

内容来自dedecms

begin

dedecms.com

WriteInteger(MMID[i]);

织梦内容管理系统

WriteRootComponent(DesignWin.Controls[i]);

织梦内容管理系统

{ 写相应媒体扩展信息 }

织梦内容管理系统

  ……

dedecms.com

   end; 本文来自织梦

WriteListEnd; 织梦内容管理系统

finally.

织梦内容管理系统

Free; 内容来自dedecms

end;

dedecms.com

FileStream.Free;

织梦内容管理系统

end; 织梦好,好织梦

 

织梦内容管理系统

WriteInteger(MMID[i])语句是写入媒体标识。 内容来自dedecms

  下面是相应的读扩展DFM的程序: 织梦好,好织梦

 

内容来自dedecms

  var copyright dedecms

PropInfo: PPropInfo;

织梦好,好织梦

Method : TMethod; dedecms.com

FileStream: TStream; 本文来自织梦

I: Integer;

织梦内容管理系统

begin copyright dedecms

FileStream := TFileStream.Create('OverView.Crd', fmOpenRead);

织梦内容管理系统

With TReader.Create(FileStream, 4096) do 本文来自织梦

try 织梦好,好织梦

while not EndOfList do 织梦内容管理系统

begin 本文来自织梦

case ReadInteger of dedecms.com

IDText: begin copyright dedecms

Ctrl := TControl(ReadRootComponent(nil));

本文来自织梦

PropInfo := GetPropInfo(Ctrl.ClassInfo, 'OnClick'); 织梦内容管理系统

Method.Code:= Self.MethodAddress(MethodName);

织梦内容管理系统

Method.Data := Self;

本文来自织梦

if Method.Code <> nil then

dedecms.com

SetMethodProp(Ctrl, PropInfo, Method);

织梦好,好织梦

DesignWin.InsertControl(Ctrl); copyright dedecms

end; 本文来自织梦

IDImage: 内容来自dedecms

  …… dedecms.com

  end; 本文来自织梦

   ……

织梦内容管理系统

WriteListEnd; 织梦好,好织梦

end; 织梦好,好织梦

finally. 本文来自织梦

Free; 织梦好,好织梦

end; 内容来自dedecms

FileStream.Free; 内容来自dedecms

end;

织梦内容管理系统

 

内容来自dedecms

  SetMethodProp过程是用于重新联接控制和它的事件处理过程。类似的功能还可以用TReader对象的OnFindMethod事件的处理过程来实现。 dedecms.com

  实现脚本语言扩展的基本方法与存取扩展类似,但它还要加扩展媒体信息转换为文本,并插入到部件的脚本描述中。

织梦好,好织梦

 

织梦好,好织梦

20.3.2 数据库BLOB字段应用 内容来自dedecms

 

织梦好,好织梦

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

织梦好,好织梦

  dedecms.com

20.3.2.1 TBlobStream的使用 本文来自织梦

 

copyright dedecms

  TBlobStream对象用一个TBlobField类型的对象作为参数来创建与BLOB字段相联的BLOB流,接着就可用流的存取方法在BLOB字段中存取数据。 织梦内容管理系统

  织梦好,好织梦

  var 织梦好,好织梦

BlobStream: TBlobStream; 织梦好,好织梦

I: Integer; 织梦内容管理系统

begin

内容来自dedecms

BlobStream := TBlobStream.Create(TBlobField(CardTable.Fields[10], bmWrite);

本文来自织梦

With TWriter.Create(BlobStream, 4096) do 本文来自织梦

try

copyright dedecms

for I := 0 to DesignWin.ControlCount - 1 do

织梦好,好织梦

begin 本文来自织梦

WriteInteger(MMID[i]); copyright dedecms

WriteRootComponent(DesignWin.Controls[i]);

copyright dedecms

{ 写相应媒体扩展信息 }

copyright dedecms

  ……

织梦内容管理系统

   end; 织梦好,好织梦

WriteListEnd;

织梦内容管理系统

finally.

copyright dedecms

Free;

织梦好,好织梦

end;

本文来自织梦

BlobStream.Free;

copyright dedecms

CardTable.Post; 织梦内容管理系统

end;

本文来自织梦

 

dedecms.com

  Fields变量是表示数据库记录的字段数组,Fields[10]正是数据库的BLOB 字段。CardTablePost方法将数据库的修改反馈到数据库的物理存储上。

织梦内容管理系统

  上面这段程序是超媒体卡片存储的部分源程序,我们就是将卡片保存在数据库BLOB字段中,实现将超文本和关系数据库两种数据管理方式结合起来。读卡片的程序如下: 织梦内容管理系统

  dedecms.com

  var

dedecms.com

PropInfo: PPropInfo;

织梦内容管理系统

Method: TMethod; 本文来自织梦

Blobtream: TStream;

dedecms.com

I: Integer;

织梦好,好织梦

begin

copyright dedecms

BlobStream := TBlobStream.Create(TBlobField(CardTable.Fields[10]), bmRead); dedecms.com

With TReader.Create(BlobStream, 4096) do

内容来自dedecms

try

内容来自dedecms

while not EndOfList do 织梦内容管理系统

begin 织梦好,好织梦

case ReadInteger of

织梦好,好织梦

IDText: begin 织梦好,好织梦

Ctrl := TControl(ReadRootComponent(nil));

内容来自dedecms

PropInfo := GetPropInfo(Ctrl.ClassInfo, 'OnClick');

本文来自织梦

Method.Code:= Self.MethodAddress(MethodName); 织梦好,好织梦

Method.Data := Self; 本文来自织梦

if Method.Code <> nil then copyright dedecms

SetMethodProp(Ctrl, PropInfo, Method);

本文来自织梦

DesignWin.InsertControl(Ctrl); 本文来自织梦

end;

copyright dedecms

IDImage: 织梦内容管理系统

  …… 织梦好,好织梦

  end; copyright dedecms

   …… 织梦内容管理系统

WriteListEnd; dedecms.com

end; 本文来自织梦

finally.

织梦内容管理系统

Free;

本文来自织梦

end;

copyright dedecms

FileStream.Free; copyright dedecms

end;

dedecms.com

 

织梦内容管理系统

20.3.2.2 BLOB字段与图形图像

内容来自dedecms

  内容来自dedecms

  在多媒体数据库中处理得比较多的是图形图像,因此早期的多媒体数据库在扩展关系数据库时往往是增加一个图像字段。BLOB字段是以二进制数据存储方式,因此它完全可以表达图形图像数据。 织梦内容管理系统

  在TBlobField对象中提供了LoadFromBitMapSaveToBitMap方法存取位图数据。它们在实现上都是使用BlobStream对象。

本文来自织梦

 

copyright dedecms

procedure TBlobField.LoadFromBitmap(Bitmap: TBitmap);

dedecms.com

var

本文来自织梦

BlobStream: TBlobStream;

内容来自dedecms

Header: TGraphicHeader;

织梦内容管理系统

begin

织梦内容管理系统

BlobStream := TBlobStream.Create(Self, bmWrite);

dedecms.com

try

copyright dedecms

if (DataType = ftGraphic) or (DataType = ftTypedBinary) then 本文来自织梦

begin

织梦内容管理系统

Header.Count := 1; 织梦好,好织梦

Header.HType := $0100; 织梦好,好织梦

Header.Size := 0; 织梦好,好织梦

BlobStream.Write(Header, SizeOf(Header)); copyright dedecms

Bitmap.SaveToStream(BlobStream); 织梦内容管理系统

Header.Size := BlobStream.Position - SizeOf(Header);

copyright dedecms

BlobStream.Position := 0; 内容来自dedecms

BlobStream.Write(Header, SizeOf(Header));

内容来自dedecms

end else 本文来自织梦

Bitmap.SaveToStream(BlobStream); 内容来自dedecms

finally

本文来自织梦

BlobStream.Free;

内容来自dedecms

end; dedecms.com

end; 本文来自织梦

 

织梦好,好织梦

procedure TBlobField.SaveToBitmap(Bitmap: TBitmap); dedecms.com

var 本文来自织梦

BlobStream: TBlobStream;

本文来自织梦

Size: Longint; 织梦内容管理系统

Header: TGraphicHeader; dedecms.com

begin dedecms.com

BlobStream := TBlobStream.Create(Self, bmRead); 织梦好,好织梦

try

内容来自dedecms

Size := BlobStream.Size; copyright dedecms

if Size >= SizeOf(TGraphicHeader) then 内容来自dedecms

begin 织梦内容管理系统

BlobStream.Read(Header, SizeOf(Header));

内容来自dedecms

if (Header.Count <> 1) or (Header.HType <> $0100) or

织梦内容管理系统

(Header.Size <> Size - SizeOf(Header)) then

copyright dedecms

BlobStream.Position := 0; 内容来自dedecms

end; copyright dedecms

Bitmap.LoadFromStream(BlobStream); 织梦内容管理系统

finally 织梦好,好织梦

BlobStream.Free; copyright dedecms

end;

织梦内容管理系统

end;

本文来自织梦

  织梦内容管理系统

程序中按两种方式存取数据,对于位图数据,数据的起点是流的Potition0处,对于图形或其它类型的Blob数据,则以流的PositionSizeOf(Header) + 1处开始, 即多了个头信息。

织梦好,好织梦

 

织梦内容管理系统

20.3.2.3 BLOB字段与文本

内容来自dedecms

  织梦好,好织梦

  Delphi BLOB字段中增加了大型文本的处理能力。可以在TBlobFieldStrings中自由地交换数据。 织梦内容管理系统

 

dedecms.com

procedure TBlobField.LoadFromStrings(Strings: TStrings);

dedecms.com

var

copyright dedecms

BlobStream: TBlobStream; 本文来自织梦

begin 织梦好,好织梦

BlobStream := TBlobStream.Create(Self, bmWrite);

dedecms.com

try 本文来自织梦

Strings.SaveToStream(BlobStream); dedecms.com

finally

内容来自dedecms

BlobStream.Free; copyright dedecms

end;

织梦好,好织梦

end; 本文来自织梦

  copyright dedecms

procedure TBlobField.SaveToStrings(Strings: TStrings); dedecms.com

var 织梦内容管理系统

BlobStream: TBlobStream; copyright dedecms

begin

本文来自织梦

BlobStream := TBlobStream.Create(Self, bmRead);

copyright dedecms

try dedecms.com

Strings.LoadFromStream(BlobStream);

copyright dedecms

finally copyright dedecms

BlobStream.Free; 内容来自dedecms

end; 织梦好,好织梦

end; dedecms.com

 

dedecms.com

20.3.2.4 BLOB字段与Stream对象

dedecms.com

 

copyright dedecms

  因为Delphi中,BLOB字段是通过BLOB流来访问的,所以可以很容易地在BLOB字段和Stream对象之间传递数据。为此,TBlobField对象提供了LoadFromStreamSaveToStream方法。

内容来自dedecms

 

本文来自织梦

procedure TBlobField.LoadFromStream(Stream: TStream);

copyright dedecms

var

内容来自dedecms

BlobStream: TBlobStream; 织梦内容管理系统

begin 内容来自dedecms

BlobStream := TBlobStream.Create(Self, bmWrite); dedecms.com

try 织梦内容管理系统

BlobStream.CopyFrom(Stream, 0); dedecms.com

finally

内容来自dedecms

BlobStream.Free;

织梦好,好织梦

end;

copyright dedecms

end;

织梦好,好织梦

 

本文来自织梦

procedure TBlobField.SaveToStream(Stream: TStream);

本文来自织梦

var 内容来自dedecms

BlobStream: TBlobStream;

织梦好,好织梦

begin dedecms.com

BlobStream := TBlobStream.Create(Self, bmRead); dedecms.com

try 内容来自dedecms

Stream.CopyFrom(BlobStream, 0); dedecms.com

finally

copyright dedecms

BlobStream.Free; dedecms.com

end;

内容来自dedecms

end; 织梦内容管理系统

 

内容来自dedecms

20.3.3 存取嵌入在OleContainer对象中的OLE服务器的数据

织梦好,好织梦

  织梦内容管理系统

  对象链接和嵌入(Object Linking and Embedding,简称OLE),是一组服务功能,它提供了一种用来源于不同应用程序的信息创建复合文档的强有力方法。

织梦好,好织梦

  通过把图像、图形、表格、声音、注解、文件和其它表示手段描述成对象,用它能在不同软件厂家提供的应用程序中更为容易地交换合成和处理数据它是应用程序的集成更为容易。OLE2.0支持直观编辑。用户不需切换到不同窗口就能在文档中直接对对象进行操作,改进了操作环境。用户不用再关注应用程序和操作环境,只需关注于使用对象技术的数据和文件,便能完成全部工作。

织梦好,好织梦

  OLE已成为操作系统功能上的一大标准,各大软商纷纷在开发工具中支持OLE 2.0规范。Delphi 2.0提供了OleContainer对象支持OLE窗户应用程序的开发。

内容来自dedecms

  尽管通过OLE可以用来源于不同应用程序的信息创建复合文档,充分体现以任务、以文档为中心的思想,但是很难分解来自其它应用程序中的嵌入数据,以进行特殊的处理。

本文来自织梦

  例如,一套多媒体电子文档管理系统,系统需要数据库管理功能文档编辑功能,全文检索功能等。在文档编辑功能的实现上,如果能利用中文Word 或写字板之类的强大的编辑排版功能,就可以省却重新开发一个文档编辑的费用,使用具有直观编辑的OLE复合文档嵌入WordDOC数据或RTF数据当然是最佳的选择。 但问题在于全文检索系统要求能直接在文档中搜索关键字,因此要求将文档数据从OLE嵌入数据或文档中的本地数据中分离出来。 织梦内容管理系统

  Delphi 2.0OleContainer部件支持存储OLE对象数据。OLE对象数据包括两部分:OLE类描述信息和OLE服务器嵌入数据。一般说来,OLE服务器嵌入数据是以服务器支持的数据格式存储的; 比方说,中文Word 6.0的嵌入数据的格式就是Word 6.0文档的格式。因此,要将文档数据从OLE 嵌入式文档中分离出来就是要访问第二部分数据。 内容来自dedecms

我们分析了Delphi 2.0OleContainer对象存取复合文档的程序,得到分离数据的方法。 dedecms.com

  让我们来看一段OleContainer对象存储数据的程序:

织梦内容管理系统

  copyright dedecms

procedure TOleContainer.SaveToStream(Stream: TStream); 内容来自dedecms

var

copyright dedecms

DataHandle: HGlobal;

本文来自织梦

Buffer: Pointer;

织梦内容管理系统

Header: TStreamHeader;

织梦内容管理系统

R: TRect;

织梦内容管理系统

 ……

织梦好,好织梦

begin 本文来自织梦

   …… 织梦好,好织梦

try

dedecms.com

   ……

内容来自dedecms

if FOldStreamFormat then

本文来自织梦

begin copyright dedecms

R := BoundsRect; 本文来自织梦

Header.PartRect.Left := R.Left; 织梦好,好织梦

Header.PartRect.Top := R.Top;

dedecms.com

Header.PartRect.Right := R.Right;

本文来自织梦

Header.PartRect.Bottom := R.Bottom;

copyright dedecms

end else copyright dedecms

begin

copyright dedecms

Header.Signature := StreamSignature;

copyright dedecms

Header.DrawAspect := FDrawAspect;

本文来自织梦

end;

dedecms.com

Header.DataSize := GlobalSize(DataHandle); copyright dedecms

Stream.WriteBuffer(Header, SizeOf(Header));

本文来自织梦

Buffer := GlobalLock(DataHandle);

本文来自织梦

try

dedecms.com

Stream.WriteBuffer(Buffer^, Header.DataSize);

本文来自织梦

finally

dedecms.com

GlobalUnlock(DataHandle); 本文来自织梦

end; copyright dedecms

finally

织梦内容管理系统

ReleaseObject(TempStorage);

本文来自织梦

ReleaseObject(TempLockBytes);

dedecms.com

end; 织梦好,好织梦

end; copyright dedecms

  织梦内容管理系统

程序中,OleContainer对象执行了两次往流中写数据的操作。

dedecms.com

   Stream.WriteBuffer(Header, Size(Header)); 织梦内容管理系统

Stream.WriteBuffer(Buffer^, Header.DataSize);

copyright dedecms

 

dedecms.com

前一语句是写入OLE类描述信息,后一句语句是写入OLE服务器的嵌入数据。HeaderTStreamHeader记录类型的变量。TStreamHeader记录的定义如下:

copyright dedecms

  织梦内容管理系统

TStreamHeader = record

本文来自织梦

case Integer of 本文来自织梦

0: ( { 新版OLE对象 }

本文来自织梦

Signature: Integer; dedecms.com

DrawAspect: Integer; 本文来自织梦

DataSize: Integer); 织梦内容管理系统

1: ( { 旧版OLE对象 } copyright dedecms

PartRect: TSmallRect);

织梦内容管理系统

end;

内容来自dedecms

  织梦好,好织梦

  因此读OLE服务器嵌入数据时,要跳过文件头的TStreamHeader记录。下面就是如何分离OLE服务器嵌入数据的程序:

织梦内容管理系统

  dedecms.com

var

本文来自织梦

Stream : TMemoryStream;

dedecms.com

FileStream : TFileStream; 本文来自织梦

begin dedecms.com

Stream := TMemoryStream.Create;

织梦好,好织梦

FileStream := TFileStream.Create('TEST.DOC', fmCreate) ;

dedecms.com

with OleContainer1 do copyright dedecms

if (State <> osEmpty) then

内容来自dedecms

SaveToStream(Stream); 内容来自dedecms

Stream.Seek(Sizeof(TStreamHeader), 0); 织梦好,好织梦

FileStream.CopyFrom(Stream, Stream.Size - SizeOf(TStreamHeader));

织梦好,好织梦

Stream.Free;

织梦内容管理系统

FileStream.Free;

织梦好,好织梦

end;

本文来自织梦

  copyright dedecms

OleContainer1包含的服务器对象是中文Word 6.0,程序中将分离出的数据存储在磁盘文件“TEST.DOC”上。如果希望存储在不同的媒介上,可以使用相应的Stream对象,分离的方法类似。但是,这种方法并非对所有的OLE服务器数据都适用,如Windows 95 附件中的写字板(WordPad)就不行。 内容来自dedecms

 

copyright dedecms

  织梦内容管理系统

精彩推荐
热点内容
最近更新