I've been looking hours over the net, using Google, trying for PDF's and still unable
to load an Image resource in Delphi 7..
My test.rc file goes like this:
1 RT_BITMAP "1.bmp"
I've added the test.rc file to my project using Project->Add to Project.. which compiled a test.res file upon build and seems to have automatically included the .res file into my project (because using the {$R test.res} would say I already use that resource). I also tried removing the test.res from the project using Project->Remove from Project.. and manually adding the {$R test.res} to my project.
However no matter how I include the test.res file..
I get the
Project Project2.exe raised exception
class EAccessViolation with message
'Access violation at address 00408D0C
in module 'Project2.exe'. Read of
address 00000001'. Process stopped.
Use Step or Run to continue.
at First I used
Image1.Picture.Bitmap.LoadFromResourceID(hInstance,1);
Because this is what I found using Google. And I got this error.
Later I tried
procedure TForm1.Image1Click(Sender: TObject);
var bBitmap : TBitmap;
begin
bBitmap := TBitmap.Create;
try
bBitmap.Handle := LoadBitmap(hInstance, '1');
Image1.Width := bBitmap.Width;
Image1.Height := bBitmap.Height;
Image1.Canvas.Draw(0,0,bBitmap);
finally
bBitmap.Free;
end;
end;
This didn't get me any errors, and nither did it show the image so the problem remains unsolved..
I'm a newbie to the use of Resources but I must load some images into resources before I release my project so the .BMP files won't be tempered with...
any help would be highly appreciated!
I reproduced exactly your same problem in a test program.
I then changed RT_BITMAP to BITMAP, recompiled RC and tested.
It works.
Related
I want to make a component that uses some resources compiled in my package's project. My component will try to use this resource (a PNG image) during runtime (at its constructor).
I want to use it in my application's project, but as soon as the component gets created, I get the following exception:
First chance exception at $7579B9BC. Exception class EResNotFound with message 'Resource xxx not found'. Process yyy.exe (6060)
What am I missing here?
EDIT
The calling code for the resource in the package's project is like this:
Png.LoadFromResourceName(HInstance, 'png_resource_name');
EDIT 2
As suggested by David, I tried using the function GetModuleHandle, but it will always return 0 if I call it from the package's project or the application's project. The code being called in the package's project is like this:
PackageModuleHandle := GetModuleHandle(PChar('my_package.bpl'));
Png := TPngImage.Create;
Png .LoadFromResourceName(PackageModuleHandle, 'png_resource_name');
Absolute paths to the bpl file won't work either.
EDIT 3
New attempt based on new answer:
PackageModuleHandle := FindClassHInstance(TMyComponent);
Png := TPngImage.Create;
Png .LoadFromResourceName(PackageModuleHandle, 'png_resource_name');
Fails with the same exception.
EDIT 4
Using ResourceHacker, and if I used it right, the resources doesn't seem to be in my bpl file. What could I be doing wrong about this? Seems such a complicated matter to such a simple feature.
CONCLUSION
I had to add the .res file of my package to the package's .dpr just after the {$R *.res} line. Like this:
{$R *.res}
{$R 'my_pacakge.res'}
Also, I had to include the my_package.rc file to my project, so the resources would get compiled to the .res after each build. That did the trick, I guess. Thanks for all the answers.
You need to use FindClassHInstance(), specifying your component's class type, instead of using the global HInstance variable or GetModuleHandle(). That way, you obtain the correct module handle regardless of whether the package gets statically linked or dynamically linked into the main executable.
You are passing HInstance, the handle of the executable module to the resource loading function. That fails because the resource lives in the package module. Therefore you need to pass the module handle for the package. You can obtain the module handle of the package like this:
PackageModuleHandle := GetModuleHandle(PChar('MyPackage.bpl'));
If you are loading your package dynamically then the call to LoadPackage returned the module handle.
Update: Remy's suggestion of using FindClassHInstance is clearly a better way to obtain the module handle.
A component that uses a resource that is implemented in a unit called MyUnit1.pas should include the following line inside:
{$R MyUnitRc.res MyUnitRc.rc}
Note that the above syntax won't work on some old delphi versions (Delphi 7). The above works on 2010,XE,XE2 and so on, and it compiles the .rc into a .res when the project builds that unit. Alternatively you would add the {$R} declaration to each statically linked application and also to your BPL's .dpr file.
That .RC file mYUnitRc.res will contain one or more lines declaring your resources. I use RCDATA declarations to load PNGs, like this:
MYIMAGENAME RCDATA "MyFile.png"
If you do it this way, instead of using an RC file added to the .dproj/.dpr only, then it will work in two important cases:
When the BPL is loading at designtime.
When the component is loading at runtime from within an application that is compiled with Runtime Packages turned off.
To handle the third case, the one that the other answers (Remy and David) deal with, you do need to call FindClassHinstance as Remy stated. However I believe you should also look at how you are including the resource file and having it compiled and linked, both within your package, and within applications that use the component.
Here is some sample code showing loading a resource at runtime into a TPngImage, that I use in my own components:
procedure TSampleControl.LoadImageFromResource( button:TSubControl);
var
png:TPngImage;
begin
if button.DefaultResourceId='' then exit;
png := TPngImage.Create;
try
try
png.LoadFromResourceName(HInstance,button.DefaultResourceId);
button.Glyph.Assign(png);
except
on E:Exception do begin
OutputDebugString( PChar(button.DefaultResourceId+' load error:'+E.Message) );
end;
end;
finally
png.Free;
end;
end;
Note that I catch resource load exceptions, which leave some elements in my control without their glyphs but at least does not crash Delphi. HInstance may need to be changed as David and Remy Point out to use LoadFromResourceName to handle the case where you need to load from the .BPL but I don't think that you can assume that a person who uses your components is always going to redistribute your BPL file, and thus FindClassHinstance is preferable to GetModuleHandle..
Update: I should have used what Remy suggested:
png.LoadFromResourceName( FindClassHInstance(TSampleControl),
button.DefaultResourceId);
Having already Googled for a solution to this, none of the suggestions work for me so either I've missed something or I've done something wrong.
I have a number of packages within my Delphi XE2 application, of which a couple of these packages contain RCDATA resources which are ultimately PNG images.
The control(s) which uses the resource(s) works absolutely fine in the Delphi XE2 designer - the resource is loaded and drawn as expected. When I come to run the main application in which the package/control is used, I'm presented with an EResNotFound exception when the control attempts to load the resource item:
handle := FindClassHInstance(Self.ClassType);
fPlaneImage := TPngImage.Create;
fPlaneImage.LoadFromResourceName(handle, 'IDC_IMG_PLANE');
And when the application runs, I get the following error:
Project PinPoint.exe raised exception class EResNotFound with message IDC_IMG_PLANE not found'.
And if I hit continue in the debugger, I then get:
Project PinPoint.exe raise exception class EPNGCouldNotLoadResource with message 'The png image could not be loaded from the resource ID.'.
I've tried passing all variations of handle into the LoadFromResource function:
fPlaneImage.LoadFromResourceName(HInstance, 'IDC_IMG_PLANE');
fPlaneImage.LoadFromResourceName(GetModuleHandle('AppCore.bpl'), 'IDC_IMG_PLANE');
fPlaneImage.LoadFromResourceName(FindClassHInstance(Self.ClassType), 'IDC_IMG_PLANE');
Yet they all yield the same exception.
I was considering whether it would be easier to create a standalone package which contained all the resources and then refer to this from each of the other packages within the project, rather than each package having their own resources however I'm unsure as to whether this would actually work.
Please could anyone offer any advice.
Try to use the below FindResModule function to get the resource module.
// use fPlaneImage.LoadFromResourceName(FindResModule('IDC_IMG_PLANE'), 'IDC_IMG_PLANE');
function FindResModule(const AResourceName: string): HINST;
var
LModule: PLibModule;
begin
LModule := LibModuleList;
while Assigned(LModule) do
begin
Result := LModule.Instance;
if (Result <> 0) and (FindResource(Result, PChar(AResourceName), RT_RCDATA) <> 0) then
Exit;
LModule := LModule^.Next;
end;
Result := 0;
end;
In case it fails most likely the resource is "eliminated by the linker". It may happen for example when you create your own packages and you miss to add the unit with the resource to your package or application file. Just add the unit to the uses clause of your application.
I see no harm if you create a separate package for resources. It should work fine but it is not actually required. Just one small hint, BPL package is not required, you may pack your resources into a DLL
In my project, i'm trying to connect one more UNIT, named Lang_Unit.pas with some classes and procedures, but, while compiling the Project, Delphi gives unknown error called "[dcc32 Fatal Error] Lang_Unit.pas(5): F2084 Internal Error: AV07953449-R26D7474C-0".
And the point is that, what if i will close my project, or remove this connected UNIT, error is not getting away.
And if i will create clear default VCL Application, its still gives this error.
And only when i'm restarting my Delphi 2010, error is getting away.
But, if i will try to edit something in the code, this error is comes again...
What is problem ? Everything was works fine, im not touched nothing.
I've just turned off my PC, then after some time turned it ON and opened my Project and edited my code, then i see this error...
If Its will help, here is my Lang_Unit.pas code :
unit Languages_UNIT;
interface
Uses
System.Generics.Collections, IniFiles;
Type
TLanguages_List = Class
private
LangType:string;
LangDescription:string;
LangFile:TIniFile;
public
Constructor Create(LType,LDes:string; LFile:TiniFile);
Function GetLangType:string;
Function GetDescription:string;
Function GetStructure:TIniFile;
End;
TLanguages_Controller = Class
public
Function GetStructureByType(RequestedType:string; LangList:TObjectList<TLanguages_List>):TIniFile;
Function TypeExists(RequestedType:string; LangList:TObjectList<TLanguages_List>):Boolean;
Procedure LoadLanguage(RequestedType:string; LangList:TObjectList<TLanguages_List>);
End;
implementation
uses Unit1;
Constructor TLanguages_List.Create(LType,LDes:string; LFile:TiniFile);
Begin
LangType:=LType;
LangDescription:=LDes;
LangFile:=LFile;
End;
Function TLanguages_List.GetLangType:string;
Begin
Result:=LangType;
End;
Function TLanguages_List.GetDescription:string;
Begin
Result:=LangDescription;
End;
Function TLanguages_List.GetStructure:TIniFile;
Begin
Result:=LangFile;
End;
Function TLanguages_Controller.GetStructureByType(RequestedType:string; LangList:TObjectList<TLanguages_List>):TIniFile;
var
i:integer;
Begin
For i := 0 to LangList.Count-1 Do
Begin
IF(LangList[i].GetLangType=RequestedType) Then
Begin
Result:=LangList[i].GetStructure;
Break;
End;
End;
End;
Function TLanguages_Controller.TypeExists(RequestedType:string; LangList:TObjectList<TLanguages_List>):Boolean;
var
i:integer;
GOTYA:Boolean;
Begin
GOTYA:=False;
For i := 0 to LangList.Count-1 Do
Begin
IF(LangList[i].GetLangType=RequestedType) Then
Begin
GOTYA:=True;
Break;
End;
End;
IF(GOTYA) Then
Result:=True
Else
Result:=False;
End;
Procedure TLanguages_Controller.LoadLanguage(RequestedType:string; LangList:TObjectList<TLanguages_List>);
var
i:integer;
SLS:TIniFile;//SELECTED LANGUAGE STRUCTURE
CS:string;//CURRENT SECTION
Begin
//GET SELECTED LANGUAGE STRUCTURE
For i := 0 to LangList.Count-1 Do
Begin
IF(LangList[i].GetLangType=RequestedType) Then
Begin
SLS:=LangList[i].GetStructure;
Break;
End;
End;
//START LOADING SELECTED LANGUAGE
//TABS SECTION LOAD
CS:='TABS';
SD_DEFNAME:=SLS.ReadString(CS,'Speed_Dials','Speed_Dials');
Form1.goleft.Hint:=SLS.ReadString(CS,'Back','Back');
Form1.goright.Hint:=SLS.ReadString(CS,'Forward','Forward');
REFLESHBTN_TEXT:=SLS.ReadString(CS,'Reflesh','Reflesh');
STOPBTN_TEXT:=SLS.ReadString(CS,'Stop','Stop');
//PAGE_POPUP SECTION LOAD
CS:='PAGE_POPUP';
Form1.ChromiumPopup.Items[0].Caption:=SLS.ReadString(CS,'Forward','Forward');
Form1.ChromiumPopup.Items[1].Caption:=SLS.ReadString(CS,'Back','Back');
Form1.ChromiumPopup.Items[2].Caption:=SLS.ReadString(CS,'Reflesh','Reflesh');
Form1.ChromiumPopup.Items[3].Caption:=SLS.ReadString(CS,'Copy_Link','Copy Link');
Form1.ChromiumPopup.Items[4].Caption:=SLS.ReadString(CS,'Save','Save');
Form1.ChromiumPopup.Items[5].Caption:=SLS.ReadString(CS,'Print','Print');
Form1.ChromiumPopup.Items[6].Caption:=SLS.ReadString(CS,'view_source','View Source');
Form1.ChromiumPopup.Items[7].Caption:=SLS.ReadString(CS,'code_debug','Code Debug');
End;
end.
Internal error means that the compiler itself is in a 'confused' state.
The way to get out of this is to:
Save your code in a safe location for later reference.
Restart Delphi
Revert the source code to the last known good state by undoing your last edits, or by loading a temp save file.
You can find the previous files in the _backup folder.
Make sure to set file type to any file.
In order to have Delphi generate a save file upon compilation you need to enable autosave
It's a good idea to have Delphi keep more than the default 10 saves. I like to set it to the max: 90.
Just keep restarting Delphi, and compile a previous version, until the internal error goes away.
Then you just recreate the code in a slightly different manner.
(You did save the original code right?)
I also had this problem (in Delphi 10 Berlin). It started shortly after I changed the name of a component in a frame. It also seemed very persistent. However I found the by right clicking the project and selecting 'Clean' followed by 'Build' solved the problem.
I had this issue with my system drive's memory less than 300mb left. It was especially choking in the cache folder. Prior to this error I had a sensible error (fatal error DBG) when I was attempting to recurse already async functions into a larger async function in a big multi threaded application. The compiler just gave up!(perhaps for circular references and too many subfunctions of a function) The two errors may not be related. But after freeing the system drive to about 2 Gigs upon restart and correcting the above mistake, I did a clean then it compiled just fine.
In my case, the solution for the F2084 error code was to change the encoding from ANSI to UTF8.
In my case, I made several packages that related one to another, and all were built as design and run time packages. But one day, I changed some of them to run-time only packages. After that I experienced this kind of error. It took me hours to realize that I should rebuilt all other related packages. After doing that, the error was away eventually.
Dear Stackoverflow users. I am in dire need for help. I have been struggling with the embedded in the Embarcadero XE2 RAD studio edition of FastReport 4.0. and more specifically I have been getting the same error, over and over again, which is the misterious "Class TfrxReport Not found" error. Below I submit a part of the code that causes the problems
procedure TForm1.buildReport(Sender: TObject);
var
DevicePic, SymbolPic: TfrxPictureView;
TitleEntry, xmlField: TfrxMemoView;
MasterDataBand: TfrxMasterData;
begin
if not ADOConnection1.Connected then
ShowMessage('Cannot build Report! Please, connect to the DB!')
else
try
//this is where the Class Not Found Exception is Thrown
frxReport1.LoadFromFile('LibreportTemplate.fr3',True);
// frxReport1.LoadFromFile('helloInfineonThree.fr3',True);
if (frxDBDataset1 = nil) then frxDBDataset1 := TfrxDBDataset.Create(Self);
// connect the report to the DATA
frxDBDataset1.DataSource := DataSource1;
frxReport1.DataSet := frxDBDataset1;
except
ShowMessage('Error has Occured! Report Template File Not Found!');
// exit from this procedure!
Exit;
end;
// If no errors have occured, go on building ur report by actually filling it up with data!
// attach dataSet to the masterdata band of the report.
MasterDataBand := frxReport1.FindObject('MasterData1') as TfrxMasterData;
MasterDataBand.DataSet := frxDBDataset1;
// prepare textfields
TitleEntry := frxReport1.FindObject('TitleEntry') as TfrxMemoView;
TitleEntry.DataSet := frxDBDataset1;
TitleEntry.DataField := 'LibFName';
xmlField := frxReport1.FindObject('xmlField') as TfrxMemoView;
// stretch the field if text too big.
xmlField.StretchMode := TfrxStretchMode.smActualHeight;
//get the XML DATA FROM THE DB.
xmlField.DataSet := frxDBDataset1;
xmlField.DataField := 'LibFXML';
// prepare images
DevicePic := frxReport1.FindObject('ImageEntry') as TfrxPictureView;
DevicePic.DataSet := frxDBDataset1;
DevicePic.DataField := 'LIBFIMAGE';
SymbolPic := frxReport1.FindObject('SymbolEntry') as TfrxPictureView;
SymbolPic.DataSet := frxDBDataset1;
SymbolPic.DataField := 'LibFSymbol';
// build and display report
frxReport1.PrepareReport();
frxReport1.ShowPreparedReport;
end;
When building and running the program, I get the following error message "Cannot Find class TfrxReport" and in DebugMode I get the following warning:
Project "MyProject.exe" raised exception class EClassNotFound with message 'Class TfrxReport not Found'.
As commented in the code above, the exception in question is thrown when executing the frxReport1.LoadFromFile('LibreportTemplate.fr3',True); command.
I tried many different approaches for solving the problem, including searching online for a solution. Here is what I did:
Manually create and destroy the frxReport1 object during Form OnCreate and OnClose - ERROR PERSISTS
As suggested in the FastReport ( I couldnt post the link on SO, cause of "Sorry, posts can't contain that content." error) forum thread, replace files in the FastReport 4\LibD16 folder. - ERROR PERSISTS
Recompile FastReport 4 RAD STUDIO 32 bit Version - ERROR PERSISTS
Recompile FastReport 4 RAD STUDIO 64 bit Version - ERROR PERSISTS
Reinstall Embarcadero RAD Studio and FastReport 4 - ERROR PERSISTS
ASK QUESTION IN STACKOVERFLOW - ????
From the thread in the fast-reports forum, it seems that the problem and the respective solution should be ( I QUOTE) :
This error causes by GroupDescendentsWith(TfrxReport, TControl); code.
This code hides TfrxReport from FierMonkey and for some reason
"FindClass" function can't find for TfrxReport class when you're
loading report(only in IDE). If you can't load report or get similar
error with "Couldn't find TfrxReport" message, put this "Link to Files"
files to "Fast
Report\LibD16" dir (replace all).
However the suggested approach DOES not Solve the problem! What should I do? Does anyone have any idea?
I've face this issue as well and I've solved it doing this,
Create a new ProjectGroup and add DPK's suitable for your delphi version (I use XE6).
You'll see the BPL's will divide into runtime and design.
Start compiling runtime fsX (X means version), fqbX, and so on. If you make a mistake in the order you will notice.
Some package need the search path $(BSDCOMMONDIR)/DCP to be added
Compile and install design packages and you'll see the TfrxReport.
You won't see results once design package is installed, I've restarted the IDE and it goes great ;)
With 2 years delay, I hope this could help!
not sure if you got your answer to this question or not... but I was having the same issue in Rad Studio XE4, using Fast Reports 4.0 Pro.
I had placed my report in a data module, which I could create / destroy when needed, and the datasets were found in there as well. I could place a BarCode element in the report designer, however, when running the application, I would get "Cannot find class TfrxBarCodeView".
After a search of the Source folder found in C:\Program Files (X86)\Fast Reports\source\ I opened a source file called frxBarcode.pas which contained the creation of the class "TfrxBarCodeView".
I simply added frxBarCode to my uses list, and all worked perfectly!
Just a thought.
Add RegisterClass(TfrxReport); somewhere on program's startup. Or, right before the line that raises the error.
I would start by
1
putting an absolute, full path to the fr3 file, and
place it in the user's document directory,
just to rule out file access issues. Do you have the source code to FastReport?
I know this is old but to somebody it might come useful.
I just run into similar problem. It never occurred to me there is a
component on the palette of Fast Reports called frxReportTableObject.
Just drop it on the form in question.
Adding frxBarCode to uses solved the problem.
I downloaded the Firebird DBX driver from http://sites.google.com/site/dbxfirebird/ and I've been able to compile the "Test Connection" project and get it to run. I pointed it to my test DB like so:
procedure TMainForm.Button1Click(Sender: TObject);
var C: TSQLConnection;
begin
C := TSQLConnection.Create(Self);
try
C.DriverName := 'FirebirdConnection';
C.Params.Add('User_Name=SYSDBA');
C.Params.Add('Password=masterkey');
C.Params.Add('Database=C:\fbtest\test.fdb');
C.Open;
if C.Connected then
ShowMessage('Connection is active')
finally
C.Free;
end;
end;
When I run it, it works fine. But when I put that exact same code in a different project, it doesn't work. I've copied the fbclient.dll (Firebird embedded driver DLL, renamed to fbclient), all of its dependencies, and the dbxdrivers.ini file to the same folder as the project's EXE is running in. I can't see any reason why this shouldn't work, but the call to .Open fails with:
Project Project1.exe raised exception
class TDBXError with message 'Unknown
driver: FirebirdConnection'.
Again, this is on the call to Open. The assignment to DriverName works just fine. Has anyone seen this problem before? Why does the exact same code work in the test project but not a different one, and is there any way I can fix it?
I found the problem. A loading class to set up the database driver had to be registered in the initialization section of DBXDynalink.pas. The test project included DBXDynalink in its uses clause, where mine didn't. I put that in and now it works.
This error generally occurs when you don't add the respective DBX driver unit to your uses list. Try adding DBXFirebird to your uses list.
Just change
C.DriverName := 'FirebirdConnection';
to
C.DriverName := 'Firebird';
and will work!