Inside the (Delphi) EXE

Storing Resource (WAV, MP3, ...) into Delphi Executables

Woman using laptop
MoMo Productions/Stone/Getty Images

Games and other types of applications which use multimedia files like sounds and animations must either distribute the extra multimedia files along with the application or embed the files within the executable.
Rather than distribute separate files for your application's use, you can add the raw data to your application as a resource. You can then retrieve the data from your application when it is needed.

This technique is generally more desirable because it can keep others from manipulating those add-in files.

This article will show you how to embed (and use) sound files, video clips, animations and more generally any kind of binary files in a Delphi executable. For the most general purpose you'll see how to put a MP3 file inside a Delphi exe.

Resource Files (.RES)

In the "Resource Files Made Easy" article you were presented with several examples of the use of bitmaps, icons and cursors from resources. As stated in that article we can use the Image Editor to create and edit resources that consist of such types of files. Now, when we are interested in storing various types of (binary) files inside a Delphi executable we'll have to deal with resource script files (.rc), the Borland Resource Compiler tool and other.

Including several binary files in your executable consists of 5 steps:

  1. Create and/or collect all the files you whish to put in an exe,
  1. Create a resource script file (.rc) that describes those resources used by your application,
  2. Compile the resource script file (.rc) file to create a resource file (.res),
  3. Link the compiled resource file into the application’s executable file,
  4. Use individual resource element.

The first step should be simple, simply decide what types of files you would like to store in you executable.

For example, we will store two .wav songs, one .ani animations and one .mp3 song.

Before we move on, here are a few important statements concerning limitations when working with resources:

a) Loading and unloading resources is not a time consuming operation. Resources are part of the applications executable file and are loaded at the same time the application runs.

b) All the (free) memory can be used when loading/unloading resources. In other words there are no limits on number of resources loaded at the same time.

c)Of course, resource file do double the size of an executable. If you want smaller executable consider placing resources and parts of your project in DLLs and Packages.

Let's now see how to create a file that describes resources.

Creating a Resource Script File (.RC)

A resource script file is a just a simple text file with the extension .rc that lists resources. The script file is in this format:

ResName1 ResTYPE1 ResFileName1
ResName2 ResTYPE2 ResFileName2
...
ResNameX ResTYPEX ResFileNameX
...

RexName specifies either a unique name or an integer value (ID) that identifies the resource. ResType describes the type of resource and the ResFileName is the full path and file name to the individual resource file.

To create a new resource script file, simply do the following:

  1. Create a new text file in your projects directory.
  2. Rename it to AboutDelphi.rc.

In the AboutDelphi.rc file, have the following lines:

Clock WAVE "c:\mysounds\projects\clock.wav"
MailBeep WAVE "c:\windows\media\newmail.wav"
Cool AVI cool.avi
Intro RCDATA introsong.mp3

The script file simply defines resources. Following the given format the AboutDelphi.rc script lists two .wav files, one .avi animation, and one .mp3 song. All statements in a .rc file associate an identifying name, type and file name for a given resource. There are about a dozen predefined resource types. These include icons, bitmaps, cursors, animations, songs, etc. The RCDATA defines generic data resources. RCDATA let you include a raw data resource for an application. Raw data resources permit the inclusion of binary data directly in the executable file.

For example, the RCDATA statement above names the application’s binary resource Intro and specifies the file introsong.mp3, which contains the song for that mp3 file.

Note: make sure you have all the resources you list in your .rc file available. If the files are inside your projects directory you don't have to include full file name. In my .rc file .wav songs are located *somewhere* on the disk and both the animation and mp3 song are located in the project's directory.

Creating a Resource File (.RES)

To use the resources defined in the resource script file, we must compile it to a .res file with the Borland's Resource Compiler. The resource compiler creates a new file based on the contents of the resource script file. This file usually has an .res extension. The Delphi linker will later reformat the .res file into a resource object file and then link it to the executable file of an application.

The Borland's Resource Compiler command line tool is located in the Delphi Bin directory. The name is BRCC32.exe. Simply go to the command prompt and type brcc32 then press Enter. Since the Delphi\Bin directory is in your Path the Brcc32 compiler is invoked and displays the usage help (since it was called with no parapeters).

To compile the AboutDelphi.rc file to a .res file execute this command at the command prompt (in the projects directory):

BRCC32 AboutDelphi.RC

By default, when compiling resources, BRCC32 names the compiled resource (.RES) file with the base name of the .RC file and places it in the same directory as the .RC file.

You can name the resource file anything you want, as long as it has the extension ".RES" and the filename without the extension is not the same as any unit or project filename. This is important, because by default, each Delphi project that compiles into an application has a resource file with the same name as the project file, but with the extension .RES. It's best to save the file to the same directory as your project file.

Including (Linking/Embeding) Resources to Executables

With the Borland's Resource Compiler we have created the AboutDelphi.res resource file. The next step is to add the following compiler directive to a unit in your project, immediately after the form directive (below the implementation key word).
 {$R *.DFM} {$R AboutDelphi.RES} 
Do not accidentally erase {$R *.DFM} part, as this is the line of code that tells Delphi to link in the form's visual part. When you choose bitmaps for speed buttons, Image components or Button components, Delphi includes the bitmap file you chose as part of the form's resource. Delphi isolates your user interface elements into the .DFM file.

After the .RES file is linked to the executable file, the application can load its resources at run time as needed. To actually use the resource, you'll have to make a few Windows API calls.

In order to follow the article you'll need a new Delphi project with a blank form (the default new project). Of course add the {$R AboutDelphi.RES} directive to the main form's unit. It's finally time to see how to use resources in a Delphi application. As mentioned above, in order to use resources stored inside an exe file we have to deal with API. However, several methods can be found in the Delphi help files that are "resource" enabled.

For example take a look at the LoadFromResourceName method of a TBitmap object.

This method extracts the specified bitmap resource and assigns it TBitmap object. This is *exactly* what LoadBitmap API call does. As always Delphi has improved an API function call to suit your needs better.

Playing Animations from Resources

To show the animation inside the cool.avi (remember it was defined in the .rc file) we'll use the TAnimate component (Win32 palette) - drop it on to the main form. Let the name of the Animate component be the default one: Animate1. We'll use the OnCreate event of a form to display the animation:
 procedure TForm1.FormCreate(Sender: TObject) ;
 begin
  with Animate1 do begin
   ResName := 'cool';
   ResHandle := hInstance;
 
   Active := TRUE;
  end;
 end;
 
That simple! As we can see, in order to play an animation from a resource we have to use the use the ResHandle, ResName or ResID properties of TAnimate component. After setting ResHandle, we set the ResName property to specify which resource is the AVI clip that should be displayed by the animation control. Asigning True to the Active property simply starts the animation.

Playing WAVs

Since we have placed two WAVE files in our executable, we will now see how to grab a song inside the exe and play it. Drop a button (Button1) on a form and assign the following code to the OnClick event handler:
 uses mmsystem;
 ...
 procedure TForm1.Button1Click(Sender: TObject) ;
 var
   hFind, hRes: THandle;
   Song: PChar;
 begin
  hFind := FindResource(HInstance, 'MailBeep', 'WAVE') ;
  if hFind <> 0 then begin
    hRes:=LoadResource(HInstance, hFind) ;
    if hRes <> 0 then begin
      Song:=LockResource(hRes) ;
      if Assigned(Song) then SndPlaySound(Song, snd_ASync or snd_Memory) ;
      UnlockResource(hRes) ;
    end;
    FreeResource(hFind) ;
  end;
 end;
 
This approach uses several API calls to load a WAVE type resource named MailBeep and play it. Note: you cal use Delphi to play system predefined sounds.

Playing MP3s

The only MP3 file in our resource has the name Intro. Since this resource is of a RCDATA type we'll use another technique to get and play the mp3 song. Just in case you don't know that Delphi can play MP3 songs read the "Build your own WinAmp" article. Yes, that's right, the TMediaPlayer can play the mp3 file.

Now, add the TMediaPlayer component to a form (name: MediaPlayer1) and add a TButton (Button2). Let the OnClick event look like:

 procedure TForm1.Button2Click(Sender: TObject) ;
 var
  rStream: TResourceStream;
  fStream: TFileStream;
  fname: string;
 begin
  {this part extracts the mp3 from exe}
  fname := ExtractFileDir(Paramstr(0))+'Intro.mp3';
  rStream := TResourceStream.Create(hInstance, 'Intro', RT_RCDATA) ;
  try
   fStream := TFileStream.Create(fname, fmCreate) ;
   try
    fStream.CopyFrom(rStream, 0) ;
   finally
    fStream.Free;
   end;
  finally
   rStream.Free;
  end;
  {this part plays the mp3}
  MediaPlayer1.Close;
  MediaPlayer1.FileName:=fname;
  MediaPlayer1.Open;
 end;
 
This code, with the help of TResourceStream, extracts the mp3 song from the exe and saves it to the applications working directory. The name of the mp3 file is intro.mp3. Then simply assign that file to the FileName property of a MediaPlayer and play the song.

One minor *problem* is that the application creates a mp3 song on a user machine. You could add a code that deletes that file before the application is terminated.

Extracting *.???

Of course every other type of a binary file can be stored as a RCDATA type. The TRsourceStream is designed specially to help us extract such file from an executable. The possibilities are endless: HTML in an exe, EXE in exe, empty database in an exe, ....