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/)
-   -   Delphi Eigenschaften unterschiedlicher Objekte ändern (https://www.delphipraxis.net/121930-eigenschaften-unterschiedlicher-objekte-aendern.html)

WIng2005 7. Okt 2008 07:49


Eigenschaften unterschiedlicher Objekte ändern
 
Hallo,

ich möchte zur Laufzeit die Eigenschaften (readonly und color) unterschiedlicher Objekte ändern.
Das betrifft bspw. TEdit, TMemo, TCombobox,TListbox, TJvListbox und TJvCombobox.
Mein Ansatz bisher war:

Delphi-Quellcode:
for i := 0 to Mainform.ComponentCount - 1 do
    Begin
    if ((Mainform.Components[i] is TEdit)
        or (Mainform.Components[i] is TMemo)
        or (Mainform.Components[i] is TListbox)
        or (Mainform.Components[i] is TJvListbox)
        or (Mainform.Components[i] is TJvComboBox)
        or (Mainform.Components[i] is TCombobox))
        and (((Mainform.Components [i]).tag=1)) then
        Begin
        with (Mainform.Components [i]) do
          readonly:=true; //mag er nicht : Undefinierter Bezeichner
        end;
End;end;
Leider hänge ich ein wenig an der markierten Stelle, und hoffe ihr könnt mir meinen Fehler ein wenig deutlich machen.

MFG
Steffen

messie 7. Okt 2008 08:04

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Mainform.Components [i] ist nur ein Zeiger, deshalb weiß der Compiler nicht, wen er da vor sich hat. Du brauchst etwas wie
Delphi-Quellcode:
if Mainform.Components[i] is TEdit then
begin
  with if Mainform.Components[i] as TEdit do
  begin
    ReadOnly := true;
  end;
Ungetestet, müsste aber etwa so gehen.

Grüße, Messie

mquadrat 7. Okt 2008 08:05

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Sicher, dass das zweite if da rein gehört?

Tyrael Y. 7. Okt 2008 08:12

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Wenn die Komponenten nicht denselben Vorfahren aufweisen, der genau die von dir zu veränderden Eigenschaften besitzt wirst du so nicht weiterkommen.

Eine TListBox hat keine Eigenschaft, die das beschreiben durch Benutzereingabe erluabt oder
nicht erlaubt, ich weiss nicht was du dabei vorhast.

Delphi-Quellcode:

for i := 0 to Mainform.ComponentCount - 1 do
Begin
    if ((Mainform.Components[i] is TCustomEdit) then
      TCustomEdit(Mainform.Components[i]).ReadOnly := True
    else
    if (Mainform.Components[i] is TCustomComboBox) then
      TCustomComboBox(Mainform.Components[i]).Style := csDropDownList;

End;end;

Bernhard Geyer 7. Okt 2008 08:17

Re: Eigenschaften unterschiedlicher Objekte ändern
 
RTTI ist das Zauberwort. Genau so wie auch die VCL/RTL aus den DFM-Ressourcen die Komponenten wieder herstellt.

Hier ein Beispiel zum setzen eines Boolean-Properties:

Delphi-Quellcode:
uses
  TypInfo;

procedure MySetPropertyBool(Component: TComponent; const PropName: String; const Value: Boolean);
var
  PropInfo: PPropInfo;
begin
  if (Component <> nil) then
  begin
    PropInfo := GetPropInfo(Component.ClassInfo, PropName);
    if (PropInfo <> nil) then
    begin
      if (PropInfo^.PropType^.Kind in [tkEnumeration]) then
        SetEnumProp(Component, PropInfo, BooleanIdents[Value]);
    end;
  end;
end;

WIng2005 7. Okt 2008 08:22

Re: Eigenschaften unterschiedlicher Objekte ändern
 
@Tyrael Y.:Klar, mein Fehler. Würde man nur die Eigenschaft color betrachten, wie könnte man den Code im ersten Beitrag entsprechend Korrigieren? Bin auf der suche nach einer kurzen "eleganten" Lösung. Andererseits, sofern ich einigen Komponenten ein readonly geben möchte, werde ich wohl den längeren Weg gehen müssen.
Ich ging davon aus, dass die Komponenten von TObject abstammen und somit

Delphi-Quellcode:
for i := 0 to Mainform.ComponentCount - 1 do
    Begin
    if ((Mainform.Components[i] is TEdit)
        or (Mainform.Components[i] is TMemo))
        and (((Mainform.Components [i]).tag=1)) then
        Begin
        with (Mainform.Components [i]) as TObject do
          readonly:=true;
        end;
End;end;
möglich wäre. Funktioniert aber irgendwie auch nicht. Möchte erreichen, dass ich nicht für jedes Objekt eine extra Abfrage laufen lassen muss.

@Bernhard: das muss ich erstmal "sacken" lassen....

MFG
Steffen

Tyrael Y. 7. Okt 2008 08:29

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Du musst nicht jede Komponente einzeln behandeln.
Guck mal bitte nochmal meinen Code an.

Du musst den gemeinsamen Vorfahren finden bei der diese von dir gesuchte Eigenschaft
definiert wird. Somit erschlägts du in einem Schritt ganz viele Komponenten.

Edit: Die Eigenschaft Color wird in TControl definiert.

Delphi-Quellcode:

for i := 0 to Mainform.ComponentCount - 1 do
Begin
    if ((Mainform.Components[i] is TCustomEdit) then
      TCustomEdit(Mainform.Components[i]).ReadOnly := True
    else
    if (Mainform.Components[i] is TCustomComboBox) then
      TCustomComboBox(Mainform.Components[i]).Style := csDropDownList;

    if (Mainform.Components[i] is TControl) then
      TControl(Mainform.Components[i]).Color := clGreen;
End;end;

messie 7. Okt 2008 08:30

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Zitat:

Zitat von WIng2005
Ich ging davon aus, dass die Komponenten von TObject abstammen und somit

Sie stammen von TComponent ab.

Grüße, Messie

WIng2005 7. Okt 2008 08:55

Re: Eigenschaften unterschiedlicher Objekte ändern
 
@Tyrael Y.:

TControl schein es nicht zu sein, oder aber ich habe eine Fehler im Code:

Delphi-Quellcode:

for i := 0 to Mainform.ComponentCount - 1 do
Begin
  if (Mainform.Components [i]).tag=1 then
  Begin
   if (Mainform.Components[i] is TControl) then
      TControl(Mainform.Components[i]).Color :=cl3DLight; //undefinierter Bezeichner Color

  end; //if
end;
(Die zweite Abfrage könnte man auch mit der ersten Verbinden, hier soll jedoch noch mehr rein....)

MFG
Steffen

Tyrael Y. 7. Okt 2008 09:05

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Hab es jetzt grade mal geprüft.
Color ist in TControl definiert, ist aber protected.

Die meisten Controls machen die Eigenschaft erst beim eigentlich benutztem Nachfahren published oder public. Tja da musst du jetzt genau gucken, welchen Controls du die Color Eigenschaft zuweisen möchtest und für jeden von denen nach einem gemeinsamen Vorfahren mit Color published bzw publich suchen. z.B bei TEdit ist es TEdit selbst.

nahpets 7. Okt 2008 09:17

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Hallo,
Zitat:

Zitat von messie
Zitat:

Zitat von WIng2005
Ich ging davon aus, dass die Komponenten von TObject abstammen und somit

Sie stammen von TComponent ab.

Grüße, Messie

Beide Ausssagen sind richtig, aber: mit den angeführten Methoden können nur die Eigenschaften geändert werden, über die TObject bzw. TComponent verfügen. ReadOnly gehört nicht dazu.
Du hast nur zwei Möglichkeiten:
Entweder Du suchst Dir aus der Hilfe den gemeinsamen Vorfahren, der über die gewünschte Eigenschaft verfügt und hangelst Dich ggfls. durch entsprechende If-Kaskaden oder Du benutzt die von Bernhard Geyer beschriebene Methode. Bernhards Methode hat den Charme, dass Du sie genau einmal implementieren musst und dann sämtliche Komponenten damit "funktionieren" und bei Änderungen am Programm musst Du an die entsprechende Stelle mit den Eigenschaftszuweisungen nicht mehr ran.

DerDan 7. Okt 2008 09:20

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Hallo,


das vom Bernd ist doch gut:

Auf den ersten blick vielleicht aufwendiger, aber dafür eine Universal-Lösung.

Mfg

Zitat:

Zitat von Bernhard Geyer
RTTI ist das Zauberwort. Genau so wie auch die VCL/RTL aus den DFM-Ressourcen die Komponenten wieder herstellt.

Hier ein Beispiel zum setzen eines Boolean-Properties:

Delphi-Quellcode:
uses
  TypInfo;

procedure MySetPropertyBool(Component: TComponent; const PropName: String; const Value: Boolean);
var
  PropInfo: PPropInfo;
begin
  if (Component <> nil) then
  begin
    PropInfo := GetPropInfo(Component.ClassInfo, PropName);
    if (PropInfo <> nil) then
    begin
      if (PropInfo^.PropType^.Kind in [tkEnumeration]) then
        SetEnumProp(Component, PropInfo, BooleanIdents[Value]);
    end;
  end;
end;


WIng2005 7. Okt 2008 09:21

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Habe es jetzt so:

Delphi-Quellcode:
for i := 0 to Mainform.ComponentCount - 1 do
Begin
if (Mainform.Components [i]).tag=1 then
Begin
  if (Mainform.Components[i] is TEdit) then
  Begin
    TEdit(Mainform.Components[i]).Color :=cl3DLight;
    TEdit(Mainform.Components[i]).readonly :=true;
  end
else if (Mainform.Components[i] is TMemo) then
  Begin
    TMemo(Mainform.Components[i]).Color :=cl3DLight;
    TMemo(Mainform.Components[i]).readonly :=true;
  end
else if (Mainform.Components[i] is TListbox) then
    TMemo(Mainform.Components[i]).Color :=cl3DLight;
end //if

else

Begin
  if (Mainform.Components[i] is TEdit) then
  Begin
    TEdit(Mainform.Components[i]).Color :=clwindow;
    TEdit(Mainform.Components[i]).readonly :=false;
  end
else if (Mainform.Components[i] is TMemo) then
  Begin
    TMemo(Mainform.Components[i]).Color :=clwindow;
    TMemo(Mainform.Components[i]).readonly :=false;
  end
else if (Mainform.Components[i] is TListbox) then
    TMemo(Mainform.Components[i]).Color :=clwindow;
end //if



end;//for
gelöst. Scheint mir nur irgendwie sehr "aufgebauscht". Die Methode von Bernhard werde ich mir heute nach der Arbeit mal anschauen... habe das Gefühl, dass das länger dauern wird :)

MFG
Steffen

WIng2005 7. Okt 2008 11:36

Re: Eigenschaften unterschiedlicher Objekte ändern
 
@Bernhard: Habe mir mal die typinfo angeschaut. Für mich scheint es , als könne man die Color-Property mit:

Delphi-Quellcode:
procedure MySetPropertyColor(Component: TComponent; const PropName: String; const Value: string);
var
  PropInfo: PPropInfo;
begin
  if (Component <> nil) then
  begin
    PropInfo := GetPropInfo(Component.ClassInfo, PropName);
    if (PropInfo <> nil) then
    begin
      if (PropInfo^.PropType^.Kind in [tkEnumeration]) then
        SetSetProp(Component, PropInfo, Value); //Wäre das überhaupt die richtige Methode?
    end;
  end;
end;

//aufgerufen mit:

MySetPropertyColor(edit1,'color','clred');
ändern. Leider bleibt der Aufruf bei mir funktionslos. Vielleicht hast du ja nen Tip, wo der Fehler liegt.

MFG
Steffen

Apollonius 7. Okt 2008 11:42

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Hier liegt doch keine Menge vor. Du musst auf tkInteger prüfen und dann mit SetOrdProp den Wert setzen.

Sharky 7. Okt 2008 11:53

Re: Eigenschaften unterschiedlicher Objekte ändern
 
So solle es gehen:
Delphi-Quellcode:
uses
  TypInfo;


procedure MySetPropertyColor(Instance: TComponent; const PropName: String; const Value: TColor);
resourcestring
  SUnknownProperty = 'Eigenschaft %s existiert nicht.';
var
  PropInfo: PPropInfo;
begin
  PropInfo := GetPropInfo(Instance, PropName);
  if PropInfo = NIL then
  begin
    raise EPropertyError.CreateResFmt(@SUnknownProperty, [PropName]);
  end;
  SetOrdProp(Instance, PropInfo, Value);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MySetPropertyColor(Edit1,'Color',clred);
end;

WIng2005 7. Okt 2008 12:00

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Ja, vielen Dank. Hatte zwischenzeitlich den Hinweis von Apollonius umgesetzt, was dann ungefähr deinem Besipiel entspricht.
Ich verstehe nur den Unterschied zwischen SetOrdProd und SetSetProd nicht ganz. Gibt es zur Typinfo ne bessere Dokumentation, als die Delphi-Hilfe bereitstellt? Möchte es nicht nur blind übernehmen...

Vielen Dank für eure Hilfe!
MFG
Steffen

Apollonius 7. Okt 2008 12:14

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Die RTTI von Delphi ist sehr schlecht dokumentiert. Den Unterschied zwischen den Funktionen sagt hier schon der Name:
SetOrdProp = set ordinal property = ordinale (= Zahl-) Eigenschaft setzen
SetSetProp = set set property = Mengen-Eigenschaft setzen

WIng2005 7. Okt 2008 12:18

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Vielen Dank, wenn du nun noch ein Beispiel für eine Mengeneigenschaft für mich hast, bin ich schon glücklich....(könnte man z.B. Anchors als Mengeneigenschaft sehen?)

Nochmals danke!!

MFG
Steffen

Apollonius 7. Okt 2008 12:20

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Ja, der Typ TAnchors ist ein klassischer Mengen-Typ.
Zitat:

Zitat von Controls.pas
Delphi-Quellcode:
 
TAnchorKind = (akLeft, akTop, akRight, akBottom);
TAnchors = set of TAnchorKind;


WIng2005 7. Okt 2008 13:49

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Vielen Dank.....

MFG
Steffen

WIng2005 1. Apr 2009 11:01

Re: Eigenschaften unterschiedlicher Objekte ändern
 
Hallo,

ich muss den Thread nocheinmal aufgreifen:

ich möchte nun unabhängig vom Komponententyp prüfen, ob dieser die Eigenschaft "color" besitzt und wenn, diese dann prüfen, ob diese einen bestimmten Farbwert hat. Hintergrund: Ich möchte zur Laufzeit die "Grundfarbe" meiner Anwednung ändern. Hierzu wollte ich alle Komponenten durchgehen und prüfen, ob diese clbtnface als Farbwert haben. Wenn ja, soll dieser entsprechend geändert werden.
Meine Ansätze bisher sind:

Delphi-Quellcode:
Procedure set_color(form:TForm);
var i:integer;
    PropInfo: PPropInfo;
    test:string;
Begin

for i := 0 to form.ComponentCount - 1 do
Begin
    PropInfo := GetPropInfo((form.Components [i]).ClassInfo, 'color');
    if Assigned(PropInfo) then
      MySetPropertyColor((form.Components [i]),'color',clred);

end //for

end;


procedure MySetPropertyColor(Component: TComponent; const PropName: String; const Value: integer);
var
  PropInfo: PPropInfo;
begin
  if (Component <> nil) then
  begin
    PropInfo := GetPropInfo(Component.ClassInfo, PropName);
    if (PropInfo <> nil) then
    begin
      if (PropInfo^.PropType^.Kind in [tkInteger]) then
        SetordProp(Component, PropInfo, Value);
    end;
  end;
end;
Leider funktioniert diese Version nicht mit allen Komponenten der Form, sodass z.B PagesControls, Panels, Buttons usw. nicht berücksichtigt werden. Labels und Edits hingegebn werden berücksichtigt. Auch ist mir nicht ganz klar, wie ich neben dem Vorhandensein auch den Wert der Eigenschaft abfragen kann. Die Anpassung sollte hierbei in der set_color erfolgen.

Vielen Dank für jeden Hinweis...


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