精品推荐
阅读排行
· 查看svchost.exe进程· PRO/E 十种技巧
· [组图] 3ds Max 高级长篇人
· [组图] PRO/E的曲面设计
· 怎样学好PRO/E软件?
· 路由技术介绍
· Pro/ENGINEER 学习资
· [组图] Photoshop制作珠宝文
· xml的应用是什么?x
· [组图] flash人物绘画教程
| 作者:佚名 来源:www.pccode.net 整理 发布时间:2006-3-8 16:14:53 发布人:wongrs |
| 20.3.1.5 动态DFM
1. 动态 动态DFM 动态DFM文件的创建和使用分别如下两种情况: ● 在程序运行过程中,由 ● 在
由Delphi的窗体设计的常规方法生成的 在Delphi应用程序中有时需要在运行过程中创建控制,然后将该控制插入另一个部件中。例如:
procedure TForm1.Button1Click(Sender: Tobject); var Ctrl: TControl begin Ctrl := TEdit.Create(Self); Ctrl.Top := 100; Ctrl.Left := 100; Ctrl.Width := 150; Ctrl.Height := 20; InsertControl(Ctrl); end;
动态插入控制的优点是可以在任何时刻、任意位置插入任意数量的任何类型的控制。因为应用程序需求在很多情况下是在程序运行中才知道的,所以动态插入控制就显得很重要。而且在很多情况下,需要保存这些界面元素,留待程序再次调用。例如应用程序界面的定制、系统状态的保存、对话框的保存等。这时生成动态 动态插入控制的不足之处是在插入控制前,无法直观地看到控制的大小、风格、位置等,也就是动态插入控制的过程是非可视化的。但可以借助于静态 在使用动态DFM文件时有两点需要注意。 ● ● 读入
2. 动态 Delphi多种类型的可视部件,如文本部件、编辑部件、图形图像部件、数据库部件、媒体媒放部件和 超媒体卡片设计要求卡片中的媒体数目和媒体种类是不受限制的,而且必须能够修改和存取卡片,因此,采用动态 下面是超媒体卡片设计子系统中的部分源程序,它演示了如何创建对象、插入对象和存取动态 ⑴ 在应用程序中注册对象
procedure TMainForm.FormCreate(Sender: TObject); begin RegisterClass(TLabel); RegisterClass(TEdit); RegisterClass(TMemo); RegisterClass(TButton); RegisterClass(TPanel); RegisterClass(TPanelP); RegisterClass(TBitBtn); … end;
⑵
procedure TMDIChild.FormClick(Sender: TObject); var Ctrl : TControl; Point: TPoint; begin GetCursorPos(Point); Point := BackGround.ScreenToClient(Point); case CurToolIndex of 1 : begin Ctrl := TLabel.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 := clWhite; 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); CurTool.Down := False; CurTool := nil; … end; 2: begin Ctrl := 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;
⑵ 存取动态
procedure TMainForm.FileOpen(Sender: TObject); begin if OpenDialog.Execute then begin DesignWin := TMDIChild.Create(Application); ReadComponentResFile(OpenDialog.FileName, DesignWin); DesignWin.Init; FileName := OpenDialog.FileName; DesignWin.Caption := FFileName; end; end;
DesignWin是在
procedure TMDIChild.Init; var I: Integer; Ctrl: TControl; begin BackGround.BringToFront; with BackGround do for I:= 0 to ControlCount - 1 do if Controls[I].Name <> ''then ObjectIns.ObjectList.Items.AddObject(Controls[I].Name, Controls[I]); end;
BackGround是 动态DFM文件的存储过程是这样的:
procedure TMainForm.FileSave(Sender: TObject); begin if DesignWin.CurControl <> nil then DesignWin.CurControl.Enabled := True; WriteComponentResFile(FFilename, DesignWin); DesignWin.Caption := FileName; end; end;
因为在DesignWin的Init方法中调用了
procedure TMDIChild.FormCloseQuery(Sender: TObject; varCanClose: Boolean); var I: Integer; Ctrl: TControl; Removed: Boolean; begin if Modified = True then if MessageDlg('Close the form?', mtConfirmation, [mbOk, mbCancel], 0) = mrCancel then CanClose := False; if CanClose = True then begin repeat removed := False; I := 0; repeat if BackGround.Controls[I].Name <> '' then begin BackGround.RemoveControl(BackGround.Controls[I]); Removed := True; end; I := I + 1 until (I >= BackGround.ControlCount) or (Removed = True); until (Removed = False); SendMessage(ObjectIns.Handle, WM_MDICHILDCLOSED, 0, 0); end; end;
3. 动态 超媒体脚本语言设计是超媒体系统设计的重要内容。脚本语言必须能够表达卡片中的多种媒体对象,必须是可编程,可理解的,必须是可执行的,应该可以由脚本语言生成超媒体系统中的卡片和链。 DFM文件可以看作是超媒体系统的卡片, ObjectBinaryToText和ObjectTextToBinary过程提供了在部件和DFM
下面是卡片和脚本语言相互转化的程序:
procedure TMDIChild.CardToScript; var In, Out: TStream; begin In := TMemoryStream.Create; Out := TMemoryStream.Create; try In.WriteComponentRes(Self.ClassName, Self); ObjectResourceToText(In, out); ScriptForm.ScriptEdit.Lines.LoadFromStream(Out); finally In.Free; Out.Free; end; end;
ScriptEdit是个文本编辑器,它的
procedure TScriptForm.ScriptToCard; var In, Out: TStream; begin In := TMemoryStream.Create; Out := TMemoryStream.Create; try ScriptForm.ScriptEdit.Lines.SaveToFromStream(In); ObjectTextToResource(In, out); In.ReadComponentRes(DesignWin); finally In.Free; Out.Free; end; end;
这两段程序是对整个卡片,即窗体级,进行转换的。 4. 超媒体编辑和表现系统与动态 超媒体系统的媒体编辑与卡片管理有其特殊的需求,比如链接需求。这时采用已有的窗体部件和媒体部件并按常规的 ● 扩展
前者是充分利用Delphi的面向对象部件开发技术,在存取和转换等处理上仍旧与常规 扩展动态DFM文件的总体思路是降低处理操作的数据的颗粒度,即从原先窗体级降低到部件级。 下面是存取操作的扩展示范:
var FileStream: TStream; I: Integer; begin FileStream := TFileStream.Create('OverView.Crd', fmOpenWrite); With TWriter.Create(FileStream, 4096) do try for I := 0 to DesignWin.ControlCount - 1 do begin WriteInteger(MMID[i]); WriteRootComponent(DesignWin.Controls[i]); { 写相应媒体扩展信息 …… end; WriteListEnd; finally. Free; end; FileStream.Free; end;
WriteInteger(MMID[i])语句是写入媒体标识。 下面是相应的读扩展DFM
var PropInfo: PPropInfo; Method : TMethod; FileStream: TStream; I: Integer; begin FileStream := TFileStream.Create('OverView.Crd', fmOpenRead); With TReader.Create(FileStream, 4096) do try while not EndOfList do begin case ReadInteger of IDText: begin Ctrl := TControl(ReadRootComponent(nil)); PropInfo := GetPropInfo(Ctrl.ClassInfo, 'OnClick'); Method.Code:= Self.MethodAddress(MethodName); Method.Data := Self; if Method.Code <> nil then SetMethodProp(Ctrl, PropInfo, Method); DesignWin.InsertControl(Ctrl); end; IDImage: …… end; WriteListEnd; end; finally. Free; end; FileStream.Free; end;
SetMethodProp过程是用于重新联接控制和它的事件处理过程。类似的功能还可以用 实现脚本语言扩展的基本方法与存取扩展类似,但它还要加扩展媒体信息转换为文本,并插入到部件的脚本描述中。
20.3.2 数据库BLOB
Delphi VCL提供了
20.3.2.1 TBlobStream的使用
TBlobStream对象用一个
var BlobStream: TBlobStream; I: Integer; begin BlobStream := TBlobStream.Create(TBlobField(CardTable.Fields[10], bmWrite); With TWriter.Create(BlobStream, 4096) do try for I := 0 to DesignWin.ControlCount - 1 do begin WriteInteger(MMID[i]); WriteRootComponent(DesignWin.Controls[i]); { 写相应媒体扩展信息 …… end; WriteListEnd; finally. Free; end; BlobStream.Free; CardTable.Post; end;
Fields变量是表示数据库记录的字段数组, 上面这段程序是超媒体卡片存储的部分源程序,我们就是将卡片保存在数据库
var PropInfo: PPropInfo; Method: TMethod; Blobtream: TStream; I: Integer; begin BlobStream := TBlobStream.Create(TBlobField(CardTable.Fields[10]), bmRead); With TReader.Create(BlobStream, 4096) do try while not EndOfList do begin case ReadInteger of IDText: begin Ctrl := TControl(ReadRootComponent(nil)); PropInfo := GetPropInfo(Ctrl.ClassInfo, 'OnClick'); Method.Code:= Self.MethodAddress(MethodName); Method.Data := Self; if Method.Code <> nil then SetMethodProp(Ctrl, PropInfo, Method); DesignWin.InsertControl(Ctrl); end; IDImage: …… end; WriteListEnd; end; finally. Free; end; FileStream.Free; end;
20.3.2.2 BLOB字段与图形图像
在多媒体数据库中处理得比较多的是图形图像,因此早期的多媒体数据库在扩展关系数据库时往往是增加一个图像字段。 在TBlobField对象中提供了
procedure TBlobField.LoadFromBitmap(Bitmap: TBitmap); var BlobStream: TBlobStream; Header: TGraphicHeader; begin BlobStream := TBlobStream.Create(Self, bmWrite); try if (DataType = ftGraphic) or (DataType = ftTypedBinary) then begin Header.Count := 1; Header.HType := $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 else Bitmap.SaveToStream(BlobStream); finally BlobStream.Free; end; end;
procedure TBlobField.SaveToBitmap(Bitmap: TBitmap); var BlobStream: TBlobStream; Size: Longint; Header: TGraphicHeader; begin BlobStream := TBlobStream.Create(Self, bmRead); try Size := BlobStream.Size; if Size >= SizeOf(TGraphicHeader) then begin BlobStream.Read(Header, SizeOf(Header)); if (Header.Count <> 1) or (Header.HType <> $0100) or (Header.Size <> Size - SizeOf(Header)) then BlobStream.Position := 0; end; Bitmap.LoadFromStream(BlobStream); finally BlobStream.Free; end; end;
程序中按两种方式存取数据,对于位图数据,数据的起点是流的
20.3.2.3 BLOB字段与文本
Delphi BLOB字段中增加了大型文本的处理能力。可以在
procedure TBlobField.LoadFromStrings(Strings: TStrings); var BlobStream: TBlobStream; begin BlobStream := TBlobStream.Create(Self, bmWrite); try Strings.SaveToStream(BlobStream); finally BlobStream.Free; end; end;
procedure TBlobField.SaveToStrings(Strings: TStrings); var BlobStream: TBlobStream; begin BlobStream := TBlobStream.Create(Self, bmRead); try Strings.LoadFromStream(BlobStream); finally BlobStream.Free; end; end;
20.3.2.4 BLOB字段与Stream
因为Delphi中,
procedure TBlobField.LoadFromStream(Stream: TStream); var BlobStream: TBlobStream; begin BlobStream := TBlobStream.Create(Self, bmWrite); try BlobStream.CopyFrom(Stream, 0); finally BlobStream.Free; end; end;
procedure TBlobField.SaveToStream(Stream: TStream); var BlobStream: TBlobStream; begin BlobStream := TBlobStream.Create(Self, bmRead); try Stream.CopyFrom(BlobStream, 0); finally BlobStream.Free; end; end;
20.3.3 存取嵌入在OleContainer
对象链接和嵌入(Object Linking and Embedding 通过把图像、图形、表格、声音、注解、文件和其它表示手段描述成对象,用它能在不同软件厂家提供的应用程序中更为容易地交换合成和处理数据它是应用程序的集成更为容易。 OLE已成为操作系统功能上的一大标准,各大软商纷纷在开发工具中支持 尽管通过OLE可以用来源于不同应用程序的信息创建复合文档,充分体现以任务、以文档为中心的思想,但是很难分解来自其它应用程序中的嵌入数据,以进行特殊的处理。 例如,一套多媒体电子文档管理系统,系统需要数据库管理功能文档编辑功能,全文检索功能等。在文档编辑功能的实现上,如果能利用中文 Delphi 2.0的 我们分析了Delphi2.0的OleContainer 让我们来看一段OleContainer
procedure TOleContainer.SaveToStream(Stream: TStream); var DataHandle: HGlobal; Buffer: Pointer; Header: TStreamHeader; R: TRect; …… begin try if FOldStreamFormat then begin R := BoundsRect; Header.PartRect.Left := R.Left; Header.PartRect.Top := R.Top; Header.PartRect.Right := R.Right; Header.PartRect.Bottom := R.Bottom; end else begin Header.Signature := StreamSignature; Header.DrawAspect := FDrawAspect; end; Header.DataSize := GlobalSize(DataHandle); Stream.WriteBuffer(Header, SizeOf(Header)); Buffer := GlobalLock(DataHandle); try Stream.WriteBuffer(Buffer^, Header.DataSize); finally GlobalUnlock(DataHandle); end; finally ReleaseObject(TempStorage); ReleaseObject(TempLockBytes); end; end;
程序中,OleContainer Stream.WriteBuffer(Buffer^, Header.DataSize);
前一语句是写入OLE
TStreamHeader = record case Integer of 0: ( { 新版OLE Signature: Integer; DrawAspect: Integer; DataSize: Integer); 1: ( { 旧版OLE PartRect: TSmallRect); end;
因此读OLE服务器嵌入数据时,要跳过文件头的
var Stream : TMemoryStream; FileStream : TFileStream; begin Stream := TMemoryStream.Create; FileStream := TFileStream.Create('TEST.DOC', fmCreate) ; with OleContainer1 do if (State <> osEmpty) then SaveToStream(Stream); Stream.Seek(Sizeof(TStreamHeader), 0); FileStream.CopyFrom(Stream, Stream.Size - SizeOf(TStreamHeader)); Stream.Free; FileStream.Free; end;
OleContainer1包含的服务器对象是中文 |
| [ ] [返回上一页] [打 印] [收 藏] |
上一篇文章:浅析Struts 体系结构与工作原理(1)
下一篇文章:开发Delphi对象式数据管理功能(九) |
