Mittwoch, 7. September 2016

Objekte einer Form zur Laufzeit duplizieren / duplicating form objects at runtime

Präambel
Während der Entwicklung stehen uns für Builder die Methoden 'ReadMethod' und 'WriteMethod' zur Verfügung. Über diese können wir vorhanden Code auslesen und auch in Methoden hinein schreiben.
Zur Laufzeit steht uns dies leider nicht zur Verfügung. Aus diesem Grund müssen wir gezielt eigene von den VFP Basisklassen abgeleitete Klassen auf unseren Forms verwenden, wenn wir tatsächlich beliebige Objekte mit individuellem Methodencode duplizieren wollen.

Da dies nun geklärt ist wenden wir uns den Möglichkeiten zu, die uns zur Laufzeit zur Verfügung stehen...

Zunächst einmal erfolgt das Duplizieren eines vorhanden Objekts auf Basis seiner Klasse. D.h. wir lesen die Klasse des Quellobjektes aus und erzeugen es im Zielcontainer auf Basis dieser Vorgabe. An dieser Stelle stehen uns nun automatisch alle in einer abgeleiteten Klasse individuell ausprogrammierten Methoden zur Verfügung. Alles was nun noch zugewiesen werden muss sind die Eigenschaften des Quellobjektes. Also werden in einer Schleife die vorhandenen Eigenschaften gelesen und zugewiesen.

Mit Hilfe der Funktion AMEMBERS() ist dies ohne weiteres machbar. Allerdings müssen wir noch dafür sorgen, dass die duplizierbaren Objekte auch auf eine Duplizieranforderung reagieren. Das Codemuster beruht auf der Annahme, dass jedes dieser Objekte innerhalb seiner RightClick Methode den Aufruf der Dupliziermethode hinterlegt hat.
Lautet der Name der Methode zum Duplizieren von Objekten bspw. 'Thisform.Copy', dann sähe der Rightclick Aufruf in etwa wie folgt aus:

Thisform.Copy(This)


Innerhalb dieser Methode wird dann folgender Code eingefügt:

LPARAMETERS vObj as Object
= AMEMBERS( gaPropArray , vObj , 1 )
WITH Thisform.container2 
    * // trying to create a same named object in the target container    
    * // in case there is already a so named object, the CATCH will fire
    TRY 
        .AddObject( vObj.Name , vObj.Class )
        FOR liLoop = 1 TO ALEN( gaPropArray , 1 )
            oNewObj = EVALUATE( [Thisform.container2.] + vObj.Name )
            IF gaPropArray( liLoop , 2 ) = [Property]
                * // Some Props are write protected, so just try to assign a new value
                TRY 
                    oNewObj.&gaPropArray( liLoop , 1 ) = vObj.&gaPropArray( liLoop , 1 )
                CATCH 
                ENDTRY 
            ENDIF         
        ENDFOR 
    CATCH 
        MESSAGEBOX([Object already exists!],0+16+0,[Can't copy object])
    ENDTRY     
ENDWITH 


Um dieses Codemuster allgemein gültig zu halten sollten unsere abgeleiteten Klassen nicht nur den Aufruf der Dupliziermethode kennen wie sie in diesem Beispiel im RightClick Ereignis hinterlegt ist. Sinnvoll ist es an dieser Stelle auch, wenn wir spezielle Eigenschaften anlegen, mit denen wir später bspw. Zielcontainer, abhängige parallel positionierte Objekte (Textbox und Label gleichzeitig duplizieren), Objektnamensvergabe und Dupliziererlaubnis steuern.