Programmieren mit Visual FoxPro, Teil 3
Nachdem wir im ersten Teil die Datenbankaspekte von Visual FoxPro beleuchtet haben und Teil zwei die objektorientierte Programmierung mit Visual FoxPro zum Thema hatte, beschäftigt sich der dritte Teil mit der Erstellung der Anwendungsoberfläche. Dazu gehören Themen wie der Umgang mit dem Form-Designer, das Eventhandling mit den Möglichkeiten, auf Aktionen des Anwenders zu reagieren und das Behandeln von Fehlern und Ausnahmesituationen.
Der Formular-Designer
Alle Ein-/Ausgabemasken, Formulare genannt, werden in Visual FoxPro mit dem Formulardesigner erstellt. Eine große Anzahl von Designtools, über 4 Symbolleisten verteilt, helfen dem Entwickler beim Entwurf seines Bildschirmformulars. Bild 1 zeigt den Formulardesigner mit den eingeblendeten Symbolleisten. Wer es gerne etwas weniger eng auf seinem Bildschirm hat, kann die Symbolleisten natürlich wegblenden oder anders anordnen. Alle über die Symbolleisten verfügbaren Funktionen können auch über Menü abgerufen werden. Eine sehr gute Unterstützung bei der Arbeit mit dem Formular-Designer sind die Kontextmenüs, die Sie an allen Stellen mit der rechten Maustaste abrufen können.
Die Symbolleisten sind frei konfigurierbar. Sie können auch die von Ihnen am häufigsten benutzten Funktionen in einer neuen Symbolleiste zusammenfassen und beim Formulardesign Ihre eigene Symbolleiste anzeigen lassen. Seltener benutzte Funktionen rufen Sie dann über das Menü oder mit der rechten Maustaste ab.
|
Bild 1: der Formulardesigner von Visual FoxPro |
Die Elemente, aus denen sich ein Bildschirmformular zusammensetzt, sind die Eingabefelder, Listboxen, Buttons, Label etc., die einen Großteil der VFP-Basisklassen bilden.
Die zur Gestaltung eines Formulars nutzbaren Basisklassen sind dabei mit folgenden Symbolen dargestellt:
|
Label. Jeder Text, der zum Layout Ihres Formulars gehört, also Feldbezeichnungen und ähnliches, wird als ein Objekt der Klasse Label im Formular abgelegt. |
|
Textfeld, Ein-/Ausgabefeld für Ihre Daten. Die Klasse Textfeld wird für jeden Datentyp (mit Ausnahme von Memofeldern) verwendet, also auch für numerische Daten oder Datumsfelder. |
|
Editbox. Editierbox für längere, mehrzeilige Texte, zum Beispiel aus Memofeldern. |
|
CommandButton. Befehlsschaltfläche, neben den Textfeldern sicher eines der häufigsten Elemente in einem Formular. Die Beschriftung der Befehlsschaltfläche erfolgt über die Eigenschaft "Caption". |
|
CommandGroup. Das ist eine Zusammenfassung von mehreren Befehlsschaltflächen zu einer Gruppe, die damit zum Beispiel eine gemeinsame Klick-Methode nutzen können. Nach wie vor kann aber auch jede einzelne Schaltfläche der Gruppe auf ein Klickereignis reagieren. |
|
OptionGroup. Optionsfelder sind nur in Gruppen möglich, was sicherlich sinnvoll ist. Zu einer richtigen Auswahl gehören halt mindestens zwei Optionen. Optionsfelder werden typischerweise mit Datenfeldern vom Typ numerisch oder integer verbunden. |
|
CheckBox. Kontrollkästchen, dient zur Anzeige und zum Setzen von logischen Werten. |
|
ComboBox. Die ComboBox ist eine Kombination aus Textfeld und Listbox. In der Listboxkönnen Angaben aus einer Tabelle oder einem Array zur Auswahl angeboten werden, während das Textfeld gleichzeitig eine direkte Eingabe ermöglicht. |
|
ListBox. Die Listbox zeigt Werte aus einer Tabelle, einem Array, dem Ergebniscursor einer Abfrage oder programmatisch eingetragene Werte in Listenform an. Die Anzeige kann mehrspaltig sein. Eine oder mehrere Zeilen können ausgewählt werden. |
|
Spinner, zu deutsch Drehfeld. Wird zum hoch- oder runtersetzen von numerischen Werten benutzt. |
|
Grid, Datenblatt in Gitterdarstellung, am ehesten dem Browse-Befehl vergleichbar. Um alle Möglichkeiten des Grids auszuleuchten, wäre sicher ein eigener Artikel notwendig. Das Grid ist ein Container, der Header- und Spaltenobjekte beinhaltet. Jede Spalte wiederum kann diverse Controls (auch mehrere gleichzeitig) enthalten, zwischen denen je nach Programmsituation umgeschaltet werden kann. |
|
Image. Mit diesem Element kann eine Bitmap-Datei in das Formular integriert werden. |
|
Timer, der Zeitgeber, der im Formular hinterlegt werden kann, ist zur Laufzeit unsichtbar. |
|
PageFrame. Seitenrahmen zur Aufnahme von Seiten im Formular. Jede Seite ist dabei mit einem Reiter versehen, der eine Bezeichnung trägt, die auf den Inhalt der jeweiligen Seite verweist. Zwischen den einzelnen Seiten wird durch Anklicken der Reiter hin- und hergeschaltet. |
|
OLEControl. Dient zur Anbindung eines OLE-Servers an das Formular. Der Server kann zur Laufzeit durch Doppelklick (Default) aktiviert werden. Da das OLEControl nicht an ein Tabellenfeld gebunden ist, werden Änderungen jedoch nicht in der Datenbank gespeichert. |
|
OLEBoundControl. Dieses OLEControl ist an ein Tabellenfeld gebunden. Das Serverdokument und die daran zur Laufzeit vorgenommenen Änderungen werden in einem Feld vom Typ Objekt gespeichert. |
|
Line. Mit dem Linienobjekt können Sie das Formular unterteilen und übersichtlicher gestalten. |
|
Shape. Damit ist es möglich, Rechtecke, Kreise oder Ellipsen in das Formular zu integrieren. |
|
Separator, Zwischenraum für Symbolleisten. Dieses Element kann nur in Symbolleisten, jedoch nicht in normalen Ein-/Ausgabeformularen genutzt werden. |
|
Sinnvollerweise verwendet man zur Gestaltung eines Formulars allerdings nicht die Basisklassen direkt, sondern daraus abgeleitete eigene Klassen, wie in Teil 2 dieses Artikels erläutert. Die Objekte der eigenen Klassen lassen sich per Drag&Drop direkt aus dem Projektmanager in das Bildschirmformular ziehen. Eine andere Möglichkeit des Zugriffs auf diese Klassen besteht darin, über das Bibliothekssymbol die in der Symbolleiste angezeigten Basisklassen gegen die Klassen einer eigenen Bibliothek auszutauschen und somit bei der Formulargestaltung direkt auf die eigenen Klassen zuzugreifen. |
|
Sind erst einmal alle oder einige Elemente im Bildschirmformular eingetragen, müssen diese herumgeschoben und arrangiert werden. Dazu, und auch zur Auswahl eines oder mehrerer Elemente dient der Zeiger-Button. |
|
Eine wichtige Hilfe bei der Gestaltung des Formulars bilden die Layout-Funktionen, die hier an Hand der Layout-Symbolleiste dargestellt sind. Damit können ausgewählte Elemente bündig ausgerichtet oder zentriert werden, auf gleiche Größen gebracht, oder vor bzw. hinter ein anderes Element plaziert werden. |
|
Auch die Farbpalette ist als Symbolleiste darstellbar. Damit können Sie interaktiv Vorder- und Hintergrundfarben ausgewählter Elemente oder des ganzen Formulars bestimmen. |
Die bis hierher aufgeführten Symbolleisten mit den darauf befindlichen Schaltflächen dienen der visuellen Gestaltung des Bildschirmformulars. Zur endgültigen Erstellung eines Formulars sind jedoch noch einige andere Dinge zu erledigen. Die dazu benötigten Funktionen können aus der Formulardesigner-Symbolleiste abgerufen werden:
|
Festlegen der Aktivierfolge. Die Aktivierfolge kann, je nach Einstellung der Optionen, interaktiv im erstellten Formular oder in Listenform in einem gesonderten Fenster festgelegt werden. Entwickler, die bereits mit FoxPro 2.x gearbeitet haben, werden sicherlich die zweite Variante bevorzugen, da Ihnen diese dann bereits bekannt ist. |
|
Umschalten zum DataEnvironment des Formulars. Mit dem DataEnvironment werden wir uns weiter unten noch eingehender befassen. |
|
Bringt das Eigenschaftenfenster in den Vordergrund oder schaltet es weg. Das Eigenschaftenfenster ist dabei immer auf das aktuell ausgewählte Objekt eingestellt, oder auf das Formular selbst, wenn kein Objekt ausgewählt ist. |
|
Umschalten zum Codefenster des Formulars. Wenn Sie im Codefenster gleich bei den für ein bestimmtes Objekt verfügbaren Methoden aufsetzen wollen, erreichen Sie dieses durch einen Doppelklick auf das gewünschte Objekt im Formular. |
|
Startet den sogenannten "Steuerelementassistenten für Formulare". Hinter diesem Unwort verbirgt sich ein Programm, mit dessen Hilfe Sie ein Formular halbautomatisch erstellen können. Sie wählen lediglich die Tabellenfelder aus, die auf dem Formular erscheinen sollen und wählen eine von fünf möglichen Stilarten aus. Der Assistent trägt dann alle benötigten Label und Ein-/Ausgabefelder im Formular ein, bringt die Felder auf die benötigte Größe und ordnet sie an, so gut es geht. Wenn der Platz nicht für alle ausgewählten Felder reicht, kann das Formular auf Wunsch auch automatisch vergrößert werden. Zur ersten, groben Erstellung eines Formulars wäre ein solcher Assistent sicher eine gute Hilfe, wenn er nicht zwei Einschränkungen hätte: Zum einen verwendet er für die Label nicht die im DBC hinterlegten Caption-Einträge, sondern die Feldnamen, zum anderen benutzt der Assistent ausschließlich seine eigene Klassenbibliothek. Eine Verwendung der Klassen, die Sie selbst aus den Basisklassen abgeleitet und eventuell schon um wichtige Dinge ergänzt haben zusammen mit dem Assistenten ist nicht möglich. |
|
Dieser Button ruft den AutoFormat-Assistenten auf. Mit diesem Assistenten können Sie eine Auswahl von Elementen Ihres Formulars auf ein einheitliches Layout einstellen. Drei Stilarten stehen zur Auswahl. Da der Assistent auf den bereits im Formular vorliegenden Objekten arbeitet, können Sie damit auch die Objekte Ihrer eigenen Klassen überarbeiten lassen. |
Eigenschaften einstellen
Alle im Formular angeordneten Elemente sowie das Formular selber sind Objekte, deren Eigenschaften eingestellt werden können. Die Eigenschaften eines visuellen Objekts bestimmen zum einen das Aussehen und das Verhalten des Objekts und beschreiben zum anderen seine Verknüpfung mit den Daten und seine Herkunft in der Klassenhierachie. Bild 2 zeigt das Eigenschaftenfenster des Formular-Designers.
|
Bild 2: Das Eigenschaftenfenster des Formular-Designers |
Eigenschaften, die das Aussehen des Objektes bestimmen, sind zum Beispiel BackColor und ForeColor, die Font-Eigenschaften und so weiter. Ein Textfeld hat alleine 37 solcher Eigenschaften. Diese Eigenschaften sind auf der Seite "Layout" zusammengefasst. Die Seite "Daten" des Eigenschaftenfensters führt alle Eigenschaften auf, die zur Verbindung eines visuellen Objekts mit seiner Datenquelle benötigt werden. Dazu gehören die Eigenschaft ControlSource, die auf den Namen des Tabellenfeldes oder des Arrayelements eingestellt wird, das die Daten enthält, oder InputMask und Format, die zur Formatierung der angezeigten Daten dienen. Eine dritte Gruppe von Eigenschaften beeinflußt das Verhalten des Objektes. Dies sind Eigenschaften wie Enabled, TabStop und so weiter. Diese, wie auch Class, ParentClass und Baseclass finden Sie auf der Seite "Andere".
Eigenschaften, die nur die Werte .T. und .F. annehmen können, können Sie durch einen Doppelklick auf ihre Zeile im Eigenschaftenfenster umschalten. Andere Eigenschaften erwarten einen numerischen oder Zeichen-Ausdruck, der über den mit "fx" beschrifteten Button mit dem Ausdruckeditor von Visual FoxPro erstellt werden kann. Wenn Sie einen Ausdruck direkt in die Eingabezeile eintragen wollen, setzen Sie ein Gleichheitszeichen davor. Daran erkennt VFP, daß es sich bei dem folgenden um einen auszuwertenden Ausdruck handelt. Über das Kontextmenü, das bei einem rechten Mausklick auf eine Eigenschaftenzeile erscheint, können Sie eine Eigenschaft auf ihren Defaultwert zurücksetzen.
Über den Menüpunkt "Formular / Neue Eigenschaft" können Sie neue Eigenschaften für Ihr Formular deklarieren. Diese hinzugefügten Eigenschaften werden ebenfalls im Eigenschaftenfenster auf der Seite "Andere" angezeigt und können dort eingestellt werden. In den Methoden des Formulars greifen Sie mit THISFORM.EigenschaftName auf Ihre selbst deklarierten Eigenschaften zu.
Methoden formulieren
Eine weitere Seite des Eigenschaftenfensters faßt alle Methoden zusammen, die das jeweilige Objekt kennt. Die Methoden eines Objekts lassen sich in zwei Arten unterteilen: 1. Methoden, mit denen das Objekt manipuliert werden kann, 2. Methoden, mit denen auf Ereignisse reagiert wird. Ein Beispiel für die erste Art ist die "Move"-Methode, mit der ein Objekt auf eine andere Position verschoben werden kann, ein Beispiel für die zweite Art dagegen die "Moved Event" genannte Methode, mit der auf die Tatsache, daß das Objekt verschoben wurde, reagiert werden kann. Alle Methoden der zweiten Art tragen im Eigenschaftenfenster den Zusatz "Event", im Handbuch und der Online-Hilfe sind sie bei der Beschreibung eines Objekts unter "Ereignisse" zu finden. Einige wichtige Methoden bei der Erstellung der Anwendungsoberfläche sind in der folgenden Tabelle zusammengefasst:
Init Event und
Destroy Event
|
Hier können Sie Code hinterlegen, der bei der Instantiierung des Objektes bzw. bei dessen Zerstörung ausgeführt werden soll. Der Init-Methode können Parameter übergeben werden.
|
Load Event und
Unload Event
|
Methoden, die beim Laden eines Formulars in den Hauptspeicher und beim Entfernen des Formulars aus dem Speicher ausgeführt werden. Formulare, deren Eigenschaft WindowType auf 1 = Modal steht, können aus der
Unload-Methode Rückgabewerte an das aufrufende Programm übergeben. |
Activate Event und DeActivate Event
|
hier kann auf das Aktivieren oder Deaktivieren eines Formulars oder einer Seite in einem Formular reagiert werden |
Click, RightClick und
DblClick Events
|
mit den dahinter stehenden Methoden können Sie auf das Anklicken eines Elementes mit der linken oder rechten Maustaste und auf einen Doppelklick reagieren |
SetFocus
|
Methode, mit der der Eingabefocus gezielt auf ein Element des Formulars gesetzt werden kann. Zu beachten ist, daß die SetFocus-Methode nicht aus den When Event oder ValidEvent-Methoden eines anderen Elementes heraus
aufgerufen werden sollte. Dies produziert zwar keinen Fehler, ergibt aber auch nicht den gewünschten Effekt, da die When und ValidEvent-Methoden darüber entscheiden, ob das aktuelle Element den Focus erhalten bzw. abgeben darf. Ein
erneutes Umsetzen des Focus aus diesem offenen Entscheidungsprozeß heraus ist unwirksam. |
GotFocus Event und LostFocus Event
|
diese Methoden ermöglichen Ihnen Programmaktionen in dem Moment, in dem das Objekt den Focus erhält bzw. verliert |
InteractiveChange und
ProgrammaticChange Events
|
hier hinterlegen Sie, was passieren soll, wenn die Value-Eigenschaft des Objektes durch den Anwender (interactive) oder durch das Programm (programmatic) verändert wird |
KeyPress Event
|
damit können Sie auf einen Tastendruck der Anwenderin reagieren |
Drag, DragDrop Event und DragOver Event
|
zusammen mit der Eigenschaft DragMode dienen diese Methoden zur Erstellung eines Drag&Drop Interfaces für Ihre Anwendung |
Error Event und ErrorMessage Even
|
Methoden zur Fehlerbehandlung. Zum Thema Fehlerbehandlung finden Sie unten noch weitere Hinweise |
MouseDown, MouseMove und MouseUp Events |
hier können Sie reagieren, je nachdem, ob die Maus über ein Objekt gezogen oder ob eine Maustaste über einem Objekt gedrückt bzw. losgelassen wurde
|
When Event und Valid Event
|
entsprechen den bereits aus FoxPro 2.x bekannten When und Valid-Snippets der GET-Objekte. Das When-Ereignis tritt ein, bevor das Objekt den Focus erhält. Durch Rückgabe eines .F. aus der WhenEvent-Methode können Sie
verhindern, daß das Objekt tatsächlich den Focus erhält. Das Valid Ereignis tritt ein, bevor das Objekt den Focus verliert. Durch Rückgabe eines .F. oder einer 0 (numerisch Null) können Sie verhindern, daß das Objekt den Focus
verliert. Allerdings gilt das so uneingeschränkt nur für Textfelder, Editierfelder, Drehfelder und Kombinationsfelder. Andere Objekte geben den Focus frei, auch wenn die ValidEvent-Methode .F. zurückgibt. Lediglich die Checkbox behält
in diesem Fall den Focus - gibt ihn aber frei, wenn Sie mit der Tab-Taste zum nächsten Element springen.
Wenn eine ValidEvent-Methode .F. zurückliefert, wird der Zeichenausdruck, der von der ErrorMessage Event Methode zurückgegeben wird, als Fehlermeldung ausgegeben. Ist diese Methode leer, gibt VFP standardmäßig die
Meldung Ungültige Eingabe aus. Wenn die ValidEvent-Methode 0 zurückliefert, wird jedoch keine Fehlermeldung ausgegeben. Das Eingabefeld behält aber weiterhin den Focus, bis eine gültige Eingabe vorgenommen wurde. |
Refresh
|
diese Methode bewirkt die erneute, aktualisierte Anzeige des Objektes |
Release
|
Methode zum programmgesteuerten Freigeben eines Objektes. Speziell bei Formularen sollte ein Schließen-Knopf den Aufruf von THISFORM.Release enthalten |
Ereignisabfolge
Bevor Sie mit der Codierung Ihrer Methoden beginnen, sollten Sie sich Klarheit darüber verschaffen, in welcher Reihenfolge Ereignisse ablaufen. Dies ist nämlich nicht immer offensichtlich. Am besten testen Sie die Ereignisabfolge, indem Sie aus den in Frage kommenden Ereignissen zunächst nur den Objekt- und den Ereignisnamen auf dem VFP Hauptbildschirm ausgeben lassen. Dazu kann folgender Code, der hier beispielhaft für die GotFocus und LostFocus Methoden aufgeführt ist, dienen:
procedure GotFocus
activate screen
? This.Name + " " + "GotFocus"
endproc
procedure LostFocus
activate screen
? This.Name + " " + "LostFocus"
endproc
Wenn Sie den Code im Codefenster des Formulardesigners in die jeweiligen Methoden eintragen (die empfohlene Variante) entfallen natürlich die "procedure" und "endproc" Zeilen.
Nachdem Sie die interessanten Methoden aller Formularelemente mit diesen Codesnippets versehen haben, führen Sie Ihr Formular aus und verfolgen Sie die Ausgaben auf dem Hauptbildschirm. Sie werden dabei manches Aha-Erlebnis haben. Beim Anklicken eines CommandButton, dessen ValidEvent-Methode .T. oder .F. zurückliefert, wird zum Beispiel folgende Ereignisabfolge durchlaufen:
When
GotFocus
Click
Valid
When
Der Focus wird also auch bei Rückgabe von .T. aus der ValidEvent-Methode nicht an das nächste Objekt weitergegeben, sondern fällt auf den CommandButton zurück, wodurch dessen WhenEvent-Methode erneut durchgeführt wird. Textfelder verhalten sich anders: Wenn die ValidEvent-Methode eines Textfeldes ein .T. zurückgibt, wird der Focus auf das nächste Objekt gesetzt, da die Eingabe in das Textfeld ja mit ENTER oder TAB abgeschlossen wurde. Liefert die ValidEvent-Methode des Textfeldes ein .F. zurück, so verbleibt der Focus im Textfeld. In diesem Fall wird die WhenEvent-Methode des Textfeldes
nicht erneut aufgerufen.
Noch etwas verwirrender wird die Sache, wenn Sie bedenken, daß bei einem Click auf den CommandButton eventuell ein Eingabefeld verlassen wird. Dann mischt sich noch dessen LostFocusEvent-Methode in die Ereignisabfolge, die dann so aussieht:
CommandButton When
Textfeld LostFocus
CommandButton GotFocus
CommandButton Click
CommandButton Valid
CommandButton When
Auch wenn Sie in der WhenEvent-Methode des CommandButtons den richtigen Arbeitsbereich eingestellt haben, so können Sie in der GotFocusEvent-Methode des gleichen Buttons nicht mehr sicher sein, daß die Einstellung noch stimmt. Durch die Abarbeitung der LostFocusEvent-Methode des Textfeldes kann alles schon wieder ganz anders sein.
ValidEvent-Methoden werden nicht durchgeführt, wenn Sie einen Button in einer Symbolleiste anklicken oder wenn Sie ein Menü aufklappen und einen der Menüpunkte anwählen. Erst wenn dem Objekt durch die daraus folgende Aktion - z.B. Ausgabe und Aktivierung eines anderen Formulars - der Focus entzogen wird, wird die ValidEvent-Methode ausgeführt. Auch wenn die daraus entstehenden Probleme durch die Verwendung von PrivateDataSessions (mehr dazu weiter unten) entschärft werden, ist der Effekt schlicht unschön. Das neue Formular steht bereits auf dem Bildschirm, das alte kann aber nicht verlassen werden, ohne eine gültige Eingabe in ein vielleicht momentan unwichtiges Eingabefeld zu tätigen.
Valid- und When, sowie RangeHigh und RangeLow sind Überbleibsel aus der FoxPro 2.x-Welt, die zur Sicherstellung der Abwärtskompatibilität benötigt werden. Bei der Neuentwicklung von Formularen sollten Sie sich von ihnen verabschieden und die Methoden verwenden, die dem Eventmodell von Visual FoxPro besser entsprechen. Mit den Methoden zum LostFocus Event und GotFocus Event läßt sich ein Verfahren zur Feldvalidierung aufbauen, bei dem eine Eingabe in ein Feld immer dann geprüft wird, wenn der Focus auf ein anderes Objekt des gleichen Formulars gesetzt wird. Dazu benötigt das Formular eine Eigenschaft wie Prueffeld, die eine Objektreferenz auf das zu prüfende Feld enthält. Diese Eigenschaft initialisieren Sie mit .NULL. . Jedes Eingabefeld erhält eine neue Methode, die vielleicht Pruefen heißt und die die Feldvalidierung enthält. Pruefen sollte wie gewohnt .T. zurückgeben, wenn der Wert des Feldes o.k. ist, sonst .F.. In der LostFocusEvent-Methode jedes Eingabefeldes tragen Sie ein:
Thisform.Prueffeld = This
und in der GotFocusEvent-Methode:
if !isnull(Thisform.Prueffeld);
and Thisform.Prueffeld.Name <> This.Name;
and !Thisform.Prueffeld.Pruefen()
Thisform.Prueffeld.SetFocus
endif
Damit haben Sie die Feldvalidierung sichergestellt und sich die Möglichkeit offengehalten, auf die Feldvalidierung zu verzichten, wenn zum Beispiel der Abbruch-Button angeklickt wird. Noch ein Hinweis dazu: Thisform.Prueffeld enthält eine Referenz auf ein Objekt Ihres Formulars. Wenn Sie das Formular jetzt schließen wollen, wird Ihnen das nicht gelingen, da ein Objekt des Formulars noch referenziert wird. Geben Sie also vor dem Aufruf der Release-Methode (oder in der Release-Methode selbst) die Referenz mit Thisform.Prueffeld = .NULL. frei.
Die Datenumgebung (DataEnvironment)
Jedes Formular enthält ein Datenumgebungsobjekt (DataEnvironment). Das Datenumgebungsobjekt kann visuell mit Tabellen und Relationen bestückt werden. Mit der rechten Maustaste rufen Sie auch hier ein Kontextmenü auf, über das Sie Tabellen zur Datenumgebung hinzufügen können. Im DBC hinterlegte persistente Relationen werden automatisch in die Datenumgebung eines Formulars übernommen, wenn Sie die beteiligten Tabellen in die Datenumgebung eintragen. Diese Relationen können natürlich auch wieder entfernt werden, wenn Sie nicht den Verknüpfungen entsprechen, die in Ihrem Formular gebraucht werden. Klicken Sie dazu einfach die Linie an, mit der die Relation dargestellt wird und drücken Sie dann die Entfernen-Taste.
Einstellbare Eigenschaften der Datenumgebung sind:
AutoOpen Tables
|
gibt an, ob die Tabellen beim Laden des Formulars automatisch geöffnet werden sollen |
AutoClose Tables
|
gibt an, ob die Tabellen automatisch beim Schließen des Formulars geschlossen werden sollen |
InitialSelected Alias
|
Tabellenalias, der bei Laden des Formulars automatisch angewählt werden soll
|
Die wichtigsten Methoden sind:
Open Tables und Close Tables |
zum programmgesteuerten Öffnen und Schließen der Tabellen der Datenumgebung
|
BeforeOpen Tables und AfterClose Tables
|
Haken, an die Sie eine eigene Verarbeitung vor dem Öffnen und nach dem Schließen der Tabellen anhängen können
|
Jede in der Datenumgebung eingetragene Tabelle (wobei Tabellen und Views gleichermaßen verwendet werden können) wird durch ein Cursorobjekt repräsentiert. Das Cursorobjekt hat ebenfalls einstellbare Eigenschaften, wie Alias, Order und ReadOnly. Von besonderem Interesse sind hier die Eigenschaften BufferModeOverride und NoDataOnLoad. Mit BufferModeOverride können Sie für jeden Cursor der Datenumgebung den Puffermodus festlegen. Die Defaulteinstellung übernimmt den für das Formular voreingestellten Puffermodus (None, Pessimistic oder Optimistic).
NoDataOnLoad ist eine Eigenschaft, die nur für Views eingestellt werden kann. Sie besagt, daß beim Öffnen des Views der zugrunde liegende SQL-Select noch nicht abgesetzt wird. Dadurch haben Sie die Möglichkeit, über Eingabefelder des Formulars zunächst eingrenzende Kriterien für den Select abzufragen. Wenn alle Kriterien für die Abfrage vorliegen, rufen Sie die REQUERY() Funktion auf und füllen so den View mit den Daten, die den angegebenen Kriterien entsprechen.
Private Datensitzungen (private DataSessions)
Aus den früheren FoxPro-Versionen ist das Konzept des Arbeitsbereichs bekannt. Ein Arbeitsbereich enthält eine geöffnete Tabelle und verwaltet deren Satznummer, Filter- und Reihenfolgesetzung. Ein bekanntes Thema war auch, daß die Anzahl der verfügbaren Arbeitsbereiche nie ausreichte. Visual FoxPro bietet nun 32.767 Arbeitsbereiche pro Datensitzung (DataSession). Das sollte zunächst mal reichen.
Neben den bekannten Arbeitsbereichen gibt es in Visual FoxPro die Möglichkeit, unterschiedliche Datensitzungen zu verwenden. Eine Datensitzung ist immer ein komplett neuer Satz von weiteren 32.767 Arbeitsbereichen. Alle Datensitzungen sind weitestgehend gegeneinander abgeschirmt. Wenn ein Formular oder ein Bericht ausgeführt wird, so werden die benötigten Tabellen wahlweise in der aktuell eingestellten Datensitzung oder in einer neuen, nur für dieses Formular reservierten, also privaten, Datensitzung eröffnet. Die DataSession-Eigenschaft des Formulars entscheidet darüber, ob für das Formular eine private Datensitzung verwendet werden soll. Etwas irreführend ist die zweite Auswahlmöglichkeit: Default DataSession. Eine Default DataSession gibt es nämlich nicht. Die Einstellung Default DataSession besagt, daß keine neue Datensitzung erstellt werden soll. Die im Moment aktive Datensitzung bleibt weiterhin aktiv. Das können Sie sich zunutze machen, zum Beispiel bei der Ausgabe von (modalen) Unterformularen eines Hauptformulars. Lassen Sie in den Unterformularen die Einstellung der Eigenschaft DataSession auf ihrem Standardwert 1 = DefaultDataSession stehen. Dann brauchen Sie für die Unterformulare keine eigene Datenumgebung (DataEnvironment) einzurichten , da diese nun die Datensitzung (DataSession) des Hauptformulars mitbenutzen und somit Zugriff auf alle Tabellen aus der Datenumgebung des Hauptformulars haben.
Formulare mit privater Datensitzung können mehrfach aufgerufen werden, ohne sich gegenseitig zu beeinflußen. So können Sie Multiuserbedingungen bereits auf Ihrer Entwicklungsmaschine simulieren. Eine neue Datensitzung ist immer eine komplette Tabellenumgebung. Alle auf die Tabellenumgebung wirksamen SET-Einstellungen müssen also pro Datensitzung durchgeführt werden. Am einfachsten delegieren Sie diese Einstellung an ein gesondertes Objekt oder an eine Methode Ihres Applikationsobjektes, die Sie aus der LoadEvent-Methode des jeweiligen Formulars aufrufen.
Fehlerbehandlung
Die vorangegangenen Versionen von FoxPro kannten nur eine Möglichkeit, Fehler und Ausnahmesituationen zu behandeln. Mit der Setzung von ON ERROR DO .... wurde ein eigener, globaler Errorhandler bekanntgemacht. Bei Auftreten eines Fehlers verzweigte FoxPro dann zu der hinter dem DO angegebenen Prozedur. Die Möglichkeit, mit ON ERROR einen globalen Errorhandler zu installieren, ist nach wie vor gegeben. In einer Applikation, die aus vielen miteinander arbeitenden Objekten besteht, sollte diesem globalen Errorhandler jedoch eine andere Rolle zufallen. Planen Sie Ihre ON ERROR Routine als globalen Errorhandler, der alle Fehler auffängt, die nicht von den Objekten selbst behandelt werden.
Jede Klasse in Visual FoxPro kennt eine eigene Fehlermethode, die ErrorEvent-Methode. Wenn diese Methode ausformuliert ist, d.h. Programmcode enthält, so wird bei Auftreten eines Fehlers während der Abarbeitung einer Objektmethode nicht die ON ERROR Routine aufgerufen, sondern die ErrorEvent-Methode des Objektes. Dabei spielt es keine Rolle, auf welcher Stufe der Veerbungshierachie der Programmcode der ErrorEvent-Methode steht. Wenn die ErrorEvent-Methode des aktuellen Objektes leer ist, so geht Visual FoxPro zunächst in der Vererbungshierachie zurück bis zu Ihrer Ableitung der Basisklasse. Nur, wenn nirgendwo dort Programmcode steht, wird die ON ERROR Routine aufgerufen. Der folgende Code in einer ErrorEvent-Methode eines Objektes behandelt den Fehler Nr. 1 = "Datei nicht vorhanden" selbst und übergibt alle anderen Fehler an den globalen Errorhandler:
LPARAMETERS nError, cMethod, nLine
local cErrHand, cMessage, cProgram
cMessage = message()
cProgram = sys(1272,THIS)+"."+cMethod
cErrHand = on("ERROR")
if !empty(cErrHand)
cErrHand = lower(cErrHand)
cErrHand = strtran(cErrHand,"error()","nError")
cErrHand = strtran(cErrHand,"program()","cProgram")
cErrHand = strtran(cErrHand,"message()","cMessage")
cErrHand = strtran(cErrHand,"lineno(1)","nLine")
endif
if nError = 1 && Datei nicht vorhanden
* Abhandlung des Fehler Nr. 1
else
&cErrHand
endif
Üblicherweise erfolgt ein Aufruf des globalen Errorhandlers über eine Anweisung wie:
ON ERROR DO MyErrHand with error(), message(), program(), lineno(1)
Dem Errorhandler werden also die wichtigsten Parameter beim Aufruf gleich übergeben. Der ErrorEvent-Methode eines Objektes wird von Visual FoxPro ebenfalls die Fehlernummer, der Name der Methode, in der der Fehler auftrat und die Zeilennummer übergeben. Um sicherzustellen, daß die Weitergabe des Fehlers an den globalen Errorhandler mit den richtigen Parametern erfolgt, wird die Aufrufzeile, die durch ON("ERROR") zurückgegeben wird, mit den aktuellen Parametern aufbereitet.
In manchen Fällen kann es sinnvoll sein, daß ein Objekt auftretende Fehler nicht selber behandelt, sondern dies dem Formular, oder allgemeiner, dem Container überläßt, in dem es sich befindet. Eine solche Fehlerkaskadierung erreichen Sie, indem Sie aus der ErrorEvent-Methode des Objektes die ErrorEvent-Methode des Containers aufrufen. Mit
if type(This.Parent) = O AND !isnull(This.Parent)
prüfen Sie, ob sich das Objekt in einem Container befindet. Wenn ja, rufen Sie dessen ErrorEvent-Methode mit
This.Parent.Error(nError,cMethod,nLine)
auf. Die übergebenen Parameter sind dieselben, die von VFP an die erste ErrorEvent-Methode übergeben werden. Beachten Sie dabei, daß die Rückgabe von message() durch den Befehl type(...) bereits verändert wird. Wenn Sie sicher sein wollen, daß die aufgerufene ErrorEvent-Methode die Original-Message ausgeben und gegebenenfalls auf das Objekt zugreifen kann, das den Fehler verursachte, sollten Sie beides als Parameter mit übergeben. Ergänzen Sie dazu die lParameters-Anweisung zu
LPARAMETERS nError, cMethod, nLine, cMessage, oObject
und formulieren Sie den Aufruf so:
LPARAMETERS nError, cMethod, nLine
local cMessage
cMessage = message()
if type("This.Parent") = "O" and !isnull(This.Parent)
This.Parent.Error(nError,cMethod,nLine,cMessage,This)
endif
Eine große Anzahl von Befehlen liefert .T. oder .F. zurück, je nachdem, ob der Befehl erfolgreich ausgeführt werden konnte, oder nicht. Einige andere Befehle aber, bei denen dieses Verhalten ebenfalls wünschenswert wäre, generieren lediglich einen Fehler, der mit einer ON ERROR Routine oder der ErrorEvent-Methode abgefangen werden muß. Meistens ist es dann recht mühsam, abhängig vom Erfolg oder Mißerfolg des durchgeführten Befehls den normalen Programmablauf wieder aufzunehmen. Eine Command-Klasse, die solche Befehle testweise ausführt und den Fehlerwert zurückliefert, kann da Abhilfe schaffen:
**************************************************
*-- Class: command
*-- ParentClass: custom
*-- BaseClass: custom
*-- führt einen Befehl aus, gibt 0 oder eine
*__ FehlerNr. zurück
*
DEFINE CLASS command AS custom
*-- letzte Fehler-Nr.
errnum = 0
*-- letzte Fehler-Meldung (Message())
errmess = ""
*-- Befehl, der den Fehler verursachte (Message(1))
errcomm = ""
Name = "command"
*-- führt den Befehl als Macro aus
PROCEDURE execute
lparameter cLine
This.errnum = 0
&cLine
return This.Errnum
ENDPROC
PROCEDURE Error
LPARAMETERS nError, cMethod, nLine
This.Errnum = nError
This.Errmess = message()
This.Errcomm = message(1)
return
ENDPROC
ENDDEFINE
*
*-- EndDefine: command
**************************************************
Um die Kommandoklasse zu nutzen, instantiieren Sie zunächst ein Objekt dieser Klasse:
oCommand = createobject(Command)
Wenn Sie nun zum Beispiel an einer Stelle Ihres Programms den weiteren Programmablauf davon abhängig machen wollen, ob die Tabelle KUNDEN exclusiv eröffnet werden konnte, oder nicht, können Sie folgendes formulieren:
if oCommand.Execute(use KUNDEN in 0 exclusive) = 0
* KUNDEN konnte exclusiv eröffnet werden
... weitere Verarbeitung
else
* KUNDEN wird von anderen benutzt (oder anderer Fehler)
... weitere Verarbeitung
endif
Was alles fehlt, was alles kommt
In diesem Artikel konnten wir Ihnen lediglich einen generellen Überblick über die Programmerstellung mit Microsoft's Visual FoxPro geben. Was noch im Detail zu beschreiben wäre, sind die Möglichkeiten und Verfahrensweisen der Client/Server-Programmierung mit Visual FoxPro, der Einsatz von OCXen und der Umgang mit OLE-Servern, die Verwendung von VFP-Klassen als OLE-Automation Server, das Erstellen eigener Wizards und Builder, das Debugging, die Anbindung einer Visual FoxPro-Applikation an das Internet und die Zusammenarbeit mit SCCS-Programmen wie Visual SourceSafe. Sie sehen, es gibt zu diesem Werkzeug noch viel zu sagen. Wir berichten weiter.
|