Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Kniffliges Problem beim Serialisieren (https://www.delphipraxis.net/85737-kniffliges-problem-beim-serialisieren.html)

SMALLID 4. Feb 2007 09:20


Kniffliges Problem beim Serialisieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hello party people,

also ich bin da auf ein sehr interessantes, wenn auch frustrierendes, und zugleich möglicherweise sogar noch logisches Problem gestoßen, an dem sich jeder gerne versuchen darf :D

Hintergrund: Entwickelt wurde eine MDI-Anwendung. In den jeweiligen MDI-Children werden in zahlreichen Controls Eingaben gemacht, die in ihrer Gesamtheit gespeichert und später wieder geladen werden sollen. Damit ich das nicht in der Manier:

"Schreibe KomponenteX.EigenschaftA in TextDatei t, gehe eine Zeile weiter, Schreibe KomponenteY.EigenschaftB in TextDatei t, gehe ..."

machen muss, habe ich das (auch dank einiger Beispiele von DelphiPraxis :D) so gelöst:

Speichern:
Delphi-Quellcode:
procedure TMainForm.FileSaveAs1Execute(Sender: TObject);
var
  FileStream : TFilestream;
begin
  if SaveDialog1.Execute then
  begin
    FileStream:=TFileStream.Create(SaveDialog1.Filename, fmCreate);
    Try
      FileStream.WriteComponent(MainForm.ActiveMDIChild);
    Finally
      FileStream.Free;
    end;
  end;
end;
Laden:
Delphi-Quellcode:
procedure TMainForm.ToolButton12Click(Sender: TObject);
var
  Child: TForm;
  FileStream : TFileStream;
begin
  if OpenDialog.Execute then
  begin
    FileStream:=TFileStream.Create(OpenDialog.Filename, fmOpenRead);
    Try
      //Eine Instanz eines Unterfensters wird erzeugt
      Child := TMDIChild.Create(MainForm);
      //Alle Enthaltenen Komponenten darin müssen aber erst gelöscht werden,
      //da beim Laden sonst eine Komponente mit demselben Namen schon existieren
      //würde. Ist quick'n'dirty, aber es funktioniert erstmal.
      While Child.ComponentCount > 0 do
      begin
        Child.Components[0].Destroy;
      end;
      //Der Stream mit allen Eigenschaften und Unterkomponenten wird nun in Child hineingelesen
      FileStream.ReadComponent(Child);
    Finally
      FileStream.Free;
    end;
  end;
end;
So das funktioniert auch soweit schon ganz gut.
Nun aber das Problem:
Aus den gesetzten Eigenschaften werden zur Laufzeit (eigene) Komponenten erzeugt (wen's interessiert: es handelt sich dabei um simple Software-Agenten, die miteinander auf einem simulierten Markt handeln sollen, sowie "Agenten-Pools", dem die Agenten angehören.)
Kurz gesagt werden die dynamisch erzeugten Komponenten weder komplett geschrieben (das ist aber nur ein educated guess, weil ich mir die Datei mal im Wordpad angeschaut hab) noch geladen. Wenn ich das Teil wieder lade, wird nicht mehr "gehandelt".
Nähere Infos:
Es wird zuerst ein Agenten-Pool (auch: "MarketCoordinator") erzeugt. Das ist eine simple Spezialisierung von TComponent mit einigen zusätzlichen Eigenschaften. Der Owner dieser Komponente ist das MDI-Child. Dann werden die Agenten erzeugt. Auch sie sind Spezialisierungen von TComponent mit einigen eigenschaften und der methode "handeln()". Der Owner eines jeden Agenten ist der angegebene Agenten-Pool.
Der Name und der Typ des Agent-Pools stehen in der gespeicherten Datei an letzter Stelle (siehe Anhang). Mehr aber nicht. Die Agenten tauchen so wie ich das sehe gar nicht auf.

Meine Vermutung:
Ohne euch auf eine falsche Spur zu kriegen! Kann es evtl. daran liegen, dass der Typ TMDIChild zwar mit den einzelnen Controls definiert ist (die stehen ja auch zur Entwurfszeit alle drin in der Definition/Formulardatei), aber nicht mit den dynamisch erzeugten Komponenten? Kann mir das nicht so richtig vorstellen, denn der Agenten-Pool wird ja zumindest mit seinem Namen auch mitgespeichert und der wurde ja dynamisch erzeugt.

Habe auch schon versucht, mit der procedure "setSubComponent" was zu reißen, aber das scheint nichts zu bringen - ist wohl für die Entwurfszeit gedacht :(

SMALLID 5. Feb 2007 14:52

Re: Kniffliges Problem beim Serialisieren
 
Update: Nur zur Info: Meine Vermutung ist vermutlich falsch ;). Es liegt an etwas anderem. Wenn ich nur eine Unterkomponente speichere (z.B. sage ich myStream.WriteComponent(AgentPool1)) werden deren Eigenschaften (eigentlich nur name und tag und sowas gespeichert, aber nicht die in "AgentPool1.Components[]" enthaltenen Komponenten. Die Kinder werden also einfach nicht geschrieben. Bleibt die Frage, warum?

Wenn jemand sich der Sache mal annehmen will aber mehr infos braucht, besorg ich die euch gerne. Naja, es ist nun nicht so, als ob das ein Riesenproblem ist. Ist ja eine grundlegende Sache, wenn das nicht richtig gestreamt wird. Aber halt eine schwerwiegende :(

marabu 6. Feb 2007 08:09

Re: Kniffliges Problem beim Serialisieren
 
Hallo,

Zitat:

Zitat von SMALLID
Ist ja eine grundlegende Sache, wenn das nicht richtig gestreamt wird. Aber halt eine schwerwiegende

ich glaube schon, dass "richtig gestreamt" wird - vielleicht hast du eine falsche Erwartungshaltung? Deine Agents und AgentPools verstellen nur den Blick auf das Wesentliche. Erstelle mal ein Mini-Projekt, welches dein Streaming-Problem aufweist, hänge es hier rein - dann werden wir das Rätsel schon lösen. Automatisches streaming findet laut Dokumentation nur mit published properties statt - wenn ich mich recht erinnere.

Grüße vom marabu

SMALLID 6. Feb 2007 18:00

Re: Kniffliges Problem beim Serialisieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe mal ein einfachst gehaltenes Projekt mit wenigen Zeilen erstellt, welches das Problem verdeutlicht:

(siehe Anhang)
Dabei wird über den ersten Button eine Komponente created, deren Owner das Fenster ist. Der zweite Button erzeugt dann eine KOmponente, deren Owner die erste Komponente ist. Der dritte Button speichert das Ganze. Wenn ihr euch dann mal die gespeicherten Dateien anseht (am besten die Textform), seht ihr, dass am Ende die erste Komponente ("ComponentA") mit gespeichert wurde. Die zweite wird aber dann nicht mitgespeichert.
Meine Frage ist nun, warum das so ist? Ich versuche schon massig Workarounds zu basteln. Bisher mit mäßigem Erfolg.

Code:
object Form1: TForm1
  Left = 46
  Top = 46
  ActiveControl = Button3
  Caption = 'Form1'
  ClientHeight = 204
  ClientWidth = 470
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poDesigned
  Visible = True
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 32
    Top = 8
    Width = 154
    Height = 25
    Caption = 'ComponentA.Create(Form1)'
    TabOrder = 0
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 32
    Top = 56
    Width = 209
    Height = 25
    Caption = 'ComponentB.Create(ComponentA)'
    TabOrder = 1
    OnClick = Button2Click
  end
  object Button3: TButton
    Left = 32
    Top = 104
    Width = 89
    Height = 25
    Caption = 'Speichern'
    TabOrder = 2
    OnClick = Button3Click
  end
  object ComponentA: TComponent
  end
end
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button3Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  ComponentA : TComponent;
begin
  ComponentA := TComponent.Create(self);
  ComponentA.Name := 'ComponentA';
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  ComponentB : TComponent;
begin
  ComponentB := TComponent.Create(FindComponent('ComponentA'));
  ComponentB.Name := 'ComponentB';
//  ComponentB.setSubComponent(true);  
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  FileStream : TFilestream;
  StringStream : TStringStream;
  StringList : TStringList;
begin
    FileStream:=TFileStream.Create('speichern-binaer.dat',fmCreate);
    StringStream := TStringStream.Create('');  
    Try
      FileStream.WriteComponent(Form1);
      FileStream.Position := 0;
      ObjectBinaryToText(FileStream, StringStream);
      StringList := TStringList.Create;
      StringList.add(StringStream.DataString);
      StringList.SaveToFile('speichern-textform.txt');
    Finally
      FileStream.Free;
      StringStream.Free;
    end;
end;
end.

oki 6. Feb 2007 19:23

Re: Kniffliges Problem beim Serialisieren
 
Hi,

hast du es schon mal mit Kompos zur Designzeit probiert?

In der Regel reicht beim Create von Compos zur Laufzeit der Owner im Create nicht aus. Es muß explizit der Parent gesetzt werden.

Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  ComponentB : TComponent;
begin
  ComponentB := TComponent.Create(FindComponent('ComponentA'));
  ComponentB.Parent := ComponentA;
  ComponentB.Name := 'ComponentB';
//  ComponentB.setSubComponent(true);  
end;
Dabei ist wir aber noch nicht ganz klar warum ComponentA der Owner sein soll. Ich gehe mal davon aus, dass alle compos auf Form1 plaziert sein sollen. Dann würde ich immer Form1 als Owner und Parent halten. Für deine Hirarchie halte ich es für besser einen eigenen Member (Property) anzulegen.

Das mit dem Parent ist aber nur eine Vermutung.

Die OH sagt auch folgendes
Zitat:

WriteComponent erstellt ein Writer-Objekt und ruft dessen Methode WriteRootComponent auf, um die in Instance angegebene Komponente und deren untergeordnete Objekte in den Stream zu schreiben.
Da steht nichts von Rekursion! Die einzige Untercompo von Form1 ist ComponenteA. ComponenteB ehört nicht mehr dazu. Wenn du das gleiche mit ComponentA machst, wird sicher ComponentB zu sehen sein, aber keine weiteren Unterkomponenten.

P.S. Ich denke das mit dem Parent war nicht.

Gruß oki

SMALLID 6. Feb 2007 19:52

Re: Kniffliges Problem beim Serialisieren
 
Infos:
- Die ComponentA soll deshalb ein Besitzer von ComponentB sein, weil sich sozusagen um eine Komposition bzw. Aggregation handelt. Die Agenten sollen einem AgentenPool angehören. Beim starten der Tätigkeiten des jeweiligen Agentenpools braucht der dann nur noch seine Kinder durchzugehen (for COmponents[i]) und die jeweils was machen zu lassen. Das wäre umständlicher, wenn die Agenten alle dem Formular gehören würden und jeder Pool sich erst wieder seine Agenten suchen müsste.

- Die Eigenschaft Parent gibt es meines Wissens nach erst ab TControl

- SetSubComponent sollte das mit der Rekursion eigentlich erledigen, hatte ich gehofft. Dem ist aber nicht so. Das ist das was mich stutzig macht. Beim Speichern eines Formulars in Delphi geht sowas doch normalerweise auch.

- Was mich noch stutziger macht, ist, dass eben der Aufruf "WriteComponent(FindComponent('ComponentA'))" statt "WriteComponent(Form1)" beim Speichern nicht darin resultiert das nun ComponentA und dann ComponentB als deren Kind geschrieben wird, sondern ebenfalls nur ComponentA in der Datei steht.

Danke für eure Hilfe! Würde mich freuen, wenn wir das Problem lösen können.

oki 6. Feb 2007 20:07

Re: Kniffliges Problem beim Serialisieren
 
Zitat:

Zitat von SMALLID
Infos:
- Die Eigenschaft Parent gibt es meines Wissens nach erst ab TControl

Jooop! Da hab ich nicht aufgepasst. Das mit den Ownern war mir im Nachgang schon klar. Macht auch Sinn.
Dann bleibt dir wohl nur einen eigenen Algotythmus zu schreiben.

Gruß oki

SMALLID 6. Feb 2007 20:33

Re: Kniffliges Problem beim Serialisieren
 
Naja können wir das jetzt als Bug bezeichnen und melden es CodeGear? Ich meine, probiert das mit dem Speichern von ComponentA statt Form1 ruhig mal aus. Da wird keine Unterkomponente gespeichert, auch wenn das so in der Onlinehilfe steht. Bei Form1 werden sie aber gespeichert (dann eben nur 1 Level). Ein bissl inkonsistent ... oder ich hab' wirklich was übersehen.

Ich werd das jetzt Workaroundmäßig mal versuchen, so zu lösen:
Ich rufe WriteComponent(FormX) auf. Dann schaue ich hartcodiert nach ob in FormX Komponenten vom Typ "ComponentA" enthalten sind (Also genauer: AgentPools). Dann mache ich für jeden AgentPool eine neue Datei auf und gebe ihr den Namen "[Name des Agentpools].dat". Da rein werden dann die Kinder des AgentPools, also die Agenten bzw. im vereinfachten Bsp. alle ComponentB's geschrieben.
Beim Lesen läuft es dann analog. Erst wird die Form geladen. Dann wird nach ComponentA's bzw. "AgentPools" geschaut, deren Name+'.dat' dann wieder den Zugriff auf den Stream mit den ComponentB's, sprich: Agents, ermöglicht.
Meiner Meinung nach eine sehr unelegante und unschöne Lösung, aber ein Workaround muss ja offenbar her. :(

marabu 7. Feb 2007 15:47

Re: Kniffliges Problem beim Serialisieren
 
Hallo,

Zitat:

Zitat von SMALLID
Ein bissl inkonsistent ... oder ich hab' wirklich was übersehen.

dass nur ComponentA gespeichert wird, entspricht völlig den Regeln. Damit Sub-Komponenten gespeichert werden, musst du laut Dokumentation die Methode GetChildren() überschreiben, welche bei der Basisklasse TComponent einfach gar nichts macht.

Grüße vom marabu

SMALLID 7. Feb 2007 17:52

Re: Kniffliges Problem beim Serialisieren
 
Dann hab' ich das tatsächlich übersehen und mir die Workaround-Arbeit wahrscheinlich umsonst gemacht. Ich würde das mit dem override von GetChildren aber dennoch noch einmal probieren. Kannst du mir dazu nochmal das Hilfethema sagen, wo das stand?

marabu 7. Feb 2007 17:59

Re: Kniffliges Problem beim Serialisieren
 
Nicht lachen jetzt, aber es steht bei mir direkt unter Delphi-Referenz durchsuchenGetChildren

SMALLID 7. Feb 2007 20:43

Re: Kniffliges Problem beim Serialisieren
 
Hmm, bei mir nicht direkt. Also ich meine ich wäre von WriteComponent nicht zu GetChildren gekommen und GetChildren hat auch nur bei TCustomForm eine Beschreibung. Bei TComponent taucht die Methode nichteinmal in der Liste auf.

Zitat:

TCustomForm.GetChildren Methode

Gibt die untergeordneten Komponenten des Formulars zurück (also die Komponenten, deren Methode GetParentComponent das Formular zurückgibt).
Klasse
TCustomForm

Syntax


Delphi-Quellcode:
 procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;

Beschreibung
Das Streamingsystem der Komponente ruft GetChildren auf, um die Ausführung eines Callback-Aufrufs für jede untergeordnete Komponente im Formular durch das Formular anzufordern. Die Callback-Aufrufe müssen in der Reihenfolge der Erstellung (Reihenfolge der untergeordneten Komponenten in der Formulardatei) erfolgen. Als untergeordnete Komponente gilt jede Komponente, die dieses Formular als Rückgabewert ihrer Methode GetParentComponent übergibt.

Proc ist die für jede untergeordnete Komponente auszuführende Callback-Funktion.

Root gibt die Top-Level-Komponente (beisielsweise ein Formular oder ein Datenmodul) an, die derzeit geladen oder gespeichert wird.
In TCustomForm-Objekten ruft GetChildren zunächst die geerbte Methode auf, die dann für jedes Steuerelement, das dieses Formular in seiner Eigenschaft Parent angibt, die Funktion in Proc ausführt. Bezeichnet der Parameter Root dieses Formular, führt GetChildren die in Proc angegebene Funktion anschließend auch für alle untergeordneten Komponenten aus, deren Eigenschaft Parent keinen Wert enthält.

oki 7. Feb 2007 21:03

Re: Kniffliges Problem beim Serialisieren
 
Das sieht doch schon mal gut aus. GetChildren ist auch bei mir unter TComponent zu finden. Ganz klar ist mir die Benutzung aber noch nicht.

Gruß oki

SMALLID 7. Feb 2007 21:58

Re: Kniffliges Problem beim Serialisieren
 
Also haltet mich für dumm oder so, aber ehrlich gesagt habe ich auch nicht so richtig Ahnung, was ich mit dem Parameter Proc anfangen soll :( Weiß da jemand Bescheid?

marabu 8. Feb 2007 09:00

Re: Kniffliges Problem beim Serialisieren
 
Hallo,

schau mal:

Delphi-Quellcode:
interface

uses
  Classes;

type
  TDemoComponent = class(TComponent)
    procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
  end;

implementation

procedure TDemoComponent.GetChildren(Proc: TGetChildProc; Root: TComponent);
var
  i: Integer;
begin
  for i := 0 to Pred(ComponentCount) do
    if not Components[i].HasParent then
      Proc(Components[i]);
end;
Wenn du ComponentA in deinem Testprojekt aus der Klasse TDemoComponent erzeugst und einen Haltepunkt in der Methode GetChildren() einbaust, dann wirst du schon sehen.

Du solltest aber schon noch ein wenig Zeit in das Studium der Delphi Streaming Funktionalität investieren, denn nur mit der Methode GetChildren() könntest du sonst schon bald ein Opfer des Eisberg-Syndroms werden. Nimm alleine mal die Methode HasParent. Neben Owner (object life cycle) und Parent (visibility) findest du dort ein weiteres Konzept (active or passive streaming).

Freundliche Grüße

oki 8. Feb 2007 13:41

Re: Kniffliges Problem beim Serialisieren
 
Joop,
da waren sie wieder meine drei Probleme. Der Verdacht mit dem Eisberg-Syndroms drängt sich automatisch auf. aber trotzdem der Standard-Spruch: "Jo, jetzt ist das klar." :lol:

Ich werd mir diesen thread mal in die Favoriten legen. Zum Glück steh ich momentan nicht vor diesem Problem. Aber sicher bald.

Gruß oki

SMALLID 8. Feb 2007 21:18

Re: Kniffliges Problem beim Serialisieren
 
Ich weine gleich :(

VIelen Dank für eure Hilfe. Das mit dem GetChildren klappt wunderbar. Jetzt tritt aber das nächste Problem auf.
Er schreibt nun alle Eigenschaften ordentlich in den Stream. Dann will ich sie wieder lesen und bekomme die Meldung "EReadError - Fehler beim Lesen von Neu5.priceMasterFS: Ungültiger Eigenschaftswert"

:(

Jetzt sitze ich schon über 2 Tage an diesem sch...önen Speichern/Laden Problem :/

oki 8. Feb 2007 21:26

Re: Kniffliges Problem beim Serialisieren
 
Hatte es denn ohne GetChildren geklappt? Vielleicht steckt das Problem ja auch wo anders.

Gruß oki

SMALLID 9. Feb 2007 00:39

Re: Kniffliges Problem beim Serialisieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
An GetChildren lag es nicht. Das Problem habe ich dadurch gelöst, dass ich in "DefineProperties" eine Anweisung "DefineProperty(...)" hatte, die den gleichen Namen definierte, wie schon im interface Teil eine property hieß.
Ich hatte also eine property priceMasterFS und habe dann in DefineProperties "DefineProperty('priceMasterFS', ...) stehen gehabt. Als ich das durch reinen Zufall auf "DefineProperty('price', ...)" geändert hab, ging es dann. Very strange. Durch die Hilfe oder so wäre ich leider nie darauf gekommen.

Jetzt aber doch noch mal zu GetChildren und Co. Das Speichern funktioniert wunderbar (siehe Code unten, das ist die Datei die dabei rauskommt). Aber wenn ich das wieder lade werden die Agenten, die normalerweise dem Agentpool untergeordnet sind direkt dem Formular untergeordnet (obwohl's in der gespeicherten Datei richtig steht). Hab ich da nochwas vergessen?

oki 9. Feb 2007 06:49

Re: Kniffliges Problem beim Serialisieren
 
Moin,

also wissen tu ich es auch nicht. Mach den Owner doch mal so sichtbar, dass er mit in die Datei aufgenommen wird. Vielleicht wird er dann beim Laden explizit richtig gesetzt. Im Moment sieht das so aus, dass durch getChieldren zwar alle Subcompos beim Speichern berücksichtgt werden, aber beim laden der Owner nicht aus der Tree-hirarchie ermittelt wird. Ich denke ein explizites sichtbar machen des Owners und dessen Laden könnte eventuell das Problem lösen.

Gruß oki

SMALLID 9. Feb 2007 18:58

Re: Kniffliges Problem beim Serialisieren
 
Ja das hatte ich wieder als "Workaround" auch schon im Sinn. Der Owner ist ja meines Wissens nach eine Read-Only-Eigenschaft. Ich müsste den dann also explizit nochmal schreiben (obwohl allein durch die Dateistruktur ja schon klar ist, welche Komponente zu wem gehört) und dann mit der Methode "InsertComponent" arbeiten. Also erst laden, dann schauen welcher Owner in der Datei-Property steht, und die Komponente dorthin einfügen.

Das ist aber so ... unelegant. Es muss doch eine elegante Möglichkeit, quasi äquivalent zu "getChildren" beim Speichern geben ...

Jens Schumann 10. Feb 2007 08:38

Re: Kniffliges Problem beim Serialisieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
wenn ich es richtig verstanden habe geht es darum die Eingaben in den Controls über das Streamingsystem zu speichern.
Ich verfolge den Thread schon einige Zeit. Leider habe ich in den Untiefen meines Archivs erst jetzt die Lösung gefunden.

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, StatusBarEx, Menus, StdCtrls;

type
  TForm1 = class(TForm)
    MainMenu1: TMainMenu;
    Datei1: TMenuItem;
    Beenden1: TMenuItem;
    SB: TStatusBarEx;
    ffnen1: TMenuItem;
    Memo1: TMemo;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    RadioButton3: TRadioButton;
    RadioButton4: TRadioButton;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    OpenDialog: TOpenDialog;
    procedure Beenden1Click(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure FormCreate(Sender: TObject);
    procedure ffnen1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    constructor Create(aOwner: TComponent); override;
  end;

var
  Form1: TForm1;

implementation

uses Utils1;

{$R *.DFM}

procedure TForm1.Beenden1Click(Sender: TObject);
begin
  Close;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
  fs: TFilestream;
  FFilename : String;
begin
  FFilename:=ApplicationPath+'controls.sav';
  fs:= TFilestream.Create(FFilename, fmCreate);
  try
    fs.WriteComponent(self);
  finally
    fs.free;
  end;
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  WriteToStatusBar(SB,'Writecomponent Test',0);
end;

procedure TForm1.ffnen1Click(Sender: TObject);
begin
  If Not Opendialog.Execute then Exit;
  Memo1.Lines.LoadFromFile(Opendialog.Filename);
end;

constructor TForm1.Create(aOwner: TComponent);
var
  fs: TFileStream;
  FFilename : String;
begin
  FFilename:=ApplicationPath+'controls.sav';
  if FileExists(FFilename) then
    begin
      CreateNew(aOwner); // Hier ist der Trick
      fs:= TFileStream.Create(FFilename, fmOpenread or fmShareDenyWrite);
      try
        fs.ReadComponent(self);
      finally
        fs.free;
      end;
    end
  else
    inherited Create(aOwner);
end;

end.
Ein Blick in die OH unter CreateNew sollte als Erklärung ausreichen


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