AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Neue Komponente mit 2 TEdit Komponenten

Ein Thema von Optiplex · begonnen am 28. Mai 2009 · letzter Beitrag vom 15. Jun 2009
Antwort Antwort
Seite 3 von 5     123 45      
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#21

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 29. Mai 2009, 13:11
Mir fällt grad ein, brauchst du da nicht ein Panel wo du dynamisch angeben kannst wieviele Paare spielen und dir dann die richtige Anzahl an Edits erstellt?

Gruß oki
42
  Mit Zitat antworten Zitat
Optiplex

Registriert seit: 5. Mär 2008
131 Beiträge
 
Delphi 2005 Personal
 
#22

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 29. Mai 2009, 14:41
Ja Oki, die Tabelle muss sich dynamisch erweiten von 8,16,32,64 Spielern, das heißt wenn die Spieleranzahl welche mitspielen diese Grenzen erreichen muss die Tabelle entsprechend erweitert werden. wird das Turnier dann gestartet müssen die fehlenden Spielern mit Freilosen aufgefüllt werden, deren Positionen in einem Array gespeichert sind.(damit nicht ein Freilos ins Finale kommt) Ist eine Partie zu ende wird der Gewinner und Verlierer ermittelt (Aufgabe für das neue Ereignis) und die Spieler werden dann entsprechend in der Tabelle einer neuen Partie zugeordnet ist eine Partie vollständig dann kann diese gespielt werden. usw.
Schön dass du mir deine Hilfe anbietest werde ich auch bestimmt nutzen und gebrauchen können.
Es kann allerdings sein, dass ich mich erst wieder nächsten Dientag melden kann, ich hoffe dass ich bis dahin recht weit bei meinem Komponentenbau gekommen bin.

Bis dann Dieter
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#23

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 29. Mai 2009, 15:35
Joop, wenn du Fragen hast, her damit. Ich bin aber auch erst am Mittwoch wieder da, und da wo ich bis dahin bin, gibs kein INet.

Gruß oki
42
  Mit Zitat antworten Zitat
Optiplex

Registriert seit: 5. Mär 2008
131 Beiträge
 
Delphi 2005 Personal
 
#24

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 2. Jun 2009, 09:08
Hallo oki,
dank deiner Hilfe habe ich die Komponente TDartResultEdit am WE entwickelt. Siehe Anhang ( TDartResultEdit.Jpg ), was noch nicht implementiert ist das OnEdirChance Ereignis. Hier muss ich mir noch genau überlegen wie ich dieses Ereignis mache. Ich habe am WE viel dazugelernt aber es haben sich auch viele Fragen ergeben die du mir vielleicht beantworten kannst

Leider musste ich feststellen, dass der Focus zum Aktiven Control auf meiner Komponente wandert. Kann man das Irgendwie verhindern in dem das Control zwar aktiviert wird aber der Focus bei meiner Komponenete bleibt. Dadurch musste ich, weil ich eine Cursorsteuerung implementiert hatte, diese Auf die OnKeyDown Ereignisse des jeweiligen Controls umleiten dies hatte zur folge das die Cursorsteuerung nicht mehr so richtig funktionierte( Vor alle bei einem TButtom). Mit
Delphi-Quellcode:
Protected
procedure WMGetDLGCode(var msg: TMessage); message WM_GETDLGCODE;
....
Procedure TDartResultEdit.WMGetDLGCode(var msg: TMessage);
begin
  inherited;
  msg.Result:= msg.Result or DLGC_WantArrows;
end;
kann man bei seiner Komponente die CursorTasten abfangen. Wie macht man das bei den SubKomponenten? Dies ist das Aktuelle OnKeyDown Ereignis das wie gesagt an den Subkomponenten hängt(Sorry hatte noch keine Zeit den Code zu bereinigen)
Delphi-Quellcode:
procedure TDartResultEdit.EditKeyDownEvent(Sender: TObject; var Key: Word; Shift: TShiftState);
var iii:integer;
  obj: tObject;
  edi:TEdit;
  btn:TButton;
begin
  obj:=nil;
  If(Key=vk_Down) or (Key=vk_up)then begin
    for iii :=0 to Parent.ComponentCount-1 do
      if Parent.Components[iii].classtype=TDartResultEdit then begin
        if TDartResultEdit(Parent.Components[iii]).enabled and
          TDartResultEdit(Parent.Components[iii]).Visible then
          case Key of
            vk_Down:
              begin
                if (TDartResultEdit(Parent.Components[iii]).Left = Left) and
                  (TDartResultEdit(Parent.Components[iii]).Top > Top)then
                  if obj=nil then obj:= Parent.Components[iii]
                else
                  if (TDartResultEdit(Parent.Components[iii]).Top < TDartResultEdit(obj).Top)
                    then obj:=Parent.Components[iii];
              end;
            vk_up:
              begin
                if (TDartResultEdit(Parent.Components[iii]).Left = Left) and
                  (TDartResultEdit(Parent.Components[iii]).Top < Top)then
                  if obj=nil then obj:= Parent.Components[iii]
                else
                  if (TDartResultEdit(Parent.Components[iii]).Top > TDartResultEdit(obj).Top)
                    then obj:=Parent.Components[iii];
              end;

          end;
      end;
      if obj<>nil then
        if TDartResultEdit(obj).Enabled and TDartResultEdit(obj).Visible then TDartResultEdit(obj).Setfocus;
  end;
  if Key=vk_Right then begin
    if Sender.ClassType =TEdit then begin
      edi:=TEdit(Sender);
      if edi.Name = FPlayerEdit1.Name then FPlayerEdit2.SetFocus;
// if edi.Name = FPlayerEdit2.Name then FBoardButton.SetFocus;
    end;
// if Sender.ClassType =TButton then FPlayerEdit1.SetFocus;
  end;
// btn:=TButton(Sender);
// if edi.Name = FPlayerEdit1.Name then FPlayerEdit2.SetFocus;
// if edi.Name = FPlayerEdit2.Name then FBoardButton.SetFocus;
// end;
  if Key=vk_Left then begin
    if Sender.ClassType =TEdit then begin
      edi:=TEdit(Sender);
      if edi.Name = FPlayerEdit2.Name then FPlayerEdit1.SetFocus;
// if edi.Name = FPlayerEdit1.Name then FBoardButton.SetFocus;
    end else FPlayerEdit2.SetFocus;
// if Sender.ClassType =TButton then FPlayerEdit2.SetFocus;
  end;
// if Key=VK_Space then Click;
  inherited;
end;
Funktioniert mit den TEdits . Ich wollte noch einen Button (Auswahl Spielort) rechts am Ende der Komponenete integrieren,(was mit deiner Beschreibung kein Problem war, auch ein eigenes Ereignis war schnell integiert),doch leider bringt dieser Button meine Cursorsteuerung durcheinandert, bei hoch und runter springt er nicht zur nächsten Komponente innerhalb der TDartResultEdit Klasse(was bei den Edits einwandfrei funktioniert) sondern auf das erste bzw. zweite Editfeld innerhalb der Subkomponenten. (Warum?).

Kann man den Text ein einem Editfeld zentrieren?

So und nun noch mal zu OnEditChance.
Die Eingabe der Edits habe ich auf Zahlen beschränkt(funktioniert). Ich muss in diesem Ereignis
1.Die Gültigkeit des eingegebenen Ergebnisses auswerten (best of)
2 Ist das Spiel durch dieses Ergebnis beendet oder läuft es noch weiter
3.Ist es ein Endergebnis (best of) dann Verlierer und Gewinner auswerten und diese in die nächste Runde springen bzw. ausscheiden lassen.

Dazu brauche ich alle TEdit.Texte und natürlich den Sender da das im meinem Programm eigentlich nur eine Routine werden soll. Was meinst du wie ich das hier am besten löse?
Du hast mir ja schon zwei eventuelle Lösungen genannt welche soll ich bevorzugen?

Da du für das Projekt Intresse hast, habe ich dir ein PrintScreen von einem Spielplan (Ist aber auch noch nicht 100% fertig) so wie er Später im LCD-Fernseher oder Leinwand zu sehen sein wird angehängt. Über die Komponente TDartResultEdit werden die Ergebnisse und die daraus folgenden Partien in diesen Spielplan eingetragen.

Sind genug Fragen auf einmal (hoffe ich werde dir nicht lästig).

Gruß Dieter

Natürlich kann sich jeder hier beteiligen der eine Lösung für meine Fragen kennt
Miniaturansicht angehängter Grafiken
spielplan_16spielerdoppelko_jpg_162.jpg   tdartresultedit_194.jpg  
  Mit Zitat antworten Zitat
Optiplex

Registriert seit: 5. Mär 2008
131 Beiträge
 
Delphi 2005 Personal
 
#25

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 4. Jun 2009, 12:38
Huch hab ich euch jetzt erschreckt?

Dieter
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#26

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 4. Jun 2009, 15:19
Hallo,

ja, eine ganze Menge Fragen, erschreckt aber nicht. Bin seit heute erst wieder zurück.
Ich denke, wir machen eins nach dem anderen. Das ganze Thema mit dem Fokus habe ich noch nicht so richtig geschnallt. Ich würd lieber mit den Ereignissen anfangen.
Du hast ja eine recht eindeutige Nummerierung deiner Spiele. Ich denke mal, dass du im Programmablauf auf die Eigaben bezüglich der Auswertung usw. reagieren willst. Wobei ich denke, dass das auch in der Kompo klappen sollte.
Ich würde der Kompo erst ein mal eine Property PlayerCount verpassen. Da gibt man dann die Anzahl der Spieler ein. Daraus wird dann auch automatisch das Schema in deiner Abbildung Spielplan_16 erstellt. Die Anzahl der TDartResultEdits ergibt sich ja automatisch. Jedes Edit sollte als Name den Text erhalten, den du über die Spielerpaare geschrieben hast mit dem suffix 1 oder 2 erhalten.
Bsp.:
Delphi-Quellcode:
  For PlayRount := 1 to PlayerCount div 2 do begin
    For Player := 1 to 2 do begin
      with TDartResultEdit.create(nil) do begin
        Name := Format('R1_%d_%d', [PlayRound, Player]);
        OnChange := self.OnDartResultEditChange;
        ...
Das ist nur ein erster Ansatz. Die Logik, wieviel Spiele wie zusammengestellt werden kennst du selbst am besten.
Jetzt nimmst du dein Ereignis On Change und wertest die Einträge aus. Somit kannst du gleich alle folgenden Felder mit den Spielernamen füllen.
Delphi-Quellcode:
procedure MyCustomControl.OnDartResultEditChange(Sender : TObject);
var SenderName : String;
    RoundChar : Char;
    PLayRound, Player : Integer;
begin
  // hier macht es Sinn, den Namen des sendenden Edit zu zerlegen.
  if not Sender is TDartResultEdit then
    Exit;
  SenderName := TComponent.Name;
  // jetzt zerlegen und auf die einzelnen Segmente prüfen
  case ORD(RoundChar) of // das ist z.B. das R
    ORD('R') : begin
      case PlayRound of // das ist das Spiel der Runde
        1 : begin
            .... // usw.
        end;
      end;
    end;
    ...
  end;
end;
Ich denke, dass es Sinn macht, die einzelnen Cases in Funktionen auszulagern. Desgleichen würde ich für die einzelnen Spieler eine eigene Klasse TPlayer = class TObject anlegen. Die dann alle in einer ObjectList halten. So wird die Verwaltung einfacher. An das Programm würde ich eigentlich nichts hoch senden. Die Einträge in die weiteren Felder kann eigentlich deine Komponente machen. Über das Programm steuerst du eigentlich nur den Input wie Anzahl Spieler, Spielername, zufällige oder feste Paarbildung usw.

Ich glaube, ich hab hier versehentlich TDartResultEdit als Eingabefeldt (Edit) des Spielstandes gesetzt. Wenn das falsch ist, sag bescheid.

Jo, sag mal, wie dier das gefällt. Dann können wir ja konkret weiter machen.

Gruß oki
42
  Mit Zitat antworten Zitat
Optiplex

Registriert seit: 5. Mär 2008
131 Beiträge
 
Delphi 2005 Personal
 
#27

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 4. Jun 2009, 16:07
Hallo Oki,

wie ich sehe hast du dir den Spielplan genau angesehen, nun noch ein paar Erklärungen dazu. also R1-1 bis R1-8 bedeutet Runde 1 Spiel 1-8 da dies ein Doppel OK System ist gibt es eine Gewinnerseite G und eine Verliererseite V daraus ergibt sich die Gewinnerrunde1 Spiel 1-4 und eine Verlierer Runde 1 Spiel1-4 usw. Verliert ein Spieler ein zweites mal scheidet er aus, verliert ein Spieler in der Gewinnerrunde kommt er in die Verliererrunde und zwar an die Sprungpunkte A-G je nachdem wie weit er in der Gewinnerrunde gekommen ist.
ich wollte bei unserer Komponente noch zweit Eigenschaften hinzufügen und zwar einmal Gewinner und Verlierer als String und hier sollten die Runde eingetragen werden bei der es weitergeht( zB G1-2/2 oder V1-2/1) die /1 bzw. /2 bedeutet, Spieler1 bzw. Spieler2 in unser Komponte. Hinterlegt wird in der entsprechenden Runde G1-2 usw. Damit könnte ich den kompletten Ablauf des Turniers mit der Ergebnistabelle steuern.

(Natürlich könnte man auch einen Array erstellen, aber darüber habe ich noch nicht nachgedacht wie der Aussehen müsste.)

So hatte ich mir das ungefähr Theoretisch vorgestellt.

Allzu weit weg sind deine Gedanken über den Ablauf ja nicht von den meinen und ich werde mir heute Abend darüber nachdenken ob deine Idee nicht besser ist, mit der Auswertung innerhalb der Komponente, wobei die Auswertung recht komplex ist.

bis dann Dieter
  Mit Zitat antworten Zitat
Optiplex

Registriert seit: 5. Mär 2008
131 Beiträge
 
Delphi 2005 Personal
 
#28

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 5. Jun 2009, 09:10
Hallo Oki,
also gegen eine Auswertung in der Komponente ist nichts einzuwenden, allerdings bräuchten wir hier noch ein Property BestOf damit die Eingabe ausgewertet werden kann (best of 3,5,7,9,11), dann muss noch ein Property Gewinner/Verlierer(Startnummer/Name des Spielers) dazu damit diese an die nächste Runde weitergegeben werden kann. Wie du sicherlich gemerkt hast ist jede Runde mit einer weiteren Runde Verlierer/Gewinner fest verknüpft und diese Verknüpfung wollte ich fest in die Komponente den Propertys Verlierrunde/Gewinnerrunde(siehe gestern) mit angeben. Diese beiden Propertys sind eigentlich nur Dummys und werden von unserer Komponente nicht beeinflust. So habe ich alle wichtigen Infos an die Komponente gelegt. Die weiteren Eintragungen in der Ergebnistabelle und im Spielplan würde ich dem eigentlichen Programm überlassen.(man braucht nur die Captions zu vergleichen und die Propertys auszutauschen) Die Anzahl der Spieler ist immer gleich bei einem Doppel OK System (entweder 8,16,32,64,128) fehlende Spieler werden durch Freilose deren Position in Runde 1 fest vorgegeben sind (damit nicht ein Freilos in die Ränge kommen kann ).Der benötigte Spielplan wird dann über die angemeldeten Spieler ausgewählt.

Ich werde dir am WE einmal zusammenschreiben wie so ein Turnier abläuft und auf was zu achten ist damit du auch die Infos alle hast.(Hoffentlich vertreibe ich dich damit nicht, weil so ein Event doch ziehmlich Komplex ist).
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#29

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 5. Jun 2009, 09:45
Hallo,
ich sehe das mit der Auswertung nicht so problematisch. Sobald ein Ergebnis in eingegeben wird ist ja klar, wer gewonnen hat. Somit ist auch gleich eindeutig, in welchem Feld (G, V usw.) der entsprechende Spieler eingetragen wird. Auch die Numerik für das entsprechende Spiel ist logisch nachvollziehbar, unabhängig von der Anzahl der Spieller und Runden. So gehen z.B. die Gewinner der Runde R1-1 und R1-2 in die Runde G1-1, aus R1-3 und R1-4 in G1-2 usw. Das ist imho wieder eine 2 zu 1 Beziehung in einer weiteren Ebene. Diese Gewinner gehen in G2-1 auf(Gewinner aus G1-1 und G1-2 nach G2-1). Wieder eine 2 zu 1 Beziehung. Der Vorteil ist sogar, dass somit ein relativ einfaches mathematisches Prinzip abgebildet werden kann. Und das gilt dann eigentlich sehr universell. Aus zwei mach eins eine Ebenen höher. Rieht ganz deutlich nach einer universellen Funktion mit einem simplen Vergleich und Inkrementieren der Spielebene.

Wenn man das im Griff hat, kann man die Ermittlung des neuen Eintragfeldes für einen Spieler recht universell über eine Funktion ermitteln, bei der man die Aktuelle Runde, beide Spielpartner und den Spielstand übergiblt. Zurück bekommt man die Bezeichner der Felder, in die die Spieler neu einzutragen sind.

Für die Übersicht des aktuellen Standes würde ich über die Spieler und die Spielerliste gehen. Dazu würde ich noch eine zusätzliche Liste der Spiele anlegen. Das in etwa so:
Delphi-Quellcode:
  TPlayResult : TPoint; // TPoint zweckentfremden für Spielstand oder gleich eigener Typ
  // Vorward-Declaration
  TPlayerClass : class;

  TPlayClass = class(TObject)
  private
    FPlayResult : TPlayResult;
    FPlayer1: TPlayerClass;
    FPlayer2: TPlayerClass;
    FRound : String;
  ....
  end;
  
  // Liste der durchgeführten Spiele jedes Spielers
  TPlayList = class(TObjectList)
  ...
  end;

  TPlayerClass = class(TObject);
  private
    FParentList : TPlayList;
    FPlayerName : String;
    ....
    FPlayList : TPlayList;
    FPosition : Integer; // aktueller Platz des Spielers im Turnier
    ...
  end;

  // Liste aller Spieler
  TPlayerList = class(TObjectList)
  private
    FParentControl : TMyControl;
  ....
  end;
Jetzt hast du folgende Möglichkeiten. Deine neues Control hat die Eigenschaften PlayerList. Wird PlayerList verändert, so kann dein Control aus dem Member Count der PlayerList den Spielaufbau generieren. Alle weiteren Eigenschaften wie zufällige Spielpaarzusammenstellung usw. lassen wir mal außer acht. Das ist Finetuning und berührt die generelle Funktion der Komponente nicht.
Über das Programm kannst du die Bearbeitung der PlayerListe incl. des einzelnen Players steuern. Ähnlich, als ob du mit einer Datenbank arbeitest. Durch die Zuweisung, Änderung reagiert deine Komponente. Willst du das automatisieren, so erhält deine PlayerList noch einen Member ParentControl. Der kann dann vom Typ deiner Komponente sein. Ist dieser Member ungleich nil, so informiert die PlayerListe automatisch das ParentControl über Änderungen, damit diese sich in der Ansicht aktualisieren kann. Das gleiche kannst du natürlich auch mit der PlayerClass machen. Der Witz währe folgender.
Mitten im Spiel bemerkt ein Spieler, dass seine Name Falsch eingetragen ist. Du änderst über die Eingabemaske den Namen in seinem zugehörigen Klassenobjekt TPlayerClass. Der Setter für den Namen ruft eine eigene Methode ChangePlayer der PlayerList auf, die ja als Member in TParentList abgelegt ist. Diese wiederum ruft die eigene Methode Change der ParentComponent auf. Die Parent Component zeichnet sich damit neu. Dabei macht es dann Sinn, wenn die Edits zusätzlich einen Member der Player haben, denen das entprechende Player-Object zugewiesen wurde. Du trägst also nicht den Namen des Spielers ein, sondern weist einen zu. Der Name wird beim zeichnen also aus der Eigenschaft PlayerName des PlayerObjectes eingetragen. Durch die Methode Change wird ja die Componente neu gezeichnet. Der Name in PlayerName des Edits hat sich in der Zwischenzeit geändert und somit neu gezeichnet.
Alles automatisch, keiner rekursiven Funktionen nötig, ändern an der Stelle wo man ändern muss, neu zeichnen und alles fertig und up to date. Großer Zauber Manitu.

Hast du in den Edits die neuen Spielstände eingetragen, so wird über die EditChange-Methode die oben beschriebene Auswertefunktion angestoßen. Ein Object der TPlayClass wird erstellt, dem Player zugewiesen, den neuen Eintragsfeldern (Edits) das richtige Playerobject zugewiesen, refresh (Change deiner Komponente) fertig.

Aktuelle Listen für Spielstand, Platz jedes Spielers usw. implementierst du als Funktionen deiner PlayerList, die du über das Hauptprogramm aufrufst und das entsprechende Ergebnis von der Funktion zurück bekommst.

Im Prinzip passiert hier folgendes. Du hast:
- Datenklassen wie TPlayClass, TPlayList (Spiel, Spielliste), TPlayerClass, TPlayerList (Spieler, Spielerliste).
- Visualisierungsklassen -> deine Komponente
- Ein-/Ausgabeklassen; deine Komponente für Spielstände, Eingabemaske für die Spieler
- GUI; Hauptprogramm, auf dem die visuellen Komponenten platziert sowie die Menüs und Buttons für die Spielsteuerung und Einstellungen platziert sind.

Joo, so würde ich es in etwa machen. Das Thema mit den PlayClass ist mir noch nicht ganz sauber. Finde im Moment aber keinen Ansatz das zu vereinfachen oder zu zentralisieren. Ich habe den Eindruck, man muss das über die PlayList aufziehen und denen die Player zuweisen und nicht umgekehrt. Kann man ja noch drüber nachdenken. Aber ich glaube so ist es richtig.

Gruß oki
42
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#30

Re: Neue Komponente mit 2 TEdit Komponenten

  Alt 5. Jun 2009, 09:50
Hatte wohl etwas lange an dem letzten Beitrag geschrieben.

Hallo optiplex
sorry für die Monologe. Ich empfehle folgendes. Wir erstellen erst die Datenmodelle. Dann die visuellen Komponenten. Das mit den Funktionen und Eigenschaften ist dann ganz einfach. Die können sucsessive erweitert werden. Wenn die Struktur und die Klassen stimmen ist das andere alles ein Klacks. Vertrau mir, ich wies was ich tu ( kennst du den Spruch? stammt aus einer alten Serie)

gruß oki
42
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 5     123 45      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz