Bei der Softwareentwicklung kann die Oberflächenentwicklung viel Zeit in Anspruch nehmen. Mit den geeigneten Technologien kann jedoch so mancher Fallstrick überwunden und sogar das Laufzeitverhalten der Applikation verbessert werden.
Um auf Oberflächenobjekte zugreifen zu können, braucht der Entwickler etwas um es "greifen" zu können. In CONZEPT 16 bilden die sogenannten Deskriptoren (engl. Handle) den "Griff" für alle Arten von Objekten, so auch für Oberflächenobjekte.
Eine einfache, jedoch veraltete, Variante den Deskriptor eines Oberflächenobjektes zu ermitteln sieht so aus:
$<Objektname>
Dieser Ausdruck gibt den Deskriptor eines Oberflächenobjektes zurück. Bei jedem Ausführen dieses Ausdrucks wird in den geladenen Dialogen nach einem Objekt mit dem angegeben Namen gesucht.
Der ermittelte Deskriptor kann direkt in einer Anweisung verwendet werden, beispielsweise so:
$edNameFirst->wpHelpTip # 'Vorname';
Die $-Schreibweise ist im Prinzip eine Kurzform des folgenden Ausdrucks:
<Startobjekt>->WinSearch('<Objektname>')
Beispiel
tWinEdit # tWinFrame->WinSearch('edNameFirst');
Die Funktion WinSearch()
sucht im Startobjekt nach einem Objekt mit dem übergebene Namen. Im Gegensatz zur $-Schreibweise, muss hier immer ein Startobjekt für die Suche angeben werden. Die Vorteile der Funktion WinSearch()
gegenüber der $-Schreibweise sind, dass der Objektname zur Laufzeit dynamisch bestimmt werden kann und das er Platzhalterzeichen (Wildcards) enthalten darf.
Bei den beiden erwähnten Varianten ist aber Folgendes zu beachten: Wird kein Objekt mit dem angegeben Namen gefunden, ergibt der Ausdruck den Wert 0 (Null) und ein Zugriff auf dieses nicht vorhandene Objekt resultiert in dem Laufzeitfehler "Deskriptor ungültig".
Wird ein Dialog im Laufe des Entwicklungsprozesses angepasst, ist dies ein typischer Fehler, der jedoch mit einfachen Mitteln umgangen werden kann.
Mit dem with
-Konstrukt wird eine logische Verbindung von der Prozedur zu den Dialogen, die sie verwendet hergestellt. Das heißt, dass die Prozedur sich nur dann fehlerfrei übersetzen lässt, wenn die referenzierten Objekte auch tatsächlich vorhanden sind. Dadurch wird verhindert, dass ein Oberflächenobjekt innerhalb einer Prozedur referenziert wird, das gar nicht vorhanden ist, weil es umbenannt oder gelöscht wurde.
Ein weiterer Vorteil der Referenzierung mit einem with
-Konstrukt ist, dass der Deskriptor schneller ermittelt werden kann, als bei der $-Schreibweise. Welches Objekt referenziert wird, wird nämlich schon beim Übersetzen der Prozedur hinterlegt, so dass nicht bei jedem Zugriff darauf danach gesucht werden muss.
Die Verwendung sieht wie folgend aus:
with <Dialogname> ... $:<Objektname> ...
Beispiel
with Contact $:edNameFirst->wpHelpTip # 'Vorname';
Zu beachten ist der Doppelpunkt zwischen dem $-Zeichen und dem Objektenamen!
Soll mehrfach auf Oberflächenobjekte zugegriffen werden, kann alternativ auch die folgende Schreibweise verwendet werden:
with <Dialogname>
{
... $:<Objektname> ...
... $:<Objektname> ...
}
Beispiel
with Contact
{
$:edNameFirst->wpHelpTip # 'Vorname';
$:edNameFirst->wpLengthMax # 40;
$:edNameLast->wpHelpTip # 'Nachname';
$:edNameLast->wpLengthMax # 40;
}
Egal ob die Referenzierung von Oberflächenobjekten mit oder ohne with
-Konstrukt vorgenommen wird: Vorraussetzung ist natürlich, dass der Dialog, in dem die Objekte enthalten sind, geladen ist.
Wird die Objektstruktur eines Dialoges verändert, auf dessen Objekte innerhalb einer Prozedur per with
-Konstrukt zugegriffen wird, muss diese Prozedur nach dem Speichern des Dialoges erneut übersetzt werden. Ansonsten tritt beim Zugriff auf ein per with
referenziertes Objekt der Laufzeitfehler "Frame abweichend" auf.
4 Antworten
Sehr gute Idee! Halte ich für sehr sinnvoll.
Praktisch wäre in manchen Situationen auch eine Präfix-Syntax. Warum nicht z.B. den OK-Butten in mehreren verschiedenen Frames über $frm1:Ok->wpBlabla und $frm2:Ok->wpBlabla oder ähnlich referenzieren.
Dadurch könnten gleich mehrere Anwendungsfälle adressiert werden:
1) Kurze ad-hoc Validierung von nur wenigen Controls
2) das Einbinden verschiedener Frames könnte man u. U. mittels eines Define erledigen
3) bei der Verwendung mehrerer Frames würde eine unübersichtliche Verschachtelung wie bei den With-Konstrukten vermieden
Bonus: Es wäre ähnlich zur Präfix-Syntax bei den Prozeduren – LIB.Library:fun(A, B, …)
@Fabian
Vielen Dank für die Anregung. Wir nehmen das gerne als Vorschlag auf.
Uns gefallen die Vorteile des With-Konstrukts, da dadurch unnötige Laufzeitfehler vermieden werden können.
Allerdings haben wir bisher auf deren Anwendung mehrheitlich verzichtet, da uns das Ganze etwas umständlich dünkt. In einer Prozedur mit hunderten von Events muss das With-Konstrukt für jeden Event separat aufgeführt werden.
Wir würden es begrüssen, wenn der zugrundeliegende Dialog (vorteilhaft sogar mehrere, vorausgesetzt es wird mit eindeutigen Objektnamen gearbeitet) einmalig eingangs Prozedur gesetzt werden könnte. So ähnlich wie ein Include, z.B. "@F:frmContact".