This question already has answers here:
How to add and use a resource from a custom package/component in Delphi?
(3 answers)
Closed 3 years ago.
I am trying to add a few images to my new component. So I did this
Project -> Resource and Images
Added a new Resource
Filename : Logo.png
Type : RCDATA
Identifier : LOGO
On the Constructor I do this :
OptionsImage.Glyph.LoadFromResource(HInstance,'Logo',RT_RCDATA);
OptionsImage.Glyph.SourceHeight:=24;
OptionsImage.Glyph.SourceWidth:=24;
In Designer this works flawlessly. But if I try to run this ... I get the
error :
Exception EResNotFound in module Project1.exe at 00074128.
Resource LOGO not found.
Why is it not finding the Logo at run time ?
Thank you for the kind help.
UPDATE 1 :
I have a GridButton.bpl in this I have on top
{$R *.res}
{$R *.dres}
With this alone , the Designer is working correctly, but If I try to run I get the error.
Now If I add to the Unit : cxGridButton.pas the same lines
{$R *.res}
{$R *.dres}
I recieve a Warning that I have duplicate resources . But now it works in Designtime and Runtime.
I must be doing something horribly wrong. But what ?
UPDATE 2
The other question is the same yes, but the answers are not working.
Meanwhile I solved it but I do not understand why is it working now.
GridButton.bpl
package GridButton;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO OFF}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS OFF}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO OFF}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE RELEASE}
{$ENDIF IMPLICITBUILDING}
{$IMPLICITBUILD ON}
requires
*******;
contains
cxGridButton in 'cxGridButton.pas';
end.
And the Unit itself has
implementation
{$R GridButton.dres}
Now it works at Designtime and at Runtime . Is there a Bug in the Resource Manager or I did something wrong ? Can someone please explain.
The resources added via Project -> Resource and Images are compiled into a separate resource file name .dres. This resource file has to be mentioned in the DPR. Usually the IDE takes care of adding this file, but that may somehow missing in your case.
Things are a bit more complicated when you compile outside the IDE - say on a build server. In that case you have to take care of creating the DRES file yourself.
Related
I noticed that in a 64 bit application, the VCL Design components I have written are grayed-out in the component pallette:
Other third party VCL components work in both 32 and 64 bit.
My BPL can compile in 32-bit and 64-bit mode. There is no code that requires 32 bit only. What can I do to unlock the components to 64 bit applications?
The BPL source code of the VCL component is:
package ......;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$ENDIF IMPLICITBUILDING}
{$DESCRIPTION '......'}
{$IMPLICITBUILD OFF}
requires
rtl,
vcl,
VclSmp,
vclx,
adortl,
dbrtl,
vclactnband,
xmlrtl,
vcldb,
Jcl,
vclie;
contains
HsGauge in 'HsGauge.pas',
.......
end.
I noticed that I cannot install the component when it is compiled in 64 bit (I'm not sure if that is the reason):
32 bit:
64 bit:
IDE is a win32 program so it can load only win32 dlls and win32 bpls, so you can’t install win64 bpl.
By default – all must work correctly and we develop a lot of components, so you broke something by your code.
In the modern version of Delphi there is a special attribute for the class that specifies the target platform for your component - “ComponentPlatformsAttribute”.
So, if you write something like:
[ComponentPlatformsAttribute(pidWin32 or pidWin64)]
TMyButton = class(TButton)
End;
This component will be valid for Win32 and Win64 platforms, but not valid (gray) for Android, IOS etc.. Try to find a solution there.
Read more https://docwiki.embarcadero.com/Libraries/Alexandria/en/System.Classes.ComponentPlatformsAttribute
P.S. If it does not help – try to create a simple bpl with a simple sample component and try to use it in win64. If it works – compare settings of this BPL with your not workable BPL. Then move differences one by one into sample BPL until that will stop working. There how you find out what’s wrong.
Delphi IDE is a 32 bit application and need 32 bit packages to be able to use components at design time.
Your 64 bit application need a 64 bit run-time package, that's why Delphi can build 64 bit packages.
If you don't use run-time package in your application then there is no need to create one.
Using Delphi 10.3... I downloaded the latest Indy files and its IndySystem260.dpk file looks like this:
package IndySystem260;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO OFF}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION OFF}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES ON}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$DEFINE VER330}
{$ENDIF IMPLICITBUILDING}
{$DESCRIPTION 'Indy 10 System'}
{$RUNONLY}
{$IMPLICITBUILD ON}
// RLebeau: cannot use IdCompilerDefines.inc here!
{$DEFINE HAS_PKG_RTL}
{$IFDEF NEXTGEN}
{$IFDEF IOS}
// there is no RTL package available for iOS
{$UNDEF HAS_PKG_RTL}
{$ENDIF}
{$ENDIF}
{$IFDEF HAS_PKG_RTL}
requires
rtl;
{$ENDIF}
{$IFNDEF WINDOWS}
{$IFDEF MSWINDOWS}
{$DEFINE WINDOWS}
{$ENDIF}
{$ENDIF}
contains
IdAntiFreezeBase in 'IdAntiFreezeBase.pas',
IdBaseComponent in 'IdBaseComponent.pas',
IdCTypes in 'IdCTypes.pas',
IdComponent in 'IdComponent.pas',
IdException in 'IdException.pas',
IdGlobal in 'IdGlobal.pas',
IdIDN in 'IdIDN.pas',
IdResourceStrings in 'IdResourceStrings.pas',
{$IFNDEF WINDOWS}
IdResourceStringsUnix in 'IdResourceStringsUnix.pas',
IdResourceStringsVCLPosix in 'IdResourceStringsVCLPosix.pas',
{$ENDIF}
IdStack in 'IdStack.pas',
IdStackBSDBase in 'IdStackBSDBase.pas',
IdStackConsts in 'IdStackConsts.pas',
{$IFDEF WINDOWS}
IdStackWindows in 'IdStackWindows.pas',
{$ELSE}
IdStackVCLPosix in 'IdStackVCLPosix.pas',
{$ENDIF}
IdStream in 'IdStream.pas',
IdStreamVCL in 'IdStreamVCL.pas',
IdStruct in 'IdStruct.pas',
{$IFDEF WINDOWS}
IdWinsock2 in 'IdWinsock2.pas',
IdWship6 in 'IdWship6.pas'
{$ELSE}
IdVCLPosixSupplemental in 'IdVCLPosixSupplemental.pas'
{$ENDIF}
;
end.
As soon as I change Project Options > Building > Delphi Compiler > DCP output directory to ..\..\..\Delphi 10.3\DCP\$(Platform)\$(Config) the DPK is changed to:
package IndySystem260;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO OFF}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION OFF}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES ON}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
{$DESCRIPTION 'Indy 10 System'}
{$RUNONLY}
{$IMPLICITBUILD OFF}
rrequires
rtl;
$contains
IdAntiFreezeBase in 'IdAntiFreezeBase.pas',
IdBaseComponent in 'IdBaseComponent.pas',
IdCTypes in 'IdCTypes.pas',
IdComponent in 'IdComponent.pas',
IdException in 'IdException.pas',
IdGlobal in 'IdGlobal.pas',
IdIDN in 'IdIDN.pas',
IdResourceStrings in 'IdResourceStrings.pas',
IdStack in 'IdStack.pas',
IdStackBSDBase in 'IdStackBSDBase.pas',
IdStackConsts in 'IdStackConsts.pas',
IdStackWindows in 'IdStackWindows.pas',
IdStream in 'IdStream.pas',
IdStreamVCL in 'IdStreamVCL.pas',
IdStruct in 'IdStruct.pas',
IdWinsock2 in 'IdWinsock2.pas',
IdWship6 in 'IdWship6.pas' {$ENDIF};
d.
Does anyone have an idea why this happens? Can it be prevented without doing manual edits to the DPK file? It is something I noticed in XE3 as well.
I noticed the following on the Indy instructions page:
Note for Cross-Platform compiling:
The current Indy 10 package projects are set for Windows compilations.
The IndySystem and IndyProtocols packages do have a few
platform-specific units in them, which are conditionally compiled via
IFDEF statements in the DPK files. This is fine for command-line
compilations, but the IDE usually doesn't handle IFDEFs in DPK files
very well, and this can also cause an associated DPROJ file to be out
of sync with its DPK file. So this may lead to issues if you want to
compile Indy 10 via the IDE for non-Windows platforms (in Delphi
versions that support this). You might need to edit the IndySystem
project to remove the IFDEFs and replace the IdStackWindows,
IdWinsock2, and IdWship6 units with the IdStackVCLPosix and
IdVCLPosixSupplemental units instead, and then edit the IndyProtocols
project to remove the IFDEFs and the IdAuthenticationSSPI and IdSSPI
units. Perhaps in a future release, we will try to automate/cleanup
this better.
It may say So this may lead to issues if you want to compile Indy 10 via the IDE for non-Windows platforms but I suspect I will have to paste the DPK code back after changing the Options.
That looks more like the "well-known" issue with mixed line breaks.
Probably the original file has unix endings and the change in the IDE converts some lines to PC endings.
It seems pretty straightforward but the code below doesn't work.
BPL:
procedure DoSomething();
begin
LogEvent('Did');
end;
exports
DoSomething;
Main EXE:
procedure CallModuleFunc;
var
H: THandle;
P: procedure();
begin
H := LoadPackage('mymod.bpl');
try
if (H <> 0) then
begin
#P := GetProcAddress(H, 'DoSomething');
if Assigned(P) then
P();
end;
finally
UnloadPackage(H);
end;
end;
Now there's no error, the bpl loads successfully with LoadPackage() but GetProcAddress() returns nil. Why? probably because name mangling. I've tried adding stdcall (both exported function and P's declaration) but that didn't solve the problem. I've seen hundreds of examples on the web that it's supposed to be working this way. I even tried GetProcAddress(H, 'DoSomething$qqsv') but it didn't work either. What am I missing here?
After hours of searches and trial and errors, I realized it had to be about something I do or did differently. The problem was that my very first version of mymod.bpl was put into Delphi's default BPL output directory (which had no export, no DoSomething() at all). Then, I had changed the BPL output directory to my project's root source directory, so that I could see the sources and the bpl modules in one place. The exe was not put into where the sources reside as it used to be in Delphi 7, it was under Debug or Release folders. What misdirecting me was that when LoadPackage() cannot find the module in exe's current dir (which was Debug/Release) it looks at Delphi's default package folder (which had the very first and wrong version of the bpl) and loads it, so no error there but also no DoSomething() because it was no longer updated by my module's compile.
I hope this explanation helps someone else who might have a similar issue to figure things out. Thanks to everyone who spared time to read this and written comments.
See below a piece of code.
It's running under Delphi XE3.
// Package declaration
package Package1;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION OFF}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES ON}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
{$IMPLICITBUILD ON}
requires
rtl,
vcl;
contains
Unit1 in 'Unit1.pas';
end.
The unit Unit1.pas
unit Unit1;
interface
uses Vcl.Forms;
procedure Test(); stdcall;
exports
Test;
implementation
procedure Test();
var F : TForm;
begin
F := TForm.Create(nil);
F.ShowModal;
F.Release;
end;
end.
The Project for testing bpl.
Contains only one Tform with one TButton.
(Package1.bpl is in the same directory of project1.exe)
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Déclarations privées }
public
{ Déclarations publiques }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
type
TProcTest = procedure;
var
PackageModule: HModule;
proc : TProcTest;
begin
PackageModule := LoadPackage('Package1.bpl');
if PackageModule <> 0 then
begin
#Proc := GetProcAddress( PackageModule, 'Test' );
if #Proc <> nil then
Proc;
UnloadPackage(PackageModule);
end;
end;
end.
You must have to add stdCall in your declaration.
procedure DoSomething();stdcall;
begin
LogEvent('Did');
end;
exports
DoSomething;
When I attempt to create a new package in Delphi XE2, there is a new construct in package dpk source file: IMPLICITBUILDING
What is that for?
package Package1;
{$R *.res}
{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION OFF}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES ON}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
{$IMPLICITBUILD ON}
requires
rtl;
end.
Please also see this discussion: Why does Delphi change Indy's dpk source file when I change project options and this.
"The compiler directives which appear between the $IFDEF IMPLICITBUILDING
and $ENDIF are normally passed as parameters by the compiler when
explicitly compiling a package. Because these options change based on
the configuration (debug / release) and target platform (Win32, Win64,
OSX32) it's problematic to have them statically defined in the package
project source. When defined in the project source they will always
override the options passed by the compiler. The $IFDEF prevents these
options from being used during explicit compilation.
In cases where a package is implicitly compiled these options will be
used, but unless your project was saved in the configuration / target
mode you want to compile for, you may not get the results you expect.
As a general rule, it's better to disable implicit building on packages
and compile them explicitly via a project group build or through project
dependencies. If you are building for only a single platform using a
single configuration then the implicit building mechanism is adequate.
IMPLICITBUILDING is defined by the compiler during the compilation of a
package that is being implicitly compiled as part of the compilation of
something that depends on it. As indicated in the comment you should
not be trying to define this value yourself"
I assume it is related to the {$IMPLICITBUILD ON} flag below the conditional block. I guess that it is set as long as the compiler is performing the implicit build (compared to an explicit build). I have no idea why the settings should only be regarded if that is the case. It is certainly not documented yet.
On one of my packages, which was adapted from another using Save-As and edit, I keep getting the following message (this is in Delphi 2007):
=======
The following changes must be made before this package can be compiled.
Choose OK to apply these changes and continue compiling.
Remove cmSizePanel_Reg.
Unit(s) cmSizePanel_Reg were found in required package cmExtRzPanel_D2007.
=======
I click OK, and it then proceeds to compile fine. This message, however, never goes away -- I get it every time I compile the package.
Here is the project source, using right-click, "View Source" to get there:
package cmBaseFrames_D2007;
{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DESCRIPTION 'CM BaseFrames - Base Frames and related panels (TcmBaseFrame, etc)'}
{$IMPLICITBUILD ON}
requires
rtl,
vcl,
Rz30Ctls90,
vclx,
cmExtRzPanel_D2007;
contains
cmBaseFrames_Reg in 'cmBaseFrames_Reg.pas',
cmBaseFrameFrame in 'cmBaseFrameFrame.pas' {cmBaseFrame: TFrame},
cmBaseSizeableFrameFrame in 'cmBaseSizeableFrameFrame.pas' {cmBaseSizeableFrame: TFrame};
end.
"cmSizePanel_Reg" isn't in the project anymore, and doesn't show up in teh Project Manager panel. It would appear that it's "hiding" somewhere in one of the file Delphi uses for the package, but I'm not seeing where. Any ideas how to stomp out this little inconvenience without having to complete re-create the package from scratch?
Try looking through the XML of your .dproj for the package. .dproj files have a knack for getting corrupted and becoming out of sync with the file list in the DPR, leading to strange problems like this.
Stale .dcp files maybe? They are the compliment to .BPL packages and contain descriptions about the BPL.