摘自大富翁ycguser刚开发开发此控件时,首先是想到此控件的数据要序列化到WORD文档中。 在建立工程时,我采用了ActiveXForm. 我在ActivexForm中加入一个USERNAME(String型)的属性后,将控件放到WORD中,发现USERNAME无法序列化到WORD文档中。这时我发现比较难办。如果这个基本的功能实现不了,那个这个控件根本无法开发下去。于是我查看了基类:TActiveXControl ,发现它已经实现了好几个序列化的接口。经过一天的调试跟踪,也没有搞明白它序列化方面的原理。现实的结果是在WORD中存不住数据。根据C++经验,只有自己去实现序列化的接口,但经过对系统支持的几个序列化接口试验以后,才发现只有实现IPersistStorage接口在WORD中才能序列化数据。 下面是是IPersistStorage实现的代码: TCanvasForm = class(TActiveForm, ICanvasForm,IPersistStorage) private { Private declarations } FUserName:String; //用户名称 FDataTime:string; //取得笔迹数据的时间 FWriteTime:Integer; //返回的时间 FIndata:oleVariant; //笔迹数据变量 array of byte 的变量 FisScale:boolean; //记录图片是否比image大 FLastTime:Integer; bdirty:Boolean; //是否保存标识 public ///////IPersistStorage function IsDirty: HResult; stdcall; function InitNew(const stg: IStorage): HResult; stdcall; function Load(const stg: IStorage): HResult; stdcall; function Save(const stgSave: IStorage; fSameAsLoad: BOOL): HResult; stdcall; function SaveCompleted(const stgNew: IStorage): HResult; stdcall; function HandsOffStorage: HResult; stdcall; function GetClassID(out classID: TCLSID): HResult; stdcall; end; ////////////////////IPersistStoge function TCanvasForm.IsDirty: HResult; stdcall; begin //if bdirty then // Result := S_False //else result:=S_OK; end; function TCanvasForm.InitNew(const stg: IStorage): HResult; stdcall; begin Result := S_OK; end; function TCanvasForm.Load(const stg: IStorage): HResult; stdcall; var stmData:IStream; OS:TOleStream; read:TReader; elementcount:integer; bty:array of byte; begin if SUCCEEDED(stg.OpenStream('PropData',nil, STGM_READWRITE or STGM_SHARE_EXCLUSIVE,0,stmData)) then begin OS:=TOleStream.Create(stmData); try read:=Treader.Create(oS,4096); try FUserName:=read.ReadWideString; FDataTime:=read.ReadWideString ; self.Height :=trunc(read.ReadSingle) ; self.Width :=trunc(read.ReadSingle) ; self.FLastTime:=trunc(read.ReadSingle ); elementcount:=trunc(read.ReadSingle ); finally read.Free; end; finally OS.Free; end; end; Result := S_OK; end;
function TCanvasForm.Save(const stgSave: IStorage; fSameAsLoad: BOOL): HResult; stdcall; var stmData:IStream; OS:TOleStream; write:TWriter; arrayElement:integer; p:pointer; begin // if not SUCCEEDED(stgSave.OpenStream('ss',nil, STGM_READWRITE or STGM_SHARE_EXCLUSIVE,0,stmData)) then OleCheck(stgSave.CreateStream('PropData',STGM_CREATE or STGM_READWRITE or STGM_SHARE_EXCLUSIVE,0,0,stmData)); OS:=TOleStream.Create(stmData); try write:=TWriter.Create(OS,4096); try write.WriteWideString(FUserName); write.WriteWideString(FDataTime); write.WriteSingle(Height); Write.WriteSingle(Width); write.WriteSingle(FLastTime); ///////////// 开始写变体数据 if not VarIsEmpty(self.FIndata) then begin arrayElement:=VarArrayHighBound(Findata,1)+1; write.WriteSingle(arrayElement); p := VarArrayLock(Findata); try write.Write(p^, arrayElement); finally VarArrayUnlock(Findata); end; end else begin arrayElement:=-1; write.WriteSingle(arrayElement); end; finally write.Free; end; finally OS.Free; end; bdirty:=true; Result := S_OK; end; function TCanvasForm.SaveCompleted(const stgNew: IStorage): HResult; stdcall; begin Result := S_OK; end; function TCanvasForm.HandsOffStorage: HResult; stdcall; begin Result := S_OK; end; function TCanvasForm.GetClassID(out classID: TCLSID): HResult; stdcall; begin classID:=Class_CanvasForm; Result := S_OK; end;
regsvr32注册一下,就可以了,找到添加了
身体还可以yq3woaini 在 哪添 加
哈哈镜(中级代码工)
在建立工程时,我采用了ActiveXForm. 我在ActivexForm中加入一个USERNAME(String型)的属性后,将控件放到WORD中,发现USERNAME无法序列化到WORD文档中。这时我发现比较难办。如果这个基本的功能实现不了,那个这个控件根本无法开发下去。于是我查看了基类:TActiveXControl ,发现它已经实现了好几个序列化的接口。经过一天的调试跟踪,也没有搞明白它序列化方面的原理。现实的结果是在WORD中存不住数据。根据C++经验,只有自己去实现序列化的接口,但经过对系统支持的几个序列化接口试验以后,才发现只有实现IPersistStorage接口在WORD中才能序列化数据。
下面是是IPersistStorage实现的代码:
TCanvasForm = class(TActiveForm, ICanvasForm,IPersistStorage)
private
{ Private declarations }
FUserName:String; //用户名称
FDataTime:string; //取得笔迹数据的时间
FWriteTime:Integer; //返回的时间
FIndata:oleVariant; //笔迹数据变量 array of byte 的变量
FisScale:boolean; //记录图片是否比image大
FLastTime:Integer;
bdirty:Boolean; //是否保存标识
public
///////IPersistStorage
function IsDirty: HResult; stdcall;
function InitNew(const stg: IStorage): HResult; stdcall;
function Load(const stg: IStorage): HResult; stdcall;
function Save(const stgSave: IStorage; fSameAsLoad: BOOL): HResult;
stdcall;
function SaveCompleted(const stgNew: IStorage): HResult; stdcall;
function HandsOffStorage: HResult; stdcall;
function GetClassID(out classID: TCLSID): HResult; stdcall;
end;
////////////////////IPersistStoge
function TCanvasForm.IsDirty: HResult; stdcall;
begin
//if bdirty then
// Result := S_False
//else
result:=S_OK;
end;
function TCanvasForm.InitNew(const stg: IStorage): HResult; stdcall;
begin
Result := S_OK;
end;
function TCanvasForm.Load(const stg: IStorage): HResult; stdcall;
var
stmData:IStream;
OS:TOleStream;
read:TReader;
elementcount:integer;
bty:array of byte;
begin
if SUCCEEDED(stg.OpenStream('PropData',nil, STGM_READWRITE or STGM_SHARE_EXCLUSIVE,0,stmData)) then
begin
OS:=TOleStream.Create(stmData);
try
read:=Treader.Create(oS,4096);
try
FUserName:=read.ReadWideString;
FDataTime:=read.ReadWideString ;
self.Height :=trunc(read.ReadSingle) ;
self.Width :=trunc(read.ReadSingle) ;
self.FLastTime:=trunc(read.ReadSingle );
elementcount:=trunc(read.ReadSingle );
finally
read.Free;
end;
finally
OS.Free;
end;
end;
Result := S_OK;
end;
function TCanvasForm.Save(const stgSave: IStorage; fSameAsLoad: BOOL): HResult;
stdcall;
var
stmData:IStream;
OS:TOleStream;
write:TWriter;
arrayElement:integer;
p:pointer;
begin
// if not SUCCEEDED(stgSave.OpenStream('ss',nil, STGM_READWRITE or STGM_SHARE_EXCLUSIVE,0,stmData)) then
OleCheck(stgSave.CreateStream('PropData',STGM_CREATE or STGM_READWRITE or STGM_SHARE_EXCLUSIVE,0,0,stmData));
OS:=TOleStream.Create(stmData);
try
write:=TWriter.Create(OS,4096);
try
write.WriteWideString(FUserName);
write.WriteWideString(FDataTime);
write.WriteSingle(Height);
Write.WriteSingle(Width);
write.WriteSingle(FLastTime);
///////////// 开始写变体数据
if not VarIsEmpty(self.FIndata) then
begin
arrayElement:=VarArrayHighBound(Findata,1)+1;
write.WriteSingle(arrayElement);
p := VarArrayLock(Findata);
try
write.Write(p^, arrayElement);
finally
VarArrayUnlock(Findata);
end;
end
else
begin
arrayElement:=-1;
write.WriteSingle(arrayElement);
end;
finally
write.Free;
end;
finally
OS.Free;
end;
bdirty:=true;
Result := S_OK;
end;
function TCanvasForm.SaveCompleted(const stgNew: IStorage): HResult; stdcall;
begin
Result := S_OK;
end;
function TCanvasForm.HandsOffStorage: HResult; stdcall;
begin
Result := S_OK;
end;
function TCanvasForm.GetClassID(out classID: TCLSID): HResult; stdcall;
begin
classID:=Class_CanvasForm;
Result := S_OK;
end;
来自:wxss, 时间:2005-9-28 14:41:00, ID:3221853 [显示:小字体 | 大字体] 各位大哥:
我在大富翁和K.top上,一直想和各位高手请教一些关于用delphi 实现ActiveX Document Server的问题。问题的提出是源于这样一个需求。我做了一个类似图形编辑的软体,用自己的程序生成自己定义的文件格式。但用户提出,需要将编辑好的东西嵌入到word文档里。我见到类似的软件实现了这个功能(如公式编辑器):它们在word里注册了一个可插入的对象,当我们新插入一个自己的对象,双击这个对象的时候,就可以回到我自己的软体里来编辑这个对象。编辑完成,退出程序,word里的对象也更新了。
我在网上找了很久,也请教了很多高手,但似乎用delphi难以实现这样的功能。甚至连如何注册成一个可插入的对象都让我难以下手。后来我发现borland新闻组里有人介绍一篇1999年的文章介绍过这类的实现,还有源码http://www.thedelphimagazine.com/disks/dmag43.zip,http://www.thedelphimagazine.com/disks/dmag42.zip, 在comcorn目录里)。该程序建立了一个Tmemo类型的可插入对象,并成功地实现了注册成一个可插入的对象。我把Tmemo类型换成其他类型如TButton,Tpanel都可以, 但有几个问题似乎是还没有解决:1.双击word里的这个对象,不能回到自己的软体进行编辑。更谈不上如何将编辑后的结果再更新到word里了。(老外的这个程式里提供了一些思路,即重载SaveToStream(const Stream: IStream);和LoadFromStream(const Stream: IStream);来传递对象的信息,但似乎没起作用),各位老大,这些地方该如何改进呢?2。老外的程序的这个TActiveXDocument对象是从TActiveXControl继承来的,在word里点击它似乎无法获得焦点,反复几次后就出错了。是不是选择从TActiveXControl继承本身就是错的?应该从哪个对象继承呢?TActiveFormControl?3。我所见过的可以实现上述需求的软体(如公式编辑器)是这样操作的,在word里单击对象,则选中,双击对象则调出程式主界面,开始编辑,存盘后退出,更新word里的对象显示。这个在程序里,我想是要重载DOverb方法来实现吧,但我一直没有成功。:(,怎么样能找到并响应这个双击事件呢?也许,关注这个问题的朋友会在http://www.evocorp.com/Delphi/ADDActiveDocuments.htm里找到另外的线索,我比较了它和comcorn的区别,很明显的是,他们之间有很类似的地方(作者在2004年才做的更新),而且,它没有demo,根据它提示的方法,我花了9牛2虎的力气建立了一个sample,但效果和dmag42.zip,comcorn有同样的问题。我自己写的demo,基本上是沿袭了dmag42.zip的框架(想要的大哥说一声,email给您),注意,不要用它给的AxCtrls.pas(delphi自己有),在uses里要加入Variants,omgw.[1] := 1;改成omgw.width[1] := 1;就可以编译成功了。运行一次程序,在word里,你就会发现,在插入--对象里有一项“delphi activex Document object”了。
这个问题很有挑战性,我研究了很久,但始终不得要领,希望各位大哥齐心协力,能在此基础上有所突破,让小弟寝食能安。
这真是一个难于归类的问题,但希望其他版的版主也能关注,尝试一下如何解决这个问题,小弟不甚感激。