Lazarus

Programming => Graphics and Multimedia => Graphics => Topic started by: PatBayford on May 22, 2018, 12:17:18 am

Title: [SOLVED] Resource files in Lazarus
Post by: PatBayford on May 22, 2018, 12:17:18 am
How do I extract individual bitmaps from a loaded resource file please? Used to be easy using the Windows API LoadBitmap function, but Lazarus does not support this, presumably as part of the multi-platform drive.
In fact, I would like to get hold of a good reference to Resource file use in Lazarus - anybody come across one?
Title: Re: Resource files in Lazarus
Post by: wp on May 22, 2018, 12:39:14 am
How do I extract individual bitmaps from a loaded resource file please?
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   pic: TPicture;
  4. begin
  5.   pic := TPicture.Create;
  6.   pic.LoadFromResourceName(HINSTANCE, 'BTN_YES');   // <---- read the resource of the program
  7.   Image1.Picture.Assign(pic);
  8.   pic.Free;
  9. end;
Title: Re: Resource files in Lazarus
Post by: PatBayford on May 22, 2018, 02:37:57 am
Thanks wp - came up with that route myself - works fine. Just wanted to make sure there was not some other, more direct route.
Title: Re: Resource files in Lazarus
Post by: wp on May 22, 2018, 09:20:40 am
Thanks wp - came up with that route myself - works fine. Just wanted to make sure there was not some other, more direct route.
More direct than a one-liner?
Title: Re: [SOLVED] Resource files in Lazarus
Post by: Thaddy on May 22, 2018, 10:00:20 am
 8) And it deserves a link to https://www.youtube.com/watch?v=b19PcuJsQbA
Title: Re: Resource files in Lazarus
Post by: ccrause on May 22, 2018, 11:30:04 am
Just wanted to make sure there was not some other, more direct route.

An alternative route to working with resources:
Code: Pascal  [Select][+][-]
  1. var
  2.   Resource: TResourceStream;
  3. begin
  4.   Resource := TResourceStream.CreateFromID(HInstance, ResID, PChar(ResourceName));
  5.   // the resource is now in a stream, so one can assign, save, read etc.
  6.   Resource.SaveToFile('ImportantData.bin');
  7. ...
This gives you direct access (AFAIK, there may be exceptions) to all resources compiled into the application.
Title: Re: [SOLVED] Resource files in Lazarus
Post by: Thaddy on May 22, 2018, 12:26:55 pm
There used to be exceptions(like Windows only...) , but there aren't any anymore (afaik). Resources are even handled correctly cross-platform.(afaik)
Title: Re: [SOLVED] Resource files in Lazarus
Post by: torbente on December 02, 2021, 11:47:58 pm
Sorry for push this old topic, but i search and was unable to find nothing:
I developed a custom procedure to get resources and save it to a file:
(the file included in the resources were added via Project->Options->Resources->Add

Code: Pascal  [Select][+][-]
  1. Procedure CreateFileFromResource(resourcename,filename:string);
  2. var
  3.   Resource: TResourceStream;
  4. begin
  5. try
  6.  
  7.   Resource := TResourceStream.Create(HInstance, resourcename, RT_RCDATA);
  8.   Resource.Position := 0;
  9.   Resource.SaveToFile(filename);
  10. finally
  11.   Resource.Free;
  12. end;
  13.  
  14. End;
  15.  

This only works if i include the unit windows in the Uses section. If not, i get the error:

Code: Pascal  [Select][+][-]
  1. nggmainform.pas(45,63) Error: Identifier not found "RT_RCDATA"

Any fix that could work cross-platform?

Thanks a lot
Title: Re: [SOLVED] Resource files in Lazarus
Post by: Gustavo 'Gus' Carreno on December 03, 2021, 12:04:17 am
Hey Torbente,

Any fix that could work cross-platform?

After following the white rabbit through the hole that is the fpcsrc I found out that:
Code: Pascal  [Select][+][-]
  1. const
  2.   RT_RCDATA = MAKEINTRESOURCE(10);

So obviously, I then tried to find where MAKEINTRESOURCE was and found out that it just a new type:
Code: Pascal  [Select][+][-]
  1. type
  2.   MAKEINTRESOURCE = pchar;

So you can now remove the dependency from the Windows unit and change your code to:
Code: Pascal  [Select][+][-]
  1. Procedure CreateFileFromResource(resourcename,filename:string);
  2. const
  3.   RT_RCDATA = PChar(10);
  4. var
  5.   Resource: TResourceStream;
  6. begin
  7. try
  8.  
  9.   Resource := TResourceStream.Create(HInstance, resourcename, RT_RCDATA);
  10.   Resource.Position := 0;
  11.   Resource.SaveToFile(filename);
  12. finally
  13.   Resource.Free;
  14. end;

After that, it will work cross-platform.

Cheers,
Gus
Title: Re: [SOLVED] Resource files in Lazarus
Post by: Sieben on December 03, 2021, 12:20:37 am
RT_RCDATA is also defined in LCLType:

Code: Pascal  [Select][+][-]
  1. {$ifdef windows}
  2.   RT_CURSOR = Windows.RT_CURSOR;
  3.   RT_BITMAP = Windows.RT_BITMAP;
  4.   //...
  5.   RT_RCDATA = Windows.RT_RCDATA;
  6.   //...
  7. {$else}
  8.   RT_CURSOR = TResourceType(1);
  9.   RT_BITMAP = TResourceType(2);
  10.   //...
  11.   RT_RCDATA = TResourceType(10);
  12.   //...
Title: Re: [SOLVED] Resource files in Lazarus
Post by: circular on December 03, 2021, 08:14:38 am
As a side note, BGRABitmap makes it easy to access resources, wether they are imported from LRS or RES files. The unit BGRABitmapTypes exposes BGRAResource instance that can return a resource by its filename:
Code: Pascal  [Select][+][-]
  1. type
  2.   { TBGRAResourceManager }
  3.  
  4.   TBGRAResourceManager = class
  5.   protected
  6.     function GetWinResourceType(AExtension: string): pchar;
  7.   public
  8.     function GetResourceStream(AFilename: string): TStream; virtual;
  9.     function IsWinResource(AFilename: string): boolean; virtual;
  10.   end;
  11.  
  12. var
  13.   BGRAResource : TBGRAResourceManager;

You can use it as:
Code: Pascal  [Select][+][-]
  1. implementation
  2.  
  3. {$R *.lfm}
  4.  
  5. uses BGRABitmap, BGRABitmapTypes, LResources;
  6.  
  7. { TForm1 }
  8.  
  9. procedure TForm1.FormPaint(Sender: TObject);
  10. var bmp: TBGRABitmap;
  11. begin
  12.   bmp := TBGRABitmap.Create;
  13.   bmp.LoadFromResource('shape.png');
  14.   bmp.Draw(Canvas, 0,0, False);
  15.   bmp.Free;
  16. end;
  17.  
  18. initialization
  19.  
  20. {$I myresource.lrs} // contains "shape.png"
  21.  
  22. end.

When using RES resources, the extension is generally ignored because it is not stored as such in the RES file, but I find it still useful to indicate what kind of data it contains.

LazPaint can save images directly into LRS or RES files (they are treated as folders).
Title: Re: [SOLVED] Resource files in Lazarus
Post by: Gustavo 'Gus' Carreno on December 03, 2021, 02:38:50 pm
Hey Sieben,

RT_RCDATA is also defined in LCLType:

That's awesome to know. I think I may update the wiki's Lazarus Resources page to make that clear.
I think a lot of the confusion comes from that example not mentioning that LCLTypes is better than including Windows.

I thank you OH SO very much for a better rabbit hole diving experience than mine :)

Cheers,
Gus
Title: Re: [SOLVED] Resource files in Lazarus
Post by: Gustavo 'Gus' Carreno on December 03, 2021, 07:30:28 pm
Hey Y'all,

I've edited the example on Lazarus Resources (https://wiki.freepascal.org/Lazarus_Resources), paragraph "Using resources in your program".

I've replaced the Windows unit by the LCLType one on the example and removed now obsolete comments.

Hopefully, this will make the example fully cross-platform.

Cheers,
Gus
TinyPortal © 2005-2018