Announcement

Collapse
No announcement yet.

Wie kann man die Eigenschaften eines Objektes auslesen/setzen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Wie kann man die Eigenschaften eines Objektes auslesen/setzen

    Hi,
    <br>
    <br>ich möchte in einer Schleife auf alle Componenten eines Formulares zugreifen, und wenn diese die Eigenschaft ReadOnly besitzen, so soll dieser Wert auf true gesetzt werden.
    <br>So in etwa stelle ich mir das vor (es folgt pseudo Code):
    <pre>
    For i := 0 to frm.ControlCount - 1 do
    For z := 0 to frm.Controls[i].PropertysCount - 1 do
    If frm.Controls[i].Property[z].Name = 'ReadOnly' Then
    frm.Controls[i].Property[z].Value := True;
    </pre>
    <br>Ich habe nichts gefunden, das die Funktionalität von PropertysCount und Property abbildet. An den Haaren herbei gezogen ist diese Vorgehensweise nicht, ich bin mir ziemlich sicher so etwas schon mal in Basic gemacht zu haben.
    <br>
    <br>Ich hoffe jemand kann mir weiter helfen. Sonst müßte ich wohl jedes Control im Code von Hand auf RaedOnly setzten (viel Arbeit).
    <br>
    <br>Danke!
    <br>
    <br>mfg
    <br>PS

  • #2
    http://www.entwickler-forum.de\webx?128@@.ee8a1d

    Comment


    • #3
      Hi,
      <br>
      <br>danke für die Antwort.
      <br>
      <br>Habe wohl noch ein paar Probleme:
      <pre>
      Procedure TFunktionen.SetComponentReadOnly(Com : TComponent; ReadOnlyValue : Boolean);
      Var
      i : Integer;
      P : PPropInfo;
      Begin
      For i := 0 to com.ComponentCount - 1 do
      Begin
      If (not (com.Components[i] is TForm)) and
      (not(com.Components[i] is TCustomDBGrid)) and
      (com.Components[i] is TWinControl) and
      (com.Components[i].Name <> '') Then
      Begin
      If (com.Components[i].ComponentCount > 0) and (com.Components[i] is TWinControl) and (com.Components[i].Name <> '') Then
      SetComponentReadOnly(com.Components[i], ReadOnlyValue);
      P := GetPropInfo(com.Components[i], 'ReadOnly');
      if P <> nil then
      SetVariantProp(com.Components[i], P, ReadOnlyValue);
      End;
      End;
      End;
      </pre>
      1)
      <br>Gibt es nicht auch so etwas wie SetBooleanProp (habe ich gesucht, aber nicht gefunden)?
      <br>
      <br>2)
      <br>wenn:
      <pre>
      procedure TForm1.FormCreate(Sender: TObject);
      begin
      //Funktionen.SetComponentReadOnly(Self, True);
      edit1.readonly := true;
      end;
      </pre>
      dann ist alles OK, aber wenn:
      <pre>
      procedure TForm1.FormCreate(Sender: TObject);
      begin
      Funktionen.SetComponentReadOnly(Self, True);
      //edit1.readonly := true;
      end;
      </pre>
      Dann bekommt man sehr eigenartige Effekte (vorallem immer wieder verschieden). Z.B. die EditBox wird mit Passwordzeichen (*) dargestellt und rechtsbündig und ein anders mal wird die EditBox mit Passwordzeichen (*) dargestellt und Zentriert, obwohl im Entwurf die EditBox ohne Passwordzeichen und linksbündig eingetragen ist.
      Ruft man jedoch die Procedure nicht in FormCreate auf sondern ...
      <pre>
      procedure TForm1.Button1Click(Sender: TObject);
      begin
      Funktionen.SetComponentReadOnly(Self, False);
      end;
      </pre>
      dann ist wieder alles in Ordnung.
      Verwendet man nun statt FormCreate FormShow, so ist das schon besser für EditBoxen, jedoch bekommt man eine Fehlermeldung wenn die Procedure auf ein DBGrid zugreift. Die Fehlermeldung lauetet ungefähr so: Der Index der Liste überschreitet das Maximum 7. (Um diesen Fehler zu reproduzieren muß man natürlich in der Proc. (not(com.Components[i] is TCustomDBGrid)) entfehrnen).
      In dem DBGrid gibt es 7 Spalten. Würde nun der Fehler in der Procedure auftreten, weil mittels com.Component[i] auf eine nicht existierende Komponente zugegriffen wurde, dann hätte man ja noch einen Anhaltspunkt wo man suchen könnte (obwohl, wo soll man da noch suchen, schließlich basiert mein i maximal auf ComponentCount - 1 (der Fehler darf eigentlich gar nicht auftreten)), jedoch wird die Procedure anstandslos ausgeführt und erst später, bei der Rückgabe der Kontrolle an das Formular wird diese Fehlermeldung erzeugt.
      Hier gilt auch wieder, das wenn die Procedure von Hand ausgeführt wird (durch drücken eines Buttons) so ist alles OK. Hilfreich wäre ein Ereignis, das aufgerufen wird, wenn wirklich alle Componenten des Formulares erzeugt wurden. Bei OnShow und OnCreate scheint das ja nicht der Fall zu sein. Ich habe jedoch kein solches Ereignis gefunden.
      <br>
      <br>Habe ich da was falsch gemacht, oder sind das Bugs (Fehler in Punkt2)?
      <br>Ich hoffe jemand kann mir hier weiterhelfen.
      <br>
      <br>Danke!
      <br>
      <br>mfg
      <br>P

      Comment


      • #4
        Hi,
        <br>
        <br>hat hier vieleicht noch jemand eine Idee?
        <br>
        <br>Danke!
        <br>
        <br>mfg
        <br>P

        Comment


        • #5
          Hallo Patrick,

          ich würde sowieso immer wenn mit den Objekten was gemacht werden soll das erst bei OnActivate(oder OnShow) machen.
          Ich glaub bei OnCreate sind manche Komponenten noch garnicht richtig erstellt(oder so ähnlich).
          Vielleicht hilfts ja auch was wenn du z.B. erst beim AfterOpen-Event vom TTable die Funktion ausführst(wegen dem DBGrid-Fehler).
          Könnte vielleicht auch ein anderer Zugriff auf DBGrid den Fehler auslösen?

          cu detlef

          ps: bin auch kein experte aber probieren kann mans ja mal :

          Comment


          • #6
            Hi,
            <br>
            <br>anscheinend liegt der Fehler in:
            <pre>
            P := GetPropInfo(com.Components[i], 'ReadOnly');
            if P <> nil then
            SetVariantProp(com.Components[i], P, ReadOnlyValue);
            </pre>
            <br>führt man die obige Funktion mit diesem Code aus, auf einem Formular mit einer EditBox und einem Button (Auslöser ist onclick des buttons(ausgeführt wird Funktionen.SetComponentReadOnly(Self, Not edit1.readonly)), so wird das Edit Feld auf Readonly gestellt. Wie gewollt. Jedoch wird es beim zweiten Drücken des Buttons nicht wieder entsperrt selbst ein Edit1.readonly := false hilft nicht mehr weiter.
            Tausche ich jedoch den Obigen Code durch
            <pre>
            If com.Components[i] is TEdit Then
            TEdit(com.Components[i]).ReadOnly := ReadOnlyValue
            Else
            Begin
            P := GetPropInfo(com.Components[i], 'ReadOnly');
            if P <> nil then
            SetVariantProp(com.Components[i], P, ReadOnlyValue);
            End;
            </pre>
            <br>aus dann funktioniert es zumindest für Tedit dann fehlt jetzt nur noch TDBEdit ...
            <br>
            <br>Ich habe natürlich keine Lust für jedes etwaige Control Ein Else If zu erstellen.
            <br>
            <br>Ist das ein Bug oder hat noch jemand eine Idee?
            <br>
            <br>Danke!
            <br>
            <br>mfg
            <br>P

            Comment


            • #7
              Anstatt SetVariantProp() sollte SetOrdProp(.., 0 oder 1) benutzt werden. Ich vermute die beschi..enen Variants sind wiedermal schuld.

              Gruß Hage

              Comment


              • #8
                Hi,
                <br>
                <br>vielen Dank Hagen.
                <br>
                <br>Genau das war's.
                <br>
                <br>Wen es interessiert so funktioniert es (sogar in TForm1.FormCreate):
                <pre>
                //Setzt alle Steuerelemente in einem Form/Komponente auf ReadOnly
                Procedure TFunktionen.SetComponentReadOnly(Com : TComponent; ReadOnlyValue : Boolean);
                Var
                i : Integer;
                P : PPropInfo;
                Begin
                For i := 0 to com.ComponentCount - 1 do
                Begin
                If (not (com.Components[i] is TForm)) and
                (com.Components[i] is TWinControl) and
                (com.Components[i].Name <> '') Then
                //ich glaube die letzte Bedingung kann man weglassen, aber...
                Begin
                If (com.Components[i].ComponentCount > 0) Then
                SetComponentReadOnly(com.Components[i], ReadOnlyValue);
                P := GetPropInfo(com.Components[i], 'ReadOnly');
                if P <> nil then
                Begin
                If ReadOnlyValue Then
                SetOrdProp(com.Components[i], P, 1) //True
                Else
                SetOrdProp(com.Components[i], P, 0); //False
                End;
                End;
                End;
                End;
                </pre>
                Ach ja es gibt noch folgende Funktionen zu dem Thema (kann sein das ich hier eine vergessen habe, schließlich hatte ich ja auch SetOrdProp anfangs übersehen):
                <br>
                <br>function GetOrdProp(Instance: TObject; const PropName: string): <br>Longint;
                <br>procedure SetOrdProp(Instance: TObject; const PropName: string;
                <br> Value: Longint);
                <br>
                <br>function GetEnumProp(Instance: TObject; const PropName: string): <br>string;
                <br>procedure SetEnumProp(Instance: TObject; const PropName: string;
                <br> const Value: string);
                <br>
                <br>function GetSetProp(Instance: TObject; const PropName: string;
                <br> Brackets: Boolean): string;
                <br>procedure SetSetProp(Instance: TObject; const PropName: string;
                <br> const Value: string);
                <br>
                <br>function GetObjectProp(Instance: TObject; const PropName: string;
                <br> MinClass: TClass): TObject;
                <br>procedure SetObjectProp(Instance: TObject; const PropName: string;
                <br> Value: TObject);
                <br>function GetObjectPropClass(Instance: TObject; const PropName: <br>string): TClass;
                <br>
                <br>function GetStrProp(Instance: TObject; const PropName: string): <br>string;
                <br>procedure SetStrProp(Instance: TObject; const PropName: string;
                <br> const Value: string);
                <br>
                <br>function GetFloatProp(Instance: TObject; const PropName: string): <br>Extended;
                <br>procedure SetFloatProp(Instance: TObject; const PropName: string;
                <br> Value: Extended);
                <br>
                <br>function GetVariantProp(Instance: TObject; const PropName: string): <br>Variant;
                <br>procedure SetVariantProp(Instance: TObject; const PropName: string;
                <br> const Value: Variant);
                <br>
                <br>function GetMethodProp(Instance: TObject; const PropName: string): <br>TMethod;
                <br>procedure SetMethodProp(Instance: TObject; const PropName: string;
                <br> const Value: TMethod);
                <br>
                <br>function GetInt64Prop(Instance: TObject; const PropName: string): <br>Int64;
                <br>procedure SetInt64Prop(Instance: TObject; const PropName: string;
                <br> const Value: Int64);
                <br>
                <br>mfg
                <br>P

                Comment


                • #9
                  <pre>

                  <code><font size=2 face="Courier New"><font color="#008080"><i>// alter code
                  <br>
                  </i></font><b>if </b>P &lt;&gt; <b>nil then
                  begin
                  if </b>ReadOnlyValue <b>Then
                  </b>SetOrdProp(com.Components[i], P, <font color="#0000FF">1</font>) <font color="#008080"><i>//True
                  </i></font><b>else
                  </b>SetOrdProp(com.Components[i], P, <font color="#0000FF">0</font>); <font color="#008080"><i>//False
                  </i></font><b>end</b>;
                  <br>
                  <font color="#008080"><i>// kann so umgeformt werden
                  <br>
                  </i></font><b>if </b>P &lt;&gt; <b>nil then
                  </b>SetOrdProp(com.Components[I], P, Ord(ReadOnlyValue));
                  <br>
                  <font color="#008080"><i>// heist ja auch SetOrdProp(..., Ord(..))
                  <br>
                  </i></font>Hagen
                  </font>
                  </code></pre&gt

                  Comment


                  • #10
                    <br>Danke!
                    <br>
                    <br>mfg
                    <br>P

                    Comment

                    Working...
                    X