I've written a Delphi package where two of components use the same PNG resource which I placed in GraphContour.res
file using following script:
compile_res.bat:
@brcc32 GraphContour.rc
GraphContour.rc:
GRAPH_CONTOUR RCDATA GraphContour.png
If both units of components include {$R GraphContour.res}
directive, components work, but I get a compiler warning:
[dcc32 Hint] H2161 Warning: Duplicate resource: Type 10 (RCDATA), ID GRAPH_CONTOUR; File C:\Borland\Components\MyControls\GraphContour.res resource kept; file C:\Borland\Components\MyControls\GraphContour.res resource discarded.
If I remove {$R GraphContour.res}
directive from units placing it into DPK file:
{$R *.res}
{$R GraphContour.res}
warnings go away, I can compile the package, the resource is being shown at design time, but at run time I get an error:
Project ComponentTest.exe raised exception class EResNotFound with message 'Resource GRAPH_CONTOUR not found'.
A bit of code from one of these two controls:
procedure TMyDisplay.CreateWnd();
var png: TPngImage;
begin
inherited;
//......................
png := TPngImage.Create;
try
png.LoadFromResourceName(HInstance, 'GRAPH_CONTOUR'); //Error is here
_knob.Center.Picture.Graphic := png;
finally
png.Free();
end;
//......................
end;
I looked into BPL file with binary viewer and found that GRAPH_CONTOUR string name is there.
I tried to use FindClassHInstance
instead of HInstance
. It didn't help.
png.LoadFromResourceName(FindClassHInstance(Self.ClassType), 'GRAPH_CONTOUR');
How to include resource to BPL properly?
Update
Here is test application I used to check for resource availability:
program Loadres;
uses Winapi.Windows;
procedure PrintLastError();
var
cchMsg, code: Cardinal;
buf: array[0..512] of WideChar;
begin
code := GetLastError();
cchMsg := FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_IGNORE_INSERTS,
nil, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), @buf, SizeOf(buf), nil);
MessageBoxW(0, @buf, 'Error', MB_ICONERROR);
end;
var
hm, hResInfo, hResData, hPngFile: NativeUInt;
rp: Pointer;
wb, rs: Cardinal;
begin
hm := LoadLibrary('C:\Documents and Settings\All Users\Documents\Embarcadero\Studio\17.0\Bpl\MyControls.bpl');
if hm = 0 then begin PrintLastError(); Exit; end;
try
hResInfo := FindResource(hm, 'GRAPH_CONTOUR', RT_RCDATA);
if hResInfo = 0 then begin PrintLastError(); Exit; end;
hResData := LoadResource(hm, hResInfo);
if hResData = 0 then begin PrintLastError(); Exit; end;
rs := SizeofResource(hm, hResInfo);
rp := LockResource(hResData);
try
hPngFile := CreateFile('TheContour.png', GENERIC_WRITE, 0, nil, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, 0);
try
WriteFile(hPngFile, rp^, rs, wb, nil);
finally
CloseHandle(hPngFile);
end;
finally
UnlockResource(hResData);
end;
finally
FreeLibrary(hm);
end;
end.
It finds resource, reports the right resource size, and writes resource to file. The file matches the original one.
FindClassHInstance
works fine. We don't see your code that uses it. We also don't know whereTMyDisplay
resides. In the package with the two controls? In which caseHInstance
would be correct. – David HeffernanEResNotFound
. One possibility is that you aren't using runtime packages. Perhaps you are compiling the source code for your component directly into your executable. – David Heffernan