![]() |
Komponente mit TPaintBox: kann nicht mit Canvas zeichenen
hallo
ich habe eine selbstentwickelte komponente, aber wenn ich diese auf ein formular platzieren möchte, dann kommt die fehlermeldung "Element '' hat kein übergeordnetes Fenster". ich habe die kompo mit TPaintBox entwickelt und möchte in dieser einen pfeil anzeigen, den ich selber mit LineTo zeichnen möchte. es liegt an die folgende procedure:
Delphi-Quellcode:
lösche ich diese 2 zeilen, dann kann ich die komponente aufs formular setzen.
function TPfeil.MalZiffer : boolean;
var i : integer; BreiteQuad,HoeheQuad : integer; begin self.canvas.MoveTo(0,0); self.canvas.LineTo(1,1); end; sind diese beiden zeilen vorhanden, dann kommt die fehlermeldung (siehe oben) hier der ganze quelltext:
Delphi-Quellcode:
weiß jemand, wodran es liegen kann?
unit Pfeil;
interface uses SysUtils, Classes, Controls, ExtCtrls, Graphics, Dialogs,Forms ; type TPfeil = class(TPaintBox) private { Private-Deklarationen } FZiffer : Integer; FZifferRandX : Integer; FZifferRandY : Integer; FZifferLueckeX : Integer; FZifferLueckeY : Integer; FZifferHFarbe : TColor; //Hintergrundfarbe FZifferRFarbe : TColor; //Randfarbe FZifferQuadRand: Integer; //Randbreite FWidthX : integer; procedure SetZiffer(Value : Integer); procedure SetZifferRandX(Value : Integer); procedure SetZifferRandY(Value : Integer); procedure SetZifferLueckeX(Value : Integer); procedure SetZifferLueckeY(Value : Integer); procedure SetZifferHFarbe(Value : TColor); procedure SetZifferRFarbe(Value : TColor); procedure SetZifferQuadRand(Value : Integer); procedure Resize; override; //Komponente wird zur Designerzeit verändert function MalZiffer : boolean; function MalQuadraht(x,y,w:integer;RFarbe,HFarbe:TColor):boolean; function ZifferAnz : boolean; protected { Protected-Deklarationen = Im Modul und alle abgeleiteten Klassen} public { Public-Deklarationen = zur Laufzeit} constructor Create(AOwner : TComponent); override; published { Published-Deklarationen = Im Objektinspector sichtbar, Designmodus } property Ziffer: Integer read FZiffer write SetZiffer; property ZifferRandX : Integer read FZifferRandX write SetZifferRandX; property ZifferRandY : Integer read FZifferRandY write SetZifferRandY; property ZifferLueckeX : Integer read FZifferLueckeX write SetZifferLueckeX; property ZifferLueckeY : Integer read FZifferLueckeY write SetZifferLueckeY; property ZifferHFarbe : TColor read FZifferHFarbe write SetZifferHFarbe; property ZifferRFarbe : TColor read FZifferRFarbe write SetZifferRFarbe; property ZifferQuadRand : Integer read FZifferQuadRand write SetZifferQuadRand; end; procedure Register; implementation procedure Register; begin RegisterComponents('Ed', [TPfeil]); end; //--------------------------------------------------------------------- constructor TPfeil.Create(AOwner : TComponent); var i : integer; begin inherited; FZifferRandX := 1; FZifferRandY := 1; FZifferLueckeX := 2; FZifferLueckeY := 2; FZifferHFarbe := clYellow; FZifferRFarbe := clRed; MalZiffer; end; //--------------------------------------------------------------------- procedure TPfeil.SetZiffer(Value: Integer); begin FZiffer := Value; MalZiffer; //Funktion Ziffer malen ZifferAnz; //Ziffer Anzeigen end; //--------------------------------------------------------------------- procedure TPfeil.SetZifferRandX(Value: Integer); begin if Value <> FZifferRandX then begin FZifferRandX := Value; MalZiffer; //Funktion Ziffer malen end; end; //--------------------------------------------------------------------- procedure TPfeil.SetZifferRandY(Value: Integer); begin if Value <> FZifferRandY then begin FZifferRandY := Value; MalZiffer; //Funktion Ziffer malen end; end; //--------------------------------------------------------------------- procedure TPfeil.SetZifferLueckeX(Value: Integer); begin if Value <> FZifferLueckeX then begin FZifferLueckeX := Value; MalZiffer; //Funktion Ziffer malen end; end; //--------------------------------------------------------------------- procedure TPfeil.SetZifferLueckeY(Value: Integer); begin if Value <> FZifferLueckeY then begin FZifferLueckeY := Value; MalZiffer; //Funktion Ziffer malen end; end; //--------------------------------------------------------------------- procedure TPfeil.SetZifferHFarbe(Value: TColor); begin if Value <> FZifferHFarbe then begin FZifferHFarbe := Value; MalZiffer; //Funktion Ziffer malen end; end; //--------------------------------------------------------------------- procedure TPfeil.SetZifferRFarbe(Value: TColor); begin if Value <> FZifferRFarbe then begin FZifferRFarbe := Value; MalZiffer; //Funktion Ziffer malen end; end; //--------------------------------------------------------------------- procedure TPfeil.SetZifferQuadRand(Value: Integer); begin if Value <> FZifferQuadRand then begin FZifferQuadRand := Value; MalZiffer; //Funktion Ziffer malen end; end; //--------------------------------------------------------------------- function TPfeil.MalZiffer : boolean; var i : integer; BreiteQuad,HoeheQuad : integer; begin self.canvas.MoveTo(0,0); self.canvas.LineTo(1,1); end; //--------------------------------------------------------------------- function TPfeil.MalQuadraht(x,y,w:integer;RFarbe,HFarbe:TColor): boolean; { x,y=Koordinaten, w=Penbreite, R+HFarbe=Rand+Hintergrundfarbe } begin { Quad := TShape.Create(Self); Quad.Parent := Self; Quad.Left := 10; Quad.Top := 10; Quad.Width := 30; Quad.Height := 30; } end; //--------------------------------------------------------------------- procedure TPfeil.Resize; begin inherited; MalZiffer; end; function TPfeil.ZifferAnz: boolean; begin // end; end. muss ich Canvas vorher aktivieren ? oder darf ich es nur zur laufzeit machen ? ich möchte es aber auch zur designzeit sehen. vielen dank im vorraus |
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
1. Warum leitest du von TPaintBox ab und nicht von TGraphicControl?
2. Warum malst du nicht in der Paint Methode? Jetzt hast du das Problem, dass dein gezeichneter Pfeil im alltäglichen Gebrauch fast nie zu sehen ist. 3. Du malst direkt im Constructor - aber dort existiert dein Canvas noch nicht. Ausserdem macht es keinen Sinn dort zu zeichnen - siehe Punkt 2. 4. Deine Komponente verlangsamt das Öffnen und Laden eines Formulars deutlich, da sie bei jeder einzelnen Property-Änderung direkt wieder MalZiffer aufruft, anstatt (zusammen mit Punkt 2) z.B. Invalidate zu nutzen. Auch braucht die Komponente nicht bei einer Propertyänderung neu gezeichnet werden, wenn sie noch aus dem Formular gestreamt wird (csLoading in ComponentState). Ansonsten noch: a) Resize wird entgegen deinem Kommentar zuf Laufzeit genauso aufgerufen. Mit Punkt 2 fällt diese Methode eh als unnötig weg. b) "Male" und nicht "Mal" c) Quadrat ohne "h" |
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
vielen dank für den tip, wäre nie darauf gekommen.
ich konnte zumindest schon mal einen strich zeichnen.
Delphi-Quellcode:
type
TPfeil = class(TGraphicControl) private { Private-Deklarationen } FZiffer : Integer; FZifferRandX : Integer; FZifferRandY : Integer; FZifferLueckeX : Integer; FZifferLueckeY : Integer; FZifferHFarbe : TColor; //Hintergrundfarbe FZifferRFarbe : TColor; //Randfarbe FZifferQuadRand: Integer; //Randbreite FWidthX : integer; procedure SetZiffer(Value : Integer); procedure SetZifferRandX(Value : Integer); procedure SetZifferRandY(Value : Integer); procedure SetZifferLueckeX(Value : Integer); procedure SetZifferLueckeY(Value : Integer); procedure SetZifferHFarbe(Value : TColor); procedure SetZifferRFarbe(Value : TColor); procedure SetZifferQuadRand(Value : Integer); procedure Resize; override; //Komponente wird zur Designerzeit verändert function MalZiffer : boolean; function MalQuadraht(x,y,w:integer;RFarbe,HFarbe:TColor):boolean; function ZifferAnz : boolean; protected { Protected-Deklarationen = Im Modul und alle abgeleiteten Klassen} procedure Paint; override; //HIER DIE NEUE PAINT-PROCEDURE public { Public-Deklarationen = zur Laufzeit}
Delphi-Quellcode:
mfg edmu
procedure TPfeil.Paint;
begin with Canvas do begin //Pen := FPen; { Stift der Komponente kopieren } //Brush := FBrush; { Pinsel der Komponente kopieren } MoveTo(0,0); LineTo(10,10); end; end; |
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
hallo
ich habe jetzt der komponente die eigenschaft Pen zugeteilt
Delphi-Quellcode:
wenn ich dieses dann bei der komponente kontrolliere, dann wird in dem
unit Pfeil;
interface uses SysUtils, Classes, Controls, ExtCtrls, Graphics, Dialogs,Forms ; type TPfeil = class(TGraphicControl) private { Private-Deklarationen } FZiffer : Integer; FZifferRandX : Integer; FZifferRandY : Integer; FZifferLueckeX : Integer; FZifferLueckeY : Integer; FZifferHFarbe : TColor; //Hintergrundfarbe FZifferRFarbe : TColor; //Randfarbe FZifferQuadRand: Integer; //Randbreite FWidthX : integer; FPen : TPen; PenColor : TColor; procedure SetZiffer(Value : Integer); procedure SetZifferRandX(Value : Integer); procedure SetZifferRandY(Value : Integer); procedure SetZifferLueckeX(Value : Integer); procedure SetZifferLueckeY(Value : Integer); procedure SetZifferHFarbe(Value : TColor); procedure SetZifferRFarbe(Value : TColor); procedure SetZifferQuadRand(Value : Integer); procedure SetPen(Value : TPen); procedure SetPenColor(Value : TColor); procedure GetPen(Value : TPen); procedure Resize; override; //Komponente wird zur Designerzeit verändert function MalZiffer : boolean; function MalQuadraht(x,y,w:integer;RFarbe,HFarbe:TColor):boolean; function ZifferAnz : boolean; protected { Protected-Deklarationen = Im Modul und alle abgeleiteten Klassen} procedure Paint; override; public { Public-Deklarationen = zur Laufzeit} constructor Create(AOwner : TComponent); override; published { Published-Deklarationen = Im Objektinspector sichtbar, Designmodus } property Ziffer: Integer read FZiffer write SetZiffer; property ZifferRandX : Integer read FZifferRandX write SetZifferRandX; property ZifferRandY : Integer read FZifferRandY write SetZifferRandY; property ZifferLueckeX : Integer read FZifferLueckeX write SetZifferLueckeX; property ZifferLueckeY : Integer read FZifferLueckeY write SetZifferLueckeY; property ZifferHFarbe : TColor read FZifferHFarbe write SetZifferHFarbe; property ZifferRFarbe : TColor read FZifferRFarbe write SetZifferRFarbe; property ZifferQuadRand : Integer read FZifferQuadRand write SetZifferQuadRand; property Pen : TPen read FPen write SetPen; end; objektinspektor zwar das plus-zeichen neben Pen angezeigt und beim betätigen wird aus plus ein minus-zeichen, aber ohne ein untermenü. es müsst jetzt eigendlich Color, Style usw. kommen. wer kann mir helfen, dass ich ein untermenü sehe. mfg edmu |
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
Hast Du den Pen denn auch instanziiert?
|
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
wie mache ich das?
|
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
Delphi-Quellcode:
FPen := TPen.Create;
|
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
Und nicht vergessen: auch wieder freigeben. Also im Constructor anlegen und im Destruktor wieder freigeben.
|
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
super, hat geklappt.
ich danke dir |
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
Eine Frage noch: Was machst du in SetPen() genau? Ich hoffe du rufst
Delphi-Quellcode:
auf...
fPen.Assign(Value);
|
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
nun ja, ich mache es so:
FPen := Value; mfg edmu |
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
Nimm besser Assign (auch für die Zuweisung von FPen zu Canvas.Pen).
|
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
wenn ich jetzt etwas im objektinspektor ändere, dann
möchte ich eine showmessage ausgeben. dieses funktioniert aber leider nicht und deshalb werden die farben auch nicht übernommen.
Delphi-Quellcode:
FPen : TPen;
property Pen : TPen read FPen write SetPen;
Delphi-Quellcode:
procedure TPfeil.SetPen(Value: TPen);
begin //if Value <> FPen then begin showmessage('pen'); FUNKIONIERT NICHT FPen.Assign(Value); self.Repaint; //end; end; |
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
Hmm, kompliziert.
Also der OI ruft nicht das writeProperty sondern das Read-Property auf. Er verändert ja nicht das Objekt selber, sondern liest das Objekt aus und ändert etwas in dem Objekt (das sind dann aber Propertys von TPen), deswegen wird nur Read verwendet. |
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
Zitat:
Zitat:
@edmu: Du rufst RePaint auf im Setter. Schau dir bitte meinen ersten Beitrag nochmal an und beachte Punkt 4. |
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
Zitat:
(Und ich denke das Showmessage, war nur zur Kontrolle) |
Re: Komponente mit TPaintBox: kann nicht mit Canvas zeichene
habe es herausbekommen.
steht alles in der delphi-hilfe, siehe "Eigenschaften untergeordneter Klassen setzen". Komponentenentwicklung.
Delphi-Quellcode:
constructor TPfeil.Create(AOwner : TComponent);
var i : integer; begin inherited Create(AOwner); { Diesen Schritt IMMER zuerst! } FPen := TPen.Create; { Stift erzeugen } FPen.OnChange := StyleChanged; { Dem OnChange-Ereignis die Methode zuweisen } FBrush := TBrush.Create; { Pinsel erzeugen } FBrush.OnChange := StyleChanged; { Dem OnChange-Ereignis die Methode zuweisen } end;
Delphi-Quellcode:
published
{ Published-Deklarationen = Im Objektinspector sichtbar, Designmodus } ... procedure StyleChanged(Sender: TObject);
Delphi-Quellcode:
procedure TPfeil.StyleChanged(Sender: TObject);
begin Invalidate; { Komponente löschen und neu zeichnen } //Die Komponente zeichnet sich nun nach jeder Änderung an einer //der Eigenschaften Pen oder Brush neu. end; schönen dank |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:22 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