下面是存取操作的擴(kuò)展示范:
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]);
{ 寫相應(yīng)媒體擴(kuò)展信息 }
……
end;
WriteListEnd;
finally.
Free;
end;
FileStream.Free;
end;
WriteInteger(MMID[i])語(yǔ)句是寫入媒體標(biāo)識(shí)。
下面是相應(yīng)的讀擴(kuò)展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過(guò)程是用于重新聯(lián)接控制和它的事件處理過(guò)程。類似的功能還可以用TReader對(duì)象的OnFindMethod事件的處理過(guò)程來(lái)實(shí)現(xiàn)。
實(shí)現(xiàn)腳本語(yǔ)言擴(kuò)展的基本方法與存取擴(kuò)展類似,但它還要加擴(kuò)展媒體信息轉(zhuǎn)換為文本,并插入到部件的腳本描述中。
20.3.2 數(shù)據(jù)庫(kù)BLOB字段應(yīng)用
Delphi VCL提供了TBlobStream對(duì)象支持對(duì)數(shù)據(jù)庫(kù)BLOB字段的存取。Delphi 的TBlobStream對(duì)象的作用在于一方面可以使Delphi應(yīng)用程序充分利用多媒體數(shù)據(jù)庫(kù)的數(shù)據(jù)管理能力。另一方面又能利用Delphi Object Pascal的程序設(shè)計(jì)能力給關(guān)系型多媒體數(shù)據(jù)庫(kù)提供底層控制能力和全方位的功能擴(kuò)展余地。
20.3.2.1 TBlobStream的使用
TBlobStream對(duì)象用一個(gè)TBlobField類型的對(duì)象作為參數(shù)來(lái)創(chuàng)建與BLOB字段相聯(lián)的BLOB流,接著就可用流的存取方法在BLOB字段中存取數(shù)據(jù)。
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]);
{ 寫相應(yīng)媒體擴(kuò)展信息 }
……
end;
WriteListEnd;
finally.
Free;
end;
BlobStream.Free;
CardTable.Post;
end;
Fields變量是表示數(shù)據(jù)庫(kù)記錄的字段數(shù)組,F(xiàn)ields[10]正是數(shù)據(jù)庫(kù)的BLOB 字段。CardTable的Post方法將數(shù)據(jù)庫(kù)的修改反饋到數(shù)據(jù)庫(kù)的物理存儲(chǔ)上。
上面這段程序是超媒體卡片存儲(chǔ)的部分源程序,我們就是將卡片保存在數(shù)據(jù)庫(kù)BLOB字段中,實(shí)現(xiàn)將超文本和關(guān)系數(shù)據(jù)庫(kù)兩種數(shù)據(jù)管理方式結(jié)合起來(lái)。讀卡片的程序如下:
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字段與圖形圖像
在多媒體數(shù)據(jù)庫(kù)中處理得比較多的是圖形圖像,因此早期的多媒體數(shù)據(jù)庫(kù)在擴(kuò)展關(guān)系數(shù)據(jù)庫(kù)時(shí)往往是增加一個(gè)圖像字段。BLOB字段是以二進(jìn)制數(shù)據(jù)存儲(chǔ)方式,因此它完全可以表達(dá)圖形圖像數(shù)據(jù)。
在TBlobField對(duì)象中提供了LoadFromBitMap和SaveToBitMap方法存取位圖數(shù)據(jù)。它們?cè)趯?shí)現(xiàn)上都是使用BlobStream對(duì)象。
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;
程序中按兩種方式存取數(shù)據(jù),對(duì)于位圖數(shù)據(jù),數(shù)據(jù)的起點(diǎn)是流的Potition為0處,對(duì)于圖形或其它類型的Blob數(shù)據(jù),則以流的Position為SizeOf(Header) + 1處開始, 即多了個(gè)頭信息。
20.3.2.3 BLOB字段與文本
Delphi BLOB字段中增加了大型文本的處理能力?梢栽赥BlobField和Strings中自由地交換數(shù)據(jù)。
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對(duì)象
因?yàn)镈elphi中,BLOB字段是通過(guò)BLOB流來(lái)訪問(wèn)的,所以可以很容易地在BLOB字段和Stream對(duì)象之間傳遞數(shù)據(jù)。為此,TBlobField對(duì)象提供了LoadFromStream和SaveToStream方法。
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對(duì)象中的OLE服務(wù)器的數(shù)據(jù)
對(duì)象鏈接和嵌入(Object Linking and Embedding,簡(jiǎn)稱OLE),是一組服務(wù)功能,它提供了一種用來(lái)源于不同應(yīng)用程序的信息創(chuàng)建復(fù)合文檔的強(qiáng)有力方法。
通過(guò)把圖像、圖形、表格、聲音、注解、文件和其它表示手段描述成對(duì)象,用它能在不同軟件廠家提供的應(yīng)用程序中更為容易地交換合成和處理數(shù)據(jù)它是應(yīng)用程序的集成更為容易。OLE2.0支持直觀編輯。用戶不需切換到不同窗口就能在文檔中直接對(duì)對(duì)象進(jìn)行操作,改進(jìn)了操作環(huán)境。用戶不用再關(guān)注應(yīng)用程序和操作環(huán)境,只需關(guān)注于使用對(duì)象技術(shù)的數(shù)據(jù)和文件,便能完成全部工作。
OLE已成為操作系統(tǒng)功能上的一大標(biāo)準(zhǔn),各大軟商紛紛在開發(fā)工具中支持OLE 2.0規(guī)范。Delphi 2.0提供了OleContainer對(duì)象支持OLE窗戶應(yīng)用程序的開發(fā)。
盡管通過(guò)OLE可以用來(lái)源于不同應(yīng)用程序的信息創(chuàng)建復(fù)合文檔,充分體現(xiàn)以任務(wù)、以文檔為中心的思想,但是很難分解來(lái)自其它應(yīng)用程序中的嵌入數(shù)據(jù),以進(jìn)行特殊的處理。
例如,一套多媒體電子文檔管理系統(tǒng),系統(tǒng)需要數(shù)據(jù)庫(kù)管理功能文檔編輯功能,全文檢索功能等。在文檔編輯功能的實(shí)現(xiàn)上,如果能利用中文Word 或?qū)懽职逯惖膹?qiáng)大的編輯排版功能,就可以省卻重新開發(fā)一個(gè)文檔編輯的費(fèi)用,使用具有直觀編輯的OLE復(fù)合文檔嵌入Word的DOC數(shù)據(jù)或RTF數(shù)據(jù)當(dāng)然是最佳的選擇。 但問(wèn)題在于全文檢索系統(tǒng)要求能直接在文檔中搜索關(guān)鍵字,因此要求將文檔數(shù)據(jù)從OLE嵌入數(shù)據(jù)或文檔中的本地?cái)?shù)據(jù)中分離出來(lái)。
Delphi 2.0的OleContainer部件支持存儲(chǔ)OLE對(duì)象數(shù)據(jù)。OLE對(duì)象數(shù)據(jù)包括兩部分:OLE類描述信息和OLE服務(wù)器嵌入數(shù)據(jù)。一般說(shuō)來(lái),OLE服務(wù)器嵌入數(shù)據(jù)是以服務(wù)器支持的數(shù)據(jù)格式存儲(chǔ)的; 比方說(shuō),中文Word 6.0的嵌入數(shù)據(jù)的格式就是Word 6.0文檔的格式。因此,要將文檔數(shù)據(jù)從OLE 嵌入式文檔中分離出來(lái)就是要訪問(wèn)第二部分?jǐn)?shù)據(jù)。
我們分析了Delphi 2.0的OleContainer對(duì)象存取復(fù)合文檔的程序,得到分離數(shù)據(jù)的方法。
讓我們來(lái)看一段OleContainer對(duì)象存儲(chǔ)數(shù)據(jù)的程序:
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對(duì)象執(zhí)行了兩次往流中寫數(shù)據(jù)的操作。
Stream.WriteBuffer(Header, Size(Header));
Stream.WriteBuffer(Buffer^, Header.DataSize);
前一語(yǔ)句是寫入OLE類描述信息,后一句語(yǔ)句是寫入OLE服務(wù)器的嵌入數(shù)據(jù)。Header是TStreamHeader記錄類型的變量。TStreamHeader記錄的定義如下:
TStreamHeader = record
case Integer of
0: ( { 新版OLE對(duì)象 }
Signature: Integer;
DrawAspect: Integer;
DataSize: Integer);
1: ( { 舊版OLE對(duì)象 }
PartRect: TSmallRect);
end;
因此讀OLE服務(wù)器嵌入數(shù)據(jù)時(shí),要跳過(guò)文件頭的TStreamHeader記錄。下面就是如何分離OLE服務(wù)器嵌入數(shù)據(jù)的程序:
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包含的服務(wù)器對(duì)象是中文Word 6.0,程序中將分離出的數(shù)據(jù)存儲(chǔ)在磁盤文件“TEST.DOC”上。如果希望存儲(chǔ)在不同的媒介上,可以使用相應(yīng)的Stream對(duì)象,分離的方法類似。但是,這種方法并非對(duì)所有的OLE服務(wù)器數(shù)據(jù)都適用,如Windows 95 附件中的寫字板(WordPad)就不行。
相關(guān)推薦:2010年9月計(jì)算機(jī)等級(jí)考試試題及答案解析專題北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |