Delphi如何在可执行文件中插入外部文件

本图片由DeepAI自动生成)

一、概述

生成小型可执行文件最广泛使用的做法之一是将项目模块化为几个EXEs、DLLs、BPLs,并保持独立的辅助文本、图像或声音文件。

这种做法有助于减少系统更新时的文件流量,因为它只对那些实际改变了的文件进行更新。

然而,如果有必要为整个系统保留一个文件,Delphi通过其IDE提供了这种可能性。

在这篇文章中,我们将看看如何在可执行文件中插入外部文件,并在以后有必要时访问它们。

二、将文件添加到项目中

虽然这个功能从Delphi第三版开始就存在,但将外部文件纳入可执行文件的方式从2009版开始已经有了很大的改进。现在你可以使用一个资源管理器,可以通过菜单Project > Resources and Images访问。在截图1中,你可以看到通过资源管理器屏幕添加的几个文件。

一旦文件被添加,它们就会出现在Delphi的项目管理器中,你可以选择它们并在对象检查器中改变它们的属性,如屏幕截图2所示。

一旦文件被添加,项目被编译,就会生成一个扩展名为*.rc的文本文件。在每一行中,它包含一个 "别名 "来引用文件、其物理路径和资源数据类型。参照图2的这个文件的内容可以在下面的图片中看到。

该文件最终e在生成*.rc文件后,Delphi将其编译成扩展名为*.dres的中间版本,这将在链接过程中使用。

三、重复使用文本文件

不符合资源(位图、图标和字体文件)预定义标准的文件,如文本文件,被封装为一种叫做RCData的二进制类型。为了访问它们,有必要使用一个叫做TResourceStream的类,它允许你使用一个代码行将文件加载到任何具有TStrings类型属性的组件中。例如,我们可以很容易地加载文件的内容,并通过以下命令在ListBox中显示它们。

var
  LStream : TResourceStream;
begin
  LStream := TResourceStream.Create(HInstance, 'TXTuf', RT_RCDATA);
  try
    ListBox1.Items.LoadFromStream(LStream);
  finally
    LStream.free;
  end;
end;

当你在调用TStrings类的LoadFromStream方法时实例化TResourceStream类时,有必要使用至少三个参数:一个名为HInstance的指针变量,引用资源的 "别名",以及一个代表资源在可执行文件中存储的数据类型的常量(例如:RT_RCDATA)。

四、重复使用图像文件

图像文件可以通过两种方式被重复使用,这取决于它们的类型。如果它们是图标图像、*.bmp文件或光标,有LoadFromResourceName方法,它允许你只用一行代码就能加载它们。

Image2.Picture.Bitmap.LoadFromResourceName(HInstance, 'IMGPredio');

请注意,由于这是一个以*.bmp为扩展名的图像,该方法不包含额外的转换程序,与其他格式的图像不同,这些图像是作为二进制文件编译的。

第二种方法用于处理PNG或JPEG图像。在这种情况下,有必要使用能够正确处理资源的类。我们可以在下面的例子中看到如何做到这一点。

procedure TFormExample.BtnImageClick(Sender: TObject);
var
  PngImage: TPngImage;
begin
  PngImage := TPngImage.Create;
  try
    PngImage.LoadFromResourceName(HInstance, 'IMGDevmediaLogo');
    Image1.Picture.Graphic := PngImage;
  finally
    PngImage.Free;
  end;
end;

05行:我们实例化了一个TPngImage类型的对象。

07行:LoadFromResourceName方法获得了被编译为RCData的*.png类型的图像的副本。

08行:我们将png实例分配给Graphic属性,结果,组件复制了我们的png,图像显示在组件中;

10行:我们释放TPngImage的本地对象以防止内存泄漏。

五、重复使用音频文件、可执行文件、DLLs和其他文件

除了我们到目前为止所考虑的那些类型之外,其他类型的文件也被编译为RCData,但是为了使用它们,你必须使用TResourceStream和TFileStream类的组合来提取它们,如下所示。在这个例子中,我们使用了一个MP3文件,但同样的代码也可以用于其他类型,比如可执行文件或DLLs。

procedure TFormExample.btnExecutarMP3(Sender: TObject);
var
  ResourceStream: TResourceStream;
  FileName: string;
  MediaPlayer: TMediaPlayer;
begin
  ResourceStream := TResourceStream.Create(hInstance, 'WAVClock', RT_RCDATA);
  try
    FileName := ExtractFilePath(Application.ExeName) + 'file.mp3';
    ResourceStream.SaveToFile(FileName);
  finally
    ResourceStream.Free;
结论
尽管资源对于在可执行文件本身中运输文件和在系统中重复使用它们非常有用,但你应该小心使用它们。由于没有有效的文件压缩,其大小通常比预期的要大。  end;

  MediaPlayer.Close;
  MediaPlayer.FileName := FileName;
  MediaPlayer.Open;
  MediaPlayer.Play;
end;

07行:我们实例化一个TResourceStream,把MP3文件的别名和数据类型(RCData)作为一个参数传给它。

09行:我们把提取文件的目录路径分配给字符串变量。

10行和第11行:我们将第7行中加载的资源的所有内容保存到文件中。

1518行:我们执行从可执行文件中提取的MP3文件。

六、结论

尽管资源对于在可执行文件本身中传输文件和在系统中重复使用它们非常有用,但还是应该小心使用它们。由于没有有效的文件压缩,其大小通常比预期的要大。

七、译者注

关于作者的结论,认为资源文件没有有效的压缩,这个其实是可以进行压缩的,Delphi有提供TZipFile类来进行压缩和解压缩。只是操作起来稍微有点麻烦,也就是说在增加资源前先对资源进行压缩,具体使用的时候,可以使用Delphi的TZipFile进行动态解压(支持内存流解压),然后就可以使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值