AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Delphi [OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?
Thema durchsuchen
Ansicht
Themen-Optionen

[OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

Ein Thema von Jazzman_Marburg · begonnen am 19. Okt 2010 · letzter Beitrag vom 20. Okt 2010
Antwort Antwort
Seite 1 von 3  1 23      
Benutzerbild von Jazzman_Marburg
Jazzman_Marburg

Registriert seit: 2. Aug 2004
359 Beiträge
 
#1

[OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

  Alt 19. Okt 2010, 18:48
Hallo Gemeinde.

Mein TImage Nachfahre TGraphPaper macht mir Kummer. Das Ding soll einfach sowas wie kariertes Rechenblatt darstellen, wo ich dann später ein Koordinaten-System uä. reichzeichne. Ich leite also von TImage ab:

Code:
TGraphPaper = CLASS(TImage)
Im Konstruktor steht:
Code:
CONSTRUCTOR TGraphPaper.Create(MyParent: TWinControl; Title: STRING);

BEGIN

  INHERITED CREATE(MyParent);
  Parent   := MyParent;
  ...
Mit INHERITED CREATE(MyParent) wird die SetBounds Methode von TImage aufgrufen (INHERITED SetBounds(ALeft, ATop, AWidth, AHeight)-- denn mein GraphPaper soll sich mit dem Resizing seines Parents neuzeichnen - bzw. dessen Größe entsp. anpassen.
Das wird hier erledigt:
Code:
PROCEDURE TGraphPaper.SetBounds(ALeft, ATop, AWidth, AHeight: INTEGER);
BEGIN

  INHERITED SetBounds(ALeft, ATop, AWidth, AHeight);

  Zeichnen;
  ...
Jetzt zum eigentlichem Problem:
In der Methode Zeichnen greife ich auf WIDTH und HEIGHT zu, um die Anzahl der Rechenkästchen zu bestimmen, die gezeichnet werden sollen. Dort knallt es aber, da eine Division durch Null erfolgt, weil: WIDTH und HEIGHT zu diesem Zeitpunkt (Create) den Wert Null haben. Klar die Zeile Parent := MyParent; kommt ja auch erst später (ich frage mich gerade: Bekommt es an dieser Stelle, die Größe seines Parents ).
Aber wie kann ich denn meinem Objekt nun initial eine Größe zuweisen, bevor das SetBounds gerufen wird?

Ich hoffe ich konnte mich halbwegs verständlich machen.
Vielleicht hat jemand ja eine Idee?

Lieben Dank
Gruß, Jazzman
--- Delphi XE Starter, Windows 8 ---
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: [OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

  Alt 19. Okt 2010, 19:07
Delphi-Quellcode:
CONSTRUCTOR TGraphPaper.Create(MyParent: TWinControl; Title: STRING);

BEGIN

  INHERITED CREATE(MyParent);
  Parent := MyParent; // <-- ist das nicht überflüssig? Wird mit inherited Create(MyParent) doch schon gesetzt
  ...
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Jazzman_Marburg
Jazzman_Marburg

Registriert seit: 2. Aug 2004
359 Beiträge
 
#3

AW: [OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

  Alt 19. Okt 2010, 19:23
Delphi-Quellcode:
CONSTRUCTOR TGraphPaper.Create(MyParent: TWinControl; Title: STRING);

BEGIN

  INHERITED CREATE(MyParent);
  Parent := MyParent; // <-- ist das nicht überflüssig? Wird mit inherited Create(MyParent) doch schon gesetzt
  ...
Ja, in der Tat -- aber es ändert nichts an der Sache wenn ich es wegnehme!
Beim ersten Aufruf von Zeichnen ist WIDTH = 0 und HEIGHT = 105: Weder 0 noch 105 machen irgendwie einen Sinn (scheint sich in diesem Stadium noch um Zufallswerte zu handeln). Bekommt mein Objekt nach INHERITED CREATE(MyParent) nun die Größe seines Parents oder nicht? Und wenn nicht: Ich kann ja nicht einfach Width = 50 un Height = 50 schreiben (nur damit mal ein beliebiger aber von Null verschiedener Wert dort steht, weil ja damit dirket wieder SetBounds gerufen wird ==> Endlos-Loop).

Sehr verwirrend das.

Gruß
Jazzman
--- Delphi XE Starter, Windows 8 ---
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#4

AW: [OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

  Alt 19. Okt 2010, 19:35
Ich leite also von TImage ab
Das ist schon mal falsch!
TImage ist ein Control um ein TPicture (Bitmap, GIF, JPeg,...) darzustellen.
(Controls sind sichtbare Steuerelement)
Es ist nicht als Basisklasse für eigene Controls gedacht.

Wenn dein Control nicht auf Tasten und Mausklicks reagieren soll dann von TGraphicControl ableiten.
Falls dein Control auf Tasten und Mausklicks reagieren soll, dann von TCustomControl ableiten.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Jazzman_Marburg
Jazzman_Marburg

Registriert seit: 2. Aug 2004
359 Beiträge
 
#5

AW: [OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

  Alt 19. Okt 2010, 19:47
Jetzt nochmal konkret nachgefragt (zu TGraphicControl komme ich später):

Wenn ich Stepwise debugge, dann springen wir nach einem Create in den Constructor:
Code:
CONSTRUCTOR TGraphPaper.Create(MyParent: TWinControl; Title: STRING);

BEGIN

  INHERITED CREATE(MyParent); // Hiernach springen wir sofort in SetBounds!
  ...
END;

PROCEDURE TGraphPaper.SetBounds(ALeft, ATop, AWidth, AHeight: INTEGER);
BEGIN

  INHERITED SetBounds(ALeft, ATop, AWidth, AHeight); // 0, 0, 0, 105

  Zeichnen;
END;
Woher kommen die Werte 0, 0, 0, 105 für ALeft, ATop, AWidth, AHeight? Wer setzt diese Werte? Bzw. kann ich sie nicht auch setzen -- und wenn ja wo und wie?

Gruß
--- Delphi XE Starter, Windows 8 ---
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.343 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: [OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

  Alt 19. Okt 2010, 19:53
Was verstehe ich denn jetzt nicht? Im Constructor wird doch der Owner gesetzt, nicht der Parent?

Versuch mal, die Parent-Zuweisung auszuklammern und zur Laufzeit zuzuweisen, nachdem der Constructor komplett durchgelaufen ist...
(Ich bin nicht sicher, aber vielleicht ist die Zuweisung zu früh.)

Alternativ kannst Du doch die Zeichnen-Funktion einfach abbrechen, wenn Width oder Height 0 sind.

Delphi-Quellcode:
procedure Zeichnen;
begin
  if (Width = 0) or (Height = 0) then
    Exit;
  ...
end;
Ich habe mir für ähnliche Zwecke eine TRaster erstellt. Diese liegt über einem "Designer" (TScrollBox). Sie ist transparent und Maustransparent, zeichnet ein Punkteraster und kann Laserlines für ein auf dem Designer selektiertes Objekt zeichnen. Vielleicht nützt Dir das ja als Anregung...

Delphi-Quellcode:
  TRaster = class(TPaintBox)
  private
    FLaserControl: TControl;
    procedure SetLaserControl(const Value: TControl);
  protected
    procedure CMHitTest(var Msg: TWMMouse); message CM_HITTEST;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Paint; override;
    function Designer: TodDesigner; virtual;
    property LaserControl: TControl read FLaserControl write SetLaserControl;
  end;


{ TRaster }

procedure TRaster.CMHitTest(var Msg: TWMMouse);
begin
  inherited;
  Msg.Result := 0;
end;

constructor TRaster.Create(AOwner: TComponent);
begin
  inherited;
end;

function TRaster.Designer: TodDesigner;
begin
  if Owner is TodDesigner then
    Result := (Owner as TodDesigner)
  else
    Result := nil;
end;

destructor TRaster.Destroy;
begin
  inherited;
end;

procedure TRaster.Paint;
var
  odDesigner: TodDesigner;
  X, Y: Integer;
  mi, ma: Integer;
begin
  inherited;
  if Owner is TodDesigner then
  begin
    odDesigner := (Owner as TodDesigner);
    if (odDesigner.ShowRasterX > 1) and (odDesigner.ShowRasterY > 1) then
    with Canvas do
    begin
      if (LaserControl <> nil) and (Designer <> nil) then
      begin
        ma := 1;
        mi := 0;
        Pen.Color := clSkyBlue;
        MoveTo(0, Designer.VertScrollBar.Position + LaserControl.Top - ma);
        LineTo(Width, Designer.VertScrollBar.Position + LaserControl.Top - ma);
        MoveTo(0, Designer.VertScrollBar.Position + LaserControl.Top + LaserControl.Height - mi);
        LineTo(Width, Designer.VertScrollBar.Position + LaserControl.Top + LaserControl.Height - mi);
        MoveTo(Designer.HorzScrollBar.Position + LaserControl.Left - ma, 0);
        LineTo(Designer.HorzScrollBar.Position + LaserControl.Left - ma, Height);
        MoveTo(Designer.HorzScrollBar.Position + LaserControl.Left + LaserControl.Width - mi, 0);
        LineTo(Designer.HorzScrollBar.Position + LaserControl.Left + LaserControl.Width - mi, Height);
        Pen.Color := clBlack;
      end;
      Y := odDesigner.RasterFrame + odDesigner.RasterYDif;
      while Y < Height do
      begin
        X := odDesigner.RasterFrame + odDesigner.RasterXDif;
        while X < Width do
        begin
          Pixels[X, Y] := clGray;
          Inc(X, odDesigner.ShowRasterX);
        end;
        Inc(Y, odDesigner.ShowRasterY);
      end;
    end;
  end;
end;

procedure TRaster.SetLaserControl(const Value: TControl);
begin
  if FLaserControl <> Value then
  begin
    FLaserControl := Value;
    Refresh;
  end;
end;
Miniaturansicht angehängter Grafiken
raster.png  
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#7

AW: [OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

  Alt 19. Okt 2010, 20:00
Dein Konstruktor ist auch falsch
Jedes Control ist auch eine Komponente; logisch weil von TComponent sich alle Controls ableiten.
Das Problem bzw. die Einschränkung ist nun, dass alle Klassen, die von TComponent ableiten folgenden Konstruktor verwenden MÜSSEN:
constructor Create(AOwner: TComponent); virtual;
Man darf zwar einen abweichenden Konstruktor erstellen, aber dieser Konstruktor wird von der VCL niemals aufgerufen!
Die VCL kennt deinen Konstruktor nicht und kann ihn daher nicht aufrufen.
Alle Daten (mit Ausnahme des Owners) müssen über Properties oder Methodenaufrufe in das Objekt gebracht werden.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Jazzman_Marburg
Jazzman_Marburg

Registriert seit: 2. Aug 2004
359 Beiträge
 
#8

AW: [OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

  Alt 19. Okt 2010, 20:03
Ja, das wird sicher helfen (TRaster) -- aber bleiben noch ein paar Fragen.
Was ich nicht verstehe:

Ich leite also von TImage ab
Das ist schon mal falsch!
TImage ist ein Control um ein TPicture (Bitmap, GIF, JPeg,...) darzustellen.
(Controls sind sichtbare Steuerelement)
Es ist nicht als Basisklasse für eigene Controls gedacht.

Wenn dein Control nicht auf Tasten und Mausklicks reagieren soll dann von TGraphicControl ableiten.
Falls dein Control auf Tasten und Mausklicks reagieren soll, dann von TCustomControl ableiten.
Ich habe mir für ähnliche Zwecke eine TRaster erstellt.
Wieso kann der Kollege für sein TRaster von TPaintBox ableiten -- mir wird aber gesagt, TImage wäre ganz falsch?

Wenn doch TImage schon fast alles enthält was ich benötige -- wieso soll man nicht davon ableiten -- stattdessen TGraphicControl nehmen, dem ich dann mühsam noch alles "beibringen" muß, was TImage schon kann?

Danke & Gruß
--- Delphi XE Starter, Windows 8 ---
  Mit Zitat antworten Zitat
Benutzerbild von Jazzman_Marburg
Jazzman_Marburg

Registriert seit: 2. Aug 2004
359 Beiträge
 
#9

AW: [OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

  Alt 19. Okt 2010, 20:11
Moooment!
Kann es sein dass ich da etwas elementares durcheinander werfe:
Ich benutze TurboDelphi -- was bekanntlich keine User eigenen Komponenten erlaubt! D.h. ich erzeuge keine visuellen Komponenten, sondern althergebracht Objekte zur Laufzeit.

Als Grundlage für mein GraphPaper habe ich ein Beispiel aus einem Buch - dort wurde von TImage abgeleitet, umd mit REGISTER die (visuelle) Komponente registriert. Ich bin dann einfach hin und dachte, naja eine Komponente kannste nicht gebrauchen, und hab dann einfach die REGISTER Prozedur weggeschmissen und den Rest so gelassen.

Kann es nicht sein, dass das der Kardnial-Fehler war?
Und ich deshalb doch lieber von TGraphicControl ableiten sollte?

(Das würde zumindest den Knoten in meinem Kopf gerade entwirren).

Jazzman
--- Delphi XE Starter, Windows 8 ---
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#10

AW: [OOP] Ableiten von TImage: Wann hat mein Objekt eine Größe?

  Alt 19. Okt 2010, 20:15
Wieso kann der Kollege für sein TRaster von TPaintBox ableiten -- mir wird aber gesagt, TImage wäre ganz falsch?
TPaintbox ist auch die falsche Basisklasse; muss dann wohl eine Jugendsünde von Stahli gewesen sein.

TPaintbox erfüllt folgenden Zweck:
das Zeichnen wird über das Event OnPaint an das Formular deligiert.
Das bedeutet man kann immer die gleiche Komponente TPaintbox verwenden und damit ganz unterschiedliche Dinge zeichnen weil der Zeichencode auf dem Formular liegt.
Wenn man von TPaintbox ableitet, dann ignoriert man damit den Sinn und Zweck der Paintbox.
TPaintbox müsste eigentlich eine "versiegelte Klasse" sein von der man nicht ableiten kann.
Andreas
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz