Neue Komponente erstellen

Rund um die LCL und andere Komponenten
Lorca
Beiträge: 196
Registriert: Di 3. Nov 2020, 12:25

Neue Komponente erstellen

Beitrag von Lorca »

Hallo zusammen,

ich möchte gerne eine neue Komponente erstellen. Hierzu habe ich ein Paket angelegt ( Package / Neues Package ) und dann über Hinzufügen / Neue Komponente eben diese neue Komponente angelegt.
Es soll eine "Audio Panel" Komponente mit drei Buttons werden( Play, Pause und Stop).
Als Vorlage habe ich TDBNavButton genommen. Diese habe ich jedoch nicht Kopiert sondern einfach nur die benötigten Methoden übernommen und entsprechen abgeändert.

Nach dem Kompilieren und anschließendem Installieren ziehe ich diese Komponente auf das Formular.
Ich sehe jedoch nur das Audio Panel. Die Buttons erscheinen nicht. Weder im Design Modus noch während der Laufzeit.

Die Klasse für die Buttons ist eine Ableitung von TBitBtn mit nur einer neuen Funktionalität: ButtonType.
Ich habe es bei den Buttons mit Self.InsertControl und mit Self.InsertComponent versucht. Aber nichts hat geholfen.
Es ist immer nur das leere Panel zu sehen.

Kann jemand etwas dazu sagen, wie vorzugehen ist?
Wo habe ich meinen Gedankenfehler?

Viele Grüße
Lorca


Source:

TYPE
TButtonType_Audio = ( bta_None, bta_Play, bta_Stop, bta_Pause );
TButtonSet_Audio = SET OF TButtonType_Audio;

TCL_AudioPanel = class( TCustomPanel )
PRIVATE
mv_Visible_Buttons : TButtonSet_Audio;
ma_Buttons : ARRAY[ TButtonType_Audio ] OF TCL_CA_Audio_Button;

END;

CONSTRUCTOR TCL_AudioPanel.Create( TheOwner: TComponent );
BEGIN
INHERITED Create( TheOwner );
Self.Height := 32;
Self.Width := 96;
Self.Caption := '';
mv_Visible_Buttons := [ bta_Play, bta_Stop, bta_Pause ];
UpdateButtons;
END;


PROCEDURE TCL_AudioPanel.UpdateButtons;
VAR lv_BTNType : TButtonType_Audio;
BEGIN
FOR lv_BTNType := Low( TButtonType_Audio ) TO High( TButtonType_Audio ) DO BEGIN
FreeThenNil( ma_Buttons[ lv_BTNType ] );
END;

FOR lv_BTNType := Low( TButtonType_Audio ) TO High( TButtonType_Audio ) DO BEGIN
IF NOT ( lv_BTNType IN Visible_Buttons ) THEN
CONTINUE;
ma_Buttons[ lv_BTNType ]:= ADD_Button( lv_BTNType );
END;
END;


FUNCTION TCL_AudioPanel.ADD_Button( iv_ButtonType : TButtonType_Audio ) : TCL_CA_Audio_Button;
VAR lo_Button : TCL_CA_Audio_Button;
BEGIN
Result := NIL;
IF NOT ( iv_ButtonType IN mv_Visible_Buttons ) THEN EXIT;
lo_Button := TCL_CA_Audio_Button.Create( Self );
lo_Button.Caption := '';
lo_Button.Width := 30;
lo_Button.Align := alLeft;
lo_Button.Visible := True;
lo_Button.ButtonType := iv_ButtonType ;
Result := lo_Button;
END;

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

Re: Neue Komponente erstellen

Beitrag von wp_xyz »

Solche Code-Schnippsel sind relativ wertlos, weil nicht alles gezeigt ist. Statt viel Zeit in die individuelle Formatierung des reinkopierten Codes zu spendieren, solltet du ein kleines Projekt mit allen benötigten Dateien zusammenstellen (aber nicht die vom Compiler erzeugten) und als zip hochladen, so dass man die Komponente selbst duch den Compiler schicken kann.

Falls ich nichts übersehe, fehlt bei Add_Button die Zuweisung des Parent, also

Code: Alles auswählen

lo_Button.Parent := Self;

charlytango
Beiträge: 843
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: Neue Komponente erstellen

Beitrag von charlytango »

@lorca -> Fürs Testprojekt:

Menü: Project(Projekt) - Publish Project(Projekt publizieren)

erzeugt ein Zipfile mit allen nötigen Dateien eines Projektes. Dann brauchst du nicht zusammensuchen was nötig ist.

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

Re: Neue Komponente erstellen

Beitrag von Lorca »

Hallo zusammen,

meinen ganz herzlichen Dank an euch.
@wp_xyz: Dein Hinweis mit "Parent := xxx" war genau das non plus Ultra :) Danke schön. Jetzt funzt es.
@charlytango: Ein wirklich super Hinweis :) Danke schön. Bis dato habe ich mit dieser Funktion nicht so richtig etwas anstellen können und mich deshalb auch nicht damit beschäftigt. Außerdem scheint es für Windows 10 kein gescheites kostenloses ZIP Programm zu geben. Alles nur 30 Tage Testversionen. Das ich nun aus meinen Quellen mit Lazarus auch ZIP Dateien erstellen kann, hat mich direkt auf die nächste Stufe katapultiert. :lol:

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

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

Re: Neue Komponente erstellen

Beitrag von wp_xyz »

Lorca hat geschrieben:
So 7. Nov 2021, 12:55
Außerdem scheint es für Windows 10 kein gescheites kostenloses ZIP Programm zu geben. Alles nur 30 Tage Testversionen.
Eingebaut: https://support.microsoft.com/de-de/win ... 3ed85e7ebc

Ansonsten PeaZip (https://peazip.github.io/), das sogar mit Lazarus geschrieben wurde und z.Zt seinen 15.Geburtstag feiert: https://forum.lazarus.freepascal.org/in ... 049.0.html

Oder natürlich 7zip (https://www.7-zip.de/).

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

Re: Neue Komponente erstellen

Beitrag von Lorca »

Wow Cool
mein herzliches Danke schön an wp_xyz,

Eine Frage bleibt mir jedoch noch:
Ich möchte gerne die Buttons in meinem Audio Panel mit einer BitMap vorbelegen.
Da es sich um eine Komponente handelt, möchte ich ungern mit LoadBitMap(Pfad + Dateiname ) arbeiten.
Viel lieber würde ich diese BitMaps aus einer Ressource holen.
Jedoch: wie bekomme ich diese BitMaps in eine Ressource? und wie hole ich diese zum Zeitpunkt ADD_Button aus der Ressource ?
Die Komponente Imagelist mochte ich nicht in meiner eigenen Komponente verwenden( oder besser vllt. doch? ).


Gruß
Lorca

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Neue Komponente erstellen

Beitrag von fliegermichl »

BitBtn1.Glyph.LoadFromResourceName(hInstance, 'BMP1');

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

Re: Neue Komponente erstellen

Beitrag von wp_xyz »

Lorca hat geschrieben:
Di 9. Nov 2021, 08:32
wie bekomme ich diese BitMaps in eine Ressource?
Schau dir z.B. die Datei lcl/images/buttons/lcl_btn_images.bat an; hier wird die Resource (resourcedateiname.res) mit den Button-Images erzeugt. Diese wird dann per {$R resourcedateiname.res} ins Package eingebunden. Aber schau vielleicht vorher mit einem Resource-Editor (z.B. XN Resource Editor) die RC_DATA Resource einer beliebigen von Lazarus erzeugten exe-Datei ein - vielleicht ist "dein" Icon ja schon vorhanden; dabei findest du dann auch den Namen, mit dem die Resource geladen wird.
Lorca hat geschrieben:
Di 9. Nov 2021, 08:32
Die Komponente Imagelist mochte ich nicht in meiner eigenen Komponente verwenden( oder besser vllt. doch? ).
Ich wäre für "vllt. doch". Denn du solltet dem User deiner Komponente die Möglichkeit geben, die fest eingebauten Icons auszutauschen. Vielleicht entwirft er seine Anwendung im aktuellen minimalistischen Strich-Design für Icons, während die von dir eingebauten fotorealistischen Icons überhaupt nicht dazupassen; oder deine Icons sind minimalistisch schwarz, aber der User ist ein Freund von Darkmode, und nun sind deine Icons auf dunklem Untergrund nicht mehr zu erkennen.

Ich würde der Komponente eine ImageList-Property spendieren, sowie einen ImageIndex für die jeweiligen Buttons. Wenn diese nicht besetzt sind, kommen die eingebauten Icons zum Zuge.

Wenn deine Buttons (TCL_CA_Audio_Button) von TSpeedButton oder TBitBtn abstammen, dann haben die schon die entsprechenden Properties und du musst diese nur von der Hauptkomponente auf die Buttons weiterleiten.

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

Re: Neue Komponente erstellen

Beitrag von Lorca »

Hallo zusammen,

danke für eure Hilfe. :) Habe jetzt eine menge Arbeit vor mir. :D
Herzlichen Dank.

Jedoch verstehe ich noch nicht ganz die direkte Zuweisung von Button.Glyph. in der Click Methode

Habe ich z.B. eine TOGGLE Glyph (zum Ein bzw.Ausschalten) und stelle diese als Property im Published Bereich zur Verfügung
gibt es eine Access Violation bei einer nochmaligen Auswahl der BitMap während des Designs.
Bei dem Standard Glyph funzt es aber. Nur bei der Toogle Glyph nicht. Obwohl ich für diese auch ein Property mit GET und SET Methoden für READ und WRITE angelegt habe.

Ebenfalls funktioniert der Austausch der beiden Bitmaps ( BITBTN.Glyph mit der Toogle Glyph ) in der Protected Methode CLICK nicht.
Im besten falle wird keine Glyph angezeigt. Im schlimmsten gibt es eine Access Violation mit der Konsequenz das Lazarus neu gestartet
werden muss.

Kann hierzu jemand etwas sagen?

Gruß
Lorca

SRY. Zip vergessen:
Zuletzt geändert von Lorca am Mi 10. Nov 2021, 07:27, insgesamt 2-mal geändert.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Neue Komponente erstellen

Beitrag von fliegermichl »

Lad doch mal deinen Code hoch, damit man es nachvollziehen kann.

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

Re: Neue Komponente erstellen

Beitrag von wp_xyz »

Lorca, mit diesem zip mutest du meiner Intelligenz Unlösbares zu: da gibt es einen Order CA und einen CO, mit ähnlichem Inhalt. In CA/Audio/ gibt es eine Unit UCA_CL_AudioButton und CA/Buttons eine UCA_CL_ToggleButton, in CO einen UCO_CL_ToggleButton und einen UCO_CL_BitBtn, usw, usw. Ja was denn nun?

Bitte: Wenn wir uns die Zeit nehmen, dir in deinem Projekt zu helfen, das wäre das mindeste, dass du dir die Zeit nimmst, ein Testprojekt evtl. mit Testpackage zu erstellen, mit dem ein Außenstehender so einfach wie möglich des Problem nachvollziehen kann. Oder wenn du alles beisammen halten willst, dann schreibe uns wenigstens auf, welche Dateien für was zu verwenden sind.

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

Re: Neue Komponente erstellen

Beitrag von Lorca »

Hallo zusammen, hallo wp_xyz

zunächst möchte ich mich für die unortodoxe ZIP Datei entschuldigen und es auch erklären.

Ich hatte die ZIP Datei vergessen. Da ich noch nie mit der Lazarusfunktion "Projekt veröffentlichen" gearbeitet habe, es aber in meinem letzten Threat so verstanden habe, das die Benötigten Dateien in die ZIP gespeichert werden, bin ich davon ausgegangen das NUR die benötigten Dateien dort gespeichert werden. Ich habe die ZIP deshalb auch nicht überprüft. Dies geschah auf Grund von Zeitmangel, da ich mich die letzten Monate mehr in Krankenhäusern aufhalte als zuhause. Ich musste also dringend ins Krankenhaus.
Nun habe ich die ZIP bereinigt und sie hier neu gepostet. Ich hoffe ich habe nichts vergessen.
Übrigens: CA steht bei mir für Cross Applications ( übergreifende Units ) und CO für Component Units :)



Es war eine Zumutung von mir an das Forum.
Deshalb meine herzliche Entschuldigung an dieses Forum.

Viele Grüße
Lorca
Komponenten.zip
(129.71 KiB) 54-mal heruntergeladen

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Neue Komponente erstellen

Beitrag von fliegermichl »

Ich habe mal versucht, das ganze auf ein Minimalbeispiel zusammen zu kürzen.
Da kann ich zwar den Bitmaps im Objektinspektor eine Grafik zuordnen,
wenn ich aber dann erneut auf den Dreipunkte Button neben klicke, bekomme ich auch eine Access Violation angezeigt.

Code: Alles auswählen

unit MyBitBtn;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils, buttons, graphics;

type
  TMyBitBtn = class(TCustomBitBtn)
  private
   fToggleOn : TBitmap;
   fToggleOff : TBitmap;
  protected

  public

  published
   property ToggleOn : TBitmap read fToggleOn write fToggleOn;
   property ToggleOff : TBitmap read fToggleOff write fToggleOff;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Uwe',[TMyBitBtn]);
end;

end.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1435
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Neue Komponente erstellen

Beitrag von fliegermichl »

Wenn ich die Bitmaps erzeuge und dann nur zuweise, funktioniert es wie gewünscht.

Code: Alles auswählen

unit MyBitBtn;

{$mode ObjFPC}{$H+}

interface

uses
  Classes, SysUtils, buttons, graphics;

type

  { TMyBitBtn }

  TMyBitBtn = class(TCustomBitBtn)
  private
   fToggleOn : TBitmap;
   fToggleOff : TBitmap;
  protected
   procedure SetToggleOn(const aBitmap : TBitmap);
   procedure SetToggleOff(const aBitmap : TBitmap);
  public
   constructor Create(TheOwner : TComponent); override;
   destructor  Destroy; override;
  published
   property ToggleOn : TBitmap read fToggleOn write fToggleOn;
   property ToggleOff : TBitmap read fToggleOff write fToggleOff;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Uwe',[TMyBitBtn]);
end;

{ TMyBitBtn }

procedure TMyBitBtn.SetToggleOn(const aBitmap: TBitmap);
begin
  fToggleOn.Assign(aBitmap);
end;

procedure TMyBitBtn.SetToggleOff(const aBitmap: TBitmap);
begin
  fToggleOff.Assign(aBitmap);
end;

constructor TMyBitBtn.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  fToggleOn := TBitmap.Create;
  fToggleOff := TBitmap.Create;
end;

destructor TMyBitBtn.Destroy;
begin
  fToggleOn.Free;
  fToggleOff.Free;
  inherited Destroy;
end;

end.

Benutzeravatar
Ally
Beiträge: 263
Registriert: Do 11. Jun 2009, 09:25
OS, Lazarus, FPC: Win und Lazarus Stable release
CPU-Target: x64

Re: Neue Komponente erstellen

Beitrag von Ally »

Hallo zusammen,

ich schließe mich da wp_xyz an:
Ich wäre für "vllt. doch".
Und möchte noch zu bedenken geben, dass, gerade auch im Hinblick auf High-DPI-Anwendungen, die Verwendung einer Imagelist einiges erleichtert.
Die meisten entsprechenden Komponenten verfügen über eine ImageList die dann auch gleich mit der gegebenenfalls vorhandene ActionList verknüpft ist.
Vielleicht mach ich da ja einen Denkfehler, aber Glyph dient doch wohl nur noch der Rückwärtskompatibilität.

Gruß Roland

Antworten