Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Form Namen Variable verwenden (https://www.delphipraxis.net/169927-form-namen-variable-verwenden.html)

Andidreas 21. Aug 2012 15:21

Form Namen Variable verwenden
 
Hallo zusammen,

über den folgenden Source erhalte die Komponenten Anzahl die sich in einer Form befinden:

Delphi-Quellcode:
Form1.ComponentCount;


Ich versuche nun in meinem Programm in einer Prozedur an den Component Count einer anderen Form ranzukommen, wobei ich mir den Namen der Form als String Variable übergeb.
Wie Funktioniert sowas? Oder ist mein Ansatz Falsch das ich den Namen der Form als String übergebe?

DeddyH 21. Aug 2012 15:24

AW: Form Namen Variable verwenden
 
Wieso als String und nicht als Instanz?

mkinzler 21. Aug 2012 15:26

AW: Form Namen Variable verwenden
 
Da müsste mit
Delphi-Quellcode:
Application.FindComponent(<Name der Form>).ComponentCount;
gehen

DeddyH 21. Aug 2012 15:28

AW: Form Namen Variable verwenden
 
Aber doch nur dann, wenn Application auch der Owner der gesuchten Form ist, oder?

mkinzler 21. Aug 2012 15:33

AW: Form Namen Variable verwenden
 
Ja. Sollte normalerweise ja so sein.

DeddyH 21. Aug 2012 15:35

AW: Form Namen Variable verwenden
 
Bei dynamisch erzeugten Formularen nicht unbedingt. Allerdings ist ja meine Frage von oben immer noch offen, aus welchem Grund das ein String ist und nicht eine Instanz oder auch eine TFormClass-Variable.

Medium 21. Aug 2012 15:37

AW: Form Namen Variable verwenden
 
Dennoch wäre es mehr als ratsam das Formular als Referenz zu übergeben, wenn diese für den Aufrufer ohenhin vorliegt.

Edit: Deddy is heut flott :)

DeddyH 21. Aug 2012 15:38

AW: Form Namen Variable verwenden
 
Zitat:

Zitat von Medium (Beitrag 1179077)
Edit: Deddy is heut flott :)

Ich muss mich heute irgendwie wach halten :lol:

Andidreas 21. Aug 2012 16:09

AW: Form Namen Variable verwenden
 
Damit man mein Vorhaben ein bißchen besser versteht noch ein paar zusätzliche Infos...
In meinem Programm gibt es mehrere Forms... In jeder Form gibt es mehrere Komponenten wie z.B. Labels etc.
Die Anforderung ist nun das der Benutzer eine csv Datei erstellen kann in der er je nach Land die Captions von Labels & Co. übersetzen kann.

Damit ich nun im OnCreate Ereignis jeder Form die csv Datei auslesen muss wollte ich mir eine Prozedur basteln an die ich den Form Namen übergebe und über die Prozedur sollen aus der csv Datei dann die richtigen Captions ausgelesen werden.

Bisher sieht das ganze nun so aus:

Delphi-Quellcode:
procedure prLoadModuleLanguage(sModule : String);

var
i : Integer;


begin

  For i := 0 To Application.FindComponent(sModule).ComponentCount -1 Do
  Begin

    //TAdvPage
    If (Application.FindComponent(sModule).Components[i] is TAdvPage) Then
    Begin
      (Application.FindComponent(sModule).Components[i] as TAdvPage).Caption := fnGetComponentCountryText('Component', sModule, 'TAdvPage', (Application.FindComponent(sModule).Components[i] as TAdvPage).Name);
    End;

    //TAdvToolBar
    If (Application.FindComponent(sModule).Components[i] is TAdvToolBar) Then
    Begin
      (Application.FindComponent(sModule).Components[i] as TAdvToolBar).Caption := fnGetComponentCountryText('Component', sModule, 'TAdvToolBar', (Application.FindComponent(sModule).Components[i] as TAdvToolBar).Name);
    End;

    //TAdvGlowButton
    If (Application.FindComponent(sModule).Components[i] is TAdvGlowButton) Then
    Begin
      (Application.FindComponent(sModule).Components[i] as TAdvGlowButton).Caption := fnGetComponentCountryText('Component', sModule, 'TAdvGlowButton', (Application.FindComponent(sModule).Components[i] as TAdvGlowButton).Name);
    End;

  End;

end;

Bisher habe ich keine bessere Idee wie ich das sonst umsetzen könnte... Ich lass mir aber gern auf die Sprünge helfen :lol:

Andidreas 21. Aug 2012 16:23

AW: Form Namen Variable verwenden
 
Und jetzt habe ich glaub das Problem das Ihr angesprochen habt...
Meine Forms werden Dynamisch erzeugt... Mit der Variante von mkinzler erhalte ich jetzt eine Zugriffsverletzung...

Wie kann ich den die Form, bzw. den Namen als Instanz oder Referenz übergeben?

@deddyH
Warum ich das bis jetzt so probiert habe ist eigentlich ganz einfach... Mir ist nichts anderes eingefallen beim rumprobieren :-O

Sir Rufo 21. Aug 2012 16:26

AW: Form Namen Variable verwenden
 
Zitat:

Zitat von Andidreas (Beitrag 1179094)
Damit ich nun im OnCreate Ereignis jeder Form die csv Datei auslesen muss wollte ich mir eine Prozedur basteln an die ich den Form Namen übergebe und über die Prozedur sollen aus der csv Datei dann die richtigen Captions ausgelesen werden.

Aber dann hast du doch auch die Instanz der Form, warum übergibst du die dann nicht direkt? :gruebel:

Delphi-Quellcode:
procedure TSomeForm.SomeFormCreate(Sender : TObject);
begin
  prLoadModuleLanguage( Self ); // <- mit Self wird die aktuelle Instanz übergeben =:o)
end;

Andidreas 21. Aug 2012 16:28

AW: Form Namen Variable verwenden
 
Zitat:

Zitat von Sir Rufo (Beitrag 1179100)
Zitat:

Zitat von Andidreas (Beitrag 1179094)
Damit ich nun im OnCreate Ereignis jeder Form die csv Datei auslesen muss wollte ich mir eine Prozedur basteln an die ich den Form Namen übergebe und über die Prozedur sollen aus der csv Datei dann die richtigen Captions ausgelesen werden.

Aber dann hast du doch auch die Instanz der Form, warum übergibst du die dann nicht direkt? :gruebel:

Delphi-Quellcode:
procedure TSomeForm.SomeFormCreate(Sender : TObject);
begin
  prLoadModuleLanguage( Self ); // <- mit Self wird die aktuelle Instanz übergeben =:o)
end;

Bis jetzt ist ja meine "prLoadModuleLanguage" Prozedur mit einer String Variablen deklariert...
Wie müsste das dann aussehen wenn ich das mit Self mache?
Sorry ich bin auf dem Gebiet nicht wirklich bewandert :oops:

DeddyH 21. Aug 2012 16:30

AW: Form Namen Variable verwenden
 
Dann nimm doch self.Name oder self.Classname, je nachdem.

Sir Rufo 21. Aug 2012 16:34

AW: Form Namen Variable verwenden
 
Zitat:

Zitat von Andidreas (Beitrag 1179094)
Delphi-Quellcode:
procedure prLoadModuleLanguage(sModule : String);

var
i : Integer;


begin

  For i := 0 To Application.FindComponent(sModule).ComponentCount -1 Do
  Begin

    //TAdvPage
    If (Application.FindComponent(sModule).Components[i] is TAdvPage) Then
    Begin
      (Application.FindComponent(sModule).Components[i] as TAdvPage).Caption := fnGetComponentCountryText('Component', sModule, 'TAdvPage', (Application.FindComponent(sModule).Components[i] as TAdvPage).Name);
    End;

    //TAdvToolBar
    ...

    //TAdvGlowButton
    ...
  End;

end;

So macht man das ja auch nicht, sondern man schaut sich an, ob das Caption nicht aus einem Vorfahren kommt, und dann arbeitet man mit dem Vorfahren.

Caption kommt normalerweise von TControl.Caption

Also im ganzen Satz:
Delphi-Quellcode:
procedure prLoadModuleLanguage(aComponent : TComponent);
var
  idx : Integer;
  lComponent : TComponent;
  lControl : TControl;
begin
  for idx := 0 to Pred( aComponent.ComponentCount ) do
  begin

    lComponent := aComponent.Components[ idx ];

    if lComponent is TControl then
    begin

      lControl := lComponent as TControl;

      lControl.Caption := fnGetComponentCountryText('Component', aComponent.ClassName, lComponent.ClassName, lComponent.Name);

    end;

  end;
end;
Irgendwelche Spezialfälle muss man natürlich gesondert behandeln, aber auch da macht es immer Sinn, den passenden Vorgänger zu suchen, sonst tippt man sich einen Wolf.

DeddyH 21. Aug 2012 16:42

AW: Form Namen Variable verwenden
 
Könnte man dann nicht gleich über Controls iterieren? Nicht-visuelle Komponenten müssen ja nicht beschriftet werden. Außerdem ist TControl.Caption IIRC protected und wird in abgeleiteten Klassen dann zu Caption oder zu Text, man bräuchte also entweder eine Unterscheidung, was sehr umfangreich werden könnte, oder ein wenig RTTI.

Sir Rufo 21. Aug 2012 16:47

AW: Form Namen Variable verwenden
 
Zitat:

Zitat von DeddyH (Beitrag 1179106)
Könnte man dann nicht gleich über Controls iterieren? Nicht-visuelle Komponenten müssen ja nicht beschriftet werden. Außerdem ist TControl.Caption IIRC protected und wird in abgeleiteten Klassen dann zu Caption oder zu Text, man bräuchte also entweder eine Unterscheidung, was sehr umfangreich werden könnte, oder ein wenig RTTI.

Controls -> Parent
Components -> Owner

Die Form ist idR der Owner, der Parent kann auch ein Panel sein und dann müsste man bei den Controls rekursiv durchgehen ;)

DeddyH 21. Aug 2012 16:50

AW: Form Namen Variable verwenden
 
Trotzdem würde ich das vorziehen, denn man kann eine Komponente ja auch dynamisch zur Laufzeit erzeugen, ohne dass man einen Owner angibt. Man kann sie natürlich auch ohne Parent erzeugen, aber dann ist sie eh nicht zu sehen, muss also auch gar nicht beschriftet werden.

Andidreas 21. Aug 2012 17:22

AW: Form Namen Variable verwenden
 
@Sir Rufo
Gibt es keine möglichkeit, das ich im OnShow ereignis einer Form die Komponenten durchsuche und die Captions etc. setze und das über eine Prozedur die ich im OnShow Ereignis aufrufe so wie von mir angedacht?

Sir Rufo 21. Aug 2012 17:29

AW: Form Namen Variable verwenden
 
Zitat:

Zitat von Andidreas (Beitrag 1179110)
@Sir Rufo
Gibt es keine möglichkeit, das ich im OnShow ereignis einer Form die Komponenten durchsuche und die Captions etc. setze und das über eine Prozedur die ich im OnShow Ereignis aufrufe so wie von mir angedacht?

:?: Das passiert doch so wie ich das geschrieben habe - gut der Aufruf müsste dann im OnShow erfolgen

himitsu 21. Aug 2012 17:31

AW: Form Namen Variable verwenden
 
Das Einzige, was halbwegs sicher ist, wenn du rekursiv alle Controls (Parent-Child-Beziehungen) durchläufst.

Die Components, bzw der Owner hat ja nichts mit der Sichtbarkeit zu tun, sondern nur mit der internen (Speicher)Verwaltung.

Andidreas 21. Aug 2012 17:32

AW: Form Namen Variable verwenden
 
Zitat:

Zitat von Sir Rufo (Beitrag 1179111)
Zitat:

Zitat von Andidreas (Beitrag 1179110)
@Sir Rufo
Gibt es keine möglichkeit, das ich im OnShow ereignis einer Form die Komponenten durchsuche und die Captions etc. setze und das über eine Prozedur die ich im OnShow Ereignis aufrufe so wie von mir angedacht?

:?: Das passiert doch so wie ich das geschrieben habe - gut der Aufruf müsste dann im OnShow erfolgen

Und die Prozedur kann dann in einer anderen Unit liegen?
Sorry wenn ich so doof nachfrage, aber ich steh grad ein klein wenig aufm Schlauch... :oops:

Uwe Raabe 21. Aug 2012 17:36

AW: Form Namen Variable verwenden
 
Kurze Zwischenfrage: ist D2005 richtig oder arbeitest du schon mit was neuerem?

DeddyH 21. Aug 2012 17:41

AW: Form Namen Variable verwenden
 
Klappt das hiermit (komplett ungetestet, da im Editor getippt)?
Delphi-Quellcode:
uses
  TypInfo;
 
function HasProperty(AClass: TObject; const APropertyName: String): Boolean;
var
  MyPropInfo: PPropInfo;
begin
  MyPropInfo := GetPropInfo(AClass.ClassInfo, APropertyName);
  Result := Assigned(MyPropInfo);
end;

function CompSetPropValue(AClass: TObject; const PropName, Caption: string): Boolean;
var
  MyPropInfo: PPropInfo;
begin
  MyPropInfo := GetPropInfo(AClass.ClassInfo, PropName);
  Result := Assigned(MyPropInfo);
  if Result then
    SetPropValue(AClass, PropName, Caption);
end;

procedure prLoadModuleLanguage(AParent: TWinControl);
const PROPNAMES: array[0..1] of string = ('Caption', 'Text');
var
  i, j: integer;
  NewText: string;
  AControl: TControl;
begin
  Assert(Assigned(AParent));
  for i := 0 to AParent.ControlCount - 1 do
    begin
      AControl := AParent.Controls[i];
      NewText := fnGetComponentCountryText('Component', AParent.ClassName,
        AControl.ClassName, AControl.Name);
      for j := Low(PROPNAMES) to High(PROPNAMES) do
        if HasProperty(AControl, PROPNAMES[j]) then      
          begin
            CompSetPropValue(AControl, PROPNAMES[j], NewText);
            break;
          end;
      if AControl is TWinControl then
        prLoadModuleLanguage(TWinControl(AControl));
    end;
end;

Sir Rufo 21. Aug 2012 17:50

AW: Form Namen Variable verwenden
 
Zitat:

Zitat von Andidreas (Beitrag 1179113)
Zitat:

Zitat von Sir Rufo (Beitrag 1179111)
Zitat:

Zitat von Andidreas (Beitrag 1179110)
@Sir Rufo
Gibt es keine möglichkeit, das ich im OnShow ereignis einer Form die Komponenten durchsuche und die Captions etc. setze und das über eine Prozedur die ich im OnShow Ereignis aufrufe so wie von mir angedacht?

:?: Das passiert doch so wie ich das geschrieben habe - gut der Aufruf müsste dann im OnShow erfolgen

Und die Prozedur kann dann in einer anderen Unit liegen?
Sorry wenn ich so doof nachfrage, aber ich steh grad ein klein wenig aufm Schlauch... :oops:

Ja, das geht problemlos, allerdings musst du wohl noch die eine oder andere Unit in die uses der Unit mit aufnehmen (z.B. Classes, Controls).

Das ist aber auf jeden fall eine Reduzierung, weil bei deinem Ansatz musst du ja deine kompletten Komponenten-Units einbinden ;)

Andidreas 21. Aug 2012 18:08

AW: Form Namen Variable verwenden
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1179115)
Kurze Zwischenfrage: ist D2005 richtig oder arbeitest du schon mit was neuerem?

Ne stimmt nicht mehr, haben mittlerweile RAD Studio XE und XE2 liegt uninstalliert in der Schublade :-D

@deddyH und Sir Rufo
Werd Eure Ansätze morgen mal ausprobieren... Aufm iPad hab ich leider kein RAD Studio :lol:

himitsu 21. Aug 2012 18:39

AW: Form Namen Variable verwenden
 
XE2 hat selber in vielen Komponenten eine Übersetzungsfunktion integriert, wo sich die Komponenten selber übersetzen, also keiner sie suchen muß und wo du dich mit deiner Funktion einklinken könntest.

Andidreas 22. Aug 2012 07:59

AW: Form Namen Variable verwenden
 
Ich habs jetzt mal so gemacht:

Delphi-Quellcode:
procedure prLoadModuleLanguage(frmModule : TForm);

var
i : Integer;


begin

  For i := 0 To frmModule.ComponentCount -1 Do
  Begin

    //TAdvPage
    If (frmModule.Components[i] is TAdvPage) Then
    Begin
      (frmModule.Components[i] as TAdvPage).Caption := fnGetComponentCountryText('Component', frmModule.Name, 'TAdvPage', (frmModule.Components[i] as TAdvPage).Name);
    End;

    //TAdvToolBar
    If (frmModule.Components[i] is TAdvToolBar) Then
    Begin
      (frmModule.Components[i] as TAdvToolBar).Caption := fnGetComponentCountryText('Component', frmModule.Name, 'TAdvToolBar', (frmModule.Components[i] as TAdvToolBar).Name);
    End;

    //TAdvGlowButton
    If (frmModule.Components[i] is TAdvGlowButton) Then
    Begin
      (frmModule.Components[i] as TAdvGlowButton).Caption := fnGetComponentCountryText('Component', frmModule.Name, 'TAdvGlowButton', (frmModule.Components[i] as TAdvGlowButton).Name);
    End;

  End;

end;

Ist der Lösungsansatz schlechter als der von deddyH oder Sir Rufo?

DeddyH 22. Aug 2012 08:04

AW: Form Namen Variable verwenden
 
Zumindest ist er unflexibler :mrgreen:

Andidreas 22. Aug 2012 08:09

AW: Form Namen Variable verwenden
 
Zitat:

Zitat von DeddyH (Beitrag 1179236)
Zumindest ist er unflexibler :mrgreen:

Weil ich immer Abfragen muss was es für eine Komponente ist?

DeddyH 22. Aug 2012 08:11

AW: Form Namen Variable verwenden
 
Genau. Sobald ein neuer Komponententyp dazukommt, musst Du den Code wieder erweitern. Und ob Du wirklich auf Components statt Controls zugreifen willst, musst Du anhand der vorherigen Diskussion selbst entscheiden.

Andidreas 22. Aug 2012 08:27

AW: Form Namen Variable verwenden
 
Wie muss ich den die "PRED" Funktion aus Sir Rufos Lösungs Vorschlag verstehen, bzw. was macht diese Funktion?

Sir Rufo 22. Aug 2012 08:33

AW: Form Namen Variable verwenden
 
-1 ;)

Andidreas 22. Aug 2012 08:37

AW: Form Namen Variable verwenden
 
:oops: darauf hätte ich auch kommen können... peinlich...

Noch eine andere Frage, in deinem Source fragst Du ab


Delphi-Quellcode:
if lComponent is TControl then


Sehe ich das richtig das damit abgefragt wird ob sich die Komponente von TControl ableitet und über eine Caption verfügt?

mkinzler 22. Aug 2012 09:07

AW: Form Namen Variable verwenden
 
Ja.

Ykcim 24. Aug 2012 09:58

AW: Form Namen Variable verwenden
 
Sorry, das war der falsche Beitrag...


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