Subsections


12. Using Windows resources

12.1 The resource directive $R

Under WINDOWS, you can include resources in your executable or library using the {$R filename} directive. These resources can then be accessed through the standard windows API calls.

When the compiler encounters a resource directive, it just creates an entry in the unit .ppu file; it doesn't link the resource. Only when it creates a library or executable, it looks for all the resource files for which it encountered a directive, and tries to link them in.

The default extension for resource files is .res. When the filename has as the first character an asterix (*), the compiler will replace the asterix with the name of the current unit, library or program.

Remark: This means that the asterix may only be used after a unit, library or program clause.

12.2 Creating resources

The Free Pascal compiler itself doesn't create any resource files; it just compiles them into the executable. To create resource files, you can use some GUI tools as the Borland resource workshop; but it is also possible to use a windows resource compiler like GNU windres. windres comes with the GNU binutils, but the Free Pascal distribution also contains a version which you can use.

The usage of windres is straightforward; it reads an input file describing the resources to create and outputs a resource file.

A typical invocation of windres would be

windres -i mystrings.rc -o mystrings.res
this will read the mystrings.rc file and output a mystrings.res resource file.

A complete overview of the windres tools is outside the scope of this document, but here are some things you can use it for:

stringtables
that contain lists of strings.
bitmaps
which are read from an external file.
icons
which are also read from an external file.
Version information
which can be viewed with the Windows explorer.
Menus
Can be designed as resources and used in your GUI applications.
Arbitrary data
Can be included as resources and read with the windows API calls.

Some of these will be described below.

12.3 Using string tables.

String tables can be used to store and retrieve large collections of strings in your application.

A string table looks as follows:

STRINGTABLE { 1, "hello World !"
              2, "hello world again !"
              3, "last hello world !" }
You can compile this (we assume the file is called tests.rc) as follows:
windres -i tests.rc -o tests.res
And this is the way to retrieve the strings from your program:
program tests;

{$mode objfpc}

Uses Windows;

{$R *.res}

  Function LoadResourceString (Index : longint): Shortstring;

  begin
    SetLength(Result,LoadString(FindResource(0,Nil,RT_STRING),Index,@Result[1],SizeOf(Result)))
  end;

Var
    I: longint;

begin
  For i:=1 to 3 do
    Writeln (Loadresourcestring(I));
end.
The call to FindResource searches for the stringtable in the compiled-in resources. The LoadString function then reads the string with index i out of the table, and puts it in a buffer, which can then be used. Both calls are in the windows unit.

12.4 Inserting version information

The win32 API allows to store version information in your binaries. This information can be made visible with the WINDOWS Explorer, by right-clicking on the executable or library, and selecting the 'Properties' menu. In the tab 'Version' the version information will be displayed.

Here is how to insert version information in your binary:

1 VERSIONINFO
FILEVERSION 4, 0, 3, 17
PRODUCTVERSION 3, 0, 0, 0
FILEFLAGSMASK 0
FILEOS 0x40000
FILETYPE 1
{
 BLOCK "StringFileInfo"
 {
  BLOCK "040904E4"
  {
   VALUE "CompanyName", "Free Pascal"
   VALUE "FileDescription", "Free Pascal version information extractor"
   VALUE "FileVersion", "1.0"
   VALUE "InternalName", "Showver"
   VALUE "LegalCopyright", "GNU Public License"
   VALUE "OriginalFilename", "showver.pp"
   VALUE "ProductName", "Free Pascal"
   VALUE "ProductVersion", "1.0"
  }
 }
}
As you can see, you can insert various kinds of information in the version info block. The keyword VERSIONINFO marks the beginning of the version information resource block. The keywords FILEVERSION, PRODUCTVERSION give the actual file version, while the block StringFileInfo gives other information that is displayed in the explorer.

The Free Component Library comes with a unit (fileinfo) that allows to extract and view version information in a straightforward and easy manner; the demo program that comes with it (showver) shows version information for an arbitrary executable or DLL.

12.5 Inserting an application icon

When WINDOWS shows an executable in the Explorer, it looks for an icon in the executable to show in front of the filename, the application icon.

Inserting an application icon is very easy and can be done as follows

AppIcon ICON "filename.ico"
This will read the file filename.ico and insert it in the resource file.

12.6 Using a pascal preprocessor

Sometimes you want to use symbolic names in your resource file, and use the same names in your program to access the resources. To accomplish this, there exists a preprocessor for windres that understands pascal syntax: fprcp. This preprocessor is shipped with the Free Pascal distribution.

The idea is that the preprocessor reads a pascal unit that has some symbolic constants defined in it, and replaces symbolic names in the resource file by the values of the constants in the unit:

As an example: consider the follwoing unit:

unit myunit;

interface

Const
  First  = 1;
  Second = 2:
  Third  = 3;

Implementation
end.
And the following resource file:
#include "myunit.pp"

STRINGTABLE { First, "hello World !"
              Second, "hello world again !"
              Third, "last hello world !" }
if you invoke windres with the -preprocessor option:
windres --preprocessor fprcp -i myunit.rc -o myunit.res
Then the preprocessor will replace the symbolic names 'first', 'second' and 'third' with their actual values.

In your program, you can then refer to the strings by their symbolic names (the constants) instead of using a numeric index.



root
2000-12-20