[1] [2] [3] [4] [5]

Teil 2 - Managerklassen (FWK_MGR)

Class Library Name FWK_MGR (FWK)
Class Library Description Managerklassen

FWK_MGR_BASE

Class Name FWK_MGR_BASE (fwk_mgr.vcx)
Description Manager für
Parent Class FWK_MGR_BASE
Classes Used NONE
Public Properties
cAddClassLib
Zusätzliche Klassenbibliotheken
cAddLibrary
Zusätzliche Libraries
cAddPath
Zusätzliche Pfade
cAddProcedure
Zusätzliche Prozedur-Dateien
cDevelopment
Dateischalter für Entwicklungsflag
cOldClassLib
Ursprüngliche Klassenbibliotheken
cOldLibrary
Ursprüngliche Libraries
cOldPath
Ursprüngliche Pfade
cOldProcedure
Ursprüngliche Prozedur-Dateien
cPropertyName
Name Eigenschaft der Maske für Selbsteintragung
cPublicName
Public Variable für Selbstreferenz
cUniqueID
Eindeutige Kennung
lEnabled
Enabling-Flag
lError
Fehlerflag
lDevelopment
Flag für Entwicklungsmodus
lInit
Initialisierungs-Flag
lOpened
Flag für Tabelle hier geöffnet
Private Properties NONE
Public Methods
Click
Aufruf von This.Parent.Click()
DbfClose
Schließen von This.cTable, Rücksetzen auf This.cOrder bzw.
wahlweise als Parameter tcTable und TcOrder
DbfOpen
Öffnen von This.cTable mit This.cOrder bzw. wahlweise als Parameter tcTable und TcOrder
DblClick
Aufruf von This.Parent.DblClick()
Destroy
Aufruf von This.DbfClose() und This.Unpublish()
Error
Weiterleitung Fehler an oBase, falls vorhanden
Init
Unique-ID und lInit setzen
Aufruf von This.dbfopen() und This.Publish()
KeyPress
Aufruf von This.Parent.Keypress()
Messagebox
Routing von Messagebox-Aufrufen auf oMessage oder oLanguage oder ggf. notfalls direkte Anzeige der Messagebox
MiddleClick
Aufruf von This.Parent.MiddleClick()
Publish
Setzen Public-Referenz, Speichern Form-Referenz
Reset
Zurücksetzen von Procedure, Classlib, Library und Path
RightClick
Aufruf von This.Parent.RightClick()
Set
Setzen von Procedure, Classlib, Library und Path
Unpublish
Zurücksetzen Public-Referenz, Löschen Form-Referenz
zReadme
 
Private Methods NONE

FWK_MGR_LANGUAGE

Class Name FWK_MGR_LANGUAGE (fwk_mgr.vcx)
Description Manager für Übersetzungen
Parent Class FWK_MGR_BASE
Classes Used NONE
Public Properties
cDefaultLanguage
Default: GER, Vorgabesprache
cLanguage
Aktuelle Sprache
cOrder
Default: SPRACHE
cPublicName
Default: oLanguage
cTable
Default: SPRACHE
Private Properties NONE
Public Methods
Destroy
Schließen der Sprachtabellen
GetLanguage
Übersetzen mit Übergabe Objektreferenz
GetLiteral
Übersetzen mit String-Übergabe
Init
Öffnen der Sprachtabellen
SetLanguage
Setzen der aktiven Sprache für Übersetzungen
Private Methods NONE

FWK_PARAM

Class Name FWK_PARAM (FWK)
Description Parameterübergabeobjekt
(Globales Parameterobjekt - "Es kann nur einen geben")
(Sollte im LOAD/UNLOAD der Form gelesen/gefüllt werden.)
Parent Class FWK_CUSTOM
Classes Used FWK_BASE
Public Properties NONE
xPar1
Platzhalter für Parameterwert 1
xPar2
Platzhalter für Parameterwert 2
xPar3
Platzhalter für Parameterwert 3
xPar4
Platzhalter für Parameterwert 4
Public Methods NONE
Destroy
Löschen von GOPARAM
Init
Übernahme der Parameter 1-4 in Properties
Publizieren des Objekts GOPARAM
Release
Löschen von GOPARAM

FWK_MGR_REGISTRY

Class Name FWK_MGR_REGISTRY (FWK)
Description Objekt um Einträge in die Registry zu handeln oRegistry kann nur einmal vorhanden sein
Parent Class FWK_CUST
Classes Used FWK_BASE
Public Properties NONE
cIniFile
Name der *.Ini Datei
cSKey_Base_BS
Basisname für Registry Schlüssel
lIniLog
Flag für Schreiben einer INI-Logdatei (durch andere Objekte)
nHKey_Current_User
= -214783647 Key für Benutzereinträge in der Registry
nRegSZ
= 1 Flag für den Typ des Wertes in der Registry
Public Methods NONE
Destroy
Objekt releasen (oRegistry)
Init
DLLs deklarieren und Objekt initialisieren
closekey
Registry Key mit Handle schließen
createkey
Neuen Schlüssel anlegen
declaredll
Deklarieren der Registry DLLs
getpps
Profile String aus der Ini Datei holen
getvalue
Wert aus der Registry holen
openkey
Schlüssel in der Registry öffnen; liefert Handle zurück
putvalue
Wert in Registry schreiben
restorepref
Voreinstellungen aus Registry holen und setzen
rgopenkey
Schlüssel in Registry öffnen und Handle zurückliefern
savepref
Voreinstellungen in Registry abspeichern
setinifile
Namen der Ini Datei festlegen

FWK_MGR_RESIZE

Class Name FWK_MGR_RESIZE (FWK)
Description Resizer paßt die Größen der Controls im aktuellen Container an
Parent Class FWK_CUST
Classes Used FWK_BASE
Public Properties NONE
aObjectlist
Array mit allen Objekten die in der Größe angepaßt werden sollen
cIgnorePath
Liste der Objektpfade, die nicht bearbeitet werden, weil sie selbst ein Resize-Objekt enthalten
cResizeObjectList
Editbox, Textbox, Commandbutton, Listbox, Container, Label, Pageframe, Grid, Combobox, Line, Spinner, Shape, Image, Checkbox
Liste der Typen von Objekten, die angepaßt werden können
lIsResizer
.T. Flag ob das Objekt der Resizer ist
nNumObjects
Anzahl der Objekte die angepaßt werden müssen
Public Methods NONE
Destroy
aObjectlist löschen (Refernzen!) und dann Objekt freigeben
Init
Default + feststellen ob die Form resizable sein soll wenn nicht gibt's hier keinen Resizer
getobject
Prüft, ob ein Objekt resizable markiert ist und trägt es in die aObjectList Liste ein
getresizers
Prüft ob Objekt ein Resizer ist und trägt den Objektpfad in den cIgnorepath ein
resize
Eigentlche Rountine zum Anpassen der Größe für alle Objekte aus der aObjectlist Liste

Teil 3 - Initialisierung Basis- und Managerklasen

1. Hauptprogramm Projekt Loader:

Das Hauptprogramm besteht nur noch aus ganz wenigen Zeilen und tut folgendes:

Sowohl aus dem Framework (FWK_BASE.VCX, FWK_MGR.VCX) als auch projektspezifische Subklassen davon (PROJ_BAS.VCX, PROJ _MGR.VCX).

2. Init der Framework-Manager-Basisklasse:

Durch das Createobject wird die Init-Methode des PROJ_MGR_LOADER (PROJ_MGR.VCX) durchlaufen. Dieser reicht den Aufruf sofort weiter an seine Parentklasse FWK_MGR_LOADER (FWK_MGR.VCX) und diese tut das selbe hoch zur Managerbasisklasse FWK_MGR_BASE (FWK_BASE.VCX). Diese initialisiert sich wie folgt:

Vorbemerkung: Das Superbasisobjekt ist die wichtigste Konzepterweiterung der Basis-Klassenbibliothek FWK_BASE.VCX gegenüber den üblichen Ansätzen des einfachen Subclassing aller Klassenarten von Visual FoxPro. Das Objekt FWK_BASE wird als globales Objekt oBASE _vor_ allen anderen Objekten instanziiert. Fast alle wesentlichen Methoden-Aufrufe (z.B. Init, Destroy, Refresh, Click usw.) werden von den Framework-Basisklassen aller Objekte auf dieses globale Objekt umgeroutet (Beispiel: Methode Commandbutton::Init ruft auf oBase.Init( THIS ) ) und übergeben eine Selbstreferenz als Parameter. Dadurch kann das Superbasisobjekt allen normalerweise redundanten Code aufnehmen (z.B. gleiche Codeabschnitte in Textbox und Spinner oder in Listbox und Combobox). D.h. Code, der für mehr als eine Klasse gültig ist, wird im Superbasisobjekt hinterlegt und nur noch rein klassenspezifischer Code ist in der Subklasse vorhanden (=Redundanzfreiheit).

Ohne das Superbasisobjekt kann aber kein weiteres Objekt instanziiert werden, deshalb prüfen die Managerbasisklasse mit dem Funktionsaufruf =this.loadobase() das Vorhandensein von oBase. Falls nicht vorhanden:

Aus der Eigenschaft "THIS.coBaseClass" wird der Name der Klasse des Superbasisobjektes geholt. Dadurch ist man nicht an die Klasse des Frameworks gebunden, sondern kann auf der Subklasse PROJ_MGR_LOADER entsprechend auf eine Subklasse der Superbasisklasse PROJ_BASE verweisen, in der projektspezifische Anpassungen vorgenommen werden können.

Mit createobject() wird dann das Basisobjekt erzeugt und dieser Vorgang in "THIS.lcreateobase" vermerkt, damit im Destroy dieses Objektes auch die Superbasisklasse wieder entfernt werden kann.

Zuerst weist sich das Superbasisobjekt mit "THIS.cUniqueID = SYS(2015)" eine eindeutige Kennung zu. Fehlen dieser Kennung bedeutet, daß es sich beim Init-Aufruf um das eigene Init handeln muß <g>.

Erläuterung: In Visual FoxPro gibt es bisher nur die Funktion COMPOBJ(), die einen aufwendigen Vergleich aller Properties durchführt, um bei zwei Referenzen festzustellen, ob diese nicht auf dasselbe Objekt verweisen. Durch einfach Zuweisung einer eindeutigen Kennung muß man nur noch die Kennung vergleichen ( oObject1.cUniqueID = oObject2.cUniqueID => Gleiches Objekt mit versch. Referenzen). Dies funktioniert auch problemlos beim Vergleichen von Objekten auf mehrern Instanzen der gleichen Maske (dort wäre der Objektname und sogar der komplette Objektpfad identisch - interessant vor allen Dingen bei Drag&Drop-Operationen).

Als nächstes wird mit "public oBase" und "oBase = THIS" eine globale Referenz auf sich selbst erzeugt, damit alle nachfolgenden Objekte das Superbasisobjekt über diese globale Referenz ansprechen können.

Sofern die Eigenschaft THIS.lNoTranslation nicht auf .T. steht (d.h. Übersetzungen global abgeschaltet werden, interessant für Oneways, die ja rein englisch laufen könnten), wird mit dem Aufruf "=THIS.setlanguagemanager()" als nächstes der Sprachmanager instanziiert, da er von fast allen nachfolgenden Objekten benötigt wird.

Aus der Eigenschaft "THIS.cLanguageclass" wird der Name der Klasse des Languagemanagers geholt. Dadurch ist man nicht an die Klasse des Frameworks gebunden, sondern kann in der Subklasse PROJ_BASE entsprechend auf eine Subklasse von FWK_MGR_LANGUAGE verweisen, in der projektspezifische Anpassungen vorgenommen werden können.

Mit createobject() wird dann der Languagemanager erzeugt und dieser Vorgang in "THIS.lCreatedLangMan" vermerkt, damit im Destroy der Superbasisklasse auch der Languagemanager wieder entfernt werden kann. Siehe Initialisierung Languagemanager.

Mit "return THIS.CustomInit()" wird die zusätzliche Custom-Init-Methode. In dieser kann man in einer Subklasse eigenen projektspezifischen Code plazieren.

Erläuterung: Alle Framework-Klassen besitzen eine Custom-Init-Methode, da es bei komplexen Objekten manchmal etwas schwierig ist, mit einem Dodefault() im Init einfach den Supercode auszuführen und dann noch schnell etwas hintendranzuhängen. Dies gilt insbesondere für das Superbasisobjekt . In der Custom-Init-Methode aller Objekte kann man einfach direkt Code schreiben ohne Dodefault() und irgendwelche anderen Regelungen beachten zu müssen und man kommt dann immer _nach_ dem Init-Code des Superbasisobjektes (alle Inits rufen dieses Superinit auf) und _vor_ dem klassenspezifischen Code (statt beim Dodefault() im normalen Init() _danach_)..

Es stehen über den Languagemanager hauptsächlich die Methoden GETLITERAL und SETLANGUAGE zur Verfügung. Letztere wird von allen Basisklassen zur Selbstübersetzung bei Initialisierung über oBase.SetLanguage aufgerufen (Hinweis: Der Umweg über oBase ist notwendig, da bei einsprachigen Applikationen garkein Languagemanager existieren würde!).

siehe unter 3. das gleiche Beispiel für die Loader-Klasse

Kurzfassung: Addieren des Pfades auf Liter, Öffnen der Tabelle Liter mit der Order Liter, Abfragen auf Datei TRANSLAT.TMP und Publizieren von oLanguage als Selbstreferenz.

siehe unter 2.4. das gleiche Beispiel für die Loader-Klasse

Es wird derzeit nur die Sprache "ger" als Default für die Benutzeroberfläche eingestellt. (Hinweis: Eine entsprechende Standortabhängige Laderoutine fehlt noch.)

siehe unter 6. das gleiche Beispiel für die Loader-Klasse

Anhang zu 2.3.:

Funktion GETLITERAL: Erhält per Referenz die Parameter tcLiteral, tcCaption, tcToolTip, tcStatus, tcHelp. In tcCaption kann wahlweise auch "CAPT", "TOOL", "STAT", "HELP" stehen, so daß nur das gewünschte Feld der Literaldatei zurückgeliefert wird. Kann jederzeit aufgerufen werden. (Hinweis: Bei Fehlen eines Literals in der Entwicklungsumgebung wird derzeit noch nicht die Maske zum sofortigen Einpflegen von neuen Literalen aufgerufen)

Funktion SETLANGUAGE: Holt sich mit this.getliteral( lcCaption, "", @lcToolTip, @lcStatus ) die benötigten Strings und setzt Caption, ToolTipText und StatusBarText des jeweils als Referenz übergebenen Objektes mit dessen Eigenschaften bzw. denen seines Parents (zweiter Parameter). (Hinweis: Holt derzeit noch nicht bei allen Klassen die ursprünglichen Literale aus der Sicherung (s.u.) zurück, so daß ein erneuter Aufruf mit einer anderen Sprache noch nicht durchgängig zuverlässig ist).

Diese Initialisierung wird von _allen_ Objekten einheitlich durchlaufen. Deshalb ist nur verhältnismäßig wenig Code hier plaziert worden, da sonst die Performance sinken könnte. Die vielen Assertions zum Sicherstellen des Vorhandenseins diverser Parameter, Eigenschaften und Methoden der aufrufenden Objekte werden in der ausgelieferten Version einfach abgeschaltet (siehe SET ASSERT OFF in der VFP-Hilfe).

siehe dazu "2.2.1. Zuweisung einer eindeutigen Kennung"

Ergänzung: Falls Kennung schon vorhanden, wird die Initialisierung abgebrochen.

Die Caption des Objektes wird für spätere weitere Übersetzungen gesichert.

Sofern die Eigenschaften "lRequired" gesetzt ist, wird die Methode THIS.Required() aufgerufen.

Hier werden einheitlich Eigenschaften für zwingend notwendige Felder gesetzen.

Hinweis: Dies ist derzeit leider nur eine Baustelle...

Sofern sich ein aufrufendes Objekt in einem Grid befindet, wird das Flag lInGrid gesetzt, so daß man später jederzeit diesen Schalter abfragen kann, ohne sich jedesmal zum Parent durchhangeln zu müssen. Desweiteren erfolgt ein:

Hier werden Grid-spezifische Eigenschaften einheitlich gesetzt, z.B. Margin oder Borderstyle, damit keine Grid-spezifische Subklasse von allen Objekten notwendig ist (dies würde den Vererbungsbaum sonst an der Programmier- statt an der Programlogik orientieren).

siehe "2.2.4. Individuelle Init-Methode aufrufen" incl. Erläuterung dort.

Hinweis: Temporär ist das Routen der Managerbasisklasse durch die Initialisierung der Superbasisklasse abgeschaltet. Stattdessen wird nur "this.cUniqueID= Sys(2015)" und "this.lInit = .T." gesetzt. Dies ist nur für Testzwecke.

[1] [2] [3] [4] [5]