Ressourcen Datei *.RES aufbauen

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

Ressourcen Datei *.RES aufbauen

Beitrag von Lorca »

Hallo zusammen,

für meine Buttons möchte ich gerne eine Ressourcen Datei anlegen und diese dann über {$R xxx.res} oder {$R xxx.rc} in meiner Komponenten einbinden.
Ich verstehe das aber noch nicht so richtig.
Was ich gelesen habe ist, man erstellt eine TXT Datei und ändert das Suffix von TXT nach RC. ( RC ist wohl nicht zwingend notwendig)
Dann trägt man die *.PNG Dateien mit Pfad ein.
z.B:
Z:\Dev\Ressourcen\BTN_Add_150.png
Z:\Dev\Ressourcen\BTN_Del_150.png
Ebenfalls liegen diese Dateien in dem gleichen Ordner wie die RC Datei

Anschließend soll man "windres" aufrufen: windres -i xxx.rc -xxx.Res. Das geht jedoch immer in die Wicken.
Fehlermeldung von Windres: "Der Befehl "gcc" ist entweder falsch geschrieben oder konnte nicht gefunden werden."

OK dieser Weg ist erst einmal eine Sackgasse.
Also nehme ich mein Programm "RessHacker", erstelle eine Image Ressource und lade die PNG Dateien ein die ich möchte und Speicher die neue res oder auch rc oder dll als eine solche ab.
Nun habe ich aber nicht mehr den Typen RC_Data sondern PNG.

Und wie lese ich diese Ressourcen aus? Mit
BITBTN.Glyph.LoadFromLazarusResource( Dateiname_ohne_Suffix ) geht es nicht.

Kann da jemand weiterhelfen? Gibt es irgendwo ein Bespiel Dokument wo ich mir das selber anlesen kann?
Denn über Dr. Google habe ich nichts gefunden was ich verstehe bzw. nachvollziehen kann


Gruß
Lorca

Benutzeravatar
Winni
Beiträge: 980
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.0.12, fpc 3.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Ressourcen Datei *.RES aufbauen

Beitrag von Winni »

Hi!

https://wiki.freepascal.org/lazres

Bitte die Notizen beachten, wie sich seit Version 1.4 die Dinge verändert haben.

Angemerkt sei, dass Die Lazarus-Resourcen (.lrs) als veraltet gelten, aber wunderbar funktionieren.

Winni

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

Re: Ressourcen Datei *.RES aufbauen

Beitrag von wp_xyz »

Spicke einfach von Lazarus: Im Order lcl/images/dbnavigator z.B. findest du die Icons für den DBNavigator. Dort ist auch eine Batch-Datei lcl_dbnav_images.bat mit diesem Inhalt:

Code: Alles auswählen

..\..\..\tools\lazres ..\..\lcl_dbnav_images.res @lcl_dbnav_images_list.txt
Das bedeutet: es wird das Tool lazres mit dem Namen der zu erzeugenden res-Datei und einer Liste der aufzunehmenden Dateien aufgerufen:
  • lazres gehört zum Lieferumfang von Lazarus und befindet sich im Ordner tools der Lazarus-Installation. Es muss zuerst compiliert werden. Am besten kopierst du dir die dabei erzeugte Datei in einen Ordner der im System-Pfad gelistet ist, oder du merkst dir den Pfad und ersetzt in "deiner" batch-Datei das "..\..\..\tools" durch den entsprechenden Pfad.
  • Auch beim Namen der zu erzeugenden res-Datei muss der Pfad angegeben werden, entweder absolut (abzuraten) oder relativ zur Position der Batch-Datei. Die res-Datei speicherst du am Besten in denselben Ordner deines Package, in dem sich die Datei befindet, in der sie per {$R...} eingebunden wird.
  • Die Namen der in der res-Datei aufzunehmenden Dateien kannst du entweder direkt als nachfolgende Parameter für lazres angeben oder, wenn es sehr viele Dateien sind, als Dateiliste (lcl_dbnav_iamge_list.txt), wobei jeder Dateiname dann in einer eigenen Zeile steht; die Dateiliste wird als solche mit einem @ als erstem Zeichen gekennzeichnet.
  • Das ist für Windows. Für Linux funktioniert alles analog.
Dein Package darf die res-Datei nur einmal einbinden; dies geschieht durch Einfügen von {$R <name_der_res_datei>.res} am Anfang des Implementierungs-Abschnitts der betreffenden Unit. Falls sich die res-Datei nicht in demselben Ordner befindet wie die Unit, muss der relative Pfad angegeben werden.

Ein in der Resource enthaltenes Bild holst du dann z.B. per Bitmap.LoadFromResourceName(HInstance, 'name_der_bild_datei_ohne_endung').

MmVisual
Beiträge: 1219
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 2.0.10 FPC 3.2)
CPU-Target: 32/64Bit

Re: Ressourcen Datei *.RES aufbauen

Beitrag von MmVisual »

Tipp:
Falls man ganz viele Dateien hat die man als Ressource mit einbinden möchte gibt es einen sehr einfachen und effizienten weg:

1) Man Zippt die Dateien in ein ZIP Archiv
2) Aus der ZIP Datei wird eine Ressource erstellt
3) In der EXE wird diese ZIP Ressource als Stream geöffnet
4) Mit der Abbrevia Komponente kann man diesen ZIP Stream verbinden und die einzelnen Dateien wiederum als Stream heraus holen

Vorteil: alles passiert im RAM, keine Dateioperation auf der Festplatte und man kann sehr leicht eine dynamische Anzahl von Dateien dem Projekt hinzu fügen ohne dass man was umprogrammieren muss.
Ich nutze dies um die Hilfe-Datein in die EXE mit einbinden zu können, die Hilfe änderst sich ständig und im Code braucht es keine einzige Änderung dazu.

https://sourceforge.net/projects/tpabbrevia/files/

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 961
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.11 FPC 3.2)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Ressourcen Datei *.RES aufbauen

Beitrag von fliegermichl »

Bei Projekten kann man auch einfach die Lazarus IDE nutzen. (Geht mWn. derzeit bei Packages nicht)
Projekt -> Projekteinstellungen -> Projekteinstellungen -> Resourcen.

Die hier zugefügten Resourcen werden automatisch eingebunden.

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

Re: Ressourcen Datei *.RES aufbauen

Beitrag von Lorca »

Hallo zusammen,

ganz herzlichen Dank an euch alle.
Die Lazres Variante gefällt mir am besten. Auch die Doku dazu ist geil. Danke.
Nun gibt es jedoch ein Problem beim installieren der Komponente.

Error: Duplicate resource: Type = 10, Name = LAZ_CANCEL_150, Lang ID = 0000

Diese Datei (LAZ_CANCEL_150) wurde nicht in die Dateiliste mit aufgenommen. Dennoch kommt dieser Fehler hoch.


Wie in der Doku beschrieben, habe ich die Dateien in die Dateiliste aufgenommen und mit Lazres "compiliert"
Dann habe ich die neue Ressoucendatei im IMPLEMENTATION Bereich aufgenommen
Ein Zugriff auf diese Ressourcen findet derzeit noch nicht statt

Was habe ich falsch gemacht? Worauf muss ich achten?

IMPLEMENTATION
{$R Button_Icons.res}



Viele Grüße
Lorca
Dateianhänge
Ressourcen.zip
(114.7 KiB) 12-mal heruntergeladen

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 961
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.11 FPC 3.2)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Ressourcen Datei *.RES aufbauen

Beitrag von fliegermichl »

Abgesehen davon, daß in der Textdatei absolute Pfade stehen, was nicht empfohlen wird, ist mit der Resourcendatei alles in Ordnung.

Hast du evtl. in deiner Unit zweimal {$R *.res} stehen?

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

Re: Ressourcen Datei *.RES aufbauen

Beitrag von wp_xyz »

Und die IDE kriegt die Änderung an Resourcen nicht unbedingt immer mit. Daher: Das Package mit "Weitere" > "Sauber neu rekompilieren" (aus dem Package-Editor heraus) neu kompilieren.

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

Re: Ressourcen Datei *.RES aufbauen

Beitrag von Lorca »

Hallo zusammen,

@wp_xyz: Ja Du hast recht. Lazarus bekommt diese Änderung nicht mit. Ich hatte Lazarus beendet, und den PC (sicherheitshalber) neu gestartet und dann kam dieser Fehler nicht mehr. :). Danke für Deine helfende Info mit "Weitere". Diesen Button haben meine Blinden Augen noch nicht gesehen :o
@fliegermichl: Auch Dir Danke schön :) Aber ich glaube die absolute Pfadangabe dient NUR dem Programm Lazres.. In der *.RES Datei gibt es keine Pfade. Währe auch dumm, denn wenn die Res Datei auf einem anderen Rechner eingesetzt werden soll würde die nicht funzen. Auch unter dem Gesichtspunkt das die *.PNG Datei auf dem Fremdrechner nicht existieren muss.

Nun wird die Komponente zwar korrekt erzeugt, aber die ICONs werden nicht gefunden. Ich verstehe das nicht.
Das Icon "Arrow_Left_Hell_Green_150" gibt es definitiv. Habe ich sogar mit dem Programm ResHacker überprüft. LazRes hat also echt sauber gearbeitet.
Auch wenn ich dieses Icon mit UpperCase('Arrow_Left_Hell_Green_150') laden wollte, wurde das Icon nicht gefunden.
Ich bin am verzweifeln. *jammer*

Gruß
Lorca

IMPLEMENTATION
{$R Button_Icons.res}

CONSTRUCTOR TCL_Toggle_Button.Create( TheOwner : TComponent );
BEGIN
INHERITED Create( TheOwner );
self.parent := TWinControl( TheOwner );
Self.Width := 30;
Self.Height := 30;
Self.Caption := '';
Self.ShowHint := True;
mo_Glyph_Toggle_On := TBitmap.Create;
mo_Glyph_Toggle_Off := TBitmap.Create;
IF csDesigning IN ComponentState THEN BEGIN
mo_Glyph_Toggle_On.LoadFromResourceName(hInstance, 'Arrow_Left_Hell_Green_150');
END;
END;
Dateianhänge
Button_Icons.txt
(3.85 KiB) 4-mal heruntergeladen
ICON_NOT_Found.PNG
ICON_NOT_Found.PNG (8.95 KiB) 375 mal betrachtet

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 4755
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Niederösterreich
Kontaktdaten:

Re: Ressourcen Datei *.RES aufbauen

Beitrag von af0815 »

Gelöscht. Zuerst denken, dann schreiben :shock:
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

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

Re: Ressourcen Datei *.RES aufbauen

Beitrag von wp_xyz »

Ich meine mich zu erinnern, dass ich dasselbe Problem in TvPlanIt hatte. Ich hatte mir damals mit folgender Hilfs-Prozedur beholfen:

Code: Alles auswählen

procedure LoadGlyphFromRCDATA(AGlyph: TBitmap; AResName: String);
var
  stream: TResourceStream;
  pic: TPicture;
begin
  stream := TResourceStream.Create(HINSTANCE, AResName, RT_RCDATA);
  try
    pic := TPicture.Create;
    try
      pic.LoadFromStream(stream);
      AGlyph.Assign(pic.Bitmap);
    finally
      pic.Free;
    end;
  finally
    stream.Free;
  end;
end; 
Bin nicht sicher, ob man das unbedingt benötigt, aber damals löste es das Problem.

Meine Erklärung war: Wenn man eine .res-Datei mit LazRes erzeugst, landen die Bilder in der Resource mit dem Namen RT_RCDATA, aber das Standard-LoadFromResourceName greift auf die Resource RT_BITMAP zu. Möglicherweise hängt das vom Typ des Bildes ab, das LoadFromResourceName aufruft; ich könnte mir vorstellen, dass ein png automatisch auf RT_RCDATA zugreift, denn im Abschnitt RT_BITMAP wird es nichts finden. Genauer nachgeforscht habe ich aber nicht.

[EDIT]
Genau, es hängt vom Typ der Graphik ab, die LoadFromResourceName aufruft. Wenn du mo_Glyph_Toggle_On als TPortableNetworkGraphic deklarierst, kannst du direkt dessen LoadFromresourceName aufrufen, denn es weiß, dass es sich um ein png handeln muss, und diese befinden sich normalerweise im RT_RCDATA Zweig. Problem: auch wenn es keiner mehr macht, aber du kannst keine bmp-Bitmaps mehr als Resource für mo_Glyph_Toggle_on verwenden.

Oder du bleibst bei der Deklaration als TBitmap (oder besser noch: du nimmst die übergreifende Deklaration TCustomBitmap) und kannst nun mit ein paar Zeilen mehr auf dem Umweg über ein TPicture auf jeden beliebigen Zweig der Resource zugreifen.

Im beigefügten Beispiel siehst du die zwei Methoden im Einsatz (getestet). (Im Programm gibt es drei Buttons, aber Button2 und Button3 machen letztendlich nur dasselbe).
Dateianhänge
loadfromresourcename.zip
(10.12 KiB) 8-mal heruntergeladen

Sieben
Beiträge: 127
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: i386

Re: Ressourcen Datei *.RES aufbauen

Beitrag von Sieben »

Oder man 'klaut' sich die entsprechende Prozedur bei TImageList, die ja sehr vielfältige Formate und auch noch Masken unterstützt, und baut sie in einen eigenen Abkömmling ein :

Code: Alles auswählen

  TResBitmap = class(TBitmap)
  public
    procedure LoadFromResName(const ResName: string; MaskColor: TColor = clNone);
  end;

//...

procedure TResBitmap.LoadFromResName(const ResName: string; MaskColor: TColor);
var Grp: TGraphic;
    Bmp: TCustomBitmap absolute Grp;
begin
  Grp := CreateGraphicFromResourceName(hInstance, ResName);
  try
    if (Grp is TCustomBitmap) then
    begin
      if (MaskColor <> clNone) then
      begin
        Bmp.TransparentColor := MaskColor;
        Bmp.Transparent := True;
      end;
      Assign(Bmp);
    end else
      if (Grp = nil) then
        raise EResNotFound.CreateFmt(ClassName+': Resource %s not found',[ResName])
      else
        raise EInvalidGraphic.Create(ClassName+': Unsupported Resourcetype');
  finally
    Grp.Free;
  end;
end;
Das unterstützt dann neben allen möglichen Bitmap-Formaten, die als RC_DATA gehen, auch noch RT_GROUP_ICON und RT_GROUP_CURSOR.

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

Re: Ressourcen Datei *.RES aufbauen

Beitrag von Lorca »

Hallo zusammen,

ganz herzlichen Dank für eure freundlichen, Informativen Ausführungen und Beispiele :)
Mit der Hilfsroutine von wp_xyz klappt es nun. Kollege Sieben hatte ein wenig später gepostet. Das werde ich dann jetzt in Angriff nehmen. Diese Vorgehensweise sieht sehr spanned aus.

Eine große Stolperfalle liegt in TResourceStream.Create(Instance: TFPResourceHMODULE; const ResName: string; ResType: PChar)

In der Unit: resource ist die Konstante als Integer wert definiert.
Der o.g. Konstructor erwartet jedoch PCHAR. Weshalb bei mir die Routine: LoadGlyphFromRCDATA zunächst Probleme machte. Mit dem Zusatz ( pChar(RT_RCDATA)) funzt es aber hervorragend. Danke :)

Lade ich nun auf diesem Wege eine Glyph in Form1.Create dann funzt es. Will ich jedoch dies, in der Methode Create einer Komponente machen, wird wie gewohnt der Name der Ressource (z.B. Edit_150 ) nicht gefunden. Auch unter der Bedingung "IF csDesigning IN ComponentState THEN" geht der Ladebefehl für die BitMap mit der gleichen Fehlermeldung auf die Bretter.

Somit ist die Vorbelegung einer BitMap innerhalb einer Komponente (nach dem Vorbild von TDBNavigator) für mich noch nicht möglich. Ich könnte mir vorstellen das zum Zeitpunkt von TCL_Toggle_Button.Create die über $R eingebundene Ressource noch nicht geladen ist. Vllt. mal im Initialisierungsblock einbinden.


Viele Grüße und nochmals Danke schön
Lorca

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

Re: Ressourcen Datei *.RES aufbauen

Beitrag von wp_xyz »

Lorca hat geschrieben:
Sa 13. Nov 2021, 11:12
Eine große Stolperfalle liegt in TResourceStream.Create(Instance: TFPResourceHMODULE; const ResName: string; ResType: PChar)

In der Unit: resource ist die Konstante als Integer wert definiert.
Der o.g. Konstructor erwartet jedoch PCHAR. Weshalb bei mir die Routine: LoadGlyphFromRCDATA zunächst Probleme machte. Mit dem Zusatz ( pChar(RT_RCDATA)) funzt es aber hervorragend. Danke :)
Ja, die vielen Units mit Überschneidungen in den Deklarationen...

Die Unit Resource habe ich bewusst noch nicht eingesetzt. Normalerweise kommen als erste Kandidaten bei Problemen mit unbekannten Bezeichnern bei mir die Units LCLIntf, LCLType, Types zum Einsatz, und da werde ich meistens fündig, bei RT_RCDATA wäre das LCLType. Wenn man plattform-unabhängig programmieren will, auf Windows aber auf keinen Fall die Unit Windows verwenden.
Lorca hat geschrieben:
Sa 13. Nov 2021, 11:12
Lade ich nun auf diesem Wege eine Glyph in Form1.Create dann funzt es. Will ich jedoch dies, in der Methode Create einer Komponente machen, wird wie gewohnt der Name der Ressource (z.B. Edit_150 ) nicht gefunden. Auch unter der Bedingung "IF csDesigning IN ComponentState THEN" geht der Ladebefehl für die BitMap mit der gleichen Fehlermeldung auf die Bretter.
Das kann eigentlich nicht sein. Z.B. beim DBNavigator werden die Icons in der Methode UpdateButtons geladen, die im Constructor des Navigators aufgerufen wird. Die Icons werden dort allerdings etwas versteckt über eine spezialisierte ImageList, LCLGlyphs, und eine Methode GetDefaultGlyph geladen (alles in Unit imglist).

Wenn bei dir das Laden im Constructor nicht funktioniert, muss das einen anderen Grund haben. Initialisierungscode ist nicht nötig.

wennerer
Beiträge: 335
Registriert: Di 19. Mai 2015, 20:05
OS, Lazarus, FPC: Linux Mint 20 Cinnamon, Lazarus Stable 2.0.10 r63673M FPC 3.2.0
CPU-Target: x86_64-linux-gtk2

Re: Ressourcen Datei *.RES aufbauen

Beitrag von wennerer »

Hallo Lorca,
wenn ich dich richtig verstehe möchtest du eine PNG in eine Komponente einbinden. Ich habe mal ein Minimal-Beispiel angehängt wie es bei mir funktioniert.
Ich mach es aber mit LazRes (also .lrs). Falls du die Mini-Komponente installierst erscheint diese im Standard-Reiter. Vielleicht hilft es dir ja weiter.

Viele Grüße
Bernd
Dateianhänge
ResTest_lrs.zip
(15.69 KiB) Noch nie heruntergeladen
Zuletzt geändert von wennerer am Di 16. Nov 2021, 20:07, insgesamt 1-mal geändert.

Antworten