嘿嘿,高难度问题,挑战你的思维!(300分)

  • 主题发起人 主题发起人 xuxiaohan
  • 开始时间 开始时间
X

xuxiaohan

Unregistered / Unconfirmed
GUEST, unregistred user!
把下面的过程修改为可以从 word 文件的 Stream (不是 oleContainer 格式的 stream )中载入;作用是取代CreateObjectFromFile;
问题关键: DataHandle := GlobalAlloc(GMEM_MOVEABLE, Header.DataSize);
[red]普通的word 的stream 是 没有 Header.DataSize;[/red]

procedure TOleContainer.LoadFromStream(Stream: TStream);
var
DataHandle: HGlobal;
Buffer: Pointer;
Header: TStreamHeader;
begin
DestroyObject;
Stream.ReadBuffer(Header, SizeOf(Header));
if (Header.Signature <> StreamSignature) and not FOldStreamFormat then
raise EOleError.CreateRes(@SInvalidStreamFormat);
DataHandle := GlobalAlloc(GMEM_MOVEABLE, Header.DataSize);
if DataHandle = 0 then OutOfMemoryError;
try
Buffer := GlobalLock(DataHandle);
try
Stream.Read(Buffer^, Header.DataSize);
finally
GlobalUnlock(DataHandle);
end;
OleCheck(CreateILockBytesOnHGlobal(DataHandle, True, FLockBytes));
DataHandle := 0;
OleCheck(StgOpenStorageOnILockBytes(FLockBytes, nil, STGM_READWRITE or
STGM_SHARE_EXCLUSIVE, nil, 0, FStorage));
OleCheck(OleLoad(FStorage, IOleObject, Self, FOleObject));
FDrawAspect := Header.DrawAspect;
InitObject;
UpdateView;
except
if DataHandle <> 0 then GlobalFree(DataHandle);
DestroyObject;
raise;
end;
end;
 
我异想天开吗?
 
去掉前面的Header读取部分,Header.DataSize用FileSize(WordFileName)代替即可。
 
Kingron,:
你的方法不行的,Header.DataSize比stream.size(也就是你说的FileSize)要大。

 
回答在这里:
TOLEContainer.LoadAsDocument(FileName:string);
请参考:
http://kingron.delphibbs.com:2090/dispbbs.asp?boardid=17&id=221
 
Kingron:
http://kingron.delphibbs.com:2090/dispbbs.asp?boardid=17&id=221 打不开。
 
Kingron:
等你呀。
 
Kingron潜水啦?
 
去论坛注册一下
 
Kingron大侠:
我已经在你的论坛注册了,怎么没有答案?链接还是打不开?
 
在 Delphi Fans共享联盟论坛 → 技术讨论区 → 编程技巧
最下面,有一个帖子:
[分享]从文件创建OLEContainer的对象
 
hello! kingron
 
其实,你要从流创建的话,把FileStream改成Stream即可,Delphi的CreateObjectFromFile已经做得很好了。你改改就可以了。
 
Kingron,
还是找不到, 连Delphi Fans共享联盟论坛都进不了,

[green]其实,你要从流创建的话,把FileStream改成Stream即可,Delphi的CreateObjectFromFile已经做得很好了。你改改就可以了。[/green]

这不合我的要求, Object已经建立了, 为何还要重新建立呢? 你知道,建立是非常耗时的, container 本身的LoadFromStream非常快, 可惜格式不同!!!
本人水平有限, 不知道Delphi为什么没有这样的功能
 
自己修改一下LoadFromStream就可以了~~~~~~~其实哪个Header就是一个Size有用,其他的没什么的,自己改改就好了,我的也是从哪里改过来的。
昨晚论坛关机了,所以你不能访问了。
 
Kingron:
我看了你的回复,你的回复就是将 stream.size 代替了 header.size, 我说过这样是不行的, 是试过了好多方法(包括你的这种方法)都不行,所以才发问的。
我知道你很忙, 还是希望你能抽出点时间,我希望这个问题能够得到解决。。。
你看看
在 olecontainer.SaveToStream(Stream: TStream); 中
有这一断:
Header.DataSize := GlobalSize(DataHandle);
Buffer := GlobalLock(DataHandle);
try
Stream.WriteBuffer(Buffer^, Header.DataSize);
finally
GlobalUnlock(DataHandle);
end;
可见这个head的size 跟stream的size是不同的,head是附加上去的。。。
 
请ActiveX高手进来讨论
 
看来这样是无法实现的。
 
procedure TOleContainer.LoadAsDocument(const FileName: string);
var
Stream: TFileStream;
DataHandle: HGLOBAL;
Buffer: Pointer;
begin
Stream := TFileStream.Create(FileName, fmOpenRead);
try
DataHandle := GlobalAlloc(GMEM_MOVEABLE, Stream.Size);
if DataHandle = 0 then OutOfMemoryError;
try
Buffer := GlobalLock(DataHandle);
try
Stream.Read(Buffer^, Stream.Size);
finally
GlobalUnlock(DataHandle);
end;
OleCheck(CreateILockBytesOnHGlobal(DataHandle, True, FLockBytes));
DataHandle := 0;
OleCheck(StgOpenStorageOnILockBytes(FLockBytes, nil, STGM_READWRITE or
STGM_SHARE_EXCLUSIVE, nil, 0, FStorage));
OleCheck(OleLoad(FStorage, IOleObject, self, FOleObject));
FDrawAspect := 1;
InitObject;
UpdateView;
except
if DataHandle <> 0 then GlobalFree(DataHandle);
DestroyObject;
raise;
end;
finally
Stream.Free;
end;
end;
 
DataHandle := GlobalAlloc(GMEM_MOVEABLE, Stream.Size);
用Stream.Size代替不行!
 
后退
顶部