Delphi中資源文件的使用

Delphi中資源文件的使用

 

Delphi中,生成一個Appliction工程時,會默認生成一個與工程同名的資源文件,即使刪除也會再度創建,但是這個資源文件中只有一個圖標和一個版本信息。

通常情況下,我們還需要更多的多種多樣的資源,雖然可以在IDE中載入並編譯到EXE文件中去,但是有時我們需要將資源與EXE分開,以便生成多語言程序或將程序改爲其它語言(如漢化)。

Delphi附帶的ImageEdit可以編輯資源文件,但只能編輯位圖、圖標和光標,無法加入字符串資源,而且只持256色的圖像。爲了將更多種類的資源,只有編寫資源腳本或者使用其它資源編輯器,如Visual Stadio 6。不過,Visual Stadio 6編輯的資源文件中包含了C++頭文件定義,並且支持的具體資源類型較多,在Delphi中是無法識別的。

只好選擇編寫資源腳本了,資源腳本文件擴展名爲.RC,可以用純文本編輯器編寫。如下面是兩個圖標與兩個字符串的腳本:

COMPUTER RCDATA "computer.ico"              /* Delphi中只支持RCDATA類型 */

WINDOWSXP RCDATA "XP.ico"

 

STRINGTABLE

BEGIN

  1 "computer(電腦)"

  2 "Windows XP"

END

將其保存爲MyRes.rc,需要注意的是,這裏包含了兩個圖標,注意文件名及路徑(這裏是與文件同一目錄)。在命令提示符窗口中將目錄切換到MyRes.rc所在的路徑,運行brcc32 MyRes.rc,其中brcc32.exeDelphi附帶的資源編譯工具。如果想將資源文件生成其中擴展名的文件(如.DLL),可以增加-fo參數,如:brcc32 MyRes.rc –of MyRes.dll

 

       接下來是對資源的引用,引用方法有靜態與動態兩種,靜態引用就是將資源文件包含到源碼中編譯到EXE中去;動態引用則是把資源文件當成DLL動態裝載。

靜態引用資源文件在Delphi中是最簡單不過了,只要在工程文件中加入一個編譯指令即可,如:

program Multi_Lang;

 

uses

  Forms,

  TestFormUnit in 'TestFormUnit.pas' {TestForm};

 

{$R MyRes.dll}            // 包含自定義的資源文件

{$R *.res}                    // 包含默認的資源文件

 

begin

  Application.Initialize;

  Application.CreateForm(TTestForm, TestForm);

  Application.Run;

end.

引用時,字符串只要LoadStr(Index)即可,而其它資源用TResourceStream讀取,只不過資源句柄就是程序本身,直接用hInstance就可以了。如:

procedure TTestForm.ReadDirect(Index: Integer);

var

  Stream: TResourceStream;

  Icon: TIcon;

  S: String;

begin

  Edit1.Text:= LoadStr(Index);    // TEdit控件中顯示所獲取的字符串

  if Index = 1 then

    S:= 'COMPUTER'

  else

    S:= 'WINDOWSXP';

// Delphi中只支持RT_RCDATA類型讀取

  Stream:= TResourceStream.Create(hInstance, S, RT_RCDATA);    // 使用hInstance句柄

  try

    Icon:= TIcon.Create;

    try

      Icon.LoadFromStream(Stream);

      Image1.Picture.Icon.Assign(Icon);          // TImage控件中顯示所獲取的圖標

    finally

      Icon.Free;

    end;

  finally

    Stream.Free;

  end; 

end;

這種引用方式在編譯就將資源與EXE文件鏈接在一起,而編譯之後就不再需要資源文件了。

動態引用方式相對更多加靈活,編譯時不需要資源文件,而是在運行時動態地入,這樣便可以控件載入不同的資源文件,這也是實現多語言程序的一種方法。

動態引用實際上只是將資源文件靜態包含到另一個工程(一般爲DLL程序)中,如:

library MyResDll;

 

uses

  SysUtils,

  Classes;

 

{$R MyRes.dll}     // 將資源文件包含到DLL工程中

 

ResourceString

  S1 = '電腦';

  S2 = '視窗';

Begin

End.

 

引用時像普通的DLL引用一樣,將其裝載後得到一個句柄,再用靜態引用的方法,使用TResourceStream來讀取。如:

procedure TTestForm.ReadDynamic(Index: Integer);

var

  Hnd: THandle;

  Stream: TResourceStream;

  Icon: TIcon;

  S: String;

  Buf: PChar;

begin

  Hnd:= LoadLibrary('MyResDll.dll');        // 裝載資源文件

  if Hnd > 0 then

  begin

    GetMem(Buf, 255);

    LoadString(Hnd, Index, Buf, 255);             // 使用LoadString裝載指定句柄的字符串

    Edit1.Text:= StrPas(Buf);

 

    if Index = 1 then

      S:= 'COMPUTER'

    else

      S:= 'WINDOWSXP';

 

    Stream:= TResourceStream.Create(Hnd, S, RT_RCDATA); // 使用裝載得到的句柄

    try

      Icon:= TIcon.Create;

      try

        Icon.LoadFromStream(Stream);

        Image1.Picture.Icon.Assign(Icon);

      finally

        Icon.Free;

      end;

    finally

      FreeMem(Buf, 255);

      Stream.Free;

    end;

 

    FreeLibrary(Hnd);

  end;

end;

這種方法似乎有點複雜。^_^

 

將上面的方法變一下,將裝載字符串的函數聲明在DLL文件中,如:


library MyResDll;

uses

  SysUtils,

  Classes;

 

{$R MyRes.dll}

 

ResourceString

  S1 = '電腦';

  S2 = '視窗';

 

const

  ResStr: array[0..1] of String = (S1, S2); // 將字符串放入數組常量

 

{ 聲明函數獲取字符串個數}

function GetStrCount: Integer; stdcall;

begin

  Result:= Length(ResStr);

end;

 

{ 聲明函數獲取指定索引號的字符串 }

function GetResStr(Index: Integer): PChar; stdcall;

begin

  if (Index >= Low(ResStr)) and (Index <= High(ResStr)) then

    Result:= PChar(ResStr[Index])

  else

    Result:= '';

end;

 

exports

  GetStrCount,

  GetResStr;

 

begin

end.

 

引用的方法與一般的函數庫引用方法一樣。如:

type

  TGetResStr = function(Index: Integer): PChar; stdcall;

 

procedure TTestForm.ReadSourceDef(Index: Integer);

var

  Hnd: THandle;

  GetResStr: TGetResStr;

begin

  Hnd:= LoadLibrary('MyResDll.dll');

  if Hnd > 0 then

  begin

    @GetResStr:= GetProcAddress(Hnd, 'GetResStr');

    Edit1.Text:= GetResStr(Index);

    FreeLibrary(Hnd);

  end;

end;

 

以上代碼在Windows XP Professional + Delphi7下測試通過,如需完整的源碼請mail我:[email protected]

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章