Difference between revisions of "Lazarus Resources"

From Lazarus wiki
Jump to navigationJump to search
(Clarified split between FPC and Lazarus resources; clarify FPC resources are preferred.)
(→‎FPC resources: No need to run resource compiler anymore; headings for adding/extracting resources)
Line 84: Line 84:
 
The main class used to work with resources is TResourceStream. LCL uses it to load embedded bitmaps, icons and form streams. Look at TGraphic.LoadFromResourceID or TIcon.LoadFromResourceHandle to see how it is used inside LCL.
 
The main class used to work with resources is TResourceStream. LCL uses it to load embedded bitmaps, icons and form streams. Look at TGraphic.LoadFromResourceID or TIcon.LoadFromResourceHandle to see how it is used inside LCL.
  
 +
== Adding resources to your program ==
 
Let's review the situation when you need to store some data inside your executable and during the program run you want to extract this data from it.
 
Let's review the situation when you need to store some data inside your executable and during the program run you want to extract this data from it.
  
We need to create the .res file. We can first prepare a .rc and then compile it.
+
First we need to tell the compiler what files to include in the resource. We do this in a .rc (resource script) file:
 
mydata.rc file:  
 
mydata.rc file:  
 
:<pre><nowiki>MYDATA        RCDATA "mydata.dat"</nowiki></pre>  
 
:<pre><nowiki>MYDATA        RCDATA "mydata.dat"</nowiki></pre>  
Where MYDATA is the resource name, RCDATA is the type of resource (look here http://msdn.microsoft.com/en-us/library/ms648009(VS.85).aspx for types exaplanation) and "mydata.dat" is a your data file. Let's compile it using the borland resource compiler:
+
Here MYDATA is the resource name, RCDATA is the type of resource (look here http://msdn.microsoft.com/en-us/library/ms648009(VS.85).aspx for explanation of possible types) and "mydata.dat" is your data file.  
:<pre><nowiki>brcc32 mydata.rc</nowiki></pre>
 
  
The res file is ready. Let's include it into your project:
+
Let's instruct the compiler to include the resource into your project:
 
<delphi>program mydata;
 
<delphi>program mydata;
  
{$R mydata.res}
+
{$R mydata.rc}
 
begin
 
begin
 
end.</delphi>
 
end.</delphi>
  
Now let's extract the stored resource into the mydata.dat file:
+
Behind the scenes, the FPC compiler actually instructs the resource compiler distributed with FPC to follow the .rc script to compile your data files into a binary .res resource file. The linker will then include this into the executable. Though this is transparent to the programmer, you can, if you want to, create your own .res file with e.g. the Borland resource compiler. Instead of using <delphi>{$R mydata.rc}</delphi> you'd use <delphi>{$R mydata.res}</delphi>.
 +
 
 +
== Using resources in your program ==
 +
Now let's extract the stored resource into a file, e.g. mydata.dat:
 
<delphi>program mydata;
 
<delphi>program mydata;
 
uses
 
uses

Revision as of 15:18, 9 February 2012

Deutsch (de) English (en) español (es) français (fr) 한국어 (ko) русский (ru)

Introduction

Resource files contain data which should be compiled into the exe file. That data could consist of images, string tables, version info, ... even a Windows XP manifest and forms. This includes data that the programmer can retrieve in his code (accessing them as files). Using resources can be handy if you want to distribute self-contained executables.

Before FPC 2.4 it was not possible to use "normal" resource files (*.res) in Lazarus because they were Win32 specific. Normal resources are recommended for FPC 2.4.0 and newer (this includes all recent Lazarus versions)

Lazarus resources

In order to use your files as Lazarus resources, you had to recreate them with lazres. Lazres can be found in the "Tools" directory (C:\Lazarus\Tools\ - you first have to compile the lazres.lpi project) of your Lazarus installation folder (maybe you will first have to compile it).

Then you can compile Lazarus resource files (*.lrs) via command line. The syntax for lazres is:

lazres <filename of resource file> <files to include (file1 file2 file3 ...)>

Example:

lazres mylazarusresource.lrs image.jpg

To use a lazarus resource file in your projects include the file with the $I compiler directive in the initialization section of your unit.

You can access the data in the resources directly or with the LoadFromLazarusResource method of the variables which will hold the file contents afterwards. LoadFromLazarusResource requires one string parameter which indicades which object should be loaded from the resource file.

Example: <delphi>procedure exampleproc; var

 Image: TImage

begin

 Image := TImage.Create;
 Image.Picture.LoadFromLazarusResource('image'); // note that there is no need for the extension

end;

initialization

 {$I mylazarusresource.lrs}</delphi>

This code includes the file mylazarusresource.lrs into the project. In the procedure exampleproc an icon object is created and loaded from the object "image" out of the resource. The file which was compiled into the resource was probably named image.jpg.

Every class that is derived from TGraphic contains the LoadFromLazarusResource procedure.

Lazarus Resource Form File

Lazarus generates .LRS files from .LFM form files.

When a LRS form file is missing, FPC reports the following error: ERROR: unit1.pas(193,4) Fatal: Can't open include file "unit1.lrs"

To solve it you can either:

  • use lazres: c:\lazarus\tools\lazres.exe unit1.lrs unit1.lfm
  • (easier): make a trivial change in the form design, revert it and save the form; this will recreate the .lrs file without needing to run lazres.

Getting the raw data of an lrs resource

You can retrieve the data of the resource with:

<Delphi>uses ...LResources...;

... procedure TForm1.FormCreate(Sender: TObject); var

 r: TLResource;
 Data: String;

begin

 r:=LazarusResources.Find('datafile1');
 if r=nil then raise Exception.Create('resource datafile1 is missing');
 Data:=r.Value;
 ...do something with the data...

end;</Delphi>

FPC resources

Starting from FPC 2.4 you can use standard .rc (resource script) and .res (compiled resource) files in your project to include resources. To turn a .rc script used in the sources into a binary resource (.res file), FPC runs the appropriate external resource compiler (windres or GoRC). Therefore that resource compiler needs to be installed and present in the PATH environment variable.

To simplify the compiling process, it is possible to use only the compiled resources in the .res files. You can precompile the resources by any available resource compiler - windres (available both on unixes and windows), GoRC (windows only), Microsoft resource compiler (rc.exe included in Visual Studio), Borland resource compiler (brcc32.exe included in Delphi, C++ Builder or Rad Studio products) or any other.

Use {$R filename.rc} or {$R filename.res} directive to include a resource file into the executable. FPC RTL provides both low-level functions as well as high-level classes to access resources.

The low-level functions are:

  • EnumResourceTypes
  • EnumResourceNames
  • EnumResourceLanguages
  • FindResource
  • FindResourceEx
  • LoadResource
  • SizeofResource
  • LockResource
  • UnlockResource
  • FreeResource

They are compatible with the Windows API functions: [1]

The main class used to work with resources is TResourceStream. LCL uses it to load embedded bitmaps, icons and form streams. Look at TGraphic.LoadFromResourceID or TIcon.LoadFromResourceHandle to see how it is used inside LCL.

Adding resources to your program

Let's review the situation when you need to store some data inside your executable and during the program run you want to extract this data from it.

First we need to tell the compiler what files to include in the resource. We do this in a .rc (resource script) file: mydata.rc file:

MYDATA         RCDATA "mydata.dat"

Here MYDATA is the resource name, RCDATA is the type of resource (look here http://msdn.microsoft.com/en-us/library/ms648009(VS.85).aspx for explanation of possible types) and "mydata.dat" is your data file.

Let's instruct the compiler to include the resource into your project: <delphi>program mydata;

{$R mydata.rc} begin end.</delphi>

Behind the scenes, the FPC compiler actually instructs the resource compiler distributed with FPC to follow the .rc script to compile your data files into a binary .res resource file. The linker will then include this into the executable. Though this is transparent to the programmer, you can, if you want to, create your own .res file with e.g. the Borland resource compiler. Instead of using <delphi>{$R mydata.rc}</delphi> you'd use <delphi>{$R mydata.res}</delphi>.

Using resources in your program

Now let's extract the stored resource into a file, e.g. mydata.dat: <delphi>program mydata; uses

 SysUtils;

{$R mydata.res} var

 S: TResourceStream;
 F: TFileStream;

begin

 // create a resource stream which points to our resource
 S := TResourceStream.Create(HInstance, 'MYDATA', RT_RCDATA); 
 try
   // create a file mydata.dat in the application directory
   F := TFileStream.Create(ExtractFilePath(ParamStr(0)) + 'mydata.dat', fmCreate); 
   try
     F.CopyFrom(S, S.Size); // copy data from the resource stream to file stream
   finally
     F.Free; // destroy the file stream
   end;
 finally
   S.Free; // destroy the resource stream
 end;

end.</delphi>