Title: Loading resources from dll-files (New title)
Question: How to load resources from a dll to an application
Answer:
First of all: I'm sorry for my bad english!
It seems much, I know. Most of it is the form code. You don't have to read that.
I went to the index, found "DLL", and saw some articles. Two of them described dynamic loading (As we have to use), the rest of them I don't remember. Then I thought: "What about writing a article about resources in Dll's?"
Resources are icons, cursors, wave-files and even strings. You name it! The first thing to do is to create at resource file. Open Notepad, and write this:
STRINGTABLE
BEGIN
101, "Thank you!";
102, "This is easy";
103, " //Some other stuff\\ ";
END
Save it as "resource.rc" (RC means Resource sCript).
Open Delphi, and create a new bat-file (Batch). Right-click on "Project 2" (Or something like that), and choose Edit/Options. Under Commands, write: "brcc32 resource.rc". Brcc32 is the Borland resource compiler. Click OK.
Right-click on the project again, and execute it. Close the project.
Now open the new resource-file in the Image Editor. Create a new icon and cursor, and name them "Icon1" and "Cursor1". Make some paintings on them, before you save the file and exit.
The resource file is now ready.
-------------------
Go back to Delphi. Choose File New Other Dll Wizard
Under the {$R *.res} clause, write {$R resource.res}. Save the dll as "ResorceDll"
The finished dll:
library ResourceDll;
uses
SysUtils,
Classes;
{$R *.res}
{$R resource.res}
begin
end.
Click Project Build ResourceDll. In the projects folder you should now find a new dll.
-------------------
NOW the fun comes: The dll-reading program. Start a new project.
The important procedures are LoadLibrary, LoadCursor, LoadIcon and LoadString.
Save the unit as "DllReaderMain" and the project as "DllReader".
Copy the code into the main unit.
Under the code you will find the form in text format.
unit DllReaderMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Buttons;
type
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
Panel3: TPanel;
Edit1: TEdit;
Button6: TButton;
Label1: TLabel;
Label4: TLabel;
Panel2: TPanel;
Label3: TLabel;
Label2: TLabel;
Button4: TButton;
Edit3: TEdit;
Edit2: TEdit;
Button5: TButton;
Edit4: TEdit;
procedure Button6Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
DllInstance: THandle; // The "address" of the dll
OldIcon: HICON; // A backup of the old icon
implementation
{$R *.dfm}
procedure TForm1.Button6Click(Sender: TObject);
begin
FreeLibrary(DllInstance); // Make sure no library is open.
DllInstance:=LoadLibrary(pchar(edit1.text)); // Load the dll, and save the address in the variable
if GetLastError 0 then // Did something happend?
begin
Label1.Font.Color:=clRed;
Label1.Caption:='Status: Something happened...';
Panel1.Enabled:=False;
Panel2.Enabled:=False;
end
else
begin // No, everything is allright
Label1.Font.Color:=clGreen;
Label1.Caption:='Status: Open';
Panel1.Enabled:=True;
Panel2.Enabled:=True;
end;
end;
procedure TForm1.Button4Click(Sender: TObject);
const
crNewCursor = 5;
begin
Screen.Cursors[crNewCursor] := LoadCursor(DllInstance, pchar(Edit2.Text)); // Try to load the cursor and save it in the Screen.Cursors array
if GetLastError 0 then
begin
Label2.Font.Color:=clRed;
Label2.Caption:='Status: Something happened...';
end
else
begin
Form1.Cursor:= crNewCursor; // Use the cursos in the form
Cursor := crNewCursor; // Use the cursor on the "Cursor-button"
Label2.Font.Color:=clGreen;
Label2.Caption:='Status: OK';
end;
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
Form1.Icon.Handle:=LoadIcon(DllInstance,pchar(Edit3.Text)); // Load the icon, and use it at once
If Form1.Icon.Handle = OldIcon then // Did it work?
Begin
Label3.Font.Color:=clRed;
Label3.Caption:='Status: Something happened...';
End
Else
Begin
Label3.Font.Color:=clGreen;
Label3.Caption:='Status: OK';
End;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
OldIcon:=Form1.Icon.Handle; // Stores the original icon
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Buff: Array [0..20] of Char; // The container of the message. You can also use a PChar.
I, Code: Integer;
begin
Val(Edit4.Text,I,Code); // Check the number in Edit4.Text. No nuber, no procedure
If Code 0 then
begin
Label4.Font.Color:=clRed;
Label4.Caption:='Status: Convert error'; // Inform the user (you)
end
else
begin
Code:=LoadString(DllInstance,StrToInt(Edit4.Text),Buff,SizeOf(Buff)); //
if Code = 0 then
begin
Label4.Font.Color:=clRed;
Label4.Caption:='Status: Something happened...';
end
else
begin
Label4.Font.Color:=clGreen;
Label4.Caption:='Status: OK';
ShowMessage(Buff); // Show the message from the "Buff" variable
end;
end;
end;
end.
----------------------
Right-click on your existing form and choose "View as text"
Change it according to this:
object Form1: TForm1
Left = 269
Top = 231
Width = 361
Height = 212
AutoSize = True
Caption = 'Dll Reader'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Panel1: TPanel
Left = 0
Top = 136
Width = 353
Height = 49
BevelInner = bvRaised
BevelOuter = bvLowered
Enabled = False
TabOrder = 0
object Label4: TLabel
Left = 216
Top = 24
Width = 87
Height = 13
Caption = 'Status: Not tried'
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlue
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
ParentFont = False
end
object Button1: TButton
Left = 136
Top = 16
Width = 75
Height = 25
Caption = 'Load string'
TabOrder = 1
OnClick = Button1Click
end
object Edit4: TEdit
Left = 8
Top = 16
Width = 121
Height = 21
TabOrder = 0
end
end
object Panel3: TPanel
Left = 0
Top = 0
Width = 353
Height = 41
BevelInner = bvRaised
BevelOuter = bvLowered
TabOrder = 1
object Label1: TLabel
Left = 216
Top = 16
Width = 84
Height = 13
Caption = 'Status: Not open'
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlue
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
ParentFont = False
end
object Edit1: TEdit
Left = 8
Top = 8
Width = 121
Height = 21
TabOrder = 0
end
object Button6: TButton
Left = 136
Top = 8
Width = 75
Height = 25
Caption = 'Open the dll'
TabOrder = 1
OnClick = Button6Click
end
end
object Panel2: TPanel
Left = 0
Top = 48
Width = 353
Height = 81
BevelInner = bvRaised
BevelOuter = bvLowered
Enabled = False
TabOrder = 2
object Label3: TLabel
Left = 216
Top = 52
Width = 87
Height = 13
Caption = 'Status: Not opened'
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlue
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
ParentFont = False
end
object Label2: TLabel
Left = 216
Top = 16
Width = 87
Height = 13
Caption = 'Status: Not opened'
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlue
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
ParentFont = False
end
object Button4: TButton
Left = 136
Top = 8
Width = 75
Height = 25
Caption = 'Load cursor'
TabOrder = 1
OnClick = Button4Click
end
object Edit3: TEdit
Left = 8
Top = 44
Width = 121
Height = 21
TabOrder = 2
end
object Edit2: TEdit
Left = 8
Top = 8
Width = 121
Height = 21
TabOrder = 0
end
object Button5: TButton
Left = 136
Top = 44
Width = 75
Height = 25
Caption = 'Load icon'
TabOrder = 3
OnClick = Button5Click
end
end
end
---------------------
Now, everything's ready to run the program.
|- "Index" of edits -|- Write ---------|
| 1 | ResourceDll |
| 2 | Cursor1 |
| 3 | Icon1 |
| 4 | "101" - "103" |
|--------------------|-----------------|
Please contact me if the code doesn't work.
I hope you have learned something from this.
Martin Strand
PS: I mentioned wave-files in the top of this article. To add a wave file to the rc-file, write:
SomeID WAVE "Filename.wav"
Example
ID_WAVE004 WAVE "ding.wav"
Use the ShellAPI function PlaySound or sndPlaySound to play the wave-file.