Announcement

Collapse
No announcement yet.

Komponente mit Subpropertys

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

  • Komponente mit Subpropertys

    Hallo zusammen,

    habe leider noch keine Erfahrung mit der
    Komp. Entwickung und habe folgendes Problem.

    Ich würde gerne eine Property mit dem Namen
    Rechteck erstellen das dann ein Subproperty
    mit dem Namen Fläche hat und die Eigenschaften
    von TBrush besitzt.
    Ebenso ein Subproperty mit dem Namen Rand
    das die Eigenschaften von TPen besitzt.

    also so: Rechteck
    Fläche - TBrush
    Rand - TPen

    wenn mir jemand helfen könnte wäre das echt Klasse da ichs leider nicht hinkriege.

    mfg Klaus

  • #2
    <pre>

    <code><font size=2 face="Courier New"><b>type
    </b>TRecheck = <b>class
    private
    </b>FBrush: TBrush;
    <b>procedure </b>SetBrush(Value: TBrush);
    <b>protected
    procedure </b>DoInvalidate(Sender: TObject);
    <b>public
    constructor </b>Create();
    <b>published
    property </b>Brush: TBrush <b>read </b>FBrush <b>write </b>SetBrush;
    <b>end</b>;
    <br>
    <b>procedure </b>TRechteck.SetBrush(Value: TBrush);
    <b>begin
    </b>FBrush.Assign(Value);
    <b>end</b>;
    <br>
    <b>procedure </b>TRechteck.DoInvalidate(Sender: TObject);
    <b>begin
    </b>Invalidate; <i>// neuzeichnen des Rechteckes veranlassen
    </i><b>end</b>;
    <br>
    <b>constructor </b>TRecheck.Create();
    <b>begin
    inherited </b>...
    FBrush := TBrush.Create;
    FBrush.OnChange := DoInvalidate; <i>// Änderungen am Brush mitbekommen
    </i><b>end</b>;
    </font>
    </code></pre&gt

    Comment


    • #3
      Hallo Hagen, Danke für Deinen Tipp,
      hilft mir leider nicht weiter, da mir
      das nicht weiter hilft. Es sollte so aussehen:

      Rechteck | Fläche --> TBrush
      | Rand --> TPen

      Kreis | Fläche --> TBrush
      | Rand --> TPen

      usw.

      weitere Hilfe wäre echt toll.

      Nochmals Danke

      Klau

      Comment


      • #4
        Ok, nochmal, das Prinzip ist das gleiche:

        <pre>

        type
        TFlaeche = class
        private
        FBrush: TBrush;
        procedure SetBrush(Value: TBrush);
        public
        procedure Assign(Source: TPersistent); override;
        published
        property Brush: TBrush read FBrush write SetBrush;
        end;<br>

        TRechteck = class
        private
        FFlaeche: TFlaeche;
        procedure SetFlaeche(Value: TFlaeche);
        published
        property Flaeche: TFlaeche read FFlaeche write SetFlaeche;
        end;<br>

        procedure TFlaeche.Assign(Source: TPersistent);
        begin
        if Source is TFlaeche then
        begin
        FBrush.Assign(TFlaeche(Source).Brush);
        end else inherited Assign(Source);
        end;<br>

        procedure TFlaeche.SetBrush(Value: TBrush);
        begin
        FBrush.Assign(Value);
        end;<br>

        procedure TRechteck.SetFlaeche(Value: TFlaeche);
        begin
        FFlaeche.Assign(Value);
        end;<br>

        </pre>

        So das Prinzip dürfte klar sein. Alle als Published deklarierten Objecte müssen immer per Assign() ihre Eigenschaften zuweisen. <br>

        Falls das immer noch nicht reicht solltest du posten warum nicht, genauer bitte.<bR>

        gruß Hage

        Comment


        • #5
          Hallo Hagen,<br>TFlaeche sollte jedoch vom Typ TPersistent abgeleitet sein. Dann werden auch die Einstellungen von TBrush in der dfm-Datei gespeichert. Und TFlaeche sollte einen constructor und destrutor haben, damit FBrush erzeugt und freigegeben werden kann.<br>Das schreibe ich nicht als Besserwisser, sondern weil Klaus schreibt, dass er noch nicht viel Erfahrung mit Komponentenentwicklung hat

          Comment


          • #6
            Jo richtig, deshalb habe ich die Klassendefinition auch nicht vollständig ausgeschrieben siehe oben.<br>
            Ich weiß ja nicht was er bevorzugt, und ober er vielleicht schon eine eigene Basisklasse deklariert hat.<br>

            Gruß Hage

            Comment


            • #7
              Hallo Hagen und Jens habes jetzt soweit:

              unit MYGraphicControl;

              interface

              uses
              Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

              type
              TFlaeche = class(TPersistent)
              private
              FBrush: TBrush;
              procedure SetBrush(Value: TBrush);
              public
              procedure Assign(Source: TPersistent); override;
              published
              property Brush: TBrush read FBrush write SetBrush;
              end;

              TRechteck = class(TPersistent)
              private
              FFlaeche: TFlaeche;
              procedure SetFlaeche(Value: TFlaeche);
              published
              property Flaeche: TFlaeche read FFlaeche write SetFlaeche;
              end;

              type
              TMYGraphicControl = class(TGraphicControl)
              private
              { Private-Deklarationen }
              FRechteck : TRechteck;
              protected
              { Protected-Deklarationen }
              public
              { Public-Deklarationen }
              constructor Create(AOwner : TComponent); override;
              destructor Destroy; override;
              published
              { Published-Deklarationen }
              property Rechteck : TRechteck read FRechteck write FRechteck;

              end;

              procedure Register;

              implementation

              constructor TMYGraphicControl.Create(AOwner: TComponent);
              begin
              inherited Create(AOwner);
              FRechteck := TRechteck.Create;

              end;
              destructor TMYGraphicControl.Destroy;
              begin
              FRechteck.Free;
              inherited Destroy;
              end;

              procedure TFlaeche.Assign(Source: TPersistent);
              begin
              if Source is TFlaeche then
              begin
              FBrush.Assign(TFlaeche(Source).Brush);
              end else inherited Assign(Source);
              end;

              procedure TFlaeche.SetBrush(Value: TBrush);
              begin
              FBrush.Assign(Value);
              end;

              procedure TRechteck.SetFlaeche(Value: TFlaeche);
              begin
              FFlaeche.Assign(Value);
              end;

              procedure Register;
              begin
              RegisterComponents('MyKomp', [TMYGraphicControl]);
              end;

              end.

              Leider kann ich auf die Fläche noch nicht zugreifen. Fehlermeldung' Keine Expandierung
              möglich'. Was mache ich noch falsch?

              mfg Klau

              Comment


              • #8
                Deine Rechteck Property sollte immer mit einer Setter Methode arbeiten, also immer:

                <pre>

                published
                property Rechteck: TRechteck read FRechteck <b>write SetRechteck</b>;

                </pre>

                In .SetRecheck() dann immer mit FRechteck.Assign(Value); arbeiten.<br>

                Genau diesen Sachverhalt wollte ich herrausarbeiten, da er absolut notwendig ist wenn deine Komponente zur Designzeit die IDE NICHT abschießen soll.<br>

                Gruß Hage

                Comment


                • #9
                  Habe das dann so gemacht,
                  TMYGraphicControl = class(TGraphicControl)
                  private
                  { Private-Deklarationen }
                  FRechteck : TRechteck;
                  procedure SetRechteck(Value: TRechteck);
                  protected
                  { Protected-Deklarationen }
                  public
                  { Public-Deklarationen }
                  constructor Create(AOwner : TComponent); override;
                  destructor Destroy; override;
                  published
                  { Published-Deklarationen }
                  property Rechteck : TRechteck read FRechteck write SetRechteck;

                  procedure TMYGraphicControl.SetRechteck(Value: TRechteck);
                  begin
                  FRechteck.Assign(Value);
                  end;

                  Habe aber immer noch den gleiche Fehler 'keine Expandierung möglich'. Ich verstehs nicht.

                  mfg Klau

                  Comment


                  • #10
                    So, jetzt wirds aber komplizierter. Wir müssen dieser neuen Klasse einen Eigenschaftseditor zuweisen damit der Objectinstektor diese auch kennt.<br>

                    Dazu muß deine Komponete in ein eigenes Laufzeit Package installiert werden. Das, nehme ich an, hast'e sowieso schon so erledigt.<br>
                    Darin darf NICHT RegisterComponent() enthalten sein.
                    Nun benötigen wir ein zweites Packages das aber nur ein Designtime Packages sein darf. Dahinein kommt nun die Procedure <b>Register</b> mit dem Aufruf RegisterComponent().<br> Zusätzlich kommt nun noch der Aufruf RegisterPropertyEditor(TypInfo(TRechteck), nil, '', TClassPropertyEditor);<br>
                    Dieses Designtime package benutzt in den Required Packages dein Laufzeitpackage in dem deine TPanel Komponenten drinnen ist. Nur dieses DesignTime Package wird dann in der IDE über Menu\Komponente\Package installieren... installiert.<br>

                    Gruß Hage

                    Comment


                    • #11
                      Ok danke für den Tip.
                      Ich werde mal schauen ob ich das hinkriege.

                      Gruß Klau

                      Comment


                      • #12
                        Hallo Hagen,

                        habs endlich hingekriegt.
                        Nochmals vielen Dank für Deine
                        Hilfe.

                        mfg Klau

                        Comment

                        Working...
                        X