Grafische Komponenente



  • Hallo,

    ich möchte eine grafische Komponente mit zunächst einer property IMColor erstellen.

    static inline void ValidCtrCheck(TComponent1 *)
    {
    	new TComponent1(NULL);
    }
    //---------------------------------------------------------------------------
    __fastcall TComponent1::TComponent1(TComponent* Owner)
    	: TComponent(Owner)
    {
    	Image = new TImage(Owner);
         Image->Parent 	= ((TWinControl*)Owner)->Parent;
         Image->Height 	= 100;
         Image->Width  	= 100;
         Image->Visible	= true;
    	IMColor		= clRed;
         DrawGrafValue();
    }
    //---------------------------------------------------------------------------
    namespace Component1
    {
    	void __fastcall PACKAGE Register()
    	{
    		TComponentClass classes[1] = {__classid(TComponent1)};
    		RegisterComponents("Standard", classes, 0);
    	}
    }
    //---------------------------------------------------------------------------
    //
    //---------------------------------------------------------------------------
    void TComponent1::DrawGrafValue(void)
    {
    	Image->Canvas->Brush->Color = IMColor;
         Image->Canvas->FillRect(Rect(0,0,Image->Width,Image->Height));
    }
    

    Wie muss ich nun vorgehen, das die Komponente immer wieder neu
    gezeichnet wird. (Paint?)



  • die komponenten von TGrapicControl ableiten und nicht von TComponent und die methode

    virtual void  __fastcall Paint(void);
    

    ueberschreiben.



  • //---------------------------------------------------------------------------
    __fastcall TGraphicControl1::TGraphicControl1(TComponent* Owner)
    	: TGraphicControl(Owner)
    {
    	Image = new TImage(Owner);
         Image->Parent 	= ((TWinControl*)Owner)->Parent;
         Image->Height 	= 100;
         Image->Width  	= 100;
         Image->Visible	= true;
    	IMColor		= clRed;
    }
    //---------------------------------------------------------------------------
    void __fastcall TGraphicControl1::Paint(void)
    {
    	DrawGrafValue();
    }
    //---------------------------------------------------------------------------
    // Zeichnet eine Balckengrafig
    //---------------------------------------------------------------------------
    void TGraphicControl1::DrawGrafValue(void)
    {
    	Image->Canvas->Brush->Color = IMColor;
         Image->Canvas->FillRect(Rect(0,0,Image->Width,Image->Height));
    }
    

    Habe das ganze nun von TGraphicControl abgeleitet sowie die virtuelle Funktion
    Paint überschrieben, ändere ich nun die Eigenschaft Farbe der Componente tu sich aber nichts.



  • Hallo,

    Du mußt dafür sorgen, dass Paint nach Ändern der Frabe auch aufgerufen wird. Wenn die Änderung von IMColor über eine set-Methode erfolgt (evtl. in einer Property) dann ruftst du einfach dort Repaint() auf. Wenn IMColor einfach nur eine Membervariable ist, mach eine Property draus.



  • Du mußt dafür sorgen, dass Paint nach Ändern der Frabe auch aufgerufen wird. Wenn die Änderung von IMColor über eine set-Methode erfolgt (evtl. in einer Property) dann ruftst du einfach dort Repaint() auf. Wenn IMColor einfach nur eine Membervariable ist, mach eine Property draus.

    Jo alles klar.

    Wie kann ich nun noch dafür sorgen das die Komponenete schon zur Entwurfszeit
    auf dem Formular sichtbar wird und bei Änderung einer Property im
    Objektinspektor neu gezeichznet wird?



  • Hallo

    das passiert automatisch, wenn du wie beschrieben ableitest und Paint() benutzt.
    Und wenn du bei den Settern der Eigenscvhaften, die du im OI anzeigen läßt, auch entsprechend die Repaint-Methode aufrufst.

    bis bald
    akari



  • Mit einem Setter lässt sich nun die Eigenschaft Color auch zur Entwurfszeit
    ändern.

    Habe nun ein anderes Problem, beim plazieren der Komponente existieren nun
    zwei Komponenten. Einmal die von mir erstellte mit der entsprechenden
    Eigenschaft Color, sowie eine weitere ohne Namen die alle Eigenschaften von
    einem Image hat. Bei dieser Komponente ändert sich dann auch die Farbe.
    Meine eigentliche Komponente bleibt dabei unsichtbar.

    //---------------------------------------------------------------------------
    class PACKAGE TGraphicControl1 : public TGraphicControl
    {
    private:
    TImage *Image;
    TColor IMColor;
    void __fastcall Paint(void);
    void __fastcall SetIMColor(TColor NewColor);
    void DrawGrafValue(void);
    __published:
    	__property TColor Color = {read=IMColor,write=SetIMColor};
    protected:
    public:
    	__fastcall TGraphicControl1(TComponent* Owner);
    
    //---------------------------------------------------------------------------
    
    //---------------------------------------------------------------------------
    __fastcall TGraphicControl1::TGraphicControl1(TComponent* Owner)
    	: TGraphicControl(Owner)
    {
    	Image = new TImage(Owner);
         Image->Parent 	= ((TWinControl*)Owner);
         Image->Height 	= 100;
         Image->Width  	= 100;
         Image->Visible	= true;
    	IMColor		= clRed;
    }
    //---------------------------------------------------------------------------
    void __fastcall TGraphicControl1::SetIMColor(TColor NewColor)
    {
    	if(Image) IMColor = NewColor;
         Repaint();
    }
    //---------------------------------------------------------------------------
    void __fastcall TGraphicControl1::Paint(void)
    {
    	DrawGrafValue();
    }
    //---------------------------------------------------------------------------
    // Zeichnet eine Balckengrafig
    //---------------------------------------------------------------------------
    void TGraphicControl1::DrawGrafValue(void)
    {
    	Image->Canvas->Brush->Color = IMColor;
         Image->Canvas->FillRect(Rect(0,0,Image->Width,Image->Height));
    }
    


  • Hallo

    und wo ist jetzt das Problem? Ich sehe keine Frage.

    bis bald
    akari



  • Meine Frage über dem Source Code.

    Habe nun ein anderes Problem, beim plazieren der Komponente existieren nun
    zwei Komponenten. Einmal die von mir erstellte mit der entsprechenden
    Eigenschaft Color, sowie eine weitere ohne Namen die alle Eigenschaften von
    einem Image hat. Bei dieser Komponente ändert sich dann auch die Farbe.
    Meine eigentliche Komponente bleibt dabei unsichtbar.



  • Hallo

    ich sehe immer noch nicht, was du nun von uns wissen willst. Was stört dich an den beschriebenen Fakten? Wie soll es werden?

    bis bald
    akari



  • mal ein paar anmerkungen...

    das Paint sollte wie bereits von mir geschrieben virtual sein, denn sonst kannst du mal später nicht von deiner komponente ableiten und das Paint in der abgeleiteten Version verwenden. (bin grad nicht sicher... oder hiess einmal virtual immer virtual?)

    wieso bekommt das TImage den selben Owner wie deine komponente und nicht die komponente selbst?

    Image         = new TImage(this);
    Image->Parent = this;
    

    ausserdem ist ein name wie TGraphicControl1 ziemlich blöd gewählt, führt schnell dazu sich zu verlesen, da auch die 1 (eins) kaum von l (L) zu unterscheiden ist...



  • Sunday schrieb:

    (bin grad nicht sicher... oder hiess einmal virtual immer virtual?)

    Genau so ist es.



  • Noch mal zur Sicherheit der Standard: Kapitel 10.3 2

    If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name and same parameter list as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.



  • Image = new TImage(this);
    Image->Parent = this;

    Ok, Owner von Image sollte natürlich meine Komponenete sein, ebenfalls
    das Parent von Image.

    Image->Parent = this; //Parent ist meine Komponente

    gibt eine Fehlermeldung "... TTemp *const nach TWinControl* nicht möglich.

    Caste ich den Pointer this auf TWinControl
    Image->Parent = ((TWinControl*)Owner)this;
    kommt der Fehler zwar nicht mehr, dafür gibt es beim benutzen der Komponenete
    eine Zugrifsverletzung.



  • Hallo

    das liegt ja auch daran, das TGraphicControl nicht von TWinControl abgeleitet ist, und damit auch nicht dein TGraphicControl1. Damit kannst du zwar diesen harten C-Style Cast machen, aber das Ergbnis ist in jedenfall fehlerhaft. Mit einem static_cast stattdessen hätte dich der Compiler davor gewarnt.

    Du must als Parent in deinem Fall den Parent von dem TGraphicControl1 übergeben

    Image->Parent = Parent;
    

    bis bald
    akari



  • Hallo,

    das liegt ja auch daran, das TGraphicControl nicht von TWinControl abgeleitet ist, und damit auch nicht dein TGraphicControl1. Damit kannst du zwar diesen harten C-Style Cast machen, aber das Ergbnis ist in jedenfall fehlerhaft. Mit einem static_cast stattdessen hätte dich der Compiler davor gewarnt.

    Ok, da TGraphicControl nicht von TWinControl abgeleitet ist darf ich den Pointer natürlich nicht auf TWinControl casten.

    Mein Code sieht nun folgendermassen aus.

    class PACKAGE TTemp : public TGraphicControl
    {
    private:
    TImage *Image;
    TColor IMColor;
    void __fastcall Paint(void);
    void __fastcall SetIMColor(TColor NewColor);
    void DrawGrafValue(void);
    __published:
        __property TColor Color = {read=IMColor,write=SetIMColor};
    protected:
    public:
    	__fastcall TTemp(TComponent* Owner);
    };
    
    //---------------------------------------------------------------------------
    __fastcall TTemp::TTemp(TComponent* Owner)
    	: TGraphicControl(Owner)
    {
        Image = new TImage(this);
        Image->Parent = Parent;    //Parent des erstellten Objects
        Image->Height     = 100;
        Image->Width      = 100;
        Image->Visible    = true;
        SetIMColor(clRed);
    }
    //---------------------------------------------------------------------------
    void __fastcall TTemp::SetIMColor(TColor NewColor)
    {
        if(Image) IMColor = NewColor;
         Repaint();
    }
    //---------------------------------------------------------------------------
    void __fastcall TTemp::Paint(void)
    {
        DrawGrafValue();
    }
    //---------------------------------------------------------------------------
    // Zeichnet eine Balckengrafig
    //---------------------------------------------------------------------------
    void TTemp::DrawGrafValue(void)
    {
        Image->Canvas->Brush->Color = IMColor;
         Image->Canvas->FillRect(Rect(0,0,Image->Width,Image->Height));
    }
    

    Nun wird die Komponenete trotz Repaint nicht mehr gezeichnet.



  • probiere mal statt Repaint ein Invalidate();...

    Repaint bzw. Invalidate brauchst du auch nur aufrufen, wenn sich eine eigenschaft auch wirklich geändert hat.



  • Invalidate() funktioniert auch nicht.

    Selbst nach dem Progstart und Änderung der Eigenschaft Color durch Button1Click
    taucht die Grafig nicht auf, obwohl der Setter SetIMColor ausgeführt wird (mit Break getestet).

    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    	Temp1->Color = clBlue;
    }
    


  • Wenn der Parent des Image der Parent der Komponente ist, wird das Image doch eigentlich auch da gezeichnet. Im Objektinspektor also garnicht.
    Warum eigentlich das Image? Eine von TGraphicControl abgeleitete Komponente hat doch ein eigens Canvas auf dem man zeichnen kann. Das könnte man doch einfach nehmen. Genau dafür ist TGraphicControl doch da.



  • Warum eigentlich das Image? Eine von TGraphicControl abgeleitete Komponente hat doch ein eigens Canvas auf dem man zeichnen kann. Das könnte man doch einfach nehmen. Genau dafür ist TGraphicControl doch da.

    Stimmt, das mit dem Image kann ich mir sparen.

    //---------------------------------------------------------------------------
    __fastcall TTemp::TTemp(TComponent* Owner)
    	: TGraphicControl(Owner)
    {
        Height     = 100;
        Width      = 100;
        SetIMColor(clRed);
    }
    //---------------------------------------------------------------------------
    void __fastcall TTemp::SetIMColor(TColor NewColor)
    {
            IMColor = NewColor;
    	Repaint();
    }
    //---------------------------------------------------------------------------
    void __fastcall TTemp::Paint(void)
    {
        DrawGrafValue();
    }
    //---------------------------------------------------------------------------
    // Zeichnet eine Balckengrafig
    //---------------------------------------------------------------------------
    void TTemp::DrawGrafValue(void)
    {
        Canvas->Brush->Color = IMColor;
         Canvas->FillRect(Rect(0,0,Width,Height));
    }
    

    So gehts.



  • Hi,
    ich würd das so machen:

    void __fastcall TTemp::SetIMColor(TColor NewColor)
    {
          if (IMColor != NewColor) {
                IMColor = NewColor;
          	Repaint();
          }
    }
    

    Dann wirds nur beim tatsächlichen Ändern neugezeichnet.

    MfG

    Alexander Sulfrian


Anmelden zum Antworten