Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Dynamischer Verweis auf Komponente (https://www.delphipraxis.net/197899-dynamischer-verweis-auf-komponente.html)

Moombas 17. Sep 2018 09:37

Delphi-Version: 10.2 Tokyo

Dynamischer Verweis auf Komponente
 
Moin zusammen,

dies ist ggf. eine blöde Frage aber ich komme da einfach nicht weiter:

Wie kann ich Dynamisch auf eine Komponente zugreifen?
Beispiel: Ich habe Buttons, deren Namen auf einer Logik basieren (einfachstes Beispiel hierfür wäre: "Name1", "Name2",...) bzw. auch deren Funktion.
Nun möchte ich nicht für jeden Button einzeln eine Funktion schreiben, sondern würde dies gerne ableiten.
Beispiel2:

Button1:
ShellExecute(Handle, 'open', PChar(Tool1E.text), PChar(Tool1P.Text), nil, SW_SHOW);
Button2:
ShellExecute(Handle, 'open', PChar(Tool2E.text), PChar(Tool2P.Text), nil, SW_SHOW);

besser wäre die "1" (bzw. die "2") aus dem Button-Namen zu ziehen (kein Problem) und dadurch den dyn. Verweis (PChar(Tool1E.text)) zu generieren (keine Ahnung wie).

Kann mir hierbei jemand weiter helfen, ich finde nur dynamische Erzeugung von Buttons etc. aber kein dynamischer Verweis.

TiGü 17. Sep 2018 09:39

AW: Dynamischer Verweis auf Komponente
 
Dein Programm oder ein fremdes Programm?

Wenn Fall eins: "findcomponent delphi" sollte in der Suchmaschine deiner Wahl weiterhelfen.

Schokohase 17. Sep 2018 09:48

AW: Dynamischer Verweis auf Komponente
 
Und ein Frame würde da nicht gehen?

Dort hättest du einen Button und zwei TextBoxen und der code im ButtonClick sähe dann so aus
Delphi-Quellcode:
ShellExecute(Handle, 'open', PChar(Tool1E.text), PChar(Tool1P.Text), nil, SW_SHOW);
In der Form erzeugst du nun einfach x-mal den Frame und bist fertig.

Uwe Raabe 17. Sep 2018 10:04

AW: Dynamischer Verweis auf Komponente
 
Vielleicht suchst du ja die Methode Delphi-Referenz durchsuchenFindComponent?
Delphi-Quellcode:
procedure TForm325.Button1Click(Sender: TObject);
var
  btn: TButton;
  edtE: TEdit;
  edtP: TEdit;
  idx: Integer;
begin
  btn := Sender as TButton;
  idx := ExtractButtonNumber(btn.Name);
  edtE := FindComponent(Format('Tool%dE', [idx])) as TEdit;
  edtP := FindComponent(Format('Tool%dP', [idx])) as TEdit;
  ShellExecute(Handle, 'open', PChar(edtE.text), PChar(edtP.Text), nil, SW_SHOW);
end;

Moombas 17. Sep 2018 10:06

AW: Dynamischer Verweis auf Komponente
 
@TiGü: Es sind Komponenten innerhalb meines Programms, jedoch in einer TPageControl. Wenn ich nun also deinem Tipp nachgehe bekomme ich folgendes als "Lösungsansatz":

TEdit(FindComponent('Tool' + copy(Name, 5, 1) + 'E')).Text

Leider ist, wenn ich mir das mal als Showmessage zur Kontrolle ausgeben lasse, immer leer. Der Name wird jedoch korrekt zusammengesetzt.
Delphi-Quellcode:
procedure TTools.Tool1BClick(Sender: TObject);
begin
  with sender as TButton do
  begin
    showmessage(TEdit(FindComponent('Tool' + copy(Name, 5, 1) + 'E')).Text); //nur zum Testen das Showmessage, hier kommt später die Shellexecute rein
  end;
  // ShellExecute(Handle, 'open', PChar(Tool1E.text), PChar(Tool1P.Text), nil, SW_SHOW);
end;
@Schokohase: Ich verstehe aktuell nicht wie du es meinst, da dein Beispiel wie eine 1:1 Kopie meines geposteten Textes aussieht. Es sind insgesamt 15 Buttons, die wiederum auf jeweils 2*15 Edit-Felder zugreifen für das Shellexecute.

@Uwe Raabe: Die Funktion habe ich auf TiGü's Hinweis hin gefunden, scheint aber irgendwie nicht 100%ig zu funktionieren (s.o.). Und die Funktion "ExtractButtonNumber" ist mir und Delphi nicht bekannt.

Uwe Raabe 17. Sep 2018 10:19

AW: Dynamischer Verweis auf Komponente
 
Zitat:

Zitat von Moombas (Beitrag 1413342)
Die Funktion habe ich auf TiGü's Hinweis hin gefunden, scheint aber irgendwie nicht 100%ig zu funktionieren (s.o.). Und die Funktion "ExtractButtonNumber" ist mir und Delphi nicht bekannt.

Die Funktion ExtractButtonNumber ist nur ein Platzhalter auf Grund deiner Angabe
Zitat:

Zitat von Moombas (Beitrag 1413336)
besser wäre die "1" (bzw. die "2") aus dem Button-Namen zu ziehen (kein Problem)

aus der ich schließen kann, daß du das irgendwie hinbekommst.

Wenn FindComponent nicht funktioniert, wäre das jetzt der richtige Zeitpunkt für ein kleines Testprojekt, bei dem das nicht funktioniert.

Schokohase 17. Sep 2018 10:24

AW: Dynamischer Verweis auf Komponente
 
Nun ja, einfach so:
Delphi-Quellcode:
unit uStartFrame;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TFrame1 = class(TFrame)
    Edit1: TEdit;
    Edit2: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

implementation

uses
  Winapi.ShellAPI;

{$R *.dfm}

procedure TFrame1.Button1Click(Sender: TObject);
begin
  ShellExecute( Handle, 'open', PChar(Edit1.Text), PChar(Edit2.Text), nil, SW_SHOW );
end;

end.
und in der Form dann
Delphi-Quellcode:
unit uMainForm;

interface

uses
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants, System.Classes,
 
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  uStartFrame;

type
  TForm1 = class( TForm )
    Frame11: TFrame1;
    Frame12: TFrame1;
    Frame13: TFrame1;
    Frame14: TFrame1;
    Frame15: TFrame1;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

end.

Moombas 17. Sep 2018 10:32

AW: Dynamischer Verweis auf Komponente
 
@Uwe Raabe:

Achso XD Das mit der Button Nummer bekomme ich so hin:
Delphi-Quellcode:
procedure TTools.Tool1BClick(Sender: TObject);
begin
  with sender as TButton do
  begin
    try
      StrToInt(copy(Name, 6, 1));
      showmessage('Tool' + copy(Name, 5, 2) + 'E'); //zur Prüfung des korrekt generierten Namens - passt
      showmessage(TEdit(FindComponent('Tool' + copy(Name, 5, 2) + 'E')).Text); //zur Prüfung des korrekten übergebenen Inhalts - leer!?
    except
      showmessage('Tool' + copy(Name, 5, 1) + 'E'); //zur Prüfung des korrekt generierten Namens - passt
      showmessage(TEdit(FindComponent('Tool' + copy(Name, 5, 1) + 'E')).Text); //zur Prüfung des korrekten übergebenen Inhalts - leer!?
    end;
  end;
//  ShellExecute(Handle, 'open', PChar(Tool1E.text), PChar(Tool1P.Text), nil, SW_SHOW);
end;
Die Showmessage werden dann natürlich durch shellexecute abgelöst, wenn hier der richtige Wert raus kommt.
Das mit dem "nicht funktionierendem Beispiel" muss ich schauen, da mein Programm mittlerweile 4170 Zeilen hat, wo auch Daten drin sind, die nicht für die Öffentlichkeit bestimmt sind müsste ich dafür ein Beispiel bauen.

Ich habe dies aber auch mal mit einem Edit-Feld getestet, welches nicht in einer TPageControl eingebettet ist und auch dort funktioniert es leider nicht.
Er scheint die Komponente nicht zu finden.

@Schokohase: Die Editfelder befinden sich nicht im gleichen Menüpunkt meiner TPageControl wie die Buttons und zudem würde ich auch dort wieder mehrere Funktionen schreiben anstatt einer (dynamischen) Funktion.

DeddyH 17. Sep 2018 10:39

AW: Dynamischer Verweis auf Komponente
 
Wenn TTools kein Formular ist, sondern irgendein Client-Control davon, wäre vielleicht FindControl statt FindComponent der bessere Ansatz. FindComponent sucht nach Komponenten, deren Owner die aufrufende Klasse ist, FindControl nach Controls, deren Parent sie ist. Bei zur Designtime hinzugefügten Komponenten ist der Owner normalerweise das Formular, vermutlich geht es deshalb nicht.

Schokohase 17. Sep 2018 10:56

AW: Dynamischer Verweis auf Komponente
 
Also würdest du so etwas brauchen
Delphi-Quellcode:
unit uStartFrame;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TFrame1 = class(TFrame)
    Edit1: TEdit;
    Edit2: TEdit;
  private
    { Private-Deklarationen }
  public
    procedure Execute();
  end;

implementation

uses
  Winapi.ShellAPI;

{$R *.dfm}

procedure TFrame1.Execute;
begin
  ShellExecute( Handle, 'open', PChar(Edit1.Text), PChar(Edit2.Text), nil, SW_SHOW );
end;

end.
Und für den Button
Delphi-Quellcode:
procedure TFormX.Button1_Click(Sender:TObject);
begin
  Frame1.Execute;
end;

Moombas 17. Sep 2018 11:18

AW: Dynamischer Verweis auf Komponente
 
@Schokohase: Nicht wirklich. Sorry aber ich glaube du hast das nicht so ganz verstanden.
Aufbau:
Edits:
Pagecontrol1 (Menu) -> PageX (Einstellungen) -> Pagecontrol2 (EinstellungenPC) -> PageY (ToolsE) -> EditE1-15 (Programmpfade) & EditP1-15 (Parameter)
Tool1E.text...Tool15E.text
Tool1P.text...Tool15P.text

Buttons:
Pagecontrol1 (Menu) -> PageZ (Programme) - >GroupBox (Toolbar) -> Button1-15 (Aufruf)
Tool1B...Tool15B

Und an dem Aufbau wird sich nichts ändern.

@DeddyH: Doch TTools ist die Form (Formname: Tools). Probiert habe ich es auch schon mit:
showmessage(TEdit(FindComponent('Application.TTool s.Tool' + copy(Name, 5, 1) + 'E')).Text);
showmessage(TEdit(FindComponent('Application.Tools .Tool' + copy(Name, 5, 1) + 'E')).Text);
showmessage(TEdit(FindComponent('TTools.Tool' + copy(Name, 5, 1) + 'E')).Text);
showmessage(TEdit(FindComponent('Tools.Tool' + copy(Name, 5, 1) + 'E')).Text);

leider kein Erfolg, er scheint das EditFeld absolut nicht zu finden. Da muss irgendwo ein Denkfehler sein.

Schokohase 17. Sep 2018 11:45

AW: Dynamischer Verweis auf Komponente
 
Nun sagen wir mal so, du hast es gar nicht erklärt. Und Nichts kann man eben nicht nicht verstehen.

Aber aus deinen Erklärungen sehe ich das es auf der PageY (ToolsE) 15 Paare von Edit-Feldern gibt (eines für den Programmpfad, das andere für die Parameter).

Diese beiden könnte man in einem Frame zusammenfassen und dem Frame eine Execute-Methode verpassen (so wie von mir gezeigt).

Aber ist schon recht ... bei dem Aufbau würde ich da auch ganz anders drangehen (kein Zugriff vom Button auf die ToolXE/ToolXP-Cotrols)

Uwe Raabe 17. Sep 2018 11:50

AW: Dynamischer Verweis auf Komponente
 
Zitat:

Zitat von Moombas (Beitrag 1413352)
er scheint das EditFeld absolut nicht zu finden. Da muss irgendwo ein Denkfehler sein.

Wenn die PAS-Datei zu geheim ist, genügt es auch nur die DFM-Datei hier zu posten. Daran könnte man den Aufbau des Forms schon erkennen.

Moombas 17. Sep 2018 11:59

AW: Dynamischer Verweis auf Komponente
 
Liste der Anhänge anzeigen (Anzahl: 1)
Das sollte kein Problem darstellen^^ s.u.

Moombas 17. Sep 2018 12:20

AW: Dynamischer Verweis auf Komponente
 
Hab aber in einem anderen Beitrag (über Google über Umwege) eine Lösung gefunden:

TEdit(Tools.FindComponent('Tool' + copy(Name, 5, 1) + 'E')).Text

-.-

Schokohase 17. Sep 2018 12:28

AW: Dynamischer Verweis auf Komponente
 
Zitat:

Zitat von Moombas (Beitrag 1413364)
Hab aber in einem anderen Beitrag (über Google über Umwege) eine Lösung gefunden:

Delphi-Quellcode:
TEdit(Tools.FindComponent('Tool' + copy(Name, 5, 1) + 'E')).Text
-.-

Die funktioniert ja super für die Button von 1-9. Aber was ist mit 10,11,12,13,14,15?
Es gibt keine Exception, aber einen falschen Zugriff auf Tool1E!

Uwe Raabe 17. Sep 2018 12:50

AW: Dynamischer Verweis auf Komponente
 
Zitat:

Zitat von Moombas (Beitrag 1413364)
Hab aber in einem anderen Beitrag (über Google über Umwege) eine Lösung gefunden:

TEdit(Tools.FindComponent('Tool' + copy(Name, 5, 1) + 'E')).Text

Wenn das Voranstellen des Formnamens (was in der Regel eher nicht gut ist) das Problem löst, dann kann das eigentlich nur bedeuten, daß der Button-Click Event nicht innerhalb der TTools-Klasse liegt. Das wäre allerdings eine nicht ganz unwichtige Information.

Moombas 17. Sep 2018 14:47

AW: Dynamischer Verweis auf Komponente
 
@Schokohase: Doch:
Delphi-Quellcode:
    try
      StrToInt(copy(Name, 6, 1));
//1-Stellig (0-9)
    except
//2-Stellig (10-99)
    end;

DeddyH 17. Sep 2018 14:52

AW: Dynamischer Verweis auf Komponente
 
Wieso sollte der Code eine Exception werfen, wenn im 6. Zeichen eine Ziffer steht?

himitsu 17. Sep 2018 14:55

AW: Dynamischer Verweis auf Komponente
 
Zitat:

Delphi-Quellcode:
showmessage(TEdit(FindComponent('Application.TTools.Tool' + copy(Name, 5, 1) + 'E')).Text);

Ich glaube du hast das FindComponent falsch verstanden.

Es ist keine globale Funktion, sondern die Methode von TComponent-Nachfahren.
In deinem Fall also
Delphi-Quellcode:
Self.FindComponent
, welches somit aus deiner TForm kommt (über die Klasse, in welcher die aufrufende Methode liegt)

Und das Ding sucht nur nach Sub-Komponenten in der angegebenen Komponente, also nach allem, von dem deine Form der Owner ist.
Komponenten-Pfade werden dabei nie aufgelöst ... nur das was "direkt" ein Child ist.


Das Selbe gilt für FindControl, was entsprechend die Parent-Beziehungen behandelt.


In der globalen Variabe Screen findet man alle Forms, welche man durchgehen und da drauf suchen könnte.

Moombas 19. Sep 2018 10:51

AW: Dynamischer Verweis auf Komponente
 
Zitat:

Zitat von DeddyH (Beitrag 1413386)
Wieso sollte der Code eine Exception werfen, wenn im 6. Zeichen eine Ziffer steht?

Er wirft eine Exception wenn dort KEINE Ziffer steht.

DeddyH 19. Sep 2018 10:59

AW: Dynamischer Verweis auf Komponente
 
Zitat:

Delphi-Quellcode:
    try
      StrToInt(copy(Name, 6, 1));
//1-Stellig (0-9)
    except
//2-Stellig (10-99)
    end;

Ach, und in dem Fall sind es dann 2 Ziffern? Ich verstehe Dein Exception-Handling nicht.

Moombas 19. Sep 2018 11:50

AW: Dynamischer Verweis auf Komponente
 
Ja genau. Aber es ist doch einfach zu verstehen. Die Namen bauen sich (logischerweise) so auf:

ButtonXABC
...
ButtonXXABC

Nun schaue ich (nach obigem Beispiel) ob an 8. Stelle eine Zahl ist. Wenn ja, dann ist an der 7. Stelle auch eine Zahl und somit sind wir im Bereich 10-99. Andernfalls sind wir im Bereich 0-9.
Oder Andres gesagt: Versucht er bei "ButtonXABC" sonst das "A" in eine Zahl zu wandeln, was nicht geht -> exception -> anderes Handling.
Delphi-Quellcode:
    try
      StrToInt(copy(Name, 8, 1));
//1-Stellig (0-9)
    except
//2-Stellig (10-99)
    end;
Alternativ hätte man auch generell 2-Stellig arbeiten können:
Button0XABC
...
ButtonXXABC
Dann bräuchte man nur prüfen ob an 7. Stelle eine "0" vorhanden ist und dementsprechend ableiten, also:
Delphi-Quellcode:
if Name[7] = '0' then
//1-Stellig (0-9)
    else
//2-Stellig (10-99)

noisy_master 21. Sep 2018 08:35

AW: Dynamischer Verweis auf Komponente
 
Also ehrlich gesagt finde ich das alles sehr aufwändig. ich würde - wenn es wirklich nur um Nummern geht - einfach das .Tag verwenden:

beim erstellen des Buttons das Tag mit der entsprechenden Nummer versehen, alle Buttons auf das gleiche onClick und dann 'tool'+inttostr((sender as Tbutton).tag)+'......'

Moombas 21. Sep 2018 09:33

AW: Dynamischer Verweis auf Komponente
 
@noisy_master: Es gibt viele Wege nach Rom ;)

Aber ich denke (nur persönliche Meinung), das in der Summe es wesentlich länger dauert, bei jedem Button manuell den "Tag" anzupassen als einmal dies (über den sowieso schon manuell gesetzten Namen) per Exception abzufangen.
Auch die Fehlerquelle ist höher, denn: Buttons mit gleichem "Tag" sind möglich ("Tag"-Änderung beim manuellen Erstellen des Buttons vergessen), mit gleichen Namen jedoch nicht (-> Fehlermeldung)!

Anders wäre dies evtl. bei generierten Buttons im Programm, da hier das Setzen des "Tag" mal "nebenbei" mit gemacht werden kann und dies mit einer dafür angelegten Variable durchgezählt werden kann.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:37 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