Delphis Komponenten lesen und schreiben Mechanismus (i)
1. Einführung in Streaming-Objekte (Streams) und Read-Write-Objekte (Filer)
In der objektorientierten Programmierung nimmt die objektbasierte Datenverwaltung eine sehr wichtige Position ein. In Delphi ist die Unterstützungsmethode des objektbasierten Datenmanagements eines seiner Hauptmerkmale.
Delphi ist eine integrierte Entwicklungsumgebung, die objektorientiertes visuelles Design mit objektorientierten Sprachen kombiniert. Der Kern von Delphi ist die Komponenten. Komponenten sind eine Art Objekt. Delphi-Anwendungen werden ausschließlich von Komponenten konstruiert, sodass die Entwicklung leistungsstarker Delphi-Anwendungen unweigerlich objektbasierte Datenverwaltungstechnologie umfasst.
Die objektbasierte Datenverwaltung umfasst zwei Aspekte:
● Verwenden Sie Objekte, um Daten zu verwalten
● Verwaltung verschiedener Datenobjekte (einschließlich Objekte und Komponenten)
Delphi ordnet objektbasierte Datenverwaltungsklassen zu Stream-Objekten (Stream) und Filer-Objekten (Filer) zu und wendet sie auf alle Aspekte der visuellen Komponentenklassenbibliothek (VCL) an. Sie bieten reichhaltige Funktionen, um Objekte in Speicher, externem Speicher und Windows -Ressourcen zu verwalten.
Stream -Objekt, auch als Streaming -Objekt bekannt, ist ein allgemeiner Begriff für TStream, Thandlestream, Tfilestream, Tmemorystream, Tresourcestream und Tblobstream. Sie stellen die Fähigkeit dar, Daten zu verschiedenen Medien zu speichern, Verwaltungsvorgänge verschiedener Datentypen (einschließlich Objekte und Komponenten) in Speicher-, Out-of-Memory- und Datenbankfeldern in Objektmethoden abzuziehen, und nutzen objektorientierte Technologievorteile vollständig Davon können Anwendungen Daten in verschiedenen Stream -Objekten ziemlich einfach kopieren.
Lesen und Schreiben von Objekten (Filer) umfassen TFiler -Objekte, Trenkerobjekte und Twriter -Objekte. Das TFiler -Objekt ist das grundlegende Objekt für das Lesen und Schreiben von Dateien sowie die Hauptanwendungen von Trader und Twriter in Anwendungen. Sowohl Trader- als auch Twriter -Objekte werden direkt von TFiler -Objekten vererbt. Das TFiler -Objekt definiert die grundlegenden Eigenschaften und Methoden des Filerobjekts.
Filerobjekte führen hauptsächlich zwei Hauptfunktionen aus:
● Zugriff auf Formulardateien und Komponenten in Formulardateien
● Geben Sie Datenpufferungen an, um das Lesen und Schreiben von Daten zu beschleunigen
Um ein Wahrnehmungsverständnis von Streaming -Objekten zu vermitteln und Objekte zu lesen und zu schreiben, schauen wir uns zunächst ein Beispiel an.
a) Schreiben Sie eine Datei
Prozedur TFOMR1.Writedata (Absender: Tobject);
Var
FileStream: tFileStream;
MyWriter: Twriter;
I: Ganzzahl
Beginnen
FileStream: = tfilestream.create ('c: /test.txt',fMopenwrite); // Erstellen Sie ein Dateistromobjekt
MyWriter: = twriter.create (fileStream, 1024);
MyWriter.WriteListBin;
Für i: = 0 bis memo1.lines.count-1 tun
Mywriter.writestring (memo1.lines [i]);
MyWriter.WriteListend;
FileStream.seek (0, sofromBeginning);
MyWriter.Free; // MyWriter -Objekt loslassen
FileStream.free;
Ende;
b) Lesen Sie die Datei
procedure tform1.readdata (Absender: tobject);
Var
FileStream: tFileStream;
MyReader: Traderer;
Beginnen
FileStream: = tFilEstream.create ('c: /test.txt',fMopenRead);
MyReader: = Trreader.Create (FileStream, 1024);
MyReader.readlistbegin;
Memo1.lines.clear; // den Textinhalt der Memo1 -Komponente löschen
Während nicht myReader.endoflist do // beachten
Beginnen
Memo1.lines.add (myReader.readstring);
Ende;
MyReader.ReadList;
MyReader.Free; // MyReader -Objekt freigeben
FileStream.free;
Ende;
Die beiden oben genannten Prozesse sind eine für den Schreibprozess und der andere für den Leseprozess. Der Schreibprozess verwendet Twriter, um den Inhalt (Textinformationen) in einem Memo als binäre Datei zu speichern, die mit TFilESTREAM auf der Festplatte gespeichert ist. Der Lesevorgang ist genau das Gegenteil des Schreibprozesses. Das Ausführen des Programms kann sehen, dass der Leseprozess die im Schreibprozess gespeicherten Informationen stark wiederherstellt.
Die folgende Abbildung beschreibt die Beziehung zwischen Datenobjekten (einschließlich Objekten und Komponenten), Streaming -Objekten und Lesen und Schreiben von Objekten.
Abbildung (1)
Es ist erwähnenswert, dass Lesen und Schreiben von Objekten wie TFiler -Objekten, Tradierobjekten und Twriter -Objekten selten von Anwendungsschreibern aufgerufen werden. und Komponentenmechanismus schreiben.
Für Streaming -Objektstrom werden viele Referenzmaterialien ausführlich eingeführt, während Referenzmaterialien für TFiler -Objekte, Trittobjekte und Twriter -Objekte, insbesondere die Lesen und Schreibmechanismen von Komponenten, selten sind. .
2. Lesen und Schreiben von Objekten (Filer) und Komponenten -Lesen und Schreibmechanismus
Das Filerobjekt wird hauptsächlich zum Zugriff auf die Formulardateien und Komponenten von Delphi in den Formulardateien verwendet.
DFM -Dateien werden für Delphi -Speicherformulare verwendet. Formen sind der Kern der visuellen Programmierung von Delphi. Das Formular entspricht dem Fenster in der Delphi-Anwendung, die visuellen Komponenten im Formular entsprechen den Grenzflächenelementen im Fenster und nicht-visuelle Komponenten wie Timer und Topendialog, die einer bestimmten Funktion der Delphi-Anwendung entsprechen. Das Design der Delphi -Anwendung ist tatsächlich auf das Design des Formulars zentriert. Daher nehmen DFM -Dateien auch eine sehr wichtige Position im Delphi -Anwendungsdesign ein. Alle Elemente in der Form, einschließlich der Eigenschaften des Formulars, sind in der DFM -Datei enthalten.
Im Delphi -Anwendungsfenster werden Schnittstellenelemente durch Eigentumsbeziehungen miteinander verbunden, sodass die Baumstruktur der natürliche Ausdruck ist. DFM -Dateien werden physisch in Text gespeichert (zuvor als Binärdateien in Delphi2.0 gespeichert) und ordnen logischerweise die Beziehungen jeder Komponente in einer Baumstruktur an. Aus diesem Text können Sie die Baumstruktur der Form sehen. Hier ist der Inhalt der DFM -Datei:
Objektform1: tform1
Links = 197
Top = 124
...
Pixelsperinch = 96
Textheight = 13
Objektknopf1: Tbutton
Links = 272
...
Caption = 'button1' '
Taborder = 0
Ende
Objektpanel1: TPANEL
Links = 120
...
Caption = 'panel1' '
Taborder = 1
Objekt Checkbox1: Tcheckbox
Links = 104
...
Caption = 'CheckBox1' '
Taborder = 0
Ende
Ende
Ende
Diese DFM -Datei wird von Twriter über den Streaming -Objektstrom generiert. .
Wenn das Programm ausgeführt wird, liest Traderer das Formular und die Komponenten über den Stream -Objektstrom, da bei Delphi das Programm die Kompilierungsanweisung {$ r *.dfm} verwendet, um die DFM -Dateiinformationen mithilfe der Kompilierung in die ausführbare Datei zu kompilieren Anweisung {$ r *.dfm}.
Trader und Twriter können nicht nur die meisten Standarddatentypen in Objektpascal lesen und schreiben, sondern auch erweiterte Typen wie Listen und Variante lesen und schreiben und sogar PerPerties und Komponenten lesen und schreiben. Trader und Twriter selbst bieten jedoch tatsächlich nur sehr begrenzte Funktionen, und der größte Teil der tatsächlichen Arbeit wird von TStream, einer sehr leistungsstarken Klasse, geleistet. Mit anderen Worten, Trader und Twriter sind eigentlich nur Werkzeuge, die nur für die Lesen und Schreiben von Komponenten verantwortlich sind.
Da TFiler eine öffentliche Vorfahrklasse von Trenänkern und Twriter ist, um Trader und Twriter zu verstehen, beginnen Sie mit TFiler.
TFiler
Schauen wir uns zunächst die Definition der TFiler -Klasse an:
TFiler = class (tobject)
Privat
Fstream: tstream;
FBuffer: Zeiger;
FbufSize: Ganzzahl;
FBUFPOS: Ganzzahl;
Fbufend: Ganzzahl;
Froot: Tcomponent;
FlookuProot: tcomponent;
Fancestor: Tpersistent;
Fignorechildren: boolean;
geschützt
Prozedur setRoot (Wert: tcomponent);
öffentlich
Konstruktor erstellen (Stream: TStream; bufsize: Integer);
Zerstörer zerstören;
Prozedur definiertemProperty (const Name: String;
Readdata: Treaderproc;
HasData: Boolean);
Prozedur definentinaryProperty (const Name: String;
Readdata, Wititedata: TStreamProc;
HasData: Boolean);
Verfahren FlushBuffer;
Eigenschaft Root: tcomponent lesen froot write setRoot;
Immobilien -LookuProot: TComponent Lesen Sie Flookuproot;
Immobilien -Vorfahren: Tpersistent Read Fancestor Write Fancestor;
Eigentum ignorechildren: boolean gelesen fignorechildren schreiben fignorechildren;
Ende;
Das TFiler -Objekt ist eine abstrakte Klasse von Traderer und Twriter, die die grundlegenden Eigenschaften und Methoden für die Speicherung von Komponenten definiert. Es definiert das Stammattribut. durch das Stream -Objekt gemacht. Solange das für das Stream -Objekt zugängliche Medien auf die Komponente vom Filerobjekt zugegriffen werden kann.
Das TFiler -Objekt enthält auch zwei öffentliche Methoden, die Eigenschaften definieren: DefineProperty und DefinebinaryProperty, mit denen das Objekt Eigenschaften lesen und schreiben kann, die im veröffentlichten Teil der Komponente nicht definiert sind. Konzentrieren wir uns auf diese beiden nachstehenden Methoden.
Mit der Methode defineProperty () werden Standarddatentypen wie Zeichenfolgen, Ganzzahlen, Booleschen, Zeichen, schwimmende Punkte und Enums bestehen.
In der DefineProperty -Methode. Der Name des Namens gibt den Namen des Attributs an, das in die DFM -Datei geschrieben werden sollte, die im veröffentlichten Teil der Klasse nicht definiert ist.
Die Parameter ReadData und Witritedata geben die Methode zum Lesen und Schreiben der erforderlichen Daten beim Zugriff auf ein Objekt an. Die Arten von Readdata -Parametern und Witritedata -Parametern sind Treaderproc bzw. TwriterProc. Diese beiden Typen werden so deklariert:
TreaderProc = Prozedur (Leser: Trader) des Objekts;
TwriterProc = procedure (Schriftsteller: Twriter) des Objekts;
Der HasData -Parameter bestimmt, ob die Eigenschaft zur Laufzeit gespeichert werden soll.
Die DEFINEBINYPROPERTY -Methode hat viele Ähnlichkeiten mit DefineProperty.
Erläutern wir die Verwendung dieser beiden Methoden unten.
Wir haben eine nicht-visuelle Komponente wie Timer auf das Formular gesetzt. ?
Öffnen Sie die DFM -Datei dieses Formulars und Sie können mehrere Zeilen sehen, die den folgenden ähneln:
Objekt Timer1: Timer
Links = 184
Top = 149
Ende
Das Streaming -System von Delphi kann nur veröffentlichte Daten speichern, aber Timer hat keine linken und oberen Attribute veröffentlicht. Wie werden diese Daten also gespeichert?
Timer ist eine abgeleitete Klasse von Tcomponent.
procedure tcomponent.defineProperties (filer: tFiler);
var
Vorfahr: tkomponent;
Info: Longint;
Beginnen
Info: = 0;
Vorfahr: = tcomponent (filer.ancestor);
Wenn Vorfahr <> nil dann info: = Ancestor.fdesignInfo;
Filer.defineProperty ('links', Readleft, Writeleft,
Longrec (fDesignInfo) .lo <> longrec (info) .lo);
Filer.DefineProperty ('Top', Refertop, Writetop,
Longrec (fdesignInfo) .hi <> longrec (info) .hi);
Ende;
TComponents DefineProperties ist eine virtuelle Methode, die die Tpersistent der Vorfahren überschreibt. In der Tpersistent -Klasse ist diese Methode eine leere virtuelle Methode.
In der Methode des DefineProperties können wir sehen, dass es ein Filerobjekt als Parameter gibt. Wert. Es nennt die DefineProperty -Methode von TFiler und definiert ReadLeft, Writeleft, LEADTOP, WriteTop -Methoden zum Lesen und Schreiben von linken und Top -Eigenschaften.
Daher hat jede von TComponent abgeleitete Komponente, auch wenn sie nicht übrig ist, und die oberen Attribute, zwei solcher Eigenschaften, wenn sie auf eine DFM -Datei gestreamt werden.
Bei der Suche nach Daten wurde festgestellt, dass nur wenige Daten das Lesen und Schreibmechanismen von Komponenten beinhalten. Da der Schreibprozess des Komponenten von der IDE von Delphi während der Entwurfsphase abgeschlossen wird, kann er nicht für den Laufprozess verfolgt werden. Daher versteht der Autor den Lesemechanismus der Komponente, indem er den ursprünglichen VCL -Code während des Programmvorgangs verfolgt und den Schreibmechanismus der Komponente durch den Lesemechanismus und den Twriter analysiert. Daher erklärt Folgendes den Lesen und Schreibmechanismus des Komponenten gemäß diesem Denkprozess, der zuerst über Trader und dann den Twriter spricht.
Trader
Schauen Sie sich zunächst die Projektdateien von Delphi an und Sie finden einige Codezeilen wie diese:
Beginnen
application.initialize;
Application.createForm (tform1, Form1);
Anwendung.Run;
Ende.
Dies ist der Eingang zum Delphi -Programm. Setzen Sie einfach die Bedeutung dieser Codezeilen ein. .
Was uns jetzt am meisten interessiert, ist der Satz, eine Form zu erstellen. Wie werden Formen und Komponenten auf den Formularen erstellt? Wie bereits erwähnt: Alle Komponenten im Formular, einschließlich der Eigenschaften des Formulars selbst, sind in der DFM -Datei enthalten. in die ausführbare Datei. Daher kann der Schluss gezogen werden, dass Sie beim Erstellen eines Formulars DFM -Informationen lesen müssen.
Wenn Sie Schritt für Schritt dem Programm folgen, können Sie feststellen, dass das Programm während der Erstellung des Formulars die Readrootcomponent -Methode des Traders aufruft. Der Zweck dieser Methode ist es, die Stammkomponente und alle Komponenten vorzulesen, die sie hat. Schauen wir uns die Implementierung dieser Methode an:
Funktion treader.readrootcomponent (root: tcomponent): tcomponent;
...
Beginnen
Readsignatur;
Ergebnis: = nil;
GlobalNameSpace.Beginwrite;
versuchen
versuchen
ReadPrefix (Flags, i);
Wenn root = nil dann
Beginnen
Ergebnis: = tcomponentClass (findClass (readStr)). Create (nil);
Result.name: = readStr;
Ende sonst
Beginnen
Ergebnisse: = root;
ReadStr; {ignorieren Sie den Klassennamen}
Wenn csdesigning in result.comPonentState dann
Readstr sonst
Beginnen
Include (result.fcomponentState, cSloading);
Include (result.fcomponentState, csReading);
Result.name: = findUniqueName (readStr);
Ende;
Ende;
Froot: = Ergebnisse;
Ffinder: = tclassFinder.create (tpersistentClass (result.classtype), true);
versuchen
Flookuproot: = Ergebnisse;
G: = globalloaded;
Wenn g <> nil dann
Geschlagen: = g sonst
Ausgeladen: = tlist.create;
versuchen
Wenn geschlagen.Indexof (froot) <0, dann dann
Beschleunigt.add (froot);
FOWER: = FROT;
Include (froot.fcomponentState, cSloading);
Inklusive (froot.fcomponentState, csReading);
Froot.readstate (self);
Ausschließen (froot.fcomponentState, csReading);
Wenn g = nil dann
für i: = 0 bis geschlagen.Count - 1 do tcomponent (getloded [i]). geladen;
Endlich
wenn g = nil dann flohed.free;
Ausgeladen: = nil;
Ende;
Endlich
Ffinder.free;
Ende;
...
Endlich
GlobalNameSpace.endwrite;
Ende;
Ende;
ReadrootComponent erster Anrufe liest Signature zum Lesen des Filer -Objekt -Tags ('TPF0'). Das Erkennen von Tags vor dem Laden von Objekten kann Fahrlässigkeit und ineffektive oder veraltete Daten lesen.
Schauen wir uns die ReadPrefix (Flags, i) an. Wenn ein Schreibobjekt eine Komponente in einen Stream schreibt, gibt es zwei Werte vor der Komponente vor Der zweite Wert gibt die Reihenfolge an, die er in der Vorfahren erstellt hat.
Wenn der Stammparameter NIL ist, wird eine neue Komponente mit dem von ReadStr gelesenen Klassennamen erstellt, und die Name -Eigenschaft der Komponente wird aus dem Stream gelesen. .
Froot.readstate (self);
Dies ist ein sehr kritischer Satz. Obwohl diese ReadState -Methode eine Methode ist, ist eine weitere Verfolgung festgestellt, dass sie tatsächlich die Readdatainner -Methode des Traders gefunden hat.
Prozedur Treader.ReadDatainner (Instanz: tcomponent);
var
OldParent, Oldbesitzer: Tcomponent;
Beginnen
zwar nicht Endoflist do ReadProperty (Instanz);
Readlist;
OldParent: = Eltern;
Oldbesitzer: = Besitzer;
Elternteil: = Instance.getChildParent;
versuchen
Eigentümer: = Instance.getchildowner;
Wenn nicht zugewiesen (Eigentümer), dann Eigentümer: = root;
Während keine Endoflist do ReadComponent (NIL);
Readlist;
Endlich
Elternteil: = OldParent;
Besitzer: = Oldbesitzer;
Ende;
Ende;
Es gibt diese Codezeile:
zwar nicht Endoflist do ReadProperty (Instanz);
Dies wird verwendet, um die Eigenschaften der Stammkomponente zu lesen. Für diese beiden unterschiedlichen Eigenschaften sollten wir zwei verschiedene Lesemethoden geben, um diese Idee zu überprüfen, um die Implementierung der ReadProperty -Methode anzusehen.
Prozedur -Trader.ReadProperty (Ainstance: tpersistent);
...
Beginnen
...
ProphInfo: = getPropInfo (Instance.classsinfo, fPropName);
Wenn Propinfo <> nil dann readPropValue (Instanz, Prophinfo) sonst
Beginnen
{Kann nicht zuverlässig von einem Fehler in einer definierten Eigenschaft wiederherstellen} zuverlässig wiederherstellen}
FcanHandleExcepts: = false;
Instance.defineProperties (self);
FcanHandleExcepts: = true;
Wenn fPropname <> '' dann
PropertyError (FPropName);
Ende;
...
Ende;
Um Platz zu sparen, wurde ein Code ausgelassen.
ProphInfo: = getPropInfo (Instance.classsinfo, fPropName);
Dieser Code soll die Informationen des veröffentlichten Eigenschaftsnamens erhalten. Aus dem folgenden Code können wir feststellen, dass der Attributwert, wenn die Attributinformationen nicht leer sind, die ReadPropValue -Methode gelesen wird und die ReadPropValue -Methode den Attributwert über die RTTI -Funktion liest, die hier nicht ausführlich eingeführt wird. Wenn die Attributinformationen leer sind, bedeutet dies, dass der Attribut fPropName nicht veröffentlicht wird und es durch einen anderen Mechanismus gelesen werden muss. Dies ist die oben erwähnte DefineProperties -Methode wie folgt:
Instance.defineProperties (self);
Diese Methode ruft tatsächlich die DefineProperty -Methode von Traderer auf:
Prozedur Treader.DefineProperty (const Name: String;
Readdata: Treaderproc;
Beginnen
Wenn sametext (Name, fPropName) und zugewiesen (readdata) dann zugewiesen werden
Beginnen
Readdata (Selbst);
FPropName: = '';
Ende;
Ende;
Es wird zunächst vergleicht, ob der Leseattributname mit dem Voreinstellungsattributnamen übereinstimmt.
OK, die Stammkomponente wurde gelesen, und der nächste Schritt sollte darin bestehen, die Komponenten der Stammkomponente zu lesen. Schauen wir uns die Methode noch einmal an:
Prozedur Treader.ReadDatainner (Instanz: tcomponent);
Es gibt einen Code, der dieser Methode folgt:
Während keine Endoflist do ReadComponent (NIL);
Genau das wird zum Lesen der untergeordneten Komponenten verwendet. Der Lesemechanismus der untergeordneten Komponente entspricht dem Lesen der oben eingeführten Wurzelkomponente, was eine tiefe Durchquerung eines Baumes ist.
Bisher wurde der Komponenten -Lesemechanismus eingeführt.
Schauen wir uns den Komponenten -Schreibmechanismus an. Wenn wir dem Formular eine Komponente hinzufügen, werden die zugehörigen Eigenschaften in der DFM -Datei gespeichert und dieser Vorgang wird von Twriter durchgeführt.
Ø Twriter
Ein Twriter -Objekt ist ein sofortiges Filerobjekt, das Daten in einen Stream schreibt. Das Twriter -Objekt wird direkt von TFiler geerbt.
Das Twriter -Objekt bietet viele Methoden, um verschiedene Arten von Daten in den Stream zu schreiben. Um die Implementierungs- und Anwendungsmethoden von Twriter -Objekten zu beherrschen, müssen Sie daher das Format der Autorenobjekte verstehen, die Daten speichern.
Das erste, was zu beachten ist, ist, dass jeder Filerobjektstrom Filer -Objekt -Tags enthält. Dieses Tag nimmt vier Bytes auf und sein Wert lautet "TPF0". Das Filer -Objekt greift auf das Tag für Writesignature- und Lesesignatur -Methoden zu. Dieses Tag wird hauptsächlich zum Leitfaden von Lesevorgängen verwendet, wenn Leserobjekte Daten (Komponenten usw.) lesen.
Zweitens muss das Autor -Objekt ein Byte -Flag -Bit hinterlassen, bevor Daten gespeichert werden, um anzugeben, welche Art von Daten später gespeichert wird. Dieses Byte ist ein Wert des Typs tvaluetype. TVAluEType ist ein Enum -Typ, der einen Byte -Raum einnimmt, und seine Definition lautet wie folgt:
Tvaluetype = (Vanull, Valist, Vaint8, Vaint16, Vaint32, Vaentended, Vastring, Vaident, Vaident,
Vafalse, Vatrute, Vabinary, Vaset, Valstring, Vanil, Vacollection);
Daher müssen Sie bei der Implementierung der einzelnen Datenschreibmethoden des Autor -Objekts zuerst das Flag -Bit schreiben und dann die entsprechenden Daten schreiben. Lesendaten. Das Valist -Logo hat einen besonderen Zweck. Wenn Sie also mehrere aufeinanderfolgende identische Elemente in das Autor -Objekt schreiben, verwenden Sie zuerst WriteListBegin, um die Valistische Flagge zu schreiben, und schreiben Sie nach dem Schreiben der Datenelemente das Vanull -Flag. Verwenden Sie die Endoflist -Funktion in der Mitte fest, ob es eine Vanull -Flagge gibt.
Werfen wir einen Blick auf eine sehr wichtige Methode für Twriter Writedata:
procedure twriter.writedata (Instanz: tcomponent);
...
Beginnen
...
WritePrefix (Flags, fchildpos);
Wenn usequalifiedNames dann verwendet werden
WriteSt (Gettypedata (ptypeinfo (instance.classtype.classinfo)). Unitname + '.' + Instance.ClassName)
anders
WriteStr (Instance.ClassName);
WriteStr (instance.name);
Eigenschaften: = Position;
if (fancestorList <> nil) und (fancestorpos <fancestorList.count) dann
Beginnen
Wenn der Vorfahr <> nil ist, dann inc (fancestorpos);
Inc (fchildpos);
Ende;
WriteProperties (Instanz);
Writelistend;
...
Ende;
Aus der Witritedata -Methode können wir das allgemeine Bild der Generierung von DFM -Dateiinformationen sehen. Schreiben Sie zuerst das Flag (Präfix) vor die Komponente und schreiben Sie dann den Namen der Klassennamen und Instanz. Dann gibt es einen solchen Satz:
WriteProperties (Instanz);
Dies wird verwendet, um die Eigenschaften der Komponente zu schreiben. Wie bereits erwähnt, gibt es in DFM-Dateien sowohl veröffentlichte Attribute als auch nicht veröffentlichte Attribute. Schauen wir uns die Umsetzung von WriteProperties an:
procedure twriter.writeProperties (Instanz: tpersistent);
...
Beginnen
Count: = gettypedata (instance.classsinfo)^. Propcount;
Wenn zählen> 0 dann
Beginnen
GetMem (PropList, Count * sizeof (Zeiger));
versuchen
GetPropinfos (Instance.classsinfo, PropList);
für i: = 0 zu zählen - 1 tun
Beginnen
Propinfo: = propList^[i];
Wenn propinfo = nil dann
Brechen;
Wenn is ers gestrichen (Instanz, Prophinfo) dann
WriteProperty (Instanz, Prophinfo);
Ende;
Endlich
Freemem (PropList, Count * sizeof (Zeiger));
Ende;
Ende;
Instance.defineProperties (self);
Ende;
Bitte beachten Sie den folgenden Code:
Wenn is ers gestrichen (Instanz, Prophinfo) dann
WriteProperty (Instanz, Prophinfo);
Die Funktion wird festgelegt, ob die Immobilie durch Speichern des Qualifikums gespeichert werden muss.
Nach dem Speichern der veröffentlichten Eigenschaft muss die nicht veröffentlichte Eigenschaft gespeichert werden.
Instance.defineProperties (self);
Die Implementierung von DefineProperties wurde bereits erwähnt.
OK, bisher gibt es noch eine Frage: Wie werden die untergeordneten Komponenten der Wurzelkomponente gespeichert? Schauen wir uns die Witritedata -Methode an (diese Methode wurde früher erwähnt):
procedure twriter.writedata (Instanz: tcomponent);
...
Beginnen
...
Wenn nicht ignorechildren dann
versuchen
if (fancestor <> nil) und (Fancestor ist nicht komponent)
Beginnen
if (fancestor ist tcomponent) und (csinline in tcomponent (fancestor). ComponentState dann) dann
Frootancestor: = tcomponent (fancestor);
FancestorList: = tlist.create;
Tcomponent (fancestor) .getchildren (addancestor, frootancestor);
Ende;
Wenn csinline in instance.comPonentState dann dann
Froot: = Instanz;
Instance.getChildren (WriteComponent, Froot);
Endlich
FancestorList.free;
Ende;
Ende;
Die Eigenschaft ignorechildren ermöglicht es einem Autor -Objekt, eine Komponente zu speichern, ohne Kinderkomponenten der Komponente zu speichern. Wenn die Eigenschaft von ignorechildren wahr ist, speichert das Autor -Objekt nicht die Kinderkomponenten, die es beim Speichern der Komponente hat. Andernfalls werden Unterkomponenten gespeichert.
Instance.getChildren (WriteComponent, Froot);
Dies ist der kritischste Satz für das Schreiben von Unterkomponenten. Auf diese Weise ist das, was wir in der DFM-Datei sehen, eine baumartige Komponentenstruktur.