TResourceStream对象
TResourceStream对象是另一类MemoryStream对象它提供对Windows 应用程序资源的访问因此称它为资源流TResourceSream也是从TCustomMemoryStream 继承的因此在TCustomMemoryStream对象的基础上定义了与指定资源模块或资源文件建立连接的构造方法并且还覆盖了Write以实现向资源文件中写数据
下面介绍TResourceStream的实现
私有域
TResourceStream没有定义新的属性但它在private部分定义了两个数据域HResInfo和HGlobol和一个私有方法Initialize它们的定义如下
TResourceStream = class(TCustomMemoryStream)
private
HResInfo: HRSRC;
HGlobal: THandle;
procedure Initialize(Instance: THandle; Name ResType: PChar)
…
end;
HRSRC是描述Windows资源信息的结构句柄HGlobal变量代表资源所在模块的句柄如果操作的是应用程序资源HGlohal就代表EXE程序的句柄如果是动态链接库(DLL)则HGlobal 代表动态链接库的句柄TResourceStream对象使用这两上变量访问应用程序或动态链接库中的资源
Initialize方法是TResourceStream对象内部使用的它的构造方法Create和CreateFromID都是调用Initialize方法完成对TResourceStream的初始化它的实现如下
procedure TResourceStreamInitialize(Instance: THandle; Name ResType: PChar)
procedure Error;
begin
raise EResNotFoundCreate(FmtLoadStr(SResNotFound [Name]))
end;
begin
HResInfo := FindResource(Instance Name ResType)
if HResInfo = then Error;
HGlobal := LoadResource(Instance HResInfo)
if HGlobal = then Error;
SetPointer(LockResource(HGlobal) SizeOfResource(Instance HResInfo))
end;
该方法实现中首先调用Windows函数FoundResource得到由参数Instance指定的模块中的名为Name和类型为ResType的资源然后调用LoadResource将资源调用内存并返回该资源在内存中的句柄最后将该资源复制到ResourceStream中方法的Instance参数代表要调用的资源所在的模块句柄模块可以是可执行文件也可以是动态链接库如果在读取资源时没在模块中发现要找的资源则产生异常事件
构造方法Create和CreateFromID
这两个方法在实现上没有大的不同顾名思义第一个方法是通过资源名构造TResourceStream; 第二个方法通过资源ID构造TResourceStream而且在实现过程中它们都调用了Initialize方法下面是它们的实现
constructor TResourceStreamCreate(Instance: THandle; const ResName: string;
ResType: PChar)
begin
inherited Create;
Initialize(Instance PChar(ResName) ResType)
end;
constructor TResourceStreamCreateFromID(Instance: THandle; ResID: Integer;
ResType: PChar)
begin
inherited Create;
Initialize(Instance PChar(ResID) ResType)
end;
这两个方法中都有Instance参数该参数值的含义在Insitialize中介绍过
Write方法
TResourceStream的Write方法只完成一件事就产生这个异常事件其实现如下
function TResourceStreamWrite(const Buffer; Count: Longint) Longint;
begin
raise EStreamErrorCreateRes(SCantWriteResourceStreamError)
end;
从方法实现中可以看到TSourceStream对象是不允许写数据的一旦往资源流中写数据将产生异常事件
析构方法Destroy
该方法产生给资源解锁然后释放该资源最后调用继承的Destroy方法释放ResourceStream其实现如下
destructor TResourceStreamDestroy;
begin
UnlockResource(HGlobal)
FreeResource(HResInfo)
inherited Destroy;
end;
回顾Initialize方法我们不难发现
● ResourceStream没有额外地给资源重新分配内存而是直接使用HGlobal句柄所指 的内存域
● ResourceStream中的资源在流的生存期始终是Lock状态因此要根据Windows 的内存使用规则合理安排ResourceStream的使用
● ResourceStream只是用于访问应用程序和动态链接库中的资源的
在Classes在单元中提供了InternalReadComponentRes函数该函数使用了TResourceStream对象从Delphi应用程序中读取部件Delphi是将窗体和部件信息放在模块资源的RCDATA段的
TBlobStream对象
从Delphi 数据库开发平台这个意义上说TBlobStream 对象是个很重要的对象TBlobStream对象提供了修改TBlobFieldTBytesField或TVarBytesField中数据的技术开发者可以象对待文件或流那样在数据库域中读写数据
传统数据库发展的一个重要趋向是往多媒体数据库发展目前比较着名和流行的数据库都支持多媒体功能多媒体数据存储中的一大难点是数据结构不规则数据量大各大数据库产品是采用BLOB技术解决多媒体数据存储中的问题Delphi的TBlobStream对象的意义就在于一方面可以使Delphi应用程序充分利用多媒体数据库的数据管理能力另一方面又能利用Object Pascal的强大程序设计能力给多媒体数据库提供全方向的功能扩展余地
使用TBlobStream对象可以在多媒体数据库的BLOB字段存储任意格式的数据一般说来许多多媒体数据库只能支持图像语音或者OLE服务器支持的数据利用TBlobStream则不同只要是程序能够定义的数据格式它都能在BLOB字段中读写而不需要其它辅助工具
TBlobStream用构造方法Create建立数据库域和BLOB流的联接用Read或Write 方法访问和改变域中的内容用Seek方法在域中定位用Truncate方法删除域中当前位置起所有的数据
TBlobStream的属性和方法
TBlobStream对象从TStream直接继承没有增添新的属性它覆盖了ReadWrite 和Seek方法提供了对BLOB字段的访问操作它增添了Truncate方法以实现BLOB字段中的删除操作
Read方法
声明
function Read(var Buffer; Count: Longint)
Longint;
Read方法从数据库域的当前位置起复制Count个字节的内容到Buffer中Buffer也必须至少分配Count个字节Read方法返回实际传输的字节数因为传输的字节数可能小于Count所以需要选择符的边界判断
[] [] [] []