Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Propertys als Stream speichern?


Daniel L. - Mo 11.10.10 17:14
Titel: Propertys als Stream speichern?
Hallo,

kennt wer eine Unit oder Komponente, mit der alle Propertys von visuellen Komponenten, die sich gerade auf einem Formular befinden, zur Laufzeit als Filestream gespeichert und wieder geladen werden können?
(Z.B. zum automatisierten Speichern und Laden von Optionen ect.)

Danke + Gruss: Daniel


Moderiert von user profile iconNarses: Topic aus Sonstiges (Delphi) verschoben am Mo 11.10.2010 um 23:33


HelgeLange - Mo 11.10.10 17:21

Das kann jede Komponente von sich aus, WriteComponent oder so heisst der Befehl und LoadComponent zum Laden.


platzwart - Mo 11.10.10 17:37

Und dann in einer Schleife alle Komponenten durchgehen mit Components und die Funktion entsprechend aufrufen.


bummi - Mo 11.10.10 17:47

vielleicht hilft Dir dies

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
unit Serialize;
// 2010 by Thomas Wassermann
interface
uses windows,classes,sysutils,dialogs;
procedure SaveComponent2Bin(Comp:TComponent;Const FN:String);
procedure LoadComponentFromBin(Comp:TComponent;Const FN:String);
procedure SaveComponent2Text(Comp:TComponent;Const FN:String);
procedure LoadComponentFromText(Comp:TComponent;Const FN:String);
implementation

procedure SaveComponent2Bin(Comp:TComponent;Const FN:String);
Var
  Stream: TFileStream;
begin
  Stream := TFileStream.Create(fn, fmCreate);
  try
    Stream.WriteComponent(Comp);
  finally
    Stream.Free;
  End;
end;


procedure LoadComponentFromBin(Comp:TComponent;Const FN:String);
Var
  Stream: TFileStream;
  MyComponent: TComponent;
begin
  Stream := TFileStream.Create(fn, fmOpenRead);
  try
    Stream.ReadComponent(Comp);
  finally
    Stream.Free;
  End;
end;

procedure SaveComponent2Text(Comp:TComponent;Const FN:String);
Var
  Stream2: TFileStream;
  Stream1: TMemoryStream;
Begin
  Stream1 := TMemoryStream.Create;
  Stream2 := TFileStream.Create(fn, fmCreate);
  try
    Stream1.WriteComponent(Comp);
    Stream1.position := 0;
    ObjectBinaryToText(Stream1, Stream2);
  finally
    Stream1.Free;
    Stream2.Free;
  End;
end;

procedure LoadComponentFromText(Comp:TComponent;Const FN:String);
Var
  Stream: TFileStream;
  Stream2: TMemoryStream;
Begin

  Stream := TFileStream.Create(fn, fmOpenRead);
  Stream2 := TMemoryStream.Create;
  try
    ObjectTextToBinary(Stream, Stream2);
    Stream2.Position := 0;
    Stream2.ReadComponent(Comp);
  finally
    Stream.Free;
    Stream2.Free;
  End;
end;

end.


Daniel L. - Di 12.10.10 13:22

Danke dafür.
Wenn ich damit die Properties einer CheckBox Komponente speichere, wird checked nur bei true gespeichert. (Anscheinend werden default Proberties nie gespeichert?)
Ich will ja Programmoptionen speichern und wieder laden, wenn ich jetzt als Vorgabe eine Checkbox auf true setzte, der Anwender sie aber auf false setzt und die neuen Optionen speichert, wird dieses beim nächten Programmstart (wo die Optionen automatisch geladen werden) nicht berücksichtigt.
Ich könnte natürlich alle checked-Proberties auf default lassen und meine Vorgaben als Datei speichern, die, solange der Anwender keine eigene erstellt hat, als Vorgabe geladen wird.
Oder kann man die default-Werte mit speichern?

Daniel


bummi - Di 12.10.10 13:35

tja, vielleicht wäre für Deine Anforderungen RTTI die bessere Alernative.


HelgeLange - Di 12.10.10 13:45

user profile iconDaniel L. hat folgendes geschrieben Zum zitierten Posting springen:
Danke dafür.
Wenn ich damit die Properties einer CheckBox Komponente speichere, wird checked nur bei true gespeichert. (Anscheinend werden default Proberties nie gespeichert?)
Ich will ja Programmoptionen speichern und wieder laden, wenn ich jetzt als Vorgabe eine Checkbox auf true setzte, der Anwender sie aber auf false setzt und die neuen Optionen speichert, wird dieses beim nächten Programmstart (wo die Optionen automatisch geladen werden) nicht berücksichtigt.
Ich könnte natürlich alle checked-Proberties auf default lassen und meine Vorgaben als Datei speichern, die, solange der Anwender keine eigene erstellt hat, als Vorgabe geladen wird.
Oder kann man die default-Werte mit speichern?

Daniel


Wenn Checked eine default property ist, dann wird im Konstruktor die entsprechende Variable intern immer auf diesen Wert gesetzt. Das im Stream zu speichern, wäre redundant.
Du musst auch bedenken, dass der Streamreader von Delphi die Komponenten automatisch erzeugt, während er sie vom Stream liest. Wenn Du diese Komponenten allerdings schon auf dem Formular hast, dann wirst Du danach 2 instanzen von jeder Komponente im Speicher haben


Dude566 - Di 12.10.10 14:00

user profile iconHelgeLange hat folgendes geschrieben Zum zitierten Posting springen:
Wenn Du diese Komponenten allerdings schon auf dem Formular hast, dann wirst Du danach 2 instanzen von jeder Komponente im Speicher haben


Habe davon jetzt nicht so die Ahnung, aber es müsste doch gehn die Komponenten per Stream zu laden, die nötigen Daten aus der geladenen in die bereits vorhandene auf dem Formular zu übertragen und den Stream dann wieder freigeben.


HelgeLange - Di 12.10.10 14:02

user profile iconDude566 hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconHelgeLange hat folgendes geschrieben Zum zitierten Posting springen:
Wenn Du diese Komponenten allerdings schon auf dem Formular hast, dann wirst Du danach 2 instanzen von jeder Komponente im Speicher haben


Habe davon jetzt nicht so die Ahnung, aber es müsste doch gehn die Komponenten per Stream zu laden, die nötigen Daten aus der geladenen in die bereits vorhandene auf dem Formular zu übertragen und den Stream dann wieder freigeben.


Ja, Komponenten haben eine Methode Assign, mit deren Hilfe lassen sich die Werte übertragen. Und man gibt nicht nur den Stream frei, sondern auch die Basiskomponente, welche man geladen hat aus dem Stream, die sollte Owner für alle sub-Komponenten sein und diese automatisch freigeben


Dude566 - Di 12.10.10 14:05

Also wäre es doch eine ganz gute Lösung für das Speichern von Properties.


bummi - Di 12.10.10 14:23

user profile iconHelgeLange hat folgendes geschrieben Zum zitierten Posting springen:
Du musst auch bedenken, dass der Streamreader von Delphi die Komponenten automatisch erzeugt, während er sie vom Stream liest. Wenn Du diese Komponenten allerdings schon auf dem Formular hast, dann wirst Du danach 2 instanzen von jeder Komponente im Speicher haben


nur wenn Readcomponent ohne Instanz aufgerufen wird
also Readcomponent(nil)


Daniel L. - Di 12.10.10 15:15

user profile iconHelgeLange hat folgendes geschrieben Zum zitierten Posting springen:

Wenn Checked eine default property ist, dann wird im Konstruktor die entsprechende Variable intern immer auf diesen Wert gesetzt. Das im Stream zu speichern, wäre redundant.
Du musst auch bedenken, dass der Streamreader von Delphi die Komponenten automatisch erzeugt, während er sie vom Stream liest. Wenn Du diese Komponenten allerdings schon auf dem Formular hast, dann wirst Du danach 2 instanzen von jeder Komponente im Speicher haben


Das versteh ich nicht so ganz.
Angenommen, auf meinem Foumular befindet sich MyCheckbox

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
FileStream := TFileStream.create ('Datei', fmCreate);
FileStream.WriteComponent (MyCheckbox);
FileStream.free;


FileStream := TFileStream.create ('Datei', fmOpenRead);
FileStream.ReadComponenet (MyCheckbox);
FileStream.free;


wo sind denn jetzt 2 Instanzen? Es gibt doch nur MyCheckbox :?:


HelgeLange - Di 12.10.10 18:23

Wenn ich mich recht entsinne, erzeugt der Delphi Stream reader die Komponente in jedem Fall neu, gibt man eine Komponenten-Variable an, wird diese überschrieben, das heisst, Dein Zeiger auf ein bestehendes Object geht verloren.

Aber das ist jetzt gerade ohne Garantie, wenn ich daheim bin heut abend, schau ich mal in altem Code nach...