Ressourcen Handle für {$R ressdatei.Res}

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Lorca
Beiträge: 196
Registriert: Di 3. Nov 2020, 12:25

Ressourcen Handle für {$R ressdatei.Res}

Beitrag von Lorca »

Hallo zusammen,

bezüglich der Ressourcen habe ich mal wieder eine Frage. Oder besser gesagt zwei Fragen.

Ich habe mir mit lazres.exe eine Ressourcen Datei (Button_Icons.Res) angelegt.
Für den Aufbau dieser Ressourcendatei habe ich alle benötigten .PNG Dateien in einem eigenen Ordner
kopiert und umbenannt.
So wurde z.B. aus menu_new_unit_150.png der neue Name "New_150" und aus laz_edit_150.png wurde "Edit_150.png"

Nun binde ich diese Ressource mit {$R Button_Icons.Res} ein.
Jetzt will ich meine Ressource: 'Edit_150' ( PNG Datei ) aus der Ressourcen Datei laden.
Image1.Picture.LoadFromResourceName(HINSTANCE, 'Edit_150')
Doch diese wird nicht gefunden. Sie ist jedoch definitiv in meiner eigenen Ressourcen Datei vorhanden.

Somit komme ich zu der Erkenntnis, das ich für meine eigene Ressourcendatei auch ein eigenes Handel
benötige. Ich bin mir aber nicht sicher. Da ich keine Vorstellung darüber habe was ich falsch mache bzw. wie ich dieses Problem lösen kann.

Nun meine Fragen:
1. Wie erstelle ich mir aus einer mit {$R xxx.Res} eingebundenen Ressourcen Datei, ein eigenes Handle? bzw. Muss ich dies überhaupt?
Was mache ich falsch?
2. Wie kann ich eine Combobox mit allen Namen der enthaltenen Bitmap Ressourcen füllen, ohne diese Namen zu kennen?
Denn die Methode "LoadFromResourceName" erwartet den Namen der BitMap Ressource und keinen Index

Viele Grüße
Lorca
Dateianhänge
TEST_Ressourcen_Lesen.zip
(172.67 KiB) 62-mal heruntergeladen

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Ressourcen Handle für {$R ressdatei.Res}

Beitrag von six1 »

m.M.n. stimmt etwas mit deiner res Datei nicht.

Anbei eine res Datei, welche zwei Bildchen enthält.

Hier die Änderungen in deinem Code; damit funktioniert es...

Code: Alles auswählen

UNIT UI_TEST_Ressourcen_Lesen;

{$mode objfpc}{$H+}

INTERFACE

USES
  Classes, Sysutils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
  Buttons, LResources;

TYPE

  { Tform1 }

  Tform1 = CLASS ( Tform)
    Button1 : Tbutton;
    COBX_BitmapNames : Tcombobox;
    Speedbutton1 : Tspeedbutton;
    PROCEDURE Button1click( Sender : Tobject) ;
    PROCEDURE Formcreate( Sender : Tobject) ;
  Private

  Public

  END ;

VAR
  Form1 : Tform1;

IMPLEMENTATION
{$R *.lfm}
{$R testres.lrs}


{ Tform1 }

PROCEDURE Tform1.Formcreate( Sender : Tobject) ;
BEGIN
  COBX_BitmapNames.Items.Clear;
// Laden der BitMap Namen ind die Combobox, aus der Ressourcen Datei ???
End;


PROCEDURE Tform1.Button1click( Sender : Tobject) ;
VAR
    Image: TImage;
BEGIN
  Image := TImage.Create(form1);
  Image.Picture.LoadFromResourceName( HInstance, 'lazarus16x16' {'Edit_150'});
  SpeedButton1.Glyph.Assign(Image.Picture.Bitmap);
  Image.free;
End;

END .   
Dateianhänge
testres.lrs
(27.35 KiB) 62-mal heruntergeladen
Gruß, Michael

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Ressourcen Handle für {$R ressdatei.Res}

Beitrag von PascalDragon »

Lorca hat geschrieben:
Mi 26. Jan 2022, 11:23
Ich habe mir mit lazres.exe eine Ressourcen Datei (Button_Icons.Res) angelegt.
Für den Aufbau dieser Ressourcendatei habe ich alle benötigten .PNG Dateien in einem eigenen Ordner
kopiert und umbenannt.
So wurde z.B. aus menu_new_unit_150.png der neue Name "New_150" und aus laz_edit_150.png wurde "Edit_150.png"
Ich sehe in der Ressourcendatei keine Edit_150. Die New_150 sehe ich allerdings. Probier es doch mal mit der aus um zu sehen, ob es überhaupt funktioniert und dann musst du herausfinden, warum die Edit_150 fehlt.
six1 hat geschrieben:
Mi 26. Jan 2022, 11:39
Anbei eine res Datei, welche zwei Bildchen enthält.
Bitte nenne die doch nicht .lrs. Mein erster Gedanke war, dass du da eine Datei mit dem alten Ressourcenformat von Lazarus hochgeladen hast...
FPC Compiler Entwickler

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Ressourcen Handle für {$R ressdatei.Res}

Beitrag von six1 »

...es ist ja bereits geraume Zeit ein Gespräch im Gange, wegen der teilweise veralteten Wiki Beiträge im Web.
Ich hatte extra nochmal nachgelesen und war der Meinung, mein solle das .lrs benennen... war wohl ein Fehler...

https://wiki.lazarus.freepascal.org/Lazarus_Resources
Gruß, Michael

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Ressourcen Handle für {$R ressdatei.Res}

Beitrag von wp_xyz »

Auch ich sehe mit dem Tool XN Resource Editor die Resource "Edit_150" nicht, dagegen sehe ich ebenfalls 'New_150'.

Aber auch wenn ich den Namen 'New_150' abrufe funktioniert dein Code nicht. Das Problem ist, dass du die Resource direkt in SpeedButton.Glyph einliest. Glyph ist aber vom Typ ein TBitmap. Für Bitmaps gibt es einen eigenen Zweig in der Resource RT_BITMAP, und Glyph sucht daher nur in diesem Zweig nach 'New_150' - und findet es nicht. Denn wenn du mit LazRes eine Resource-Datei aus .png-Bildern erzeugst, dann schreibt es diese in den Zweig RT_RCDATA.

Ich habe das in meinem Test so gelöst, indem ich ein png-Image erzeuge, die Resource per png.LoadFromResourceName in dieses einlese und erst dann dem Glyph zuweise:

Code: Alles auswählen

PROCEDURE Tform1.Button1click( Sender : Tobject) ;
var
  png: TPortableNetworkgraphic;
BEGIN
  png := TPortableNetworkgraphic.Create;
  try
    png.LoadFromResourceName(HInstance, 'New_150');
    SpeedButton1.Glyph.Assign(png);
  finally
    png.Free;
  end;
End;
Zur Frage "Auslesen eines Resource-Verzeichnisses" habe ich diesen Beitrag im internationalen Forum gefunden: https://forum.lazarus.freepascal.org/in ... #msg374343. Basierend darauf kam ich dann zu folgendem funktionierenden Code:

Code: Alles auswählen

PROCEDURE Tform1.Formcreate( Sender : Tobject) ;
var
  res: TResources;
  stream: TFileStream;
  reader: TAbstractResourceReader;
  i: Integer;
  item: TAbstractResource;
BEGIN
  COBX_BitmapNames.Items.Clear;

  // Laden der BitMap Namen ind die Combobox, aus der Ressourcen Datei ???
  res := TResources.Create;
  stream := TFileStream.Create('Button_Icons.res', fmOpenRead);
  try
    reader := TResources.FindReader(stream);  // ACHTUNG: Das ruft den Constructor des Readers auf --> reader.Free nötig
    res.LoadfromStream(stream, reader);
    for i := 0 to res.Count-1 do begin
      item := res.Items[i];
      COBX_BitmapNames.Items.Add(Format('%s (%s)', [item.Name.Name, item._Type.Name]));
    end;    
  finally
    reader.Free;
    stream.Free;
    res.Free;
  end;
End;
Die "10", die von der Format-Anweisung hinten an den Resource-Namen angehängt wird, ist der Zahlenwert des Resource-Type RT_RCDATA.

Lorca
Beiträge: 196
Registriert: Di 3. Nov 2020, 12:25

Re: Ressourcen Handle für {$R ressdatei.Res}

Beitrag von Lorca »

Hallo zusammen,

herzlichen Dank für eure freundlichen Antworten. :)

Mit dem Programm RessHacker kann ich alle enthaltenen Icons finden. Sowohl ADD_150 als auch NEW_150. Und alle anderen auch.
Dank eurer Antworten verstehe ich nun auch warum. Denn das Programm Resshacker (http://www.angusj.com) listet
den Inhalt als RT_Data auf. Deshalb dürften Icons mit dem Typ RT_Data nicht mit dem Tool: XN Resource Editor erscheinen.
Warum bzw. ob lazres.exe nun einmal .PNG Dateien als RT_Data und einmal als RT_BitMap speichert weiß ich nicht. Kann es mir auch sehr schwer vorstellen, das dieses Programm die PNG Dateien mit unterschiedlichen Typen speichert. Jedoch könnte dies ein Grund dafür sein, warum einige PNG's gefunden werden und andere nicht. Scheinbar dürften mit dem Typ RT_Data wohl alle Bitmaps gefunden werden. Vllt. liegt es aber auch nur an eine Toleranzgrenze im RessHacker?
Egal, jeden falls funzt dieses Beispiel bei mir. Danke schön :)


Nun zur Frage 2:
@wp_xyz:
Den ersten Teil deiner Antwort mit dem Laden des SpeedButton.Glyph habe ich verstanden und auch direkt umgesetzt. :)
Danke dafür.

Der zweite Teil deiner Antwort funzt bei mir nicht.
Leider geht der Befehl:
reader := TResources.FindReader(stream); in die Wicken.
Obwohl ich in dieser Methode einen BreakPoint gesetzt habe, geht der Debugger nicht rein. (Warum nicht???)
Somit kann ich nicht weiter analysieren, warum er das Format nicht findet. Der Autor des von Dir genannten Beitrages schreibt das es möglicherweise nicht funktioniert. Ich gehe davon aus das Du das Coding mal durchlaufen laufen lassen hast. Deshalb stelle ich mir die Fragen:
Was fehlt bei mir? Was läuft bei mir schief?
Muss ich weitere Units einbinden? Gibt es vllt. eine weitere Klasse "TResources" in einer anderen Unit als: "Resource"?


Viele Grüße
Lorca
Dateianhänge
ErrorMsg.png
ErrorMsg.png (13.12 KiB) 1323 mal betrachtet

PascalDragon
Beiträge: 825
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Ressourcen Handle für {$R ressdatei.Res}

Beitrag von PascalDragon »

Lorca hat geschrieben:
Do 27. Jan 2022, 09:39
Mit dem Programm RessHacker kann ich alle enthaltenen Icons finden. Sowohl ADD_150 als auch NEW_150. Und alle anderen auch.
Du hast in deinem initialem Post aber EDIT_150 geschrieben und nicht ADD_150 und ersteres existiert eben nicht in der Ressourcendatei.
Lorca hat geschrieben:
Do 27. Jan 2022, 09:39
Leider geht der Befehl:
reader := TResources.FindReader(stream); in die Wicken.
Obwohl ich in dieser Methode einen BreakPoint gesetzt habe, geht der Debugger nicht rein. (Warum nicht???)
Der Code von TResources ist Teil der FCL und damit ohne Debug Informationen kompiliert.
FPC Compiler Entwickler

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Ressourcen Handle für {$R ressdatei.Res}

Beitrag von wp_xyz »

Verdammt, ich habe vergessen, die uses-Zeile mit reinzukopieren:

Code: Alles auswählen

uses
  resource, resreader;
Die Fehlermeldung hatte ich anfangs auch, sie bedeutet, dass, da die resource Unit sehr allgemein ausgelegt ist, noch eine Reader-Unit benötigt wird, die das Format der Resource kennt - es gibt neben .res ja auch noch die .lrs Dateien. Wenn man die resreader-Unit mit einbindet, ist bekannt, dass .res-Dateien gelesen werden sollen.

Lorca
Beiträge: 196
Registriert: Di 3. Nov 2020, 12:25

Re: Ressourcen Handle für {$R ressdatei.Res}

Beitrag von Lorca »

Hallo zusammen,

@PascalDragon
SRY, 4 confusion :)
Das mit dem Add und Edit hast Du recht. Der Initiale Code war richtig. Der Name heißt "Edit_150" und nicht "Add_150"
Warum ich jetzt ADD reingeschrieben habe liegt wohl an meiner altersbedingten Demenz :lol:

@wp_xyz:
Cool: gez funzt datt auch :)
Danke schön

Nochmals danke für euren unermüdlichen Einsatz :)
Ihr seit echt Klasse.


Viele Grüße
Lorca

Antworten