Eigentlich sind wir zum jetzigen Zeitpunkt nur eine Zeile weiter als bei der Position "2. Init der Framework-Manager-Basisklasse", trotzdem fange ich hier mal mit einer neuen Zählung an, da jetzt die eigentliche Manager-Klassen-Initialisierung beginnt.
3.1. Setzen diverser Einstellungen
Über den Aufruf "THIS.Set()" wird die Set-Methode aufgerufen, die Standardeinstellungen vornimmt - allerdings nicht für die normalen SET-Befehl der Umgebungssteuerung. Für jeden Teilbereich wird aus einem Propertie der notwendige Wert geladen. Auf der Ebene des Frameworks werden nur allgemeine Framework-Klassen gesetzt, auf der Projektspezifischen Ebene der Manager aus PROJ_MGR.VCX sind in den Properties aber jeweils die "richtigen" Werte eingestellt. Es werden die folgenden fünf Teilbereiche für den aktuellen Manager ergänzt:
3.1.1. Setzen von zusätzlichen Pfaden
Aus der Eigenschaft "this.cAddPath" werden zusätzlich notwendige Pfadangaben geladen und zum allgemeinen Pfad mit SET PATH dazuaddiert. Der ursprüngliche Status wird in einer cOld-Eigenschaft vermerkt und beim Destroy des Objektes wieder hergestellt. Beispiel: Der Loader setzt fast alle allgemeinen Pfade z.B. auf die DBFS-Unterverzeichnisse.
3.1.2. Setzen von allgemeinen Klassenbibliotheken
Aus der Eigenschaft "this.cAddClassLib" werden zusätzlich notwendige Klassenbibliotheken geladen und mit SET CLASSLIB ADDITIVE gesetzt. Der ursprüngliche Status wird in einer cOld-Eigenschaft vermerkt und beim Destroy des Objektes wieder hergestellt. Beispiel: Der Messagemanager setzt sich die zusätzliche Klassenbibliothek FWK_MESS.VCX.
3.1.3. Setzen von Prozedur-Dateien
Aus der Eigenschaft "this.cAddProcedure" werden zusätzlich notwendige Prozedur-Dateien geladen und mit SET PROCEDURE ADDITIVE gesetzt. Der ursprüngliche Status wird in einer cOld-Eigenschaft vermerkt und beim Destroy des Objektes wieder hergestellt. Beispiel: Der Loader setzt sich die zusätzliche Prozedure-Dateie "UTILITY". (Hinweis: Die Prozedurdatei CSVLIB wird demnächst nicht mehr gelade, sobald alle Aufrufe auf das Service-Objekt oString umgeleitet sind. Hier ist aber noch ein Performance-Test notwendig).
3.1.4. Setzen von Libraries
Aus der Eigenschaft "this.cAddLibrary" werden zusätzlich notwendige Libraries geladen und mit SET LIBRARY ADDITIVE gesetzt. Der ursprüngliche Status wird in einer cOld-Eigenschaft vermerkt und beim Destroy des Objektes wieder hergestellt. Beispiel: Der Servicemanager FWK_SRV_TOOLS (FWK_SRV.VCX) setzt sich die zusätzliche Library FOXTOOLS (sein einziger Existenzzweck, da es eine Wrapper-Klasse ist).
3.1.5. Instanziieren von Service-Objekten bzw. weiteren Managern:
Aus der Eigenschaft "this.cAddService" werden die Klassennamen von weiteren Managern bzw. Serviceklassen geladen. Mit "lcService = alltrim( listvalue( lcAddService, lnCounter ) )" wird in einer Schleife die Liste der zusätzlichen Klassen abgearbeitet und mit "=createobject( lcService )" das jeweilige Objekt instanziiert. Der ursprüngliche Status wird hier nicht vermerkt, sondern im Destroy wird das Destroy der Manager- bzw. Serviceklassen aufgerufen, sofern diese noch vorhanden sind (Services könnten sich zwischenzeitlich selbst deinstalliert haben mangels Bedarf für Ihre Dienste). Wichtig ist dafür die Namenskonvention, da nur aufgerufen werden kann, wenn der Manager eine Public-Referenz hat, die "o" zzgl. dem Klassennamen ab _MGR_ folgend entspricht. Beispiel: Der Loader setzt sich die zusätzlichen Manager FWK_MGR_USER, FWK_MGR_VERSION, FWK_MGR_MESSAGE, FWK_MGR_REGISTRY und FWK_MGR_DATA.
Wichtiger Hinweis: Hier müßte man jetzt eigentlich sagen, "Begeben Sie sich zum Start, begeben Sie sich direkt dorthin...", da jetzt für jeden instanziierten Manager exakt die gleiche Routine abläuft wie bisher für den Loader seit "2. Init der Framework-Manager-Basisklasse". Das ist der Vorgang an welchem sich die Anwendung eigentlich selbst an den Haaren aus dem Sumpf zieht, da nach Initialisierung des Loaders plötztlich alle anderen benötigten Manager und Service-Klassen als Objekte zur Verfügung stehen. Nach Abschluß des Hochziehens aller Manager und der wiederum von diesen angeforderten Manager und Services geht es dann mit der Initialisierung des Loaders weiter:
Sonderfall Usermanager: Falls die Eigenschaft lDevelopment über die Initialisierung der Managerbasisklasse für den Usermanager gesetzt wird (z.B. durch Vorhandensein der Datei NOLOG.TMP, siehe Eigenschaft cDevelopment von PROJ_MGR_USER) wird lLoggedIn auf .T. gesetzt und mit dem Aufruf =this.set_user( this.cDefaultUser, this.cdefaultusername, "", .T. ) der in den Eigenschaften eingetragene Default-User automatisch eingeloggt. Das eigentliche Einloggen erfolgt allerdings _nicht_ im Init des Usermanagers (was eigentlich ein logischer Ort wäre), da im Loader wesentlich mehr Initialisierung notwendig ist und erst nach call_Install() aber vor call_Oneway() die Useranmeldung erfolgen kann.
3.2. Setzen des Entwicklungsschalters:
Über den Aufruf der Methode "this.set_development()" wird der Schalter this.lDevelopment auf .T. gesetzt, sofern die Datei "this.cDevelopment" vorhanden ist. Dieser Schalter wird je nach Manager für andere Zwecke verwendet. Beispiel: Beim Loader ist es tatsächlich der globale Entwicklerschalter, beim Usermanager schaltet er das Login auf automatisch für Entwickler, beim Sprachmanager wird dadurch die Übersetzung abgeschaltet.
3.3. Öffnen einer Standardtabelle für den Manager:
Über den Aufruf "this.dbfopen()" wird die Haupttabelle des Managers geöffnet. Die Tabelle "this.cTable" wird mit der Order "this.cOrder" geöffnet und das Öffnen in "this.lOpen" vermerkt, so daß beim Destroy über die korrespondierende Methode "DbfClose()" die Haupttabelle wieder geschlossen bzw. gemäßt "this.cOldOrder" die ursprüngliche Order wieder hergestellt werden kann.
Ergänzung: Diese Methode kann auch direkt mit Tabellenname und Order aufgerufen werden, um eine weitere Tabelle zu öffnen. Die Properties werden in diesem Falle nicht verwendet und Restaurierungsparameter müssen selbst vermerkt und an "Dbfclose" übergeben werden.
Hinweis: Der ganze Vorgang des Öffnen und Schließens von Tabellen sowie des Wechsels zwischen Tabellen soll durch das Standardobject "FWK_SELECT" ersetzt werden. In einem einzigen Propertie werden dann alle benötigten Parameter als komma-separierte Liste geführt und einfach an dieses Objekt übergeben. Eine Referenz auf dieses Objekt wird dann in enem Propertie hinterlegt und im Destroy automatisch zerstört. Dies ist aber noch nicht fertig.
3.4. Publizieren einer Selbstreferenz:
Über die Methode "this.publish()" kann jeder Manager eine öffentliche Selbstreferenz und/oder eine Referenz auf der zugrundeliegenden Form anlegen lassen:
3.4.1. Setzen einer Public-Referenz
Ein in "this.cPublicName" gespeicherte Name wird über PUBLIC als globale Variable angelegt und "THIS" dorthinein gespeichert. Alle anderen Objekte können jetzt dieses Objekt direkt ansprechen. Beim RELEASE der Public-Variable wird dieses Objekt nicht zerstört.
3.4.2. Setzen einer Form-Referenz
Ein in "this.cPropertyName" hinterlegter Name einer Eigenschaft der Form, auf welcher das Objekt ggf. plaziert ist, wird verwendet, um in diese Eigenschaft ebenfalls ein "THIS" als Referenz zu hinterlegen. Dies findet z.B. Verwendung beim FWK_MGR_NAVIGATOR, welcher die Navigation über Menü/Toolbars in Stammdatenmasken steuert und global über diese Eigenschaft der Maske angesteuert werden kann. Im Destroy eines Objektes wird automatisch die korrespondierende Funktion "this.UnPublish" aufgerufen und alle Objektreferenzen werden wieder entfernt (was vorher nicht ganz der Fall war und extrem störende Nebeneffekte aufweisen kann, z.B. Nicht-Wiederfreigabe von Masken, welche dann als unsichtbare Restobjekte vorhanden sind und ggf. das saubere Beenden der Anwendung verhindern).
Beispiel: Menü oder Toolbar können mit "_screen.activeform.oData.Next()" auf den nächsten Satz gehen, ein Button auf der Maske würde stattdessen "thisform.oData.Next()" verwenden. Die Buttonklasse kann aber zwischen beiden Vorgehensweisen von alleine unterscheiden, so daß nur der Name der Eigenschaft und die gewünschte Methode in einem Propertie des Buttons hinterlegt werden muß (cClickAction - siehe Dokumentation FWK_BASE.DOC).
Hinweis: Das Publizieren sollte ursprünglich vor dem eigentlichen Set-Aufruf erfolgen, damit nachfolgend instanziierte Manager und Servies auf das aktuell instanziierte Objekt zugreifen könnten. Da ist aber das Konzept noch nicht ganz zu Ende gedacht gewesen, da hier ja das Objekt sein Init noch nicht abgeschlossen hat und dadurch eigentlich noch gar nicht existiert...
3.5. Selbst-Registrierung für Services
Services führen eine Liste der sie verwendenden Objekte. Sofern sie von keinem anderen Objekt mehr benötigt werden, können sie sich selbst aus dem Speicher entfernen, um Resourcen freizugeben. Sofern die Eigenschaft "this.nRegisterCounter" den Wert "0" statt dem Defaultwert " .NULL." hat, registrieren sie sich allerdings gleich selbst mit der Methode "this.register()".
3.5.1. Registriermethode
Die Methode "Register" führt in dem Array "this.aObjects" eine Liste. Verzeichnet werden dort Objektreferenzen auf die Anwender "this.aObjects( lnLine, 1 ) = oTHIS" sowie deren eindeutige Kennung "this.aObjects( lnLine, 2 ) = oTHIS.cUniqueID", zwecks Wiederauffindung ohne die Verwendung von COMPOBJ() (siehe "2.2.1. Zuweisung einer eindeutigen Kennung").
Jetzt sind wir wiederum in der zweiten Zeile des Inits der eigentlichen Framework-Loader-Klasse, die erste Zeile war das DoDefault() welches alle bisherigen Ereignisse ausgelöst hat.
4.1. Setzen des Shutdown-Handlings:
Mit der Methode "this.set_onshutdown()" wird die vorhandene "ON SHUTDOWN"-Routine gesichert und eine neue Routine gesetzt, die beim Verwenden des Closers wahlweise den Loader beendet (sofern noch vorhanden) oder direkt auf "oBASE.QUIT()" geht, um ein ggf. noch vorhandenes Superbasisklassenobjekt zu beseitigen, welches dann versucht, die Applikaton mit Gewalt zu Beenden.
4.2. Verstecken der VFP-Toolbars in der Entwicklungsumgebung:
Mit der Methode "this.hideVFPtoolbars()" werden in der Entwicklungsumgebung die Werkzeuge von Visual FoxPro vom Bildschirm entfernt. Im Destroy wird mit "ShowVFPToolbars" die Umgebung des testenden Entwicklers ggf. wiederhergestellt.
Hinweis: Bisher wird noch nicht ein ggf. vorhandenes Standard-Konfigurationsprogramm für den Entwicklerarbeitsplatz aufgerufen (um z.B. den Projektpad des Menüs wieder aufzubauen).
4.3. Einstellen des Basis-Directories:
Mit der Methode "this.set_basedir()" wird das Basisverzeichnis "this.cBaseDir" der Applikation auf "=sys(5)+curdir()" eingestellt, sofern in einer Subklasse kein anderes Verfahren ausprogrammiert wird.
4.4. Setzen von Speziellen Settings:
Mit der Methode "this.set_specialsettings()" werden folgende besonderen Einstellungen vorgenommen:
4.4.1. DualInterface abschalten
Mit "this.lDualInterface" wird festgelegt, daß die Unterstützung für die leider etwas krisenanfälligen Dual Interfaces von ActiveX-Controls abgeschaltet werden soll.
4.4.2. Vordergrundspeicher
Der Vordergrundspeicher für Visual FoxPro wird gemäß "this.nBufferSizeForeground" eingestellt, da sonst Windows NT sehr schnell mit dem Swappen anfängt, welches die Gesamtperformance der Applikation erheblich beeinträchtigen kann. (Hinweis: Aufgrund der vorliegenden marginalen Hauptspeicherausstattung von nur 32 MB bei Verwendung von NT muß der Defaultwert wohl runtergesetzt werden - die Arbeitsplätze swappen ja schon beim Öffnen und Bewegen von mehreren Fenstern...).
4.4.3. Hintergrundspeicher
Der Hintergrundspeicher für Visual FoxPro wird gemäß "this.nBufferSizeBackground", um Platz für andere aktive Applikationen zu schaffen. (Hinweis: Auch hier muß man wohl runtersetzen).
4.5. Setzen von Globalen Settings:
Mit der Methode "this.set_systemsettings()" werden SET-Einstellungen hardcodiert für die Applikation gesetzt. Es gibt noch eine Sondermethode für das Setzen von anderen Werten falls "this.lDevelopment" gesetzt ist:
4.6. Setzen der Entwicklungsumgebung
Mit der Methode "this.set_development()" sollen Einstellungen für Entwickler gesetzt werden. Derzeit wird hier nur eine Debugger-Klasse instanziiert, welche in der Eigenschaft "this.cDebugClass" vorgegeben werden kann. Diese Debugger-Klasse setzt z.B. Tastenbelegungen und (später) das Coverage-Verhalten incl. Anzeige (siehe geplanten Vortrag von wOOdy zu Coverage-Auswertungen).
4.7. Prüfen der Konfigurationsdatei:
Mit der Methode "this.call_configfpw()" wird die Konfigurationsdatei "this.cConfigFile" auf Vorhandensein geprüft und bei Nichtvorhanden wird eine Default-Konfigurationsdatei angelegt und die Anwendung neu gestartet.
4.8. Aufrufen der Parameter-Auswahl für die Tester:
Mit der Methode "this.set_testing()" soll _zukünftig_ eine spezielle Auswahlfunktionalität für die Testumgebung nachgebaut werden.
4.9. Aufruf der Mandantenauswahl
Mit der Methode "this.set_mandant()" soll _zukünftig_ eine spezielle Auswahlfunktionalität für Mandanten eingebaut werden (ist aber evtl. auch innerhalb von Testing abbildbar - hier werden später dann Ideen gesucht).
4.10. Aufruf einer Installationsapplikation:
Mit der Methode "this.call_install()" wird die Installationsapplikation "this.cInstallApp" (Default INSTALL.APP) gesucht und ggf. ausgeführt. Danach wird der Loader neu gestartet,
4.11. Aufruf einer zusätzlichen Konfigurationsdatei:
Mit der Methode "this.call_backdoor()" wird eine Datei "this.cBackdoorfile" gesucht und ggf. zeilenweise abgearbeitet, um Eigenschaften für die lokale Station umzusetzen und/oder Standort-spezifische Methoden aufzurufen.
4.12. Installieren von speziellen Managern:
Mit der Methode "this.set_manager()" sollen _zukünftig_ anders zu installierende Spezialmanagerklassen aufgerufen werden. Derzeit nur in Subklassen interessant.
4.13. Titel des Hauptfensters setzen:
Mit der Methode "this.set_mainwindcaption()" wird der Titel des Visual FoxPro-Fenster auf "this.cMainWindCaption" gesetzt und der Ursprungstitel vermerkt zwecks Wiederherstellung im Destroy.
4.14. Wegwerfen einer ggf. vorhandenen Startmaske:
Mit der Methode "this.release_form" wird ggf. die Maske "this.cSplashForm" aufgelöst, falls während des Startvorganges eine Anzeigemaske aufgerufen wurde. (Hinweis: Aufruf fehlt noch).
4.15. Einloggen des Benutzers:
Mit der Methode "this.call_login()" wird die Klasse "this.cLoginApp" instanziiert oder wahlweise die entsprechende Applikation gestartet. Darüber erfolgt die Anmeldung des Benutzers wie folgt:
4.15.1. Erzeugen eines Login-Objektes:
Mit "createobject()" wird die Loginmaske "this.cloginform" erzeugt und angezeigt. Die bisherige Login-Applikation wird nicht mehr benötigt.
4.15.2. Suchen des passenden Benutzers:
Mit einem SQL-Statement wird nach dem eingegebenen Benutzernamen in der Tabelle USER gesucht. Allerdings muß der Benutzereintrag das Flag "useradm.lCorrect" gesetzt haben. Diese Logik ist derzeit noch in der Login-Maskenklasse statt im Usermanager und wird demnächst verlagert.
4.15.3. Überprüfen des Passworts:
Mit dem Aufruf "oUser.Encrypt( thisform.txtPassword.value )" wird das Benutzerpasswort verschlüsselt und mit dem eingegebenen Passwort verglichen. Diese Logik ist derzeit noch in der Login-Maskenklasse statt im Usermanager und wird demnächst verlagert.
4.15.4. Eintragen des Benutzers
Bei Erfolg der Aktionen 4.15.1. bis 4.15.3. wird der Benutzer mit "oUser.set_user( lcUser, cname, cfirstname, .T. )" im Usermanager eingetraggen und das lLoggedIn-Flag von der Set_user-Funktion gesetzt. Auch dieser Vorgang soll aus der Maske in den Usermanager verlagert werden.
4.16. Aufruf eines Oneways:
Nach erfolgreichem Einloggen des Benutzers wird mit der Methode "this.call_oneway()" eine z.B. per eMail nachgereichte Oneway-Applikation mit dem Namen "this.cOnewayApp" (Default ONEWAY.APP) aufgerufen und ausgeführt. Bei Fehlermeldung des Oneways wird die Applikation neu gestartet.
4.17. Ggf. Ausloggen des Benutzers:
Sofern das Einloggen des Benutzers nicht erfolgreich war oder eine Installationsapplikation aufgerufen wurde oder ein Oneway nicht erfolgreich abgearbeitet werden konnte, wird der Loader mit "this.onshutdown( .F. )" beendet.
Nach erfolgreichem Initialisieren der Manager-Loaderklasse wird jetzt die projektspezifische Loader-Subklasse initialisiert. Derzeit wird dort folgendes gemacht:
5.1. Setzen von zusätzlichen Pfadangaben
Hier werden jetzt zusätzliche Pfadangaben initialisiert. Dies geschieht über eine Standardmethode der Managerbasisklasse, der wahlweise Variablen, Pfadangaben oder Funktionen zum Auffinden einer Pfade enthaltenden lokalen Datei übergeben werden können:
5.1.1. Laden von Pfadangaben aus Variable
Sofern eine globale Variable vorhanden ist, könnte ein Pfad aus ihr geladen werden.
5.1.2. Ggf. Funktion ausführen, die Pfad holt
Mit "this.set_alternatepath(getenv("USER") + ".PTH")" wird geschaut, ob es eine benutzerspezifische Datei mit der Endung "PTH" gibt, welche die lokalen Pfadangaben enthält und diese werden gesetzt.
5.1.3. Ggf. Pfaddatei öffnen und eigentlichen Pfad holen
Mit "this.set_alternatepath("c:\fwk_path.txt")" bzw. "this.set_alternatepath("c:\local\fwk_path.txt")" wird nach einer lokalen Datei "fwk_path.txt" gesucht und darin enthaltene Pfade ggf. gesetzt.
Hinweise: Im Destroy hat die anwendungsspezifische Subklasse des Loaders die entsprechenden Aufräumfunktionen für das Löschen der globalen Referenzen "release oApp, oEnv" sowie das Entfernen der derzeit noch nicht namenskonformer Manager mit "oMenu.Destroy()" und "oPrint.Destroy()". Dies wird demnächst aber Entfallen.
Nun sind wir wieder zurück im Hauptprogramm, welche gemäß 1.3. nun die Methode "Start()" des erfolgreich instanziierten Loaders aufruft. Diese Methode läßt nun die eigentliche Anwendung wie folgt starten:
6.1. Maskenaufruf
Die Maske "this.cMainform" wird aufgerufen. Diese Maske startet nunmehr wie folgt:
6.1.1. Versteckeln der aufrufenden Maske:
Da manchmal pseudo-modale Benutzeroberflächen aufrecht erhalten werden
sollen, haben alle Masken die Möglichkeit, die sie aufrufende Masken unsichtbar
zu machen, damit der Anwender nicht mehr auf die aufrufende Maske zurückschalten
kann. Die aufrufende Maske muß dafür beim Aufruf der aktuellen Maske
eine Selbstreferenz übergeben (Beispiel: "DO FORM
6.1.2. Startmodus zurücksetzen für Non-Toplevel-Masken
In der Eigenschaft "RunMode" vermerkt die Maske mit dem Aufruf "set_runmode( "STARTED" )" den aktuellen Status. Dies ist für den Resizer und andere Serviceklassen wichtig, damit diese nicht zum ungeeigneten Zeitpunkt aufgerufen werden.
6.1.3. Benutzeroberfläche übersetzen:
Sofern nicht die Eigenschaft "lNoTranslation" gesetzt ist, wird über den Aufruf "thisform.SetLanguage()" die Caption der Maske übersetzt. Die Methode reicht den Aufruf an "oBase.SetLanguage" weiter welches wiederum "oLanguage.SetLanguage" aufruft und sich per "this.getliteral" den eigentlichen Text holt.
6.1.4. Resizer addieren
Mit der Methode "call_resizer()" wird ggf. ein Resizer "cResizerClass" auf der Maske plaziert.
6.1.5. Menumanager aufrufen
Mit der Methode "call_menuman()" wird der Menumanager aufgerufen und ihm werden die Eigenschaften "cMenuString" und "nMenuLevel" zwecks Aufbau des gewünschten Menüs übergeben (siehe Menümanager von Thomas Seiler für weitere Details).
6.1.6. oBase-Init aufrufen
Aufruf der Init-Methode des Superbasisobjektes, siehe "2.4. Initalisierung des Loaders über das Superbasisobjekt:". Hinweis: Weitere Details zur Standardmaskenklasse finden sich in FWK_BASE.DOC.
6.2. Read events aufrufen
Die Methode "this.call_readevents()" wird aufgerufen, die das eigentliche Eventhandling von Benutzeraktionen startet, sofern man sich nicht in der Entwicklungsumgebung befindet. Das eigentliche Programm läuft jetzt und der Anwender kann aus dem Menü oder aus Buttons der Hauptmaske oder ggf. aus Toolbars entsprechende Funktionen anwählen.
Folgende Einstellungen sollten unter Optionen - Forms eingetragen sein: | ||
---|---|---|
Grid Lines: | Yes | |
Snap to Grid: | Yes | |
Show Position: | Yes | |
Tab Ordering: | by List | |
Design Area: | 800*600 | |
Form-Klasse: | FWK_FORM | (FWK_BASE.VCX) |
Formsetklasse: | FWK_FORMSET | (FWK_BASE.VCX) |
oder wahlweise keine/projektspezifische Maskenklassen |
Folgende Fieldmappings sollten eingetragen sein: | ||
---|---|---|
Character | fwk_textbox | (fwk_base) |
Character(b) | fwk_textbox | (fwk_base) |
Currency | fwk_textbox | (fwk_base) |
Date | fwk_textbox | (fwk_base) |
Datetime | fwk_textbox | (fwk_base) |
Double | fwk_textbox | (fwk_base) |
Float | fwk_textbox | (fwk_base) |
General | fwk_oleboundcontrol | (fwk_base) |
Integer | fwk_textbox | (fwk_base) |
Logical | fwk_checkbox | (fwk_base) |
Memo | fwk_editbox | (fwk_base) |
Memo (b) | fwk_editbox | (fwk_base) |
Numeric | fwk_textbox | (fwk_base) |
Multiple | fwk_grid | (fwk_base) |
Label | fwk_label | (fwk_base) |
Wahlweise natürlich Eintragung einer Entwickler- oder projektspezifischen Subklasse der Basisklassen. |
Folgende Klassenbibliotheken sollten unter Controls - Class Libs eingetragen sein: | |
---|---|
fwk_bas | Basisklassen |
fwk_fld | Felderklassen |
fwk_mgr | Managerklassen |
fwk_button | Buttonsklassen |
fwk_toolbar | Toolbarklassen |
Folgende ActiveX-Controls sollten unter Controls - ActiveX eingetragen sein:
Dynazip ZIP Control
RTF Control
andere projektspezifische ActiveX-Controls
Ggf. eine entsprechende SourceControl-Software wie MS Visual Source Safe oder kompatibel.
Objekt | Vorsilbe | Beispiel |
---|---|---|
Checkbox | chk | chkReadOnly |
Combobox | cbo | cboEnglish |
Befehlsknopf | cmd | cmdCancel |
Container | cnt | cntCustomerInfo |
Steuerung | ctl | ctlMisc |
Editbox | edt | edtComments |
Form | frm | frmFileOpen |
FormSeite | fpg | fpgList |
FormSet | frs | frsCustomerInfo |
Grid | grd | grdPrices |
GridSpalte | grc | grcCompanyName |
GridKopf | grh | grhLineTotal |
Bild | img | imgIcon |
Label | lbl | lblHelpMessage |
Linie | lin | linVertical |
Listbox | lst | lstPolicyCodes |
OLE | ole | oleObject1 |
Optionsknopf | opt | optFrench |
Optionsgruppe | opg | opgType |
OutlineSteuerung | otl | otlViews |
PageFrame | pgf | pgfLeft |
Shape (Kreis, Quadrat, Rechteck, abgerundetes Rechteck und abgerundetes Quadrat) |
shp | shpCircle |
Spinner | spn | spnDaysShown |
Textbox | txt | txtGetText |
Timer | tmr | tmrAlarm |
Toolbar | tbr | tbrEditReport |
Gültigkeitsbereich | Vorsilbe | Beispiel |
---|---|---|
Public/Global | g | gcUserName |
Private | p | pcState |
Local | l | lnCounter |
Parameter | t | tdRun |
Klasse | keine | Customer |
Konstante (#DEFINE) | Großbuchstaben | TRUE |
Typ | Vorsilbe | Beispiel |
---|---|---|
Zeichen | c |
cLastName |
Numerisch | n |
nRangeLo |
Logisch | l |
lMarried |
Datum | d |
dPurchased |
Memo | m |
mComments |
General | g |
gWordDoc |
Währung | y |
ySalary |
Fließkomma | f |
fResults |
Double | b |
bValue |
Bild | p |
pEmployee |
DatumZeit | t |
tRecorded |
Objektinstanz | o |
oJanitor |
Array | a |
aMonths |
Typ des Codes | Beispiel für Kopf |
---|---|
Standardprogramme | * Programm * Autor * Projekt * Erstellt * Copyright *) Beschreibung * Liste der wichtigen Änderungen |
Typ des Codes | Beispiel für Kopf |
---|---|
Procedure/Function | PROCEDURE Sample * Name der Procedure * Autor * Datum der Erstellung * Copyrighthinweis *) Beschreibung der Procedure * Liste der wichtigen Änderungen |
Standardkommentarzeichen | Erläuterung |
---|---|
*-- | für Pseudocode |
* | für in Kommentar umgewandelten Code oder für Kopfinformation |
*{ | für Beginn der Anmerkungen zu Änderungen und Anpassungen |
*} | für Ende der Anmerkungen zu Änderungen und Anpassungen |
*? | Für Programmierer- kommentare (z.B. Ideen für die Zukunft, Verbesserungen, Fragen oder Probleme) |