20.1.6 TResourceStream對象
TResourceStream對象是另一類MemoryStream對象,它提供對Windows 應用程序資源的訪問,因此稱它為資源流。TResourceSream也是從TCustomMemoryStream 繼承的。因此在TCustomMemoryStream對象的基礎上,定義了與指定資源模塊或資源文件建立連接的構造方法,並且還覆蓋了Write,以實現向資源文件中寫數據。
下面介紹TResourceStream的實現
1. 私有域
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 TResourceStream.Initialize(Instance: THandle; Name, ResType: PChar);
procedure Error;
begin
raise EResNotFound.Create(FmtLoadStr(SResNotFound, [Name]));
end;
begin
HResInfo := FindResource(Instance, Name, ResType);
if HResInfo = 0 then Error;
HGlobal := LoadResource(Instance, HResInfo);
if HGlobal = 0 then Error;
SetPointer(LockResource(HGlobal), SizeOfResource(Instance, HResInfo));
end;
該方法實現中,首先調用Windows函數FoundResource得到由參數Instance指定的模塊中的名為Name和類型為ResType的資源,然後調用LoadResource將資源調用內存,並返回該資源在內存中的句柄,最後,將該資源復制到ResourceStream中。方法的Instance參數代表要調用的資源所在的模塊句柄。模塊可以是可執行文件,也可以是動態鏈接庫。如果在讀取資源時沒在模塊中發現要找的資源則產生異常事件。
2. 構造方法Create和CreateFromID
這兩個方法在實現上沒有大的不同。顧名思義,第一個方法是通過資源名構造TResourceStream; 第二個方法通過資源ID構造TResourceStream,而且在實現過程中,它們都調用了Initialize方法。下面是它們的實現:
constructor TResourceStream.Create(Instance: THandle; const ResName: string;
ResType: PChar);
begin
inherited Create;
Initialize(Instance, PChar(ResName), ResType);
end;
constructor TResourceStream.CreateFromID(Instance: THandle; ResID: Integer;
ResType: PChar);
begin
inherited Create;
Initialize(Instance, PChar(ResID), ResType);
end;
這兩個方法中都有Instance參數,該參數值的含義在Insitialize中介紹過。
3. Write方法
TResourceStream的Write方法只完成一件事,就產生這個異常事件,其實現如下:
function TResourceStream.Write(const Buffer; Count: Longint): Longint;
begin
raise EStreamError.CreateRes(SCantWriteResourceStreamError);
end;
從方法實現中可以看到,TSourceStream對象是不允許寫數據的。一旦往資源流中寫數據將產生異常事件。