Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Undeklarierter Bezeichner (MediaPlayer) (https://www.delphipraxis.net/192089-undeklarierter-bezeichner-mediaplayer.html)

Sveni795 19. Mär 2017 14:10

Undeklarierter Bezeichner (MediaPlayer)
 
Hallo Zusammen,

um mich kurz vorzustellen,

ich habe seit 1 Jahr meine Ausbildung abgeschlossen und arbeite in der Firma mit Delphi 10.1
Nun aber auch privat da ich wirklich noch Anfänger bin. Ich habe nun ein Problem mit meinem Quellcode.

Ich bin mir sicher mein Problem ist für fortgeschrittene schnell zu lösen... :|


Ich möchte versuchen über eine "Click.Button" Funktion einen Sound abzuspielen.
Hierfür verwende ich eine Mediaplayer componente. (Das ganze wird eine Multiplattform Anwendung)

Wird der Button geclickt passiert folgendes:
Code:
procedure TTabbedForm.Button1Click(Sender: TObject);
begin
  DataLink :=
    ('C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\xx.mp3');
  playsound(DataLink);
end;
Ich möchte also den Link in einer Stringvariable übertragen und dem Procedure "playsound" übertragen. "DataLink" ist golbal angelegt
Hier nun die PlaySound procedure:
Code:
procedure PlaySound(VAR DataLink: string);
begin
  MediaPlayer1.FileName := DataLink;
  MediaPlayer1.Play;
end;
Nun kommt die Fehlermeldung MediaPlayer1.FileName sei ein Undeklarierter Bezeichner
Wenn ich die MediaPlayer1 funktionen gleich in der ButtonClick Procedure ausführe funktioniert alles ohne Probleme.:pale:

Hat vielleicht jemand einen Tipp?

Vielen Dank
Gruß

Mavarik 19. Mär 2017 14:15

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Playsound gehört nicht zur Form...

Daher ist "ohne" die Form Mediaplayer1 auch nicht erreichbar.

dummzeuch 19. Mär 2017 14:15

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von Sveni795 (Beitrag 1364721)
Code:
procedure TTabbedForm.Button1Click(Sender: TObject);
begin
  DataLink :=
    ('C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\xx.mp3');
  playsound(DataLink);
end;
Code:
procedure PlaySound(VAR DataLink: string);
begin
  MediaPlayer1.FileName := DataLink;
  MediaPlayer1.Play;
end;
Nun kommt die Fehlermeldung MediaPlayer1.FileName sei ein Undeklarierter Bezeichner
Wenn ich die MediaPlayer1 funktionen gleich in der ButtonClick Procedure ausführe funktioniert alles ohne Probleme.:pale:

<Glaskugel auspack>
Lass mich raten: MediaPlayer1 ist eine Komponente auf dem Formular TTabbedForm. Und PlaySound ist eine Prozedur, aber keine Methode von TTabbedForm.

Mach mal aus PlaySound eine Methode von TTabbedForm und es wird funktionieren.

</Glaskugel wieder einpack>

a.def 19. Mär 2017 14:16

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Hallo.

Als erstes: mach mal das
Delphi-Quellcode:
var
in
Delphi-Quellcode:
procedure playSound()
weg.
Als zweites ein paar Fragen die nix mit dem Problem zu tun haben:
- wo ist DataLink in Button1 deklariert?
- warum übergibst du den String nicht direkt an playSound() so wie unten zu sehen
und
- warum stellst du Klammern um den String bei der Deklaration?

Delphi-Quellcode:
 procedure TForm1.playSound(DataLink: string);
 begin
  MediaPlayer1.FileName := DataLink;
  MediaPlayer1.Play;
 end;

procedure TForm1.Button5Click(Sender: TObject);
begin
 playSound('C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\spasti alter.mp3');
end;

Mavarik 19. Mär 2017 14:27

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von a.def (Beitrag 1364724)
Als erstes: mach mal das
Delphi-Quellcode:
var
in
Delphi-Quellcode:
procedure playSound()
weg.

Wieso?

ok ggf. Const aber weg... eher nicht...

haentschman 19. Mär 2017 14:30

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Hallo und willkommen hier...:dp:

Ich würde das File als Konstante anlegen. Wenn du mal an verschieden Stellen den gleichen Sound hast, brauchtst nur die Konstante ändern. :thumb:
Delphi-Quellcode:
const
  conSoundBlubb = 'C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\spasti alter.mp3'
  conSoundBla = 'C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\spasti neuer.mp3'
.
.
.
procedure TForm1.playSound(DataLink: string);
 begin
  MediaPlayer1.FileName := DataLink;
  MediaPlayer1.Play;
 end;

procedure TForm1.Button5Click(Sender: TObject);
begin
 playSound(conSoundBla);
end;
.
procedure TForm1.Button6Click(Sender: TObject);
begin
 playSound(conSoundBla);
end;
.
procedure TForm1.Button7Click(Sender: TObject);
begin
 playSound(conSoundBlubb);
end;
PS: Gewöhne dir gleich zu Anfang an, vernünftige Bezeichnungen für die Komponenten, Variablen, Objekte etc. zu verwenden. :thumb:

a.def 19. Mär 2017 14:33

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von Mavarik (Beitrag 1364728)
Zitat:

Zitat von a.def (Beitrag 1364724)
Als erstes: mach mal das
Delphi-Quellcode:
var
in
Delphi-Quellcode:
procedure playSound()
weg.

Wieso?

ok ggf. Const aber weg... eher nicht...

Hast recht. Aber var ist doch total unnötig. const ist da schon besser. Also entweder nix oder const aber nicht var.

Sveni795 19. Mär 2017 14:35

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von a.def (Beitrag 1364724)
Hallo.

Als erstes: mach mal das
Delphi-Quellcode:
var
in
Delphi-Quellcode:
procedure playSound()
weg.
Als zweites ein paar Fragen die nix mit dem Problem zu tun haben:
- wo ist DataLink in Button1 deklariert?
- warum übergibst du den String nicht direkt an playSound() so wie unten zu sehen
und
- warum stellst du Klammern um den String bei der Deklaration?

Delphi-Quellcode:
 procedure TForm1.playSound(DataLink: string);
 begin
  MediaPlayer1.FileName := DataLink;
  MediaPlayer1.Play;
 end;

procedure TForm1.Button5Click(Sender: TObject);
begin
 playSound('C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\spasti alter.mp3');
end;


Vielen Dank für die Antworten.

Die vielen Formatfehler etc kommen einfach daher das ich eigentlich nur C gelernt habe und mich nun in Pascal einarbeite. Das wird besser.

Wenn ich den String direkt übergebe sagt mir der Compiler es seien zu viele Parameter

DataLink ist global deklariert

Das mit den Klammern habe ich nicht verstanden. Sorry :|

haentschman 19. Mär 2017 14:38

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Hallöle... 8-)
statt:
Delphi-Quellcode:
DataLink := ('C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\xx.mp3');
...
das:
Delphi-Quellcode:
DataLink := 'C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\xx.mp3';
...

a.def 19. Mär 2017 14:39

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von Sveni795 (Beitrag 1364731)
Zitat:

Zitat von a.def (Beitrag 1364724)
Hallo.

Als erstes: mach mal das
Delphi-Quellcode:
var
in
Delphi-Quellcode:
procedure playSound()
weg.
Als zweites ein paar Fragen die nix mit dem Problem zu tun haben:
- wo ist DataLink in Button1 deklariert?
- warum übergibst du den String nicht direkt an playSound() so wie unten zu sehen
und
- warum stellst du Klammern um den String bei der Deklaration?

Delphi-Quellcode:
 procedure TForm1.playSound(DataLink: string);
 begin
  MediaPlayer1.FileName := DataLink;
  MediaPlayer1.Play;
 end;

procedure TForm1.Button5Click(Sender: TObject);
begin
 playSound('C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\spasti alter.mp3');
end;


Vielen Dank für die Antworten.

Die vielen Formatfehler etc kommen einfach daher das ich eigentlich nur C gelernt habe und mich nun in Pascal einarbeite. Das wird besser.

Wenn ich den String direkt übergebe sagt mir der Compiler es seien zu viele Parameter

DataLink ist global deklariert

Das mit den Klammern habe ich nicht verstanden. Sorry :|

Guck dir meinen Beitrag nochmal an und hau die globale Variable weg die brauchst du nicht.

Mavarik 19. Mär 2017 14:45

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von Sveni795 (Beitrag 1364731)
Wenn ich den String direkt übergebe sagt mir der Compiler es seien zu viele Parameter

DataLink ist global deklariert

Das mit den Klammern habe ich nicht verstanden. Sorry :|

Logisch...

Es gibt verschiede Arten von Übergrabeparamtetern

Delphi-Quellcode:
Procedure Foo(S : String);
Procedure Foo(Var S : String);
Procedure Foo(Const S : String);
Procedure Foo(Out S : String);
Ohne Parameter wird von der übergebenen Variablen eine Kopie erzeugt.
Lokale Änderungen haben keinen Effekt nach außen.
Hier kannst Du auch
Delphi-Quellcode:
Foo('Whatever');
übergeben.

Bei Var, erwartet der Compiler auch eine Variable da diese innerhalb der Procedure änderbar ist. Somit kannst du bei VAR keine Konstante 'Whatever' übergeben.

Const, kann beides übernehmen, da innerhalb der procedure (Compilermagic) der String nicht geändert werden kann...

Out ist fast wie Var - zeigt jedoch, dass die Variable als Ausgabeparameter definiert ist und die Procedure keine Initialisierung hiervon erwartet.

und Klammern weg bedeitet:

Delphi-Quellcode:
S := 'Cool';
und nicht
Delphi-Quellcode:
S := ('Cool');

Mavarik

a.def 19. Mär 2017 14:49

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Ich warte ja noch immer auf einen "Thumbs-Up"-Button, "Danke"-Button oder etwas ähnliches ;)

Sveni795 19. Mär 2017 14:51

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Wahnsinn dieses Feedback :)

So ich habe nun die Ratschläge angenommen und entsprechend angepasst:

Code:
  const
    conSoundxx = 'C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\xx.mp3';

procedure TTabbedForm.Button1Click(Sender: TObject);
begin
  TTabbedForm.playSound(conSoundxx);
end;

procedure TTabbedForm.playSound(DataLink: string);
 begin
  MediaPlayer1.FileName := DataLink;
  MediaPlayer1.Play;
 end;
Die Variable "DataLink" gibt es nun nicht mehr global, die habe ich gelöscht.
Die wird doch jetzt nur noch local verwendet.

Das Problem, dass der Mediaplayer nicht bezeichnet ist, ist jetzt weg. Aber er mag die "Const" nicht.
Diese habe zu viele Parameter!?

Mavarik 19. Mär 2017 14:51

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von a.def (Beitrag 1364736)
Ich warte ja noch immer auf einen "Thumbs-Up"-Button, "Danke"-Button oder etwas ähnliches ;)

:thumb: aber wofür?

Mavarik 19. Mär 2017 14:53

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von Sveni795 (Beitrag 1364737)
Aber er mag die "Const" nicht.
Diese habe zu viele Parameter!?

Hast Du Const auch in der Deklaration angegeben? Also einmal "oben" und "unten"?

a.def 19. Mär 2017 14:55

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Aber er mag die "Const" nicht.
So etwas musst du dir unbedingt abgewöhnen. Das ist genau wie... "Mein PC geht nicht" oder "... funktioniert nicht". :stupid:

haentschman 19. Mär 2017 15:09

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Aber er mag die "Const" nicht.
Schreibe mal die Konstante im Interface Teil:
Delphi-Quellcode:
interface

const
  conSoundxx = 'C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\xx.mp3';

uses

type
...
Vielleicht solltest du den Delphi Crashkurs dir mal reinziehen... Da erfährst du viel über den Aufbau. Wo gehört was hin...
Crashkurs:
https://www.delphi-treff.de/tutorial...phi-crashkurs/
E-Book:
https://www.delphi-treff.de/downloads/e-book/

Sveni795 19. Mär 2017 15:15

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von haentschman (Beitrag 1364742)
Zitat:

Aber er mag die "Const" nicht.
Schreibe mal die Konstante im Interface Teil:
Delphi-Quellcode:
interface

const
  conSoundxx = 'C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\xx.mp3';

uses

type
...
Vielleicht solltest du den Delphi Crashkurs dir mal reinziehen... Da erfährst du viel über den Aufbau. Wo gehört was hin...
Crashkurs:
https://www.delphi-treff.de/tutorial...phi-crashkurs/
E-Book:
https://www.delphi-treff.de/downloads/e-book/


Danke, werde ich jetzt erst mal machen.

Stand jetzt habe ich das zwar im Interface gemacht. Aber er sagt mir immer bei:
Code:
procedure TTabbedForm.Button1Click(Sender: TObject);
begin
  TTabbedForm.playSound(conSoundAlter);
end;
Fehler "Zu viele Parameter"

Aber wie du schon gesagt hast werde ich mir jetzt die Crashkurse zurerst reinziehen!

haentschman 19. Mär 2017 15:17

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Hänge das komplette Projekt (ZIP) mal an. Da können wir das mal durchgehen und die Fehler mit Kommentaren markieren. :thumb:

Mavarik 19. Mär 2017 15:19

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von Sveni795 (Beitrag 1364743)
Fehler "Zu viele Parameter"

Jetzt wird es anstrengend...

Poste doch mal den Sourcecode und nicht immer nur eine Zeile... Da können wir auch nix sehen!

a.def 19. Mär 2017 15:26

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von Sveni795 (Beitrag 1364743)
Fehler "Zu viele Parameter"

Das heißt dann wohl, dass playSound() keine Parameter annehmen kann, weil nichts dafür deklariert wurde.

Sveni795 19. Mär 2017 15:34

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Zitat:

Zitat von Mavarik (Beitrag 1364745)
Zitat:

Zitat von Sveni795 (Beitrag 1364743)
Fehler "Zu viele Parameter"

Jetzt wird es anstrengend...

Poste doch mal den Sourcecode und nicht immer nur eine Zeile... Da können wir auch nix sehen!

Code:
unit TabbedTemplate;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  System.Variants,
  FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.TabControl,
  FMX.StdCtrls, FMX.Gestures, FMX.Controls.Presentation, FMX.Media;

type
  TTabbedForm = class(TForm)
    HeaderToolBar: TToolBar;
    ToolBarLabel: TLabel;
    TabControl1: TTabControl;
    TabItem1: TTabItem;
    TabItem2: TTabItem;
    TabItem3: TTabItem;
    TabItem4: TTabItem;
    GestureManager1: TGestureManager;
    Button1: TButton;
    MediaPlayer1: TMediaPlayer;
    procedure FormCreate(Sender: TObject);
    procedure FormGesture(Sender: TObject; const EventInfo: TGestureEventInfo;
      var Handled: Boolean);
    procedure Button1Click(Sender: TObject);
   procedure PlaySound;

  private
    { Private declarations }
  public
    { Public declarations }
  end;


const
  conSoundAlter = 'C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\xx.mp3';

var
  TabbedForm: TTabbedForm;





implementation

{$R *.fmx}

procedure TTabbedForm.FormCreate(Sender: TObject);
begin
  { This defines the default active tab at runtime }
  TabControl1.ActiveTab := TabItem1;
end;

procedure TTabbedForm.FormGesture(Sender: TObject;
  const EventInfo: TGestureEventInfo; var Handled: Boolean);
begin
{$IFDEF ANDROID}
  case EventInfo.GestureID of
    sgiLeft:
      begin
        if TabControl1.ActiveTab <> TabControl1.Tabs[TabControl1.TabCount - 1]
        then
          TabControl1.ActiveTab := TabControl1.Tabs[TabControl1.TabIndex + 1];
        Handled := True;
      end;

    sgiRight:
      begin
        if TabControl1.ActiveTab <> TabControl1.Tabs[0] then
          TabControl1.ActiveTab := TabControl1.Tabs[TabControl1.TabIndex - 1];
        Handled := True;
      end;
  end;
{$ENDIF}
end;




procedure TTabbedForm.Button1Click(Sender: TObject);
begin
  TTabbedForm.playSound(conSoundAlter);
end;

procedure TTabbedForm.playSound(DataLink);
 begin
  MediaPlayer1.FileName := DataLink;
  MediaPlayer1.Play;
 end;


end.
Hier mal der ganze Code.

haentschman 19. Mär 2017 15:42

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Ich korrigiere den mal durch. Moment... 8-) Benutze bitte den Delphi Helm Button statt dem Code Button. Da hat man auch den Delphi Style...

Tipps:
* Benutze einen CodeFormatter bist du einigermaßen sicher bist.
* Verwende sprechende Namen. In 2 Monaten weißt du nicht mehr was Label245 ist. 8-)
* Die Variablen/ Namen haben keine Längenbegrenzung. :warn: Deshalb gibt es keine Notwendigkeit für Abkürzungen.

Delphi-Quellcode:
unit TabbedTemplate;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  System.Variants,
  FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.TabControl,
  FMX.StdCtrls, FMX.Gestures, FMX.Controls.Presentation, FMX.Media;

const
  conSoundAlter = 'C:\Users\Sven\Documents\Embarcadero\Studio\Projekte\Soundbord\Sounds\xx.mp3';

type
  TTabbedForm = class(TForm)
    HeaderToolBar: TToolBar;
    ToolBarLabel: TLabel;
    TabControl1: TTabControl; // bitte bessere Namen...automatisch mit Namensveränderung über den OI
    TabItem1: TTabItem; // bitte bessere Namen...automatisch mit Namensveränderung über den OI
    TabItem2: TTabItem; // bitte bessere Namen...automatisch mit Namensveränderung über den OI
    TabItem3: TTabItem; // bitte bessere Namen...automatisch mit Namensveränderung über den OI
    TabItem4: TTabItem; // bitte bessere Namen...automatisch mit Namensveränderung über den OI
    GestureManager1: TGestureManager; // bitte bessere Namen...automatisch mit Namensveränderung über den OI
    Button1: TButton; // bitte bessere Namen...automatisch mit Namensveränderung über den OI
    MediaPlayer1: TMediaPlayer; // bitte bessere Namen...automatisch mit Namensveränderung über den OI
    procedure FormCreate(Sender: TObject);
    procedure FormGesture(Sender: TObject; const EventInfo: TGestureEventInfo; var Handled: Boolean);
    procedure Button1Click(Sender: TObject); // bitte bessere Namen...automatisch mit Namensveränderung über den OI
  private
    procedure PlaySound(DataLink: string); // hier fehlt der Parameter mit Typ .... Sichtbarkeit private besser
  public
    { Public declarations }
  end;

var
  TabbedForm: TTabbedForm;

implementation

{$R *.fmx}

procedure TTabbedForm.FormCreate(Sender: TObject);
begin
  { This defines the default active tab at runtime }
  TabControl1.ActiveTab := TabItem1;
end;

procedure TTabbedForm.FormGesture(Sender: TObject; const EventInfo: TGestureEventInfo; var Handled: Boolean);
begin
{$IFDEF ANDROID}
  case EventInfo.GestureID of
    sgiLeft:
      begin
        if TabControl1.ActiveTab <> TabControl1.Tabs[TabControl1.TabCount - 1] then // then gehört in die gleiche Zeile
        begin // begin/end ... besser auch wenn es bei einzeiligen Anweisungen nicht nötig ist
          TabControl1.ActiveTab := TabControl1.Tabs[TabControl1.TabIndex + 1];
        end;
        Handled := True;
      end;

    sgiRight:
      begin
        if TabControl1.ActiveTab <> TabControl1.Tabs[0] then
        begin // begin/end ... besser auch wenn es bei einzeiligen Anweisungen nicht nötig ist
          TabControl1.ActiveTab := TabControl1.Tabs[TabControl1.TabIndex - 1];
        end;
        Handled := True;
      end;
  end;
{$ENDIF}
end;

procedure TTabbedForm.Button1Click(Sender: TObject);
begin
  playSound(conSoundAlter);
  // TTabbedForm.playSound ist ganz falsch! Du greifst nicht auf die Instanzvariable, das wäre "TabbedForm"", zu sondern auf die Klasse.
  // da die Sichtbarkeit nun private ist kannst du das "TabbedForm" auch weglassen
end;

procedure TTabbedForm.playSound(DataLink: string);
begin // verschoben
  MediaPlayer1.FileName := DataLink;
  MediaPlayer1.Play;
end;

end.

a.def 19. Mär 2017 16:02

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Delphi-Quellcode:
procedure PlaySound;
// und
procedure TTabbedForm.playSound(DataLink);
Ist doch klar, dass das nicht funktioniert.

Sveni795 19. Mär 2017 16:16

AW: Undeklarierter Bezeichner (MediaPlayer)
 
Vielen lieben Dank an alle.
Ich weiß ich muss noch eine Menge lernen!...

Ganz liebe Grüße und nochmals Danke für die Geduld:roll::roll::roll:

haentschman 19. Mär 2017 16:25

AW: Undeklarierter Bezeichner (MediaPlayer)
 
:thumb:
Bitteschön. So lange du deinen Beitrag zu lernen leistest, wirst du hier immer kompetente Hilfe finden. :thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:26 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz