Announcement

Collapse
No announcement yet.

EClassNotFound bei eingebetter Komponente

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • EClassNotFound bei eingebetter Komponente

    Guten Tag<p>
    Ich habe eine Komponente von TListBox abgeleitet, in deren private-Abschnitt ein TEdit definiert wird,<br>
    das in der Create-Methode erzeugt wird und das dort auch Ereignismethoden zugewisen bekommt.<br>
    Seine Parent-Eigenschaft wird auf SELF gesetzt, also auf die Komponente selbst.<br>
    Im Entwurfmodus erscheint nun eine ListBox mit einem Editfeld.<br>
    Beim Start des Programms erhalte ich die Fehlermeldung EClassNotFound; Klasse TEdit nicht gefunden.<br>
    Wenn man eine TEdit-Komponente ins Formular setzt, läuft das Programm und die Komponente einwandfrei.<br>
    Die Delphi-Hilfe sagt, daß die Komponente im Formular nicht im Stream gefunden wurde.<p>
    Weiss jemand einen Trick ?<p>
    Danke, Marcus

  • #2
    im TMyListBox.Create wird RegisterClass(TEdit) aufgerufen.
    Die Sache ist die das wenn das Componentenstreaming-system versucht ein Object zu initialisieren. Dazu benötigt es die Zuordnung eines Klassennamens als String zu einem Zeiger auf die dazugehörige Klassendefinition im Codesegment. Also bei Laden eines Objectes aus einem Stream, z.B. DFM resource, findet ein TReader Object das Token für ein Object. Dieses Token weist den Reader an als nächstes einen String auszulesen -> der Klassenname z.b. 'TEdit'. Als nächstes muß der TReader ein solches Object erzeugen, dazu brauch er aber den Klassentyp = TClass. Dieser Klassentyp ist nichts anderes als ein Zeiger ins Codesegment an deren Position der Compiler/Linker diesen "Record" abgelegt hat. Die Klassendefinition enthält die RTTI,VMT,DMT,Interfacetabelle usw. Nun, wie wird aber der Reader mit der Zuordnung von Klassennamen zu Klassentypzeiger fertig ? Ganz einfach, mit registerClass() oder RegisterClasses([]) wird eine Klasse = Zeiger auf einen Klasserecord in einer Liste abgelegt. Nun kann man diese Liste iterieren und jeweils die Klasse raussuchen die den gleichen Klassennamen = 'TEdit' besitzt, das resultat ist der Klassentyp. Diese ganze Vorgehensweise ist notwendig das ein TWriter ja nicht direkt den Zeiger speichern kann. Bei jedem neustart einer Anwendung oder Compilation ändert sich das Codesegment und somit auch die Zeiger auf die Klassen. Ein so gespeichertes Object könnte beim nächsten Laden NIEMALS korrekt initialisiert bzw. erzeugt werden.

    Nun, warum funktioniert TEdit's in einem TForm OHNE es zu registrieren ? Ganz einfach, alle auf einem TForm benutzten Objecte (TComponents) werden dem TForm als typisierte PUBLISHED Member zugeordnet. Der Compiler erzeugt nun eine TMyForm Klassendefinition im Codesegment die auch die publiched Member und deren Typen enthält, sprich die TMyForm-Klassendefinition enthält diese Infos in deren RTTI, Run Time Typ Information. Da nun der class of TMyForm in deren eigenen Klasse die Klassen der eingebetteten Object bekannt ist kann dies der TReader ausnutzen indem er diese Typ Infos = Zeiger auf Sub-Klassen ausliest.

    In deiner Komponente könntest Du das TEdit als PUBLISHED definieren, müsstest aber das Streamingsystem ändern damit funktioniert.
    Sollte der TReader die Klasse NICHT durch die Owner-RTTI ermitteln können versucht der TReader es mit den durch RegisterClass() registrierten Klassen.

    Gruß hage

    Comment

    Working...
    X