Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Parent Problem bei eigener Komponente (https://www.delphipraxis.net/184236-parent-problem-bei-eigener-komponente.html)

Stegi 11. Mär 2015 13:37

Parent Problem bei eigener Komponente
 
Hallo,

ich habe ein Problem und konnte im www bislang noch keine Lösung finden. Vielleicht fehlen mir auch nur die passenden Suchbegriffe. Vieleicht finde ich hier eine Lösung für mein Problem.

Ich habe mir eine Eigenen Komponente erzeugt. Um das Beispiel verständlich zu halten basiert meine Komponente auf ein TPanel.

Code:
  TMeineKompo = class(TPanel)
  public
    Pan1: TPanel;
    Pan2: TPanel;
    constructor Create(aOwner: TComponent); override;
  end;
Ich registriere die Kompononete entsprechend und kann diese dann auch aus meiner Toolpalete in meinem Dialog ziehen.
Jetzt möchte ich zur Designzeit in dem Dialog weitere Komponenten (z.B. Panel) in das Panel (Pan2) meiner Komponente platzieren. Ich kann zwar ein Panel unter der Komponente hängen, jedoch ist der Parent nicht mein gewünschtes Panel Pan2 sonder die Komponente selbst.

Wie bekomme ich das hin, dass ich weitere Komponenten zur Designzeit in delphi in das Panel Pan2 meiner Komponente packen kann?

Ich hoffe ich konnte mein Problem einigermaßen nachvollziehend erklären. ;-)

Viele Grüße
Stegi

Daniel 11. Mär 2015 13:42

AW: Parent Problem bei eigener Komponente
 
Moin und willkommen in der Delphi-PRAXiS. :-)

Nach Deiner Beschreibung fehlt Dir ein Wert im Set "ControlStyle". Dort kannst - musst - Du definieren, dass Du gern als Basis für andere Controls dienen möchtest:
http://docwiki.embarcadero.com/Libra...l.ControlStyle

In etwa wie folgt:

Delphi-Quellcode:
constructor TMeineKompo.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := ControlStyle + [csAcceptsControls];
//...
end;

Der schöne Günther 11. Mär 2015 18:11

AW: Parent Problem bei eigener Komponente
 
Ohne es ausprobiert zu haben- Müsste er das nicht durch das Erben von
Delphi-Quellcode:
TPanel
bereits erledigt haben? Sein Problem ist ja nicht dass man auf dem Designer keine Controls hineinwerfen könne, sondern dass die hineingesteckten nicht direkt im
Delphi-Quellcode:
TPanel
-Nachfahren, sondern in einem da drin bereits enthaltenen Container landen sollen.

Spontan hätte ich gesagt, dazu müsste man einfach nur das von
Delphi-Quellcode:
TWinControl
geerbte
Delphi-Quellcode:
procedure InsertControl(AControl: TControl);
überschreiben. Aber das ist nicht virtuell.

Und somit hätte ich spontan auch keine Idee.

himitsu 11. Mär 2015 20:48

AW: Parent Problem bei eigener Komponente
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1293069)
Aber das ist nicht virtuell.

Im Notfall kann man die Insert-Notification behandeln und die bereits hinzugefügte Komponente in das andere Panel verschieben (Parent ändern)

Aber ob der FormDesigner dann noch anbietet diese Komponenten zu bearbeiten, weiß ich auch nicht.

Chris211183 12. Mär 2015 07:54

AW: Parent Problem bei eigener Komponente
 
im Constructor

Delphi-Quellcode:
Pan1 := TMein(bla).Create(Self);
Pan1.Parent := Self;
.
.
.
würde das mit den Panels über nen Setter machen

FPan1 usw

DeddyH 12. Mär 2015 08:04

AW: Parent Problem bei eigener Komponente
 
Es geht um die Designzeit, da bringt es ja nichts, im Konstruktor den Parent setzen zu wollen.

Sir Rufo 12. Mär 2015 08:07

AW: Parent Problem bei eigener Komponente
 
Zitat:

Zitat von DeddyH (Beitrag 1293106)
Es geht um die Designzeit, da bringt es ja nichts, im Konstruktor den Parent setzen zu wollen.

Wieso nicht? Der Konstruktor einer Komponente wird auch zur Designzeit aufgerufen ;)

DeddyH 12. Mär 2015 08:21

AW: Parent Problem bei eigener Komponente
 
Ja nee is klar.

Chris211183 12. Mär 2015 08:33

AW: Parent Problem bei eigener Komponente
 
Zitat:

Zitat von Sir Rufo (Beitrag 1293107)
Zitat:

Zitat von DeddyH (Beitrag 1293106)
Es geht um die Designzeit, da bringt es ja nichts, im Konstruktor den Parent setzen zu wollen.

Wieso nicht? Der Konstruktor einer Komponente wird auch zur Designzeit aufgerufen ;)

Denke ich auch...

Sir Rufo 12. Mär 2015 08:41

AW: Parent Problem bei eigener Komponente
 
Zitat:

Zitat von DeddyH (Beitrag 1293110)
Ja nee is klar.

Dann erkläre mir doch bitte einmal, was auf dieser Seite (
Delphi-Quellcode:
TComponentState
)
die Werte für
Delphi-Quellcode:
csDesigning
und
Delphi-Quellcode:
csDesignInstance
bedeuten.

Wenn also eine Komponente zur Designzeit niemals auch nur irgendwas da zum Leben erweckt, wozu sind denn diese komischen Dingsbums-Dinger da?

himitsu 12. Mär 2015 08:53

AW: Parent Problem bei eigener Komponente
 
Außer bei TForms, welche über CreateForm erstellt werden, sind diese Property im Constructor niemals richtig befüllt. (man kann sie ja erst setzen, wenn die Komponente befüllt wurde :zwinker:)

Chris211183 12. Mär 2015 10:49

AW: Parent Problem bei eigener Komponente
 
Wichtiger ist doch aber jetzt, ob Stegis Problem gelöst ist oder ob nicht

:witch:

oki 12. Mär 2015 12:11

AW: Parent Problem bei eigener Komponente
 
Schon mal probiert die beiden Panels in den Container Controls der eigenen Komponente beim Construct zu packen?

Stegi 17. Mär 2015 13:33

AW: Parent Problem bei eigener Komponente
 
Hi,

sorry, konnte heute erst die Vorschläge versuchen auszuprobieren. Leider ohne Erfolg.
Im Constructor von meiner Komponente werden bereits die zwei Panels erzeugt und der Parent der zwei Panels ist selbstverständlich die Kompononente selbst.
Aber dennoch klappt es nicht.

Man müsste irgendwie allen Komponenten die man in die eigenen Kompononete zieht die eigenen Komponente als Parent mitgeben. :gruebel:

oki 18. Mär 2015 07:09

AW: Parent Problem bei eigener Komponente
 
So klappt es:

Delphi-Quellcode:
unit PanelUnit;

interface

uses ExtCtrls, Classes;

type
  TMyPanel = class(TPanel)
  private
    Panel1 : TPanel;
    { private-Deklarationen }
  protected
    { protected-Deklarationen }
    procedure CreateWnd(); override;
  public
    { public-Deklarationen }
    Constructor Create(AOwner : TComponent); override;
  published
    { published-Deklarationen }
  end;

  procedure Register();


implementation

procedure Register();
begin
  RegisterComponents('oki', [TMyPanel]);
end;
{ TMyPanel }

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


procedure TMyPanel.CreateWnd;
begin
  inherited;
  Panel1 := TPanel.Create(self);
  Panel1.Parent := self;
  self.Owner.InsertComponent(Panel1);
end;

end.
Gruß oki

himitsu 18. Mär 2015 07:27

AW: Parent Problem bei eigener Komponente
 
Und so hast du dir eine wunderschöne Endlosschleife gebastelt.

MyPanel hat Panel1 als Owner
und Panel1 hat das MyPanel als Owner.

Als Ergebnis halten sich beide gegenseitig im Speicher und am Ende hat man ein Speicherleck,
genauso, als wenn MyPanel garkeinen Owner hätte und es Panel1 nicht gäbe.

Außerdem wird/kann CreateWnd mehrmals zur Laufzeit aufgerufen werden, womit es mehrere Panel1 geben könnte.




Die Variable Panel1 wird sonst nirgendwo anders verwendet und kann auch gut und gern einfach nur eine Lokale in CreateWnd sein.
Wozu das Create hier im Beispiel sein soll, weiß wohl keiner.

Delphi-Quellcode:
unit PanelUnit;

interface

uses ExtCtrls, Classes;

type
  TMyPanel = class(TPanel)
  private
    { private-Deklarationen }
  protected
    { protected-Deklarationen }
    //procedure CreateWnd(); override;
  public
    { public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
  published
    { published-Deklarationen }
  end;

  procedure Register();

implementation

procedure Register();
begin
  RegisterComponents('oki', [TMyPanel]);
end;

{ TMyPanel }

//procedure TMyPanel.CreateWnd;
constructor TMyPanel.Create(AOwner: TComponent);
var
  Panel1: TPanel;
begin
  inherited;
  Panel1 := TPanel.Create(self);
  Panel1.Parent := self;
  if Assigned(Owner) then
    Owner.InsertComponent(Panel1);
end;

end.
Hab den Thread jetzt nicht mehr so ganz im Kopf, aber wozu soll das Panel1 jetzt eigentlich dienen?
Delphi-Quellcode:
unit PanelUnit;

interface

uses ExtCtrls, Classes;

type
  TMyPanel = class(TPanel)
  private
    { private-Deklarationen }
  protected
    { protected-Deklarationen }
    //procedure CreateWnd(); override;
  public
    { public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
  published
    { published-Deklarationen }
  end;

  procedure Register();

implementation

procedure Register();
begin
  RegisterComponents('oki', [TMyPanel]);
end;

{ TMyPanel }

//procedure TMyPanel.CreateWnd;
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited;
  if Assigned(Owner) then
    Owner.RemoveComponent(Panel1);
end;

end.

oki 18. Mär 2015 07:54

AW: Parent Problem bei eigener Komponente
 
Hi himitsu.

Okay, hab ich alles etwas leichtfertig zusammengehackt :oops:. Ich entschuldige mich dafür und werde in Zukunft sorgsamer sein.

Gleichfalls hast du aber auch nicht gründlich gelesen.
Zitat:

MyPanel hat Panel1 als Owner
und Panel1 hat das MyPanel als Owner.
Das ist so nicht korrekt. Panel1 hat MyPanel als Owner und Parent. Panel1 liegt im Componentskontainer der Parent-Komponente von MyPanel. Du hast recht, wenn jemand das Panel1 löscht ist Panel1 in MyPanel nicht mehr instanziiert, die Variable aber nicht null. Also eher Panel1 gar nicht als Member in der Komponente halten. Da geb ich dir in deinem Code-Beispiel recht. Von Endlosschleife sehe ich aber nichts. Hilf mir auf die Sprünge.
Wo liegt eigentlich der Unterschied zwischen meinem und deinem Code-Beispiel, außer dass Panel1 nich private ist (seh ich ein, ist ein Fehler meinerseits) und dass du den Code von CreateWnd nach Create verschoben hast? (Das Assign ist eine vernünftige Ergänzung für den Fall, dass MyPanel per Code ohne Owner erzeugt wird).

Zitat:

Wozu das Create hier im Beispiel sein soll, weiß wohl keiner.
Naja, Create ist halt beim Testen übrig geblieben. Ist das jetzt so schlimm?

Das CreateWnd mehrfach aufgerufen wird ist mir neu. Dank für den Hinweis. Ist das schon immer so oder erst ab einer speziellen Delphi-Version?

Deinen zweiten Code-Abschnitt verstehe ich nicht. Was soll das RemoveComponent?

Gruß oki

himitsu 18. Mär 2015 08:02

AW: Parent Problem bei eigener Komponente
 
CreateWnd wird jedesmal aufgerufen, wenn das interne Window (HWND) neu erstellt wird, das passiert z.B. beim Ändern des Parent, oder beim Umstellen des FormStyle usw.


Ups, mit dem Owner hab ich falschrum geguckt. :oops:
Delphi-Quellcode:
procedure TMyPanel.CreateWnd;
begin
  inherited;
  Panel1 := TPanel.Create(self);
  Panel1.Parent := self;
  Self.Owner.InsertComponent(Panel1);
end;
entspricht
Delphi-Quellcode:
procedure TMyPanel.CreateWnd;
begin
  inherited;
  //Panel1 := TPanel.Create(self);
  Panel1 := TPanel.Create(nil);
  Panel1.Owner := Self;

  Panel1.Parent := Self;

  //Self.Owner.InsertComponent(Panel1);
  Panel1.Owner := Self; // hatte das vorhin als Self.Owner := Panel1; übersetzt
end;
Demnach wäre das InsertComponent dann nur "nutzlos", da der Owner bereits gesetzt wurde.

Hmmmmmmmmmmmmmmmm... :gruebel:
Also der zweite Code, lies einfach nur den Owner weg, durch weglassen des Panel1 .... unter der Annahme der falschen Richtung des InsertComponent.

Delphi-Quellcode:
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited;
  if Assigned(Owner) then
    Owner.RemoveComponent(Panel1);
end;
hätte man auch als
Delphi-Quellcode:
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited Create(nil);
end;
schreiben können, aber ist ja nun doch falsch.

oki 18. Mär 2015 08:15

AW: Parent Problem bei eigener Komponente
 
Delphi-Quellcode:
self.Owner.InsertComponents(Panel1);
ist aber genau der Punkt, der zur Designzeit Zugriff auf das Panel1 liefert. Ohne gehts nicht. Bitte achte drauf, InsertComponent rufe ich nicht für MyPanel auf, sondern für dessen Owner!
Das ist doch
Delphi-Quellcode:
Panel1 := TPanel.Create(self);
  Panel1.Parent := self;
gleich dem
Delphi-Quellcode:
Panel1 := TPanel.Create(nil);
  Panel1.Owner := Self;

  Panel1.Parent := Self;
mit dem kleinen Problem, dass Owner eine nur-lese-Eigenschaft ist und so nicht gehen sollte. Führt aber alleine nicht dazu, dass man weitere Controls in Panel1 zur Designzeit legen kann.

CreateWnd hatte ich immer so verstanden, dass das nach dem Create aufgerufen wird wenn ein Handle verfügbar ist. Das ist beim Create noch nicht da. Das das bei einer vorhandenen Componente zur Lebenszeit wiederholt aufgerufen wird ist mir noch nie vorgekommen. Wenn ich in einer eigenen Komponente das Handle benötige habe ich den Code immer da platziert, auch für weitere Objekte. Hatte nie Probleme. :shock: Muss ich noch mal nachlesen.

Gruß oki

himitsu 18. Mär 2015 08:53

AW: Parent Problem bei eigener Komponente
 
Zitat:

Delphi-Quellcode:
procedure TMyPanel.Create(AOwner: TComponent);
begin
  inherited;
  Panel1 := TPanel.Create(self);
  Panel1.Parent := self;
  Owner.InsertComponent(Panel1);
end;

Warum hinterher verbiegen, wenn man auch gleich den richtigen Owner übergeben könnte?
Delphi-Quellcode:
constructor TMyPanel.Create(AOwner: TComponent);
begin
  inherited;
  Panel1 := TPanel.Create(Owner); // aka Self.Owner, anstatt nur Self
  Panel1.Parent := Self;
end;
Und daß sich Komponenten nur im OI bearbeiten lassen, wenn sie die Form als Owner besitzen, wurde gleich zu Beginn von jemandem erwähnt. :stupid:
(rate mal wer AOwner/Owner des MyPanel ist)

oki 18. Mär 2015 10:17

AW: Parent Problem bei eigener Komponente
 
Hallo Himitsu,

ich glaube, wir sind uns im Grunde einig, verstehen aber vielleicht die Aufgabenstellung unterschiedlich. Ich vermute mal, du meinst ausschließlich das Problem, wie man eine Komponente in einem eigenen Panel (MyPanel) zur Erstellungszeit einfügt. Dafür reicht dein Code. Ich habe den Threadersteller aber so verstanden, dass er zur Designzeit auf dem erstellten Panel (Panel1 und nicht MyPanel) weitere Komponenten platzieren will. Dazu braucht er aber Zugriff auf das eingebettete Panel1 zur Designzeit. Das ist nur möglich, wenn er das eingebettete Panel1 in die Liste Components des Formulars packt. Erst dann kann er zur Designzeit weitere Komponenten in Panel1 platzieren.
Zitat:

Jetzt möchte ich zur Designzeit in dem Dialog weitere Komponenten (z.B. Panel) in das Panel (Pan2) meiner Komponente platzieren. Ich kann zwar ein Panel unter der Komponente hängen, jedoch ist der Parent nicht mein gewünschtes Panel Pan2 sonder die Komponente selbst.
Ich denke, an der Stelle reden wir aneinander vorbei.

Mir erschließt sich nicht wirklich, warum er nicht zur Designzeit auch Panel1 in MyPanel platziert und das unbedingt innerhalb der Kompo passieren muss. Egal, mit dem Zugriff auf Panel1 ergeben sich aber weitere Probleme wie:
- Panel1 kann somit auch zur Designzeit entfernt werden,
- Liegt MyPanel nicht auf der Form, sondern auf einem weiteren Panel reicht self.Owner.InsertComponent nicht aus. Es muss das Formular gesucht werden. Das kann man sicher über eine rekursive Funktion durch alle Owner mit Rückgabe des "Letzten" lösen.
- Panel1 kann über den OI zur Designzeit verändert werden (Position, Größe etc.). Was soll statisch bleiben? Hier müssten dann diverse Methoden überladen werden um diese Änderungen zu verhindern.

Und so gibt es bestimmt noch Dinge an die ich nicht gedacht habe, weis ja auch nicht welche konkreten Eigenschaften die Komponente haben soll. Wurde nicht genannt.

Grundsätzlich gehe ich aber davon aus, dass die grundlegende Aufgabenstellung ist, Wie kann ich in meiner Komponente ein Panel integrieten, in das ich zur Designzeit weitere Komponenten legen kann.


Gruß oki

Stegi 23. Mär 2015 04:43

AW: Parent Problem bei eigener Komponente
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

oki, du hast es richtig verstanden.
Vielleicht versuche ich noch einmal den Grund für mein Vorhaben zu schildern. Ich möchte eine Komponente erstellen die wie eine Art Groupbox fungiert nur ohne einen Rahmen und mit einen farblichen Balken oberhalb. Ähnlich den MS Word Optionen (siehe Bild).

Hierfür dachte ich, ich erstelle eine Komponente abgeleitet vom TCustomPanel welches ein weiteres Panel alTop hat und ein weiteres Panel alclint in dem alle weiteren Komponente zur Designzeit reingepackt werden können. Ich möchte dies für alle meine Kollegen so einfach und effizient wie möglich machen. Sie sollen sich nicht mehr um margins, font, farben etc. kümmern müssen sondern einfach nur ihre Komponenten mit Align = alTop hineinwerfen müssen.

Ich hoffe ich konnte etwas mehr Licht ins dunkle meiner Idee bringen. ;-)

Gruß
Stegi


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:46 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