delphi资源文件制作及使用详解 |
2010 - 04 - 13 17 : 32 |
一、引子: |
现在的Windows应用程序几乎都使用图标、图片、光标、声音等,我们称它们为资源(Resource)。最简单的使用资源的办法是把这些资源的源文件打入软件包,以方便程序需要的时候调用。资源是程序的一部分,程序要正常运行就离不了资源文件。但是它是不可执行代码。 |
为了更好地管理资源,Delphi中提供了一种.RES类型的资源文件。它可以把我们程序中所需要的资源整合到一个资源文件(.RES)下来。在编译应用程序时直接编译进了可执行程序里,成为应用程序的整合体。 |
这样做的好处是: 1 。由于定位资源比在磁盘中定位文件花费时间少,所以应用程序执行会更快。 2 。多种资源可以放在一个文件中,减少了图标、图片、光标、声音等文件数量。不用怕用户在使用过程中的不小心而损坏了资源文件致使程序无法正常运行。 |
缺点是:因为资源文件的加入从而加大了编译出的可执行程序的字节数,当资源文件较大时会使应用程序变得看起来雍肿。 |
使用资源文件的优点很显著,其缺点也很突出。所以在实际应用中就要根据情况权衡利弊、灵活使用,这已不在本文的讨论之列。下面仅就Delphi系统编程中对于资源文件的使用方法做一个大致的总结。 |
二、创建资源文件: |
注意事项:创建的资源文件名不要和工程名相同,因为Delphi创建工程时会自动创建一个和工程名相同的资源文件。并且最好将资源文件保存到和工程文件同一个文件夹中。 |
1 .首先创建一个.Rc的纯文本文件。格式如下: |
资源标识符 关键字 资源文件名 |
格式说明: |
① 资源标识符:程序中调用资源时的特定标号; |
② 关键字:标识资源文件类型;例如: |
Wave : 资源文件是声音文件; |
RCDATA: JPEG文件; |
AVI : AVI动画; |
ICON : 图标文件; |
BITMAP: 位图文件; |
CURSOR: 光标文件; |
RMI : RMI音乐文件; |
MIDI : MIDI音乐文件 |
③ 资源文件名:加入的资源文件名(要带扩展名,可以带路径名构成全文件名); |
④ 举例: MyWav WAVE "FileName . Wav" |
MyMID MIDI "C:\My Documents\my music\canyon . MID" |
MyAVI AVI "SpeedIs . AVI" |
例中资源文件名可以不加引号。假设我们把上述三行保存成Sample . RC文件。 |
2 。使用Borland资源编译器(BRCC32 . EXE)转化.Rc文件成.Res文件。 |
在DOS命令行下输入下列命令: |
C: //转在C:驱 |
CD\ //退回根目录 |
CD\ Program Files\Borland\Delphi7\Bin //进入BRCC32.EXE的所在目录 |
Brcc32 Sample . Rc //把Sample.RC转换成资源文件Sample.RES |
注意转换前需要把Sample . RC文件中指定的未带全路径名的文件Copy进当前目录C:\ Program Files\Borland\Delphi7\Bin中来,才可保证转成.RES文件不出错。如果转换过程没有报错,则成功。 |
三、引用资源文件 |
把上一步骤生成的资源文件Sample . RES放到要建立的工程的同一个目录中来。 |
为了存取我们的资源文件,必须告诉Delphi链接我们的资源文件到应用程序中。因此要在源代码中加入一条编译指令完成上述功能。这条指令必须紧跟在窗口指令后,如下形式: |
{$R *.DFM} //Delphi自带编译指令 |
{$R Sample.RES} //新加入的编译资源文件的指令 |
不要删除 {$R *.DFM} 指令,因为这行代码告诉Delphi链接下面的资源到窗口的资源中。 |
四、调用资源文件 |
1 。存取资源文件中的位图(Bitmap) |
程序中如果想存取资源,必须调用一些Windows API函数。保存在资源文件中的位图、光标和图标可以通过调用LoadBitmap、LoadCursor和LoadIcon函数存取。 |
现举例说明如何存取资源文件中位图并显示在Timage控件中。 |
procedure TfrMain . btnCanvasPic(Sender: TObject); |
begin |
Image1 . Picture . Bitmap . Handle :=LoadBitmap(hInstance, '资源标识符' ); |
end ; |
注:如果位图没有装载成功,程序仍旧执行,但是Image将不再显示图片。可以根据LoadBitmap 函数的返回值判断是否装载成功,如果装载成功返回值是非 0 ,如果装载失败返回值是 0 。 |
另外一个存取显示位图的方法如下: |
procedure TfrMain . btnLoadPicClick(Sender: TObject); |
begin |
Image1 . Picture . Bitmap . LoadFromResourceName(hInstance, '资源标识符' ); |
end ; |
2 。存取资源文件中的光标 |
Screen . Cursors[]是一个光标数组,使用光标文件我们可以将定制的光标加入到这个属性中。因为默认的光标在数组中索引值是 0 ,所以除非想取代默认光标,最好将定制的光标索引值设为 1 。 |
procedure TfrMain . btnUseCursorClick(Sender: TObject); |
begin |
Screen . Cursors[ 1 ] :=LoadCursor(hInstance, '资源标识符' ); |
Image1 . Cursor := 1 ; |
end ; |
3 。存取资源文件中的图标 |
将图标放在资源文件中,可以实现动态改变应用程序图标。 |
procedure TfrMain . LoadIconClick(Sender: TObject); |
begin |
Application . Icon . Handle := LoadIcon(hInstance, '资源标识符' ); |
End ; |
4 。存取资源文件中的AVI |
在工程中添加一TAnimate控件(在Win32控件面板上),在需要的地方加入: |
procedure TfrMain . LoadIconClick(Sender: TObject); |
begin |
Animate1 . ResName := 'MyAvi' ; //资源标识 |
Animate1 . Active := True ; |
End ; |
实践中的一点总结:并不是所有的AVI资源都可以用TAnimate组件来播放,编定程序时要测试。遇到不能用TAnimate组件来播放的AVI资源,则可以把它从资源文件里分离出来,再使用相应的播放组件比如TMediaPlayer来播放。使用完再把分离出来的临时文件删除掉。可以参考后面 " 7 。"的说明。 |
5 。存取资源文件中的JPEG |
把jpeg单元加入到 Interface 的 uses 中。 |
procedure TForm1 . LoadJPGClick(Sender: TObject); |
var |
Fjpg : TJpegImage ; |
FStream : TResourceStream ; |
begin |
Fjpg := TJpegImage . Create ; |
FStream := TResourceStream . Create(hInstance, '资源标识符' ,RT_RCDATA) ; |
FJpg . LoadFromStream(FStream) ; |
Image1 . Picture . Bitmap . Assign(FJpg); |
end ; |
6 。存取资源文件中的Wave |
把MMSystem加入到 Interface 的 uses 中 |
procedure TForm1 . LoadWaveClick(Sender: TObject); |
begin |
PlaySound( 'MyWav' ,hInstance,Snd_ASync or Snd_Memory or snd_Resource) ; |
end ; |
实践中的一点结论:PlaySound()的参数Snd_ASync表示异步播放方式,Snd_Sync表示同步播放方式。( 1 )当采用异步方式的时候,WAV资源可以作为背景音乐来应用;但是当有连续多次异步调用的时候,则可能会丢弃最后一次调用之前的所有播放,用户得到的效果只是最后一次调用的声音。( 2 )当采用同步方式的时候,WAV资源会独占资源,导致WAV文件未播放完之前用户无法对应用程序进行任何操作,直至它的调用结束。所以如果有大的同步WAV资源时,会造成应用程序界面的停滞。但是这种方式却可以连续地一个不漏地执行多次调用。 |
7 。其他资源的调用: |
可以把资源文件中的源文件分离出来,建立一个临时的物理文件存在于应用程序路径下,然后可以用相应类型的组件来或方法来使用该文件。当程序退出时再不忘把该临时文件删除掉。 |
例如: |
var |
tmpDirectory : string ; |
myres : TResourceStream; |
begin |
tmpDirectory := ExtractFilePath(paramstr( 0 )); |
if not FileExists(tmpDirectory + 'Music1.RMI' ) then |
begin |
myres := TResourceStream . Create(hinstance, 'music1' , 'RMI' ); |
myres . SaveToFile(tmpDirectory + 'Music1.RMI' ); //从资源文件中分离出来 |
myres . Free; |
。。。。。。。。。。 |
end ; |
程序退出的时候删除: |
if FileExists(tempDirectory + 'music1.RMI' ) then |
DeleteFile(tempDirectory + 'music1.RMI' ); |
五、结束语 |
位图、光标和图标、AVI动画、JPEG和Wave文件等可以放到资源文件中。上面我们介绍了如何将资源加入到资源文件中,并介绍了在Delphi中动态存取资源文件的方法。Delphi编译工程会自动创建一个和工程名相同的资源文件(如果没有其他的资源,主窗口的图标会放在这个资源文件中)。但是建议最好不要改变这个资源文件。 |
六、参考资料: |
1 。http: //www.delphiok.com/bcjq/all/114.htm 来自Delphi技巧网; |
2 。http: //www.delphibbs.com/delphibbs/dispq.asp?lid=2358589 ; |
http: //www.delphibbs.com/delphibbs/dispq.asp?lid=2369429 ; |
http: //www.delphibbs.com/delphibbs/dispq.asp?lid=2370212 ;来自大富翁论坛 |
特向以上网站和大富翁Wind8Bell、迷糊、miaofeng、app2001等表示感谢! |
可以自己做一个RC文件,例如 sample . rc ,RC文件其实就是一个资源文件的描述文本, |
通过"记事本"程序创建就行了。然后可以输入一些我们要定义的资源,例如: |
MEN BITMAP c:\bitmap\men . bitmap |
ARJ EXEFILE c:\arj . exe |
MOV AVI c:\mov . avi |
然后用BRCC32把这个RC文件编译成sample . res(真正的资源文件)。 |
在Delphi的工程文件中使用 $R 编译指令让Delphi包括资源到EXE文件里面。 |
{$R sample.res} |
这样我们就可以在这个单一的执行文件中调用资源了。举例如下: |
EXEFILE: |
procedure ExtractRes(ResType, ResName, ResNewName : String ); |
var |
Res : TResourceStream; |
begin |
Res := TResourceStream . Create(Hinstance, Resname, Pchar (ResType)); Res . SavetoFile(ResNewName); |
Res . Free; |
end ; |
AVI: |
procedure LoadAVI; |
begin |
{Avi1是一个TAnimate类} |
Avi1 . ResName:= 'AVI' ; |
Avi1 . Active:= True ; |