AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Die Delphi-IDE Wann sind objecte auf der IDE fertig initialisert?
Thema durchsuchen
Ansicht
Themen-Optionen

Wann sind objecte auf der IDE fertig initialisert?

Ein Thema von DrUArn · begonnen am 27. Feb 2018 · letzter Beitrag vom 28. Feb 2018
Antwort Antwort
DrUArn

Registriert seit: 20. Mär 2003
130 Beiträge
 
Delphi 10.3 Rio
 
#1

Wann sind objecte auf der IDE fertig initialisert?

  Alt 27. Feb 2018, 17:16
Hallo, Comm,

nachdem ich beim Schreiben des folgenden Beispiels vergessen hatte, die da noch feld-freie get- und set-Routinen von ShowOpts mit Leben zu erfüllen (insbesondere read machte da wohl sehr große Probleme) - es wird Datenmüll eingelesen und die dazugehörige *.dfm hat Fehler - nun meine Frage:

Wann hat man bei einem Object auf der Ide alle Eigenschaften zur Verfügung (z.B. Parent, Name, auch Left und Top)?

Im Beispiel sollten bei
TSimpTestRich_UA.create weitere Subkomponenten (hier SubRichEd) hinzugefügt werden (jetzt im Beispiel ausgeklammert). Hier fehlt aber die Eigenschaft parent noch, die SubRichEd braucht, um sich darzustellen.
Dazu habe ich dann die
Procedure expresscontrols(doother:boolean);virtual;
genutzt, die z.B. in FormCreate gerufen werden kann. Das funktioniert auch, ist aber irgendwie unbequem.

Dann habe ich gesehen, dass all die noch nicht gesetzten Eigenschaften (Name, Parent ... ) von TSimpTestRich_UA bei seinen setEigenschafts-Routinen (z. B. procedure SetShowpts(const Value: tshowOpts_UA)) gesetzt sind und ich dort einem Zug die SubRichEd erzeugen kann.(und dass auf der IDE auch noch dargestellt wird - wusste ich nicht).

Mit einer Dummy-Eigenschaft
(procedure setReadyForTmp(const Value: boolean)
kann ich dann auch weitere Komponenten erzeugen, löschen usw.

Gibt es irgendwo einen Programm-Punkt, den man statt meines Dummy's nutzen kann - also irgendeine Meldung des Programms "Bin fertig, alles was eingelesen werden kann ist da'?

Grüße Uwe

Mit Mouse links oder rechts kann man die beiden Editoren (SubRichEd und ein memo-Feld) ein und ausschalten

Delphi-Quellcode:

const
lzSubrichName='Subrich';
lzMemoName='Memo';

type
tShowOpt_UA =(ShowSubRichEd_UA, ShowstatBar_UA,ShowHeadContr_UA);
tShowOpts_UA = set of tShowOpt_UA;

TSimpTestRich_UA = class(TRichEdit)
private
    FSubRichEd: trichedit;
    FShowOpts:tShowOpts_UA;
    FReadyForTmp:boolean;
    function GetShowpts: tshowOpts_UA;
    procedure SetShowpts(const Value: tshowOpts_UA);
    procedure setReadyForTmp(const Value: boolean);
  { private declarations }

protected
  { protected declarations }
public
  { public declarations }

published
  { published declarations }
    property ReadyForTmp: boolean read FReadyForTmp write setReadyForTmp;
    property ShowOpts: tshowOpts_UA read GetShowpts write SetShowpts;

    property SubRichEd: trichedit read FSubRichEd write FSubRichEd;

    constructor Create(AOwner:TComponent);override;
    procedure CreateSubrichEd;virtual;
    procedure DeleteSubrichEd;virtual;

    procedure createTmpMemo;
    function getTmpMemo:tmemo;
    procedure deleteTmpMemo;

    function getComponentName(anam:string):string;

    procedure expresscontrols(doother:boolean);virtual;

    Procedure onselfMouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);virtual;//ermöglicht hier das Bewegen und Veränderung der Größe bei Gedrückter Stringtaste
end;


{ TSimTestrich_UA }

constructor TSimpTestrich_UA.Create(AOwner: TComponent);
begin
  inherited;
  Width:=2*width;
  //ShowOpts:=showopts-[ShowSubRichEd_UA]; geht hier nicht, da wohl die setRoutinen der Eiogenschaften noch nicht gerufen werden dürfen
  // CreateSubrichEd; hier ist Name und z.B. ShowOpts nicht geladen
  //lines.add('Mein Name in Create: '+ name); geht hier nicht, Meldung: Element '' hat kein übergeordnetes Fenster, heißt wohl, Parent ist noch nicht gesetzt

  onmousedown:=onselfMouseDown;//zum Testen
end;

procedure TSimpTestRich_UA.CreateSubrichEd;
begin
  if not assigned(SubRichEd) then
  begin
  SubRichEd:=trichedit.create(self);
  SubRichEd.parent:=self.parent;
  SubRichEd.name:=getComponentName(lzSubrichName); //ein eindeutiger Name
  SubRichEd.top:=self.top-5;
  SubRichEd.Height:=self.Height-10;
  SubRichEd.left:=self.left+self.Width;
  SubRichEd.width:=self.Width-10;
  end;
end;


procedure TSimpTestRich_UA.createtmpmemo;
begin
if getTmpMemo =nil then
 with tmemo.create(self) do
 begin
   parent:=self.parent;
   top:=self.top+self.Height;
   left:=self.left;
   name := getComponentName(lzMemoName); // eindeutiger Name
 end;
end;

procedure TSimpTestRich_UA.DeleteSubrichEd;
begin
if assigned(SubRichEd) then subriched.free;
subriched:=nil; //sonst ergäbe ein erneutes Assignde TRUE, obowohl das object gelöscht ist
//freeandnil(SubRichEd); geht nicht da E2197 Konstantenobject kann nicht als Var-Parameter weitergegeben werden
end;


procedure TSimpTestRich_UA.deleteTmpMemo;
begin
getTmpMemo.free;
//freeandnil(getTmpMemo) geht nicht
end;

procedure TSimpTestrich_UA.expresscontrols(doother: boolean);
 var i:integer;
begin
// das wäre die Notlösung, wenn man alle componenten in TSimpTestrich_UA.Create eerzeugen würde, aber parent dot noch nicht bekannt ist
for I := 0 to componentcount-1 do
  if components[i] is tcontrol then
  begin
   with tcontrol(components[i]) do
   begin
     parent:=self.parent;
   end;
    if components[i] is trichedit
    then
      begin
          trichedit(components[i]).Lines.Add('Mein Name in Expresscontrols: '+components[i].Name);
      end;
  end;
end;


function TSimpTestRich_UA.getComponentName(anam: string): string;
begin
result:=name // der eigene Name
        +'_'+
        anam // der Componetenname
        +'_'+
        'UA//eine persönliche Erweiterung
end;

function TSimpTestRich_UA.GetShowpts: tshowOpts_UA;
begin
  result:= FShowOpts
end;


function TSimpTestRich_UA.getTmpMemo: tmemo;
begin
  result:=findcomponent(getComponentName(lzMemoName)) as tmemo;
end;

procedure TSimpTestRich_UA.onselfMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 if button =mbRight then
begin
  //showopts ändeern - in setShoOpts werden dann die Componenten erzeugt oder gelöscht
  if ShowSubRichEd_UA in ShowOpts then showOpts:= ShowOpts-[showsubriched_UA]
  else showOpts:= ShowOpts+[showsubriched_UA];
 end;
 if button =mbLeft then
begin
   setReadyForTmp(not ReadyForTmp);
 end;

end;

procedure TSimpTestRich_UA.setReadyForTmp(const Value: boolean);
begin
//alle anderen Komponenten erzeugen oder löschen
FReadyForTmp:=value;
if value then
begin
createTmpMemo;
//und alle anderen ohne Feld
end else
begin
  deleteTmpMemo
//und alle anderen ohne Feld
end;

end;

procedure TSimpTestRich_UA.SetShowpts(const Value: tshowOpts_UA);
begin
    FShowOpts:=Value;
    if ShowSubRichEd_UA in ShowOpts then createsubriched
    else deletesubriched;
{
    if ShowSubRichEd_UA in ShowOpts then SubRichEd.Show
    else SubRichEd.hide;
}


// geht beim setzten von ShowSubriched in der IDE nicht - hat noch kein Fenster
// if ShowSubRichEd_UA in ShowOpts then subriched.lines.add('bin sichtbar')
// else subriched.lines.add('bin UNsichtbtar');


end;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

AW: Wann sind objecte auf der IDE fertig initialisert?

  Alt 27. Feb 2018, 17:24
Delphi-Referenz durchsuchenTComponent.Loaded

In der IDE oder im Programm, immer wenn die Komponente aus einer DFM deserialisiert wird.
Und in den Settern kannst du auf csLoading bzw. csReading prüfen, während des Ladens.

Setter: bei csLoading nix machen, außer Wert zu speichern
Loaded: nach "allen" Settern dann das machen

Setter: ohne csLoading alles normal/sofort machen, während der Laufzeit

Zitat:
Delphi-Quellcode:
if assigned(SubRichEd) then subriched.free;
subriched:=nil;//sonst ergäbe ein erneutes Assignde TRUE, obowohl das object gelöscht ist
FreeAndNil(subriched); //if Assigned(SubRichEd) then FreeAndNil(subriched);
ohne Assigned, denn das ist schon im Free eingebaut

PS: eigentlich ist das ein NilAndFree, denn FreeAndNil setzt erst die Variable sicher auf NIL und gibt dann frei, wenn es nicht NIL war.
$2B or not $2B

Geändert von himitsu (27. Feb 2018 um 17:33 Uhr)
  Mit Zitat antworten Zitat
DrUArn

Registriert seit: 20. Mär 2003
130 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Wann sind objecte auf der IDE fertig initialisert?

  Alt 27. Feb 2018, 23:57
@ Himitsu,
danke für den Tip (das habe ich schon lange gesucht).


Meine Lösung nun:
für alles spätere
Delphi-Quellcode:
// ....
   published
   Procedure loaded;override;
// ...


procedure TSimpTestRich_UA.loaded;
begin
  inherited;
  if ReadyForTmp then createTmpMemo else deleteTmpMemo //je nach Wert von ReadyForTmp die Objecte laden oder löschen
end;

in den Settern (wobei ich die Definition von CSLOAding bzw. CSReading in meiner Hilfe nicht finden kann):
Delphi-Quellcode:
procedure TSimpTestRich_UA.SetShowpts(const Value: tshowOpts_UA);
begin
  FShowOpts:=Value;

  if not(csloading in ComponentState) then
  // if not(csreading in ComponentState) then exit;
  begin
      if ShowSubRichEd_UA in ShowOpts then createsubriched
      else deletesubriched;
  end;
{
    if ShowSubRichEd_UA in ShowOpts then SubRichEd.Show
    else SubRichEd.hide;
}


// geht beim setzten von ShowSubriched in der IDE nicht - hat noch kein Fenster
// if ShowSubRichEd_UA in ShowOpts then subriched.lines.add('bin sichtbar')
// else subriched.lines.add('bin UNsichtbtar');


end;
Aber: in meinem Beispiel ist "csLoading in compoentstate" immer true - d.h. an dieser Stelle wird das Objekt nicht erzeugt oder gelöscht!!, lasse ich die Prüfung weg, wird die Initialisierung durchgeführt - nur weiß ich eben da nicht, ob z.B. TSimpTestRich_UA.Parent schon gesetzt ist usw. -in meinem Beispiel ist das alles schon geschehen.



und was das löschen von Componenten (hier SubRichEd) bertrifft:
- stimmt: Subriched.free darf man ungeprüft anwenden.
- freeandnil(SubRichEd); geht nicht !! da Fehler E2197 Konstantenobject kann nicht als Var-Parameter weitergegeben werden

- bleibt die Frage, muß ich in meiner Löschprocedure
Delphi-Quellcode:
procedure TSimpTestRich_UA.DeleteSubrichEd;
begin
subriched.free;//kann auch auf nil angewendet werden
subriched:=nil; //sonst würde bei Eerneutem löschen wieder versucht zu löschen obowohl das object gelöscht ist
//freeandnil(SubRichEd); //geht nicht da E2197 Konstantenobject kann nicht als Var-Parameter weitergegeben werden
end;
subriched:=nil; setzen.

Ich denke ja. Scheinbar kriegt der Owner (TSimpTestRich_UA) nichts von der Löschung mit.
Lasse ich
subriched:=nil;
weg, wird beim nächsten Versuch mit der gleichen Routine ein Fehler ausgelöst (ungültige Zeigeroperation).


Also nochmal
Danke für den Tip

Gruß Uwe

Geändert von DrUArn (28. Feb 2018 um 00:32 Uhr) Grund: ausprobiert
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

AW: Wann sind objecte auf der IDE fertig initialisert?

  Alt 28. Feb 2018, 09:49
Achtung, bei Allem während der Ausführung des Contructor, da ist ComponentState noch nicht gesetzt. (geht ja erst nach Erstellen der Klasse, bzw. man hätte es machen können, ähnlich wie beim csDestroying, dachte aber nicht dran)
Aber da kann man sich behelfen, wenn man nach csLoading oder csDesigning im Owner.ComponentState schaut.
> beim Aufrufen von Gettern/Settern im Constructor muß also immer aufgepasst werden. (meistens macht man sowas aber besser garnicht und geht immer nur direkt auf die Felder)

Zitat:
Aber: in meinem Beispiel ist "csLoading in compoentstate" immer true - d.h. an dieser Stelle wird das Objekt nicht erzeugt oder gelöscht!!,
Wenn du im Code (z.B. Button-Click) auf den Property/Setter zugreifst, dann ist es True?



Ups, das ist ja das Property.
Dort muß natürlich das Feld (Variable) rein, also FreeAndNil(FSubRichEd) .

Über den Setter darf man bei sowas eh nie gehen.
> Die Komponente freigeben und dann dem Property NIL zuweisen ... wäre blöd, wenn dort dann der Setter nochmal versucht auf die alte Komponente zuzugreifen.
Ausnahme: Der Setter gibt das Objekt frei (da natürlich auch über die Variable), wenn man ihm NIL zuweist, aber da vorher natürlich auch nicht extern die Komponente zerstören.


Ist echt eigenartig.
TComponent, TComponentState usw. sind wirklich nicht "richtig" in der XE-Hilfe vorhanden.
http://docwiki.embarcadero.com/RADSt...mponent_Branch <- alles weg, auch in C++
http://docwiki.embarcadero.com/RADSt.../en/TComponent <- aber hier wird csLoading dennoch gefunden
http://docwiki.embarcadero.com/RADSt...ses.TComponent <- und nach Modulen/Units einsortiert war es auch noch nicht

http://docwiki.embarcadero.com/Libra...ComponentState <- nochmal die Hilfe des aktuellen Delphi (auch über Delphi-Referenz durchsuchenTComponentState)

Seit 2010 sind alle Hilfen auch Online verfügbar, aber es schadet meistens nicht, wenn man einfach nur in die aktuelle Hilfe schaut, bei solchen Basics.
http://geheimniswelten.de/sonstiges/...iler/#Compiler

http://docwiki.embarcadero.com/Libra...ComponentState <- in XE3 ist es wieder drin
https://www.freepascal.org/docs-html...nentstate.html <- Lazarus und FreePascal kennen es natürlich auch (die VCL/RTL ist ja in großen Teilen mit Delphi 7 vergleichbar)
http://lazarus-ccr.sourceforge.net/d...nentstate.html
http://delphi.wikia.com/wiki/TComponentState_Type <- die haben es auch nicht


Da du dir die Referenzen nicht merkst, sondern oftmals über FindComponent suchst, und das auch noch mit zusammengesetzen Namen,
> siehe TSimpTestRich_UA.getComponentName
solltest du unbedingt auch Delphi-Referenz durchsuchenTComponent.SetName überschreiben und dort diese Namen mit anpassen.
Entweder Self.Name niemals für SubKomponenten verwenden, oder diese Namen immer mit synchronisieren. (ich nutze sowas auch gern, für ein einfacheres/besseres Debugging und Logging)

Zitat:
Delphi-Quellcode:
   published
   Procedure loaded;override;
Und man sollte NIEMALS unbedacht die Sichtbarkeiten von Überschriebenem unbedacht verändern.
> hier protected

Und in Hinblick auf C++Builder (das kann Delphi-Code nutzen) und in Bezug auf die Serialisierung von Property, inkl. einem CVS, sollte man die Groß-/Kleinschreibung auch gleich behalten.
$2B or not $2B

Geändert von himitsu (28. Feb 2018 um 10:02 Uhr)
  Mit Zitat antworten Zitat
DrUArn

Registriert seit: 20. Mär 2003
130 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: Wann sind objecte auf der IDE fertig initialisert?

  Alt 28. Feb 2018, 12:44
Hi Himitsu,

danke für's mitdenken.

"Wenn du im Code (z.B. Button-Click) auf den Property/Setter zugreifst, dann ist es True?"

-> dann ist das FALSE, und man kann über SetShowpts(const Value: tshowOpts_UA) hier den SubRichEd ein und ausschalten.

Nur bei der Initialisierung, nach TSimpTestRich_UA.Create(AOwner:TComponent);overrid e;,wenn danach automatisch eine Eigenschaft nach der anderen über die Setter eingelesen wird, ist dort (csloading in ComponentState) TRUE.

Aber dein Hinweis ist schon richtig: Erst wenn alles gelesen ist, sollte man den Rest initialisieren.

Delphi-Quellcode:
protected
  { protected declarations }
procedure Loaded;override;// nun wieder versteckt

...

procedure TSimpTestRich_UA.Loaded;
begin
  inherited;
  setReadyForTmp(FReadyForTmp);//die anderen Komponenten initialisieren
  SetShowpts(FShowOpts);
end;
... so ich den unbedingt die Setter so nutzen will - die Warnung habe ich schon verstanden.

Finde ich aber praktisch: Man kann über FShowOpts:tShowOpts_UA; und dessen Setter die Kompenenten ein und ausschalten.
Diese Komponenten bekomme ich sogar in der IDE und im Objekt-Inspektor zu sehen, wenn ich die entsprechende Option anklicke (ShowOpts:=[ShowSubRichEd_UA, ...] oder setReadyForTmp:=true) an der Stelle, wohin ich sie in ihrem Create hinrechne.
Komponenten mit Feld kann ich sogar im Objekt-Inspektor editieren (z.B. Left, Top), die Änderungen werden aber nicht übernommen - logisch - läuft ja über Create.

Und man kann viel Unfug mit solchen Settern anrichten: Habe zum Test im Objekt-Inspektor in die Eigenschaft "SubRichEd" einen auch auf dem Desktop liegend TrichEdit eingebunden - das geht auch, und man kann diesen Richedit auch nutzen, aber wehe, man löscht in der IDE diesen Richedit mal schnell weg - dann kann man das Programm nicht mehr compilieren noch den SubRichEd vom Desktop nehmen, noch das Delphi mit speichern beenden. Mußte dann händisch aus der *.dfm die störenden Objekte (SubrichEd und Richedit) entfernen,
um wieder normal starten zu können.

"Entweder Self.Name niemals für SubKomponenten verwenden, oder diese Namen immer mit synchronisieren"
und hier war ich der irrigen Ansicht, daß, wenn ich mehrere TSimpTestRich_UA's auf den Desktop lege, es zu Namensdopplungen kommen kann - ist aber nicht so, da das nur beim Owner nicht passieren darf, Parent(hier tForm) ist das egal.

"oder diese Namen immer mit synchronisieren" heißt ? self.Name unbedingt selbst festlegen?


Grüße Uwe

Geändert von DrUArn (28. Feb 2018 um 12:51 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#6

AW: Wann sind objecte auf der IDE fertig initialisert?

  Alt 28. Feb 2018, 12:58
Und man kann viel Unfug mit solchen Settern anrichten: ...
Man muß es nur richtig machen.

Delphi-Quellcode:
type
  TMyClass = class(TComponent)
  private
    FInstance: TComponent;
    procedure SetInstance(Value: TComponent);
  protected
     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  published
    property Instance: TComponent read FInstance write SetInstance;
  end;

procedure TMyClass.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited;
  if Operation = opRemove then begin
    if FInstance = AComponent then
      FInstance := nil;
  end;
end;

procedure TMyClass.SetInstance(Value: TComponent);
begin
  //if Assigned(FInstance) then begin
  // FInstance.RemoveFreeNotification(Self);
  FInstance := Value;
  if Assigned(FInstance) then begin
    FInstance.FreeNotification(Self);
end;
FreeNotification hat keine Referenzzählung.
Weitere Property und auch Onwer oder Parent registrieren das ebenfalls, also einfach garnicht deregistrieren. (macht die TComponent von selber, wenn Einer von Beiden freigegeben wird)
Also kann man deregistrieren, aber nur wenn man die volle Kontrolle über alle Referenzen besitzt, oder wenn man definitiv nur die eintige Referenz sein kann. (nur interne Instanzen, auf die es von Extern keinen Zugriff gibt)

FInstance.FreeNotification(Self); und Self.FreeNotification(FInstance); ist das Gleiche ... die registrieren sich gegenseitig.



Unter ARC könnte man auch Weak-Referenzen nutzen, wo das ARC diese global registriert und auf NIL setzt, wenn jemand die Instanz freigibt.
var [weak] Instance: TComponent;
$2B or not $2B

Geändert von himitsu (28. Feb 2018 um 13:08 Uhr)
  Mit Zitat antworten Zitat
DrUArn

Registriert seit: 20. Mär 2003
130 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Wann sind objecte auf der IDE fertig initialisert?

  Alt 28. Feb 2018, 13:41
Hallo Himitsu,

das ist mir als Laien-Delphianer dann doch zu hoch.
Bin schon stolz darauf, ein trichedit gezwungen zu haben, mir Cell-Bereiche, die ich definiert habe, anzuzeigen und in diesen Bereichen wie in einer Tabellen-Celle editieren zu können.

By the way: im Zusammenhang mit meinem Beispielprojekt oben gibt es noch ein Problem mit einem modalen Fenster (darf das etwas löschen, was nicht in dessen Owner-Liste steht).
Sollte ich dazu einen neuen Thread aufmachen oder kann ich hier weiter machen?
Es gibt hier im Forum ja strenge Regeln ... .

Grüße Uwe
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#8

AW: Wann sind objecte auf der IDE fertig initialisert?

  Alt 28. Feb 2018, 13:54
Ist eigentlich recht einfach, siehe kurzes Beispielcode.

Du hast eine Referenz zu einer externen oder fremden Komponente, welche jemand löschen könnte.
Nun sagst du dieser Komponente via FreeNotification "Gib mir Bescheid, wenn du verschwindest".
Das macht diese Kompnente dann im Notification-Event, wo du die Verbindung zwischen den Komponenten trennen kannst, also z.B. deine Variable auf NIL setzt.
$2B or not $2B
  Mit Zitat antworten Zitat
DrUArn

Registriert seit: 20. Mär 2003
130 Beiträge
 
Delphi 10.3 Rio
 
#9

AW: Wann sind objecte auf der IDE fertig initialisert?

  Alt 28. Feb 2018, 14:14
Hallo Himitsu,

der Absturz ist mir auf der IDE passiert, nicht bei laufendem Programm. Ich schaue mir deinen Code noch an, aber dazu brauche ich wohl länger.

Ich versuch's mal mit dem Showmodal-Fenster:
(die mich interessierende Stelle habe ich weiter unten nochmal editiert)

Delphi-Quellcode:
procedure TSimpTestRich_UA.ShowOptsEditor;
//mal bitte nicht den Sinn dieser Routine hinterfragen - normalerweise steckt sie in
//einer Komponente, die nach außen mit Window-Messages kommuniziert

//mit dem Editor kann mann die Oben Beschriebenen Komoponenten (SubRichEd,...) laden und wieder löschen

var i,l,t,checkwidth:integer;
    tb:tbutton;
    tf:tform;
begin
  {das Modalfenster}
  tf:=tform.create(application);
  tf.name:='DockEinstellungen';
  tf.Caption:='DockEinstellungen von '+ owner.name;
  tf.AutoSize:=true;
  tf.formstyle:=fsstayontop;

 {die Checkbox-Box}
 if not assigned(groupbox) //beim ersten Aufruf kann sie nicht assigned sein
   then groupbox:=tgroupbox.create(owner);//Owner ist TSimpTestRich_UA
 groupbox.parent:=tf;//der Anzeige-Ort für die Groupbox ist das modale Fenster
 groupbox.name:='do_Groupbox';

l:=10; t:=20; checkwidth:=0;
{checkboxes zuordnen}
for I := integer(Low(tShowopt_UA)) to integer(High(tShowopt_UA)) do
begin
  with tcheckbox.create(groupbox) do
  begin
  parent:=groupbox;
  left:=l;top:=t;
  caption:=DockOptsCaps_UA[tShowopt_UA(i)];
  name:=DockOptsCaps_UA[tShowopt_UA(i)];
    if checkwidth<height + length(caption)* groupbox.font.size then
          checkwidth:=length(caption)* groupbox.font.size; //größte Breite mitrechnen

  checked:= tShowopt_UA(i) in Showopts;
  tag:=integer(tShowopt_UA(i));
  inc(t,height);
  OnClick:=onCheckboxclick; //was soll bei Clicken passieren
  end;
end;

inc(t,20);
{eine Extra-Checkbox, um zu bestimmen, ob die Eigenschaft sofort gesetzt werden soll - True=Ja}
  with tcheckbox.create(groupbox) do
  begin
  parent:=groupbox;
  left:=l;top:=t;
  checked:=false;
  caption:='sofort anwenden';
  name:='sofort_anwenden';
  end;
inc(t,20);

{noch die obligaten Schließen-Knöpfe}
with tbutton.create(tf) do
begin
parent:=tf;
top:=t;left:=groupbox.left;
name:='DockOptsButton_OK';
Caption:='OK/Schliessen';
ModalResult:=mrOk;
end;

with tbutton.create(tf) do
begin
parent:=tf;
top:=t;left:=groupbox.left+Width;
name:='ShowOptsButton_Abbrechen';
Caption:='Abbrechen';
ModalResult:= mrCancel;
t:=t+Height;
end;



for i := 0 to groupbox.controlcount-1 do
  groupbox.Controls[i].Width:=checkwidth; // alle Cjeckckboxen haben die gleich max. Breite -vielleicht nicht nötig

  groupbox.width:=checkwidth;//Groupbox auch die größte Breite
  groupbox.Height:=t+10;

  groupbox.name:='Andockoptionen';

{Erscheinungsort errechenen - geht aber nicht}
  tf.left:=left;
  tf.top:=top;


if tf.showmodal=mrok then
  onCheckboxclick(self);//normalerweise rufen die Checkboxen oncheckboxclick auf, hier vereinbarungsgemäß setzen dort ohne Prüfung sofortsetzen

tf.free;

{??lebt die Groupbox noch oder ist sie weg??
wenn ja, wie so - DER owner ist doch TSimpTestRich_UA?
}


if assigned(groupbox)
then
begin
  try
  groupbox.free; //ergibt Fehler
  except
  lines.add('groupbox scheint assigned, aber ist nicht löschbar');
  groupbox:=nil;
  end;
end;

// wenn ich GrouBox nicht nil setze und das Fenster neu aufrufe, gibts auch einen Fehler
//lesen von 000000 und das programm ist kaputt


end;

Wichtig für mich zum Verstehen ist nur dieser Teil:

Delphi-Quellcode:
// ....

if tf.showmodal=mrok then
  onCheckboxclick(self);//normalerweise rufen die Checkboxen oncheckboxclick auf, hier vereinbarungsgemäß setzen dort ohne Prüfung sofortsetzen

tf.free;

{??lebt die Groupbox noch oder ist sie weg??
wenn ja, wie so - DER owner ist doch TSimpTestRich_UA?
}


if assigned(groupbox)
then
begin
  try
  groupbox.free; //ergibt Fehler
  except
  lines.add('groupbox scheint assigned, aber ist nicht löschbar');
  groupbox:=nil;
  end;
end;

// wenn ich GrouBox nicht nil setze und das Fenster neu aufrufe, gibts auch einen Fehler
//lesen von 000000 und das programm ist kaputt

// ....
Es fühlt sich so an , als ob beim Schließen dieses modalen Fensters TF ein Object (hier GroupBox) gelöscht wird, obwohl es dem Shomodal-Fenster TF nicht gehört, also nicht in der Owner-Liste steht.


Und auf dem Desktop auftauchen tut dieses Fenster wo es will
{Erscheinungsort errechenen - geht aber nicht}
tf.left:=left;
tf.top:=top;


Grüße Uwe
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#10

AW: Wann sind objecte auf der IDE fertig initialisert?

  Alt 28. Feb 2018, 14:21
Der gezeigte Notification-Code ist vor allem für den Form-Designer gut, aber er geht überall. (Runtime im Programm, IDE oder sonstwo)

Tipp: Du hast doch ein DesignTime-Package mit deiner Komponente.
Da nun statt deiner Anwendung die IDE angeben, also im Menü > Tools > Startparameter
> Host-Anwendung: C:\Program Files (x86)\Embarcadero\RAD Studio\8.0\bin\bds.exe
> eventuell noch die Parameter: -np -pDelphi

Und nun kanns du deine Komponente in der IDE debuggen, innerhalb einer zweiten IDE-Instanz.
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort

 

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 06:37 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