Komponentenentwickulung Eigenschaft mit Untereigenschaft erstellen



  • Ich hab mich jetzt dazu entschlossen, meine benötogete Comm-Port-Kompo doch selber zu schreiben, weil ich so gleich nochwas lerne.

    Und schon gibts die ersten Probleme.

    Ich möchte eine EIGENschaft DCB erstellen mit den dazugehörigen Untereigeschaften. Also wie bei TEdit, da gibts z. Bsp. Font und als Untereigenschaft Height oder Color. Bei mir wäre das in dem Beispiel DCB und dann z. Bsp. BaudRate.

    Hab schon in der BCB Hilfe geschaut aber nix gefunden, wobei ich nicht ausschliese das es dort steht, wenn man nur weis unter was man suchen muss.

    Kann mir jemand helfen?

    P.S. Und wie bekomme ich da ne Auswahliste mit verschiedenen werten, wie zum Beispiel bei den BorderStyles, hin.



  • Verwende dazu eine andere Klasse die von TObject (vielleicht auch nicht;) ) ableitet. Dann müssen alle Members die im Objektinspektor (oder wie das heißt) angezeigt werden müssen unter __published: stehen. Die Klasse muss auch unter __published: In Deiner Komponente stehen. Die BorderStyles funktionieren mit dem Typ Set oder set (vielleicht auch nicht) schau es in der Hilfe nach. Wenn Du aber einen speziellen Editor verwenden willst Um die Klasse zu modizifieren (wie z.B. bei TMainMenu) dann musst Du diesen selbst erstellen, wie das geht weiß ich leider (noch) nicht, aber soweit ich weiß werden die Quelltexte mitgeliefert.



  • Also ich bin soweit, das ich weis bzw. vermute das ich eine eigene Klasse von TPropertyEditor bleiten und dann für meine Kompo registrieren muss. Allerdings habe ich nicht herausfinden können, wie ich da die verschiedenen Werte, die zur Auswahl stehen hineinbringe. Und das mit dem erweiterbaren Eigenschaften hab ich auch noch nicht gefunden.



  • wie bereits im anderen Thread erwähnt:

    was du brauchst ist ein Set.

    Sets werden automatisch so angezeigt.

    Siehe auch:
    http://www.c-plusplus.net/forum/viewtopic.php?t=42520&highlight=tsetproperty



  • Ich habs jetzt mit einem TSet probiert aber das Ergebnis war nicht das was ich will bzw. das habe ich schon anders gelösst.

    Ist TSet immer bool, ich ha da zumindest immer bool erhalten.

    Mein Probelm ist ich hab z. Bsp die Eigenschaft BaudRate. In diese soll man im Objectinspector reinklicken und aus einer Liste einen auswählen können welcher dann gesetzt wird.

    Ich probier nun schon zwei Tage rum aber das wird einfach nix.



  • Hier ein Beitrag zum Thema von Bigwill aus einem anderen Thread:

    Bigwill schrieb:

    Auf den Beitrag hier drüber hin, habe ich gerade folgendes probiert.

    class  PACKAGE CDCB : public TPersistent
    {
    private:
            DCB FDCB;
    
    public:
    
    __published:
            __property DWORD BaudRate = {read=FDCB.BaudRate, write=FDCB.BaudRate};
            __property DWORD fBinary  = {read=FDCB.fBinary , write=FDCB.fBinary };
            __property DWORD fParity  = {read=FDCB.fParity,  write=FDCB.fParity };
    };
    #endif
    
    #include "CDCB.h"
    //---------------------------------------------------------------------------
    class PACKAGE TComm : public TComponent
    {
    private:
      DCB FDCB;
      CDCB* myDCB;
    
    protected:
              void __fastcall SetBaudRate(DWORD br){FDCB.BaudRate=br;}
    
    public:
              __fastcall TComm(TComponent* Owner);
              __fastcall ~TComm();
    
    __published:
              __property DWORD BaudRate = {read=FDCB.BaudRate, write=SetBaudRate};
              __property CDCB *DCB_Settings = {read=myDCB, write=myDCB};
    
    };
    //---------------------------------------------------------------------------
    

    Aber irgendwie kommt da keine Liste bei mir. Muss man beim kompilieren eventl. noch was bestimmtes einstellen?

    @Bigwill : Bitte mit dem Thema in diesem Thread bleiben, damit das Thema zusammenbleibt.



  • Bigwill schrieb:

    Ich möchte eine EIGENschaft DCB erstellen mit den dazugehörigen Untereigeschaften. Also wie bei TEdit, da gibts z. Bsp. Font und als Untereigenschaft Height oder Color. Bei mir wäre das in dem Beispiel DCB und dann z. Bsp. BaudRate.

    Für diese Werte gibs jeweils einen Property- Editor. Für Komponenten, die sich in einer Komponente befinden benutzt man in der Regel SetSubComponent(true) um die Eigenschaften der Sub-Komponete im Objektinspektor sichtbar zu machen.

    Bigwill schrieb:

    P.S. Und wie bekomme ich da ne Auswahliste mit verschiedenen werten, wie zum Beispiel bei den BorderStyles, hin.

    Dafür muss man ein Property- Editor ableiten.

    ICh versuch heute abend oder morgen ein Beipiel hinzubekommen...



  • Danke, das ist sehr nett.



  • AndreasW schrieb:

    Hier ein Beitrag zum Thema von Bigwill aus einem anderen Thread:

    class  PACKAGE CDCB : public TPersistent
    {
    private:
            DCB FDCB;
    
    public:
    
    __published:
            __property DWORD BaudRate = {read=FDCB.BaudRate, write=FDCB.BaudRate};
            __property DWORD fBinary  = {read=FDCB.fBinary , write=FDCB.fBinary };
            __property DWORD fParity  = {read=FDCB.fParity,  write=FDCB.fParity };
    };
    #endif
    

    Ist es nicht eine Rekursion?

    In dem Text den ich oben gepostet habe sind auch Fehler, z.B. muss man von TPersisten ableiten und nicht von TObjekt, und der Datentyp für BorderStyles ist Set.



  • hallo,

    eine komponente wird je nachdem was sie später darstellen bzw. leisten soll abgeleitet. eine kompo die zur entwurfszeit sichtbar sein soll damit man eigenschaften im oi editieren kann zur laufzeit aber unsichtbar ist (wie z. B. TOpenDialog) wird i. d. Regel von TComponent abgeleitet. alles was vor TComponent kommt ist noch keine komponente im sinne der cbuilder kompos sondern lediglich eine klasse (diese kann aber nicht im oi angezeigt werden). es wäre also sinnvoll die TComPort-Kompo von TComponent abzuleiten. Sets sind mengen, und eine menge mathematisch definiert ist etwas, das etwas enthalten kann oder eben auch nicht (deshalb bool) ist_enthalten=true; ist_nicht_enthalten=false. megen werdem im cbuilder folgendermaßen definiert:

    Set<type, minval, maxval>
    

    man kann mengen durch die schiebeoperatoren << >> etwas zuweisen bzw. herausholen. dann gibt es noch die funktion contains hiermit kann man prüfen, ob etwas enthalten ist oder nicht

    for (int i = 0; i < 255; i++)
      if (A.Contains(i))
        Memo1->Lines->Add(i);
    

    der unterschied zwischen einer menge und einem aufzählungstyp ist, bei einem aufzählungstyp kann man immer nur eines wählen, während bei einer menge 0,1 oder viele ausgewählt werden können. in der praxis existieren jedoch für viele mengen auch entsprechende aufzählungstypen. hier ein in der praxis nachvollziehbares beispiel:

    //Header:
    enum TAbc //Aufzählungstyp
    {
            Eins, Zwei, Drei
    };
    
    typedef Set<TAbc, Eins, Drei> TAbcSet; //Mengentyp bzw. Set.
    
    class TForm1 : public TForm
    {
    __published:	// Von der IDE verwaltete Komponenten
            TButton *Button1;
            void __fastcall Button1Click(TObject *Sender);
    private:
            TAbcSet FAbc;
    public:		// Anwender-Deklarationen
            __fastcall TForm1(TComponent* Owner);
    };
    
    //CPP
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
         FAbc<<Eins<<Zwei<<Drei;
         if (FAbc.Contains(Eins))
            ShowMessage("ja");
    }
    

    nachdem du zu deiner Set-Definition entsprechende propertys im published bereich deklariert hast, erscheint das ganze bereits wie gewollt im oi.

    __published:
      __property TAbcSet Abc = {read=FAbc,write=FAbc}
    

    wobei du für die read/write direktive jeweils deine eigenen zugriffsmethoden angeben musst falls vorhanden...

    mfg
    murph



  • Was Bigwill möchte ist sowas im Objektinspektor ( wenn ich richtig liege):
    solch eine EIgenschaft:

    + Optionen
    

    expandiert:

    - Optionen    [eine zusammenfassung]
        Name      com-Port1           // String   
        BaudRate  4                   //DWORD  
        fBinary   9                   //DWORD  
        fParity   6                   //DWORD   
        connect   true                // bool- Wert
    

    also verschiedene Typen und keine reinen bool- Werte wie Sets.
    Das mach die Sache etwas schwieriger. Müsste aber gehn..



  • class  PACKAGE CDCB : public TPersistent 
    { 
    private: 
            DCB FDCB; 
    
    public: 
    
    __published: 
            __property DWORD BaudRate = {read=FDCB.BaudRate, write=FDCB.BaudRate}; 
            __property DWORD fBinary  = {read=FDCB.fBinary , write=FDCB.fBinary }; 
            __property DWORD fParity  = {read=FDCB.fParity,  write=FDCB.fParity }; 
    }; 
    #endif
    

    Diese Klasse sollte nur als Aufnahme für die DCB Struktur dienen, da ich irgendwo (keine Ahnung mehr wo) gelesen hatte, das man solche Eigenschaften nicht aus Strukturen erstellen kann und DCB ist ja nunmal eine Struktur.

    Meine richtige Kompontene ist natürlich von TComponent abgeleitet und enthält dann diese Klasse. Damit hatte ich auch schon mein erstes Proplem gelösst, nähmlich das in der Entwicklungsumgebung alle Eigenschaften der DCB Struktur, als Unterelement von DCB angezeigt wurden (also so zum aufklappen, wie zum Bsp. bei Font).

    Dies geht aber auch noch ganz anders und ich bin schon auf den Code von Andres gespannt. Aber viel wichtiger ist halt im moment die Implementierung ines Aufzählunstyps. Ich weis das ich dazu irgendeine T....property ableiten muss, nur nicht welche und wie. Bzw. wo man das ganze dann in der Komponente hinschreibt und registriert. Dieen "List-Typ" wollte ich dann z. Bsp. für die Eigenschaft BaudRate der DCB Struktur benutzen, da es dafür verschiedene #define's gibt die mann dann darin auswählen können sollte. Oder für die Stopbits wo man dann zwischen 1 1,5 und 2 wählen kann (also ich brauche keinen Mengentyp, da immer nur eins gültig ist.

    Aber ich warte jetzt mal auf Andreas nächstes Posting oder eines von euch anderen, welcher ein kleins Bsp. dazu zur Verfügung stellt.

    Also einmal eine Struktur so kapseln, das man au deren Eigenschaften als Sub zugreifen kann und dann eine dieser Eigenschaften als Liste.

    Danke schonmal an alle die helfen.

    P.S. nicht das ihr denkt ich bin faul-hab dazu schon in mehreren Büchern und der Hilfe Brocken zusammengesucht, nur was wirklich funktionierendes ist halt bis jetzt nicht rausgekommen. Dazu kommen dann auch immer noch ein paar nette Fehlermeldungen der IDE, wozu die Hilfe nur schreibt, man soll Boröland informieren, wenn sowas kommt. 😃 Also mach ich quasie für die Bugsucher.

    P.S.S Andreas war nehn Moment schneller aber er hat verstanden was ich möchte. Wobei bei seinem Beispiel Option die DCB-Struktur sein sollte und die Eigenschaften dieser Struktur dann das was unten aufgeht.
    Und eine der Eigenschaften sollte dann halt noch eine Liste sein, so als Bsp.



  • ähm,

    hab mir deine Ansätze noch mal angeschaut.
    Du Nasenbär hast bestimmt vergessen die Instanz zu erzeugen 😃

    wie wäre es mit :

    myDCB=new CDCB;
    

    im Konstruktor von TComm ?

    nur mal so geraten... 🙂



  • und ich bin schon auf den Code von Andres gespannt

    ich hatte mal wieder zu weit gedacht. Natürlcih reicht es aus eine Klasse zu erzeugen, die die Properties enthält. Sie muss natürlich mindestens von TPersitent abgeleitet sein, weil dort die Speicherroutinen für die Formulardatei implementiert wurden.

    Mein anderer Ansatz wäre über die Kombination von zwei Eigenschaftseditoren.
    Den Haupteditor abgeleitet von TOrdinalProperty und für jede untergeordnete Eigenschaft einen entsprechenden Eigenschaftseditor. Als Basis dient dazu eine Ableitung von TNestedProperty.

    Dieser Weg ist allerding recht schwierig, weshalb ich ihn jetzt aus Zeitgründen nicht nachstelle. Im Tutorial werde ich aber versuchen ein möglichst gelungenes Beispiel zu geben.



  • Ne hatte ich nicht, wirklich. 😃
    Aber was ich Nasenbär vergessen hatte bzw. da noch nich wusste ist, das ich aus welchem Grund auch immer einfac nochmal auf Komponente installieren gehen musste. hab die Kompo quasie nochmal drüber installiert, dann ging es. Manchmal übernimmt der bei mir Änderungen an der Kompo komischerweise nähmlich nicht gleich in die, die ich in die KOmpopalette eingefügt habe.

    P.S. Ich war das übrigens auch mit der Mail an dich, brauchst also nicht hetzen mit dem Bsp. für mich (nicht das du für mich Überstunden machst) - ich probier einfach weiter den Builder zum Absturz zu bringen und das kann ich inzwischen echt gut. 😃 😃

    Andreas war schon wieder schneller. *grml
    Aber wie implementier ich den nun in obrige Klasse so ne Liste als Eigenschaft?



  • enum TListe{Wert1,Wert2,Wert3};
    class  PACKAGE CDCB : public TPersistent  
    {  
    private:  
            DCB FDCB;  
       TListe FListe;
    public:  
    
    __published:  
            __property DWORD BaudRate = {read=FDCB.BaudRate, write=FDCB.BaudRate};  
            __property DWORD fBinary  = {read=FDCB.fBinary , write=FDCB.fBinary };  
            __property DWORD fParity  = {read=FDCB.fParity,  write=FDCB.fParity };  
            __property TListe Liste= {read=FListe,  write=FListe};  
    };  
    #endif
    

    😉



  • Bigwill schrieb:

    P.S. Ich war das übrigens auch mit der Mail an dich, brauchst also nicht hetzen mit dem Bsp. für mich (nicht das du für mich Überstunden machst) - ich probier einfach weiter den Builder zum Absturz zu bringen und das kann ich inzwischen echt gut. 😃 😃

    hehe, ja, da bin ich auch Meister drin... 🙂



  • Cool, das hatte ich so auch schon mal, nur mit anderen Bezeichnern. Nur dann hat wieder der Builder rumgesponnen und die Auswahlliste immer leer gelassen.

    Aber dann mach ich ahlt mal wiedr ein neues Projekt.

    Dann müsste ich aber doch noch eine Read and write Methode implementieren, da ja beim lesen und schreiben auch gleichzeitig der Wert in der DCB Struktur geämdert werden muss, stimmst?

    void __fastcall SetBaudRate(TListe wert)
    {
      switch(wert)
      {  
        case 0:
          FDCB.BaudRate = 100;
          Liste = wert;
          break:
       case 1:
        .....
      };
    }
    

    So in etwa, war jetzt trocken, müsste das gehen? Nur bei der read ätte ich jetzt auf Anhieb keine Ahnung wie ich das mache, ist bestimmt zuuuuuu einfach.



  • Aktueller Stand:

    enum TListe{Wert1,Wert2,Wert3};
    
    //---------------------------------------------------------------------------
    class  PACKAGE CDCB : public TPersistent
    {
    private:
       DCB FDCB;
       TListe FListe;
    public:
    
    protected:
          void __fastcall SetBaudRate(int wert)
          {
              switch(wert)
              {
                case 0:
                      FDCB.BaudRate = 100;
                      FListe = Wert1;
                      break;
                case 1:
                      FDCB.BaudRate = 200;
                      FListe = Wert2;
                      break;
                default:
                      FDCB.BaudRate = 300;
                      FListe = Wert3;
                      break;
              };
          }
    
    __published:
            //__property DWORD BaudRate = {read=FDCB.BaudRate, write=FDCB.BaudRate};
            __property DWORD fBinary  = {read=FDCB.fBinary , write=FDCB.fBinary };   
            __property DWORD fParity  = {read=FDCB.fParity,  write=FDCB.fParity };   
            __property TListe BaudRate= {read=FListe,  write=SetBaudRate};
    };   
    
    //---------------------------------------------------------------------------
    
    class PACKAGE TComm : public TComponent
    {
    private:
         CDCB *FDCB;
    
    protected:
    
    public:
            __fastcall TComm(TComponent* Owner);
    
    __published:
            __property CDCB *DCB = {read=FDCB, write=FDCB};
    
    };
    //---------------------------------------------------------------------------
    #endif
    

    Leider meckert er folgendermassen:

    [C++ Fehler] Comm.h(49): E2347 Keine Entsprechung der Parameter in write mit Zugriffsspezifikation der Eigenschaft BaudRate

    Ich weis aber nicht was der fürn Parameter erwartet ich dachte ein enum ist vom Typ her int??

    Oder ist das so agnz verkehrt?



  • Hi Michael,

    SetBaudRate(int wert)
    

    Der Parameter in der Funktion muss den selben Typ haben wie die Eigenschaft. Hier also DWORD

    SetBaudRate(DWORD wert)
    

    wäre also besser...


Anmelden zum Antworten