• Blog
  • Resources in Delphi: How to insert external files in the executable

Resources in Delphi: How to insert external files in the executable

How to access external files later when necessary

Publish date:
    DISCOVER MORE OF WHAT MATTERS TO YOU

    Resources in Delphi: How to insert external files in the executable

    Overview

    One of the most widely used practices for generating a small executable is to modularize the project into several EXEs, DLLs, BPLs, and keep separate auxiliary text, image, or sound files.

    This practice is helpful for decreasing file traffic during system updates by performing the update only on those files that have actually changed.

    However, if it is necessary to keep a single file for the whole system, Delphi offers this possibility through its IDE.

    In this article, we will have a look at how to insert external files inside the executable and access them later when it is necessary.

    Adding files to the project

    Although this feature has existed since Delphi version 3, the way to incorporate external files into the executable has Although this feature has existed since Delphi version 3, the way to incorporate external files into the executable has been significantly improved since version 2009. Now you can use a resource manager that can be accessed via the menu Project > Resources and Images. In Screenshot 1 you can see several files added through the resource manager screen.

    Files added through the resource manager screen

    Once files are added, they appear in Delphi’s Project Manager, where you can select them and change their properties in the Object Inspector as shown in Screenshot 2.

    Delphi's Project Manager

    Once the files have been added, when the project is compiled, a text file with extension *.rc is generated, which contains on each line an “alias” to reference the file, its physical path and the resource data type. The content of tOnce the files are added and the project is compiled, a text file with the extension *.rc is generated. On each line, it contains an “alias” to reference the file, its physical path, and the resource data type. The content of this file referring to Figure 2 can be seen in the following image.

    Text file with extension *.rc

    After the *.rc file has been generated, Delphi compiles it into an intermediate version with extension *.dres, which will be used during the linking process, and later generates a new file with extension *.res, which is finally eAfter a *.rc file is generated, Delphi compiles it into an intermediate version with the extension *.dres, which will be used during the linking process, and it will generate a new file with the extension *.res, which will be finally encapsulated inside the executable.

    Reusing text files

    Files that do not fit into the predefined standards for resources (bitmaps, icons, and font files), such as text files, are encapsulated as a binary type called RCData. To access them, it is necessary to use a class called TResourceStream, which allows you to load the file into any component that has a property of the TStrings type, using a single code line. For example, we can easily load the contents of the file and display them in a ListBox with the following command:

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

    When you are instantiating the TResourceStream class while calling the LoadFromStream method of the TStrings class, it is necessary to use at least three parameters: a pointer variable called HInstance, the “alias” that references the resource, and a constant that represents the data type in which the resource is stored in the executable.

    Reusing image files

    Image files can be reused in two ways, depending on their type. If they are icon images, *.bmp files, or cursors, there is the LoadFromResourceName method, which allows you to load them with just one code line:

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

    Note that since this is an image with the *.bmp extension, the method does not contain additional conversion routines, unlike in the cases with images of other formats, which are compiled as binaries.

    The second method is used for dealing with PNG or JPEG images. In such cases, it is necessary to use classes that properly handle the resource. We can see how it can be done in the example below.

    123456789101112
    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;

    Line 05: We instantiate an object of the TPngImage type;

    Line 07: The LoadFromResourceName method gets the copy of the image of the *.png type that was compiled as RCData;

    Line 08: We assign the png instance to the Graphic property, as a result, component make a copy of our png and the image is displayed in the component;Line 10: We free our local object of TPngImage to prevent memory leaks.

    Reusing audio files, executables, DLLs, and others

    Files of the types other than those that we have considered so far are also compiled as RCData, but to use them you have to extract them using the combination of classes TResourceStream and TFileStream, as shown below. In this example, we used an MP3 file, but the same code can work for other types as well, such as executables or DLLs.

    12345678910111213141516171819
    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;

    Line 07: We instantiate a TResourceStream, passing the alias of the MP3 file and the data type (RCData) as a parameter;

    Line 09: We assign the path of a directory to extract the file to the string variable;

    Lines 10 and 11: We save all the contents of the resource loaded in line 7 into the file;

    Lines 15 to 18: We execute the MP3 file extracted from the executable.

    Conclusion

    Although resources can very useful for transporting files in the executable itself and reusing them within the system, you should be careful with them. Since there is no effective file compression, its size usually increases more than expected.

    Subscribe to our newsletter and get amazing content right in your inbox.

    This field is required
    This field is required Invalid email address

    Thank you for subscribing!
    See you soon... in your inbox!

    confirm your subscription, make sure to check your promotions/spam folder

    Subscribe to our newsletter and get amazing content right in your inbox.

    You can unsubscribe from the newsletter at any time

    This field is required
    This field is required Invalid email address

    You're almost there...

    A confirmation was sent to your email

    confirm your subscription, make sure to check
    your promotions/spam folder