DFM 檔案可視為超媒體卡片,DFM 腳本能表達多種控制項(媒體物件),具物件導向表達、可編輯、可轉換為 DFM,堪稱優良腳本語言形式。ObjectBinaryToText/ObjectTextToBinary 實現元件與 DFM 腳本互轉;ObjectResourceToText/ObjectTextToResource 實現 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;
procedure TScriptForm.ScriptToCard;
var In, Out: TStream;
begin
In := TMemoryStream.Create; Out := TMemoryStream.Create;
try
ScriptForm.ScriptEdit.Lines.SaveToStream(In);
ObjectTextToResource(In, Out);
In.ReadComponentRes(DesignWin);
finally In.Free; Out.Free; end;
end;
以上為表單級轉換,ObjectBinaryToText/ObjectTextToBinary 可細化至元件級,支援媒體物件級編輯。
常規 DFM 處理難滿足超媒體特殊需求(如連結)。兩大策略:
本文探討策略二:降低顆粒度從表單級至元件級。
寫入:逐元件寫入媒體 ID 与元件資料
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;
讀取:依媒體 ID 分派建立元件並重連事件
with TReader.Create(FileStream, 4096) do
try
while not EndOfList do
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;
finally Free; end;
SetMethodProp 重連事件,亦可用 TReader.OnFindMethod 實現。腳本擴展同理,額外將媒體資訊轉文本插入元件腳本描述中。