OnCreate

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
malabarista
Beiträge: 321
Registriert: Sa 11. Jun 2016, 12:16
OS, Lazarus, FPC: Linux Mint 18.1 L1.6.2-1 FPC 3.0.0
CPU-Target: 64Bit
Wohnort: Konstanz

OnCreate

Beitrag von malabarista »

Ich habe in meinen Formularen im OnCreate verschiedene Initialisierungen vorgenommen.

Jetzt habe ich festgestellt (etwas spät), daß alle Formulare beim Programmstart automatisch erzeugt werden und somit OnCreate aufgerufen wird.
Das macht mir Probleme.

Deshalb muss ich also meine Initialisierungen zu einem anderen Event vornehmen.
Was für ein Event wird denn verwendet, wenn ich programmintern ein Formlar aufrufe ?
Meine Formular-Aufrufe sehen im allgemeinen folgendermaßen aus:

Code: Alles auswählen

 
...
procedure TFoffice.tische(Sender: TObject);
var
  tisch_v:TFtisch;
 
begin
   tisch_v:=TFtisch.Create(Nil);
   tisch_v.Show;
end;                       
...
 
Oder ist dieser Aufruf völlig falsch ?
Muss das völlig anders geschehen ?

Benutzeravatar
theo
Beiträge: 11005
Registriert: Mo 11. Sep 2006, 19:01

Re: OnCreate

Beitrag von theo »

Verstehe dein Problem zwar nicht gänzlich, aber allgemein bieten sich OnShow oder OnActivate für so etwas an.

wp_xyz
Beiträge: 5268
Registriert: Fr 8. Apr 2011, 09:01

Re: OnCreate

Beitrag von wp_xyz »

malabarista hat geschrieben:

Code: Alles auswählen

procedure TFoffice.tische(Sender: TObject);
var
  tisch_v:TFtisch;
begin
   tisch_v:=TFtisch.Create(Nil);
   tisch_v.Show;
 
Oder ist dieser Aufruf völlig falsch ?
Völlig falsch nicht, aber gefährlich. Der Parameter, der bei Create angegeben wird, ist der "Owner" eines Objekts. Das ist das Objekt, der dafür zuständig ist, die zu erzeugende Instanz, also "tisch", wieder freizugeben. Du verwendest dafür "nil", also niemand, also musst du das machen, sonst hat du ein Speicherleck. Zudem ist die Instanz "tisch" eine lokale Variable der aufrufenden Prozedur, du hast also nach dem Verlassen der Prozedur keine Chance mehr zu erkennen, welches Objekt da zu zerstören ist. Pascal hat keine Garbage-Collection, die dafür sorgen würden, dass ein Objekt, dessen Gültigkeit erlischt (beim Verlassen von "tische"), automatisch freigegeben wird.

Besser: Verwende self als Owner. Self meint die Klasse, zu der die aufrufende Methode gehört. Damit wird TFtisch immer dann zerstört, wenn auch TOffice zerstört wird. "nil" verwende ich als Owner nur im überschaubaren Zusammenhang, wo man erkennen kann, dass das Objekt auch wieder zerstört wird, also so:

Code: Alles auswählen

procedure TFoffice.tische(Sender: TObject);
var
  tisch_v: TFtisch;
begin
  tisch_v := TFtisch.Create(nil);
  try
    TuEtwasMitTisch(tisch_v);
  finally
    tish_v.Free;
  end;
end;

MmVisual
Beiträge: 1605
Registriert: Fr 10. Okt 2008, 23:54
OS, Lazarus, FPC: Winuxarm (L 4.2 FPC 3.2.2)
CPU-Target: 32/64Bit

Re: OnCreate

Beitrag von MmVisual »

Mann kann in den Projektoptionen einstellen welche Formulare alle zum Start automatisch erzeugt werden sollen. Lazarus macht das in der Regel automatisch.
Für mein Projekt erzeuge ich das Unterformular selbst, also ich merke mir in einer globalen Variable das erzeugte Formular, in etwa so:

Code: Alles auswählen

Var fSub1: TFSub;
 
Procedure FrmMain.Button1Click(Sender)
Begin
  If Not Assigned(fSub1) Then
    fSub1 := TFSub.Create(Self);
  fSub1.Show;
End;
 
Procedure FrmMain.OnDestroy(Sender)
Begin
  If Assigned(fSub1) Then
    fSub1.Free;
End;
 
Bei größeren Projekten startet die EXE schneller, dafür benötigt das erstmalige Öffnen des Sub-Formulars etwas mehr Zeit, was meist verkraftbar ist. Hingegen wenn zum Start gleich 20 Formulare erzeugt werden, das merkt man schon.
EleLa - Elektronik Lagerverwaltung - www.elela.de

wp_xyz
Beiträge: 5268
Registriert: Fr 8. Apr 2011, 09:01

Re: OnCreate

Beitrag von wp_xyz »

@MmVisual: Das OnDestroy brauchst du in diesem Fall nicht, weil du das Unterformular mit Owner self erzeugt hast, FrmMain kümmert sich also darum selber. Ich erinnere mich sogar an Zeiten mit Delphi, also diese Konstruktion einen Laufzeitfehler verursacht hat, weil man das Formular, das FrmMain gleich zerstören wollte, plötzlich nicht mehr da war.

malabarista
Beiträge: 321
Registriert: Sa 11. Jun 2016, 12:16
OS, Lazarus, FPC: Linux Mint 18.1 L1.6.2-1 FPC 3.0.0
CPU-Target: 64Bit
Wohnort: Konstanz

Re: OnCreate

Beitrag von malabarista »

@MmVisual: das ist gut.
Denn ich brauche manche Formulare öfters.

Was passiert denn eigentlich mit einem Formular beim "Close" ?
Ist es dann nur invisble und noch vorhanden ? Und braucht beim nächsten Aufruf nur visible gemacht zu werden (d.h. ein Show)?
Oder muss man es nach dem Close zerstören und freigeben ?

wp_xyz
Beiträge: 5268
Registriert: Fr 8. Apr 2011, 09:01

Re: OnCreate

Beitrag von wp_xyz »

OnClose hat den Parameter CloseAction, mit dem man festlegt, was passieren soll, insbesondere caHide (verbergen) oder caFree (zerstören). Voreingestellt für den Fall, dass OnClose nicht verwendet wird, ist caHide.

Martin V
Beiträge: 142
Registriert: Sa 30. Jan 2010, 19:35
OS, Lazarus, FPC: Linux64, Wiindows32, MacOS, Lazarus 1.8.2
CPU-Target: xxBit

Re: OnCreate

Beitrag von Martin V »

Es geht auch um das richtige Timing. Zuerst findet Create statt, später erst dann Show. Create organsiert den Speicher, Show erzeugt das Fenster am Bildschirm. Man sollte nicht in einem OnCreate ein Create und ein Show einer Kindkomponente schreiben, evtl. gibt es bei Create noch keinen Windowhandle des Parentfensters. Also in Create nur Kindkomponenten createn und erst in Show dann das Show der Kindkomponente aufrufen. Folgendes muß man dabei bedenken:

1. Show wird jedesmal aufgerufen, wenn das Fenser von minimert nach groß gesetzt wird oder aber wenn es aus anderen Gründen neu gezeichnet werden muß. Wenn man hier ein Create einer Kindkomponente hineinschreibt, wird es jedes Mal neu erzeugt. Also muß man abfragen, ob das Show wirklich erstmalig aufgerufen wurde, ich mache das mit einer Boolean Variable FirstShow, die ich in Create auf false setze und beim ersten Show auf true. In den FirstShow Block kann man dann nicht nur das Show, sondern auch das Create der Kindkomponenten reinschreiben.

2. Ich schreibe immer Show zusammen mit WindowState := wsNormal und BringToFront. Sonst kann es passieren, dass das Fenster unterhalb eines anderen auftaucht oder im minimized Zustand (also nur in der Taskliste erscheint).

P.S. In einer anderen delphiähnlichen Entwicklungsumgebung (WDSibyl) gibt es einen OnSetupShow Event, der einem die FirstShow Abfrage erspart. Das könnte man mal anregen.

malabarista
Beiträge: 321
Registriert: Sa 11. Jun 2016, 12:16
OS, Lazarus, FPC: Linux Mint 18.1 L1.6.2-1 FPC 3.0.0
CPU-Target: 64Bit
Wohnort: Konstanz

Re: OnCreate

Beitrag von malabarista »

Dankeschön: eure Beiträge haben mein Verständnis zum "Lebenslauf" eines Formulars deutlich verbessert.

@Martin V: gute Idee mit der FirstShow-Variable.
Ich werde dies noch etwas erweitern durch das Einführen einer zusätzlichen Funktion "start" in dem betreffenden Formular.
Denn ich möchte aus Sicherheitsgründen beim jeweiligen Starten eines Formulars die notwendigen Datenbanken öffnen (und beim onClose schliessen).

Das heisst mein Aufruf sieht dann so aus:

Code: Alles auswählen

 
Procedure FrmMain.Button1Click(Sender)
Begin
  If Not Assigned(fSub1) Then
    fSub1 := TFSub.Create(Self);
  fSub1.Start;  // <--
  fSub1.Show;
End;
 

wp_xyz
Beiträge: 5268
Registriert: Fr 8. Apr 2011, 09:01

Re: OnCreate

Beitrag von wp_xyz »

malabarista hat geschrieben:die notwendigen Datenbanken öffnen (und beim onClose schliessen)
Das ist eine neue Information, die du bisher nicht gegeben hast. Ein (bei mir) beliebter Fehler ist in diesem Zusammenhang, die Datenbank-Komponenten auf ein Datenmodul zu klicken (richtig), aber nicht dafür zu sorgen, dass das Datenmodul als erstes Formular erzeugt wird. Also: "Projekt-Optionen" öffnen und unter "Formulare" das Datenmodul an die erste Stelle der automatisch erzeugten Formulare verschieben.

Antworten