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

Die Behandlung von Arrays

Zusätzlich zu den neuen Funktionen, die Arrays zurückgeben (ATagInfo(), ASessions() und ADLLS()) enthält Visual FoxPro 7 auch zahlreiche Änderungen in den Funktionen, die mit den Arrays umgehen, sowie eine zusätzliche große Änderung im Bezug auf die Arrays, die Funktionen im Allgemeinen betrifft.

Als Erstes die große Änderung. Es ist jetzt möglich, eine Funktion ein Array zurückgeben zu lassen. In älteren Versionen von VFP war dies nicht möglich. In VFP 7 kann eine Funktion ein Array zurückliefern, vorausgesetzt das Array befindet sich immer noch im Bereich der Anwendung, wenn die Funktion beendet wurde. In der Praxis bedeutet dies, dass die Möglichkeit auf Methoden eingeschränkt ist, die Arrays zurückgeben, die Eigenschaften sind. In diesem Beispiel (das Sie in Colors.PRG auf der Begleitdiskette finden) verfügt die Klasse über eine Array-Eigenschaft, die aRGB genannt wird. Die Methode RGBComp akzeptiert eine Farbe als Parameter und gibt ein Array zurück, das die Komponenten rot, grün und blau der Farbe enthält. Damit imitiert sie das Verhalten der Funktion RGBComp der FoxTools, mit Ausnahme der Art der Rückgabe der Werte.

DEFINE CLASS Colors AS Custom
* Color handling code
DIMENSION aRGB[3]
 
FUNCTION RGBComp(nColor) AS Array
* RGBComp returns the Red, Green and
* Blue Components of a color in an
* array
 
This.aRGB[1] = -1
This.aRGB[2] = -1
This.aRGB[3] = -1
 
IF VARTYPE(nColor)="N"
   This.aRGB[3] = INT(nColor/(256^2))
   nColor = MOD(nColor,(256^2))
   This.aRGB[2] = INT(nColor/256)
   This.aRGB[1] = MOD(nColor,256)
ENDIF
 
RETURN @This.aRGB
 
ENDDEFINE

Beachten Sie, dass Sie dem zurückzugebenden Array ein „@“ voranstellen müssen. Dies entspricht der Art, wie Sie einen Parameter als Referenz übergeben.

Um die Methode nutzen zu können, müssen wir natürlich zunächst die Klasse instanziieren:

oColors = NewObject("Colors", ;
          "Colors.PRG")

Anschließend rufen wir die Methode auf und speichern den Rückgabewert in einem Array. Wenn das Array nicht existiert, wird es (innerhalb einer privaten Datensitzung) erstellt. Sollte es mit den falschen Dimensionen existieren, werden diese angepasst:

aResult = oColors.rgbcomp(255)

Zwei der Funktionen zur Behandlung von Arrays wurden geändert, um sie besser einsetzbar zu machen. Sowohl ASCAN() als auch ASORT() besitzen jetzt die Möglichkeit, Groß- und Kleinschreibung zu ignorieren. ASCAN() hat noch zusätzlich weitere neue Fähigkeiten: Sie können jetzt wählen, ob Sie eine exakte Suche (im Sinne von SET EXACT) durchführen wollen, Sie können die Suche auf eine bestimmte Spalte beschränken und Sie können ASCAN() anweisen, die Zeilennummer statt der Elementnummer in einem zweidimensionalen Array zurückzugeben. Diese Änderungen wurden seit Jahren von der Gemeinschaft der VFP-Entwickler gefordert.

Lassen Sie uns einen Blick auf die Syntax und einige Beispiele werfen. Als Erstes nehmen wir ASORT(), da es am wenigsten geändert wurde. Die Funktion hat einen neuen (fünften) Parameter, nFlags, der angibt, ob die Suche nach Groß- und Kleinschreibung unterscheiden soll. Wird dieser Parameter nicht angegeben oder ist er 0, werden Groß- und Kleinschreibung beachtet, so wie wir es aus früheren Versionen von FoxPro kennen. Enthält der Parameter den Wert 1, werden Groß- und Kleinschreibung ignoriert (da der Parameter nFlags genannt wird, ist es möglich, dass in der Zukunft noch weitere Schalter hinzugefügt werden. Vergleichen Sie die Behandlung des Befehls ASCAN() weiter unten, um zu sehen, wie die Werte eines Flags addiert werden, damit mehrere Auswahlmöglichkeiten kombiniert werden können).

Diese Abfrage erstellt ein Array, mit dem wir arbeiten können. Es zieht drei Mal den Vornamen der Tabelle Employee aus TasTrade, jeweils eines in der vorgegebenen Form, in Kleinschreibung und in Großschreibung.

SELECT First_Name FROM _SAMPLES+"TasTrade\Data\Employee";
UNION ;
SELECT LOWER(First_Name) FROM _SAMPLES+"TasTrade\Data\Employee" ;
UNION ;
SELECT UPPER(First_name) FROM _SAMPLES+"TasTrade\Data\Employee" ;
INTO ARRAY aNames
 
Hier ein Teil der Ergebnisse aus dem Aufruf von ASORT() ohne das neue Flag:
 
ANAMES                  Pub            A    
   (    1,    1)                       C     "ALBERT    "
   (    2,    1)                       C     "ANDREW    "
   (    3,    1)                       C     "ANNE      "
   (    4,    1)                       C     "Albert    "
   (    5,    1)                       C     "Andrew    "
   (    6,    1)                       C     "Anne      "
   (    7,    1)                       C     "CAROLINE  "
   (    8,    1)                       C     "Caroline  "
   (    9,    1)                       C     "JANET     "
   (   10,    1)                       C     "JUSTIN    "
   (   11,    1)                       C     "Janet     "
   (   12,    1)                       C     "Justin    "
   (   13,    1)                       C     "LAURA     "
   (   14,    1)                       C     "LAURENT   "
   (   15,    1)                       C     "Laura     "
   (   16,    1)                       C     "Laurent   "

Beachten Sie, dass hier keiner der Namen in Kleinschreibung angezeigt wird. Diese befinden sich alle am Ende des Listing.

Um das neue Flag zu nutzen, ohne eine Anfangsposition oder die Anzahl der Elemente anzugeben, übergeben Sie als zweiten und dritten Parameter jeweils –1. Hier der Aufruf, mit dem aNames korrekt sortiert ausgegeben wird: 

ASORT(aNames, -1, -1, 0, 1)

Hier ein Teil des Ergebnisses. Beachten Sie, dass in jeder Gruppe keine Vorhersage möglich ist, welche Version des Namens als Erste angezeigt wird. Die Funktion sieht „ANDREW“, „Andrew“ und „andrew“ als identisch an.

ANAMES                  Pub            A    
   (    1,    1)                       C     "ALBERT    "
   (    2,    1)                       C     "albert    "
   (    3,    1)                       C     "Albert    "
   (    4,    1)                       C     "ANDREW    "
   (    5,    1)                       C     "Andrew    "
   (    6,    1)                       C     "andrew    "
   (    7,    1)                       C     "anne      "
   (    8,    1)                       C     "ANNE      "
   (    9,    1)                       C     "Anne      "
   (   10,    1)                       C     "CAROLINE  "
   (   11,    1)                       C     "caroline  "
   (   12,    1)                       C     "Caroline  "
   (   13,    1)                       C     "Janet     "
   (   14,    1)                       C     "janet     "
   (   15,    1)                       C     "JANET     "
   (   16,    1)                       C     "Justin    "
   (   17,    1)                       C     "JUSTIN    "
   (   18,    1)                       C     "justin    "
   (   19,    1)                       C     "laura     "
   (   20,    1)                       C     "Laura     "
   (   21,    1)                       C     "LAURA     "
   (   22,    1)                       C     "Laurent   "
   (   23,    1)                       C     "LAURENT   "
   (   24,    1)                       C     "laurent   "

ShowASort.SCX auf der Begleitdiskette gibt Ihnen die Möglichkeit, mit ASORT() zu experimentieren.

ASCAN() verfügt über zwei neue Parameter. Der hinzugefügte fünfte Parameter ist nSearchColumn – damit wird angezeigt, in welcher Spalte gesucht werden soll. Sie können ihn mit den Parametern für die Startposition und der Anzahl der Elemente für eine nur teilweise Suche innerhalb der Spalte kombinieren. Alternativ können Sie sowohl für die Startposition als auch für die Anzahl der Elemente –1 angeben, wenn die gesamte Spalte durchsucht werden soll.

Um unser Beispiel vorzubereiten, erstellt diese Zeile ein Array, das die Informationen über die persistenten Relationen in der Datenbank TasTrade enthält:

ADBOBJECTS(aRelns,"RELATION")0

Das Array enthält fünf Spalten: die erste ist der Name der untergeordneten Tabelle in der Relation, die zweite der Name der übergeordneten Tabelle. Die dritte und vierte Spalte enthält die Namen der Tags, die für die Verwaltung dieser Relation benötigt werden. In der letzten Spalte finden Sie einen Wert, der den Typ der relationalen Integrität für diese Relation anzeigt.

Wenn wir die erste Relation finden wollen, die eine bestimmte Tabelle als untergeordnet nutzt, müssen wir sicherstellen, dass wir nur in der ersten Spalte suchen. Als Beispiel findet dieser Aufruf die erste Relation, in der die Tabelle Products als untergeordnete Tabelle vorkommt.

? ASCAN( aRelns, "PRODUCTS", -1, -1, 1) && displays 16

Der neue sechste Parameter, nFlags, gibt uns die Möglichkeit, die Suche auf unterschiedliche Arten zu verbessern. In Visual FoxPro 7 kann nFlags vier additive Bitwerte annehmen, die Sie in Tabelle 2 sehen.

Tabelle 2. Die Flags von ASCAN() – Addieren Sie die Werte, um den Parameter nFlags zu erstellen.
Bit Wert Bedeutung

0

0

Die Suche unterscheidet zwischen Groß- und Kleinschreibung. Vorgabewert.

0

1

Suche unterscheidet nicht zwischen Groß- und Kleinschreibung.

1

0

EXACT ist ausgeschaltet. Arbeitet nur, wenn Bit 2 gesetzt ist (4).

1

2

EXACT ist eingeschaltet. Arbeitet nur, wenn Bit 2 gesetzt ist (4).

2

0

Die aktuellen Einstellungen von SET EXACT gelten.

2

4

Benutzen der Einstellung von Bit 1.

3

0

Gibt die Elementnummer der passenden Zeile zurück.

3

8

Gibt die Zeilennummer der passenden Zeile zurück, wenn es sich um ein zweidimensionales Array handelt.

Wenn wir noch einmal zum letzten Beispiel zurückgehen, können wir verschiedene Änderungen antesten. Die sinnvollste ist das Erhalten der Zeilennummer statt der Elementnummer:

? ASCAN( aRelns, "PRODUCTS", -1, -1, 1, 8) && displays 4

Vielleicht wollen wir auch Missverständnisse durch die Groß- und Kleinschreibung der Daten im Array ausschließen. Wir können also dem Flag den Wert für die Unterscheidung der Groß- und Kleinschreibung hinzufügen:

? ASCAN( aRelns, "PRODUCTS", -1, -1, 1, 9) && displays 4

Die Flags für die Behandlung der EXACT-Einstellungen sind ein wenig verwirrend. Es ist kein Unterschied, welchen Wert Sie Bit 1 übergeben, wenn Sie Bit zwei nicht den Wert 4 zuweisen. Damit erhalten Sie die Möglichkeit, entweder die aktuelle Einstellung von SET EXACT zu nutzen oder sie für die Suche zu überschreiben. Die Addition von 4 zu nFlags stellt sicher, dass Sie mit der Einstellung EXACT OFF suchen, die Addition von 6 bewirkt, dass ASCAN() mit EXACT ON sucht. Unabhängig davon, welchen Wert Sie übergeben, hat dies keine Auswirkungen außerhalb des einzelnen Aufrufs von ASCAN().

Die Behandlung des Datums

Einige Änderungen bringen Verbesserungen im Umgang mit dem Datum. Die neue Funktion QUARTER() nimmt ein Datum und teilt Ihnen mit, in welches Quartal des Jahres es fällt. Sie können einen Startmonat für das Jahr angeben, so dass Sie neben dem Kalenderjahr auch das Fiskaljahr behandeln können. Ein Beispiel:

? QUARTER( {^ 2000-9-23} )

gibt 3 zurück, da der 23. September im dritten Quartal des Jahres liegt. Aber wenn Sie ein Jahr angeben, das am 1. Juli beginnt, also folgendermaßen:

? QUARTER( {^ 2000-9-23}, 7 )

gibt die Funktion statt dessen 1 zurück.

SET(“CENTURY“) hat eine neue Option erhalten. Wenn Sie als zweiten Parameter eine 3 übergeben, gibt die Funktion das höchste Rollover-Datum zurück, so wie es in der Systemsteuerung eingestellt ist. Diese Möglichkeit gilt nur für Windows 98 und 2000. In allen anderen Versionen gibt SET(“CENTURY“, 3) –1 zurück.

Erweiterte Werkzeuge der Benutzeroberfläche

Eine Anzahl der Änderungen betreffen das Erstellen der Benutzeroberfläche. Sie können in zwei Kategorien eingeteilt werden: in solche, die Kontrollelemente und solche, die sich auf andere Eingabemechanismen beziehen.

Erweiterungen der Kontrollelemente

Viele der Änderungen an den Kontrollelementen unterstützen das neue flache Aussehen. Viele Kontrollelemente haben die neue Einstellung „Hot Tracking“, die sie flach aussehen lassen, außer die Maus wird über sie gezogen. In diesem Moment erscheinen sie entweder erhöht oder gedrückt. Die Einstellung von Hot Tracking arbeitet nur, wenn Style auf Graphical gesetzt ist.

Alle Kontrollelemente haben die neuen Ereignisse MouseEnter und MouseLeave, die Ihnen die Möglichkeit eröffnen, eine Aktion auszuführen, wenn die Maus über das Kontrollelement geführt wird. Diese Ereignisse erhalten die gleichen Parameter wie MouseMove: die Maustasten sind gerade gedrückt sowie die aktuelle Position der Maus.

Die Schaltflächen haben die neue Eigenschaft VisualEffect, die nur zur Laufzeit verfügbar ist und die die Schaltfläche erhöht oder gedrückt erscheinen lässt. Durch die Manipulation dieser Eigenschaft in den Methoden MouseEnter und MouseLeave können Sie Ihre eigenen Hot Tracking-Effekte erstellen.

Das Formular in Abbildung 1 zeigt Ihnen die neue Einstellung SpecialEffect, die Ereignisse MouseEnter und MouseLeave, die Eigenschaft VisualEffect sowie eine Reihe anderer Änderungen der Benutzeroberfläche, die im nächsten Abschnitt beschrieben werden. Das Formular finden Sie als UIChanges.SCX auf der Begleit-CD.

Abbildung 1. Was ist neu bei den Formularen? - Dieses Formular demonstriert einige der Änderungen der Kontrollelemente und anderer Eingabetechniken, einschließlich der neuen Ereignisse MouseEnter und MouseLeave, die Eigenschaft VisualEffect für Schaltflächen und die neue Einstellung Hot Tracking für die Eigenschaft SpecialEffect.

Einige Änderungen bei den Grids behandeln seit Langem nachgefragte Erweiterungen. Die Eigenschaft WordWrap wurde dem Header-Objekt hinzugefügt, so dass die Header nicht mehr auf eine Zeile beschränkt sind. Im Formular in Abbildung 2, das Sie auf der Begleitdiskette als GridSample.SCX finden, ist WordWrap für die erste Spalte auf .T., für die anderen Spalten auf .F.  gesetzt.

Abbildung 2. Neue Features des Grid - Spaltenüberschrifen können bei Bedarf gewrappt werden. Zusätzlich können Sie herausfinden, ob es eine Änderung an der Spalte oder an der Zeile war, die BeforeRowColChange oder AfterRowColChange ausgelöst hat.

Bereits seit Visual FoxPro haben sich die Entwickler gefragt, weshalb die Ereignisse BeforeRowColChange und AfterRowColChange nicht in die getrennten Ereignisse BeforeRowChange, BeforeColChange, AfterRowChange und AfterColChange aufgeteilt waren. Obwohl VFP 7 nicht so weit geht, macht es die neue Eigenschaft RowColChange einfach, festzustellen warum die beiden Ereignisse ausgelöst werden. Sie enthält einen Wert, der anzeigt, was geändert wurde: die Zeile (1), die Spalte (2), beides (3) oder nichts (4). Im Formular in Abbildung 2 wird eine Messagebox angezeigt, die mitteilt, was ausgelöst wird. Hier der Code:

LPARAMETERS nColIndex
 
#DEFINE MB_ICONINFORMATION      64      && Information message
 
LOCAL cWhatChanged
 
DO CASE
CASE This.RowColChange = 0
   cWhatChanged = "nothing has"
CASE This.RowColChange = 1
   cWhatChanged = "row only has"
CASE This.RowColChange = 2
   cWhatChanged = "column only has"
CASE This.RowColChange = 3
   cWhatChanged = "row/column have"
ENDCASE
MESSAGEBOX("In AfterRowColChange - " + cWhatChanged + " changed", ;
"Grid Information",;
MB_ICON INFORMATION)
 
RETURN

Eine andere neue Eigenschaft, die den Code betrifft, den Sie schreiben müssen, ist hWnd, die den Formularen und Toolbars hinzugefügt wurde. Diese Eigenschaft enthält immer den Handle des Formulars oder der Toolbar. Sie kann in den Funktionen des Windows API genutzt werden. In älteren Versionen müssen Sie mehrere Funktionsaufrufe starten, um diese Information zu erhalten. Abbildung 3 zeigt ein Formular, das seine hWnd an eine API-Funktion übergibt und sich selbst in einen Kreis verwandelt. Den Code des Formulars wie er aus dem Klassenkatalog exportiert wurde, sehen Sie weiter unten (ich danke dabei David Frankenbach, der mir diese Technik gezeigt hat). Auf der Begleitdiskette finden Sie das Formular unter MkCircle.SCX.

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