Virtual OS/2 International Consumer Education
VOICE Homepage: http://de.os2voice.org
Dezember 2002

[Inhaltsverzeichnis]
[Vorherige Seite] [Nächste Seite]
[Artikelverzeichnis]

editor@os2voice.org


DrDialog, oder wie ich lernte, REXX zu lieben - Teil 4

Von Thomas Klein © Dezember 2002

Ein herzliches "Willkommen zurück" von jemandem, der noch immer überwältigt ist von den Eindrücken der diesjährigen Warpstock Europe! Diesen Monat wird uns DrDialog einen Einblick in die Grundlagen der GUI-Entwicklung (mit REXX) geben, denn wir schauen uns die Komponenten an, die zum Standardumfang einer jeden grafischen Benutzeroberfläche gehören - ungeachtet der Plattform.

Aber zuerst kümmern wir uns um die 'Hausaufgaben' von letztem Monat... wie man REXXs strip()-Funktion verwendet, um führende/folgende Leerzeichen aus einer Zeichenkette zu entfernen. Wie in der Hilfedatei REXX.INF bereits angegeben ist, lautet die Syntax:

STRIP(String1 [,option] [,zeich])

Zur Erinnerung - eckige Klammern bezeichnen optionale Argumente:
[zeich] gibt das Zeichen an, das aus String1 entfernt werden soll, und ist standardmäßig SPACE (also das Leerzeichen) - wenn Sie also hier kein Zeichen explizit angeben, wird strip() Leerzeichen entfernen.
[option] ist ein optionaler Befehl, mit dem Sie angeben können, welche Art des angegebenen Zeichens aus String1 entfernt werden soll: Führende ("Leading"), Folgende ("Trailing") oder Beide ("Both"). Von diesem Befehl muß nur der erste Buchstabe angegeben werden (z.B. "L" für 'leading'; also 'führende' Zeichen). Die Standardvorgabe für diesen Parameter ist 'Both' und strip() entfernt damit sowohl führende als auch folgende Zeichen vom Typ [zeich]. Fassen wir es kurz:
Wenn Sie führende und folgende Leerzeichen aus String1 entfernen wollen, brauchen Sie nur anzugeben:

STRIP(String1)

Da es sich bei strip() um eine Funktion handelt, gibt es auch einen Rückgabewert. Genau genommen gibt sie die Zeichenkette zurück, die (in unserem Fall) von den Leerzeichen befreit wurde. Wir müssen also entweder eine Variable angeben, die den Rückgabewert entgegennimmt

NEUSTRING = STRIP(String1)

oder sie im Rahmen einer anderen Anweisung einsetzen, wie bspw. SAY die lediglich das Ergebnis anzeigt wie in

SAY STRIP(String1)

Un um zu verdeutlichen, wie das im Rahmen unseres letztmonatigen Beispiels auszusehen hätte, hier die Version 1 mit 'Zwischenvariablen':

Grusstext = Auswahl.Item( Auswahl.Select() )
Grussname = strip( Eingabe.Text() )
call ausgabe.text( Grusstext || " " || Grussname || "." )

...oder...

Grusstext = Auswahl.Item( Auswahl.Select() )
Grussname = Eingabe.Text()
call Ausgabe.text(Grusstext || " " || strip( Grussname ) || ".")

Zu guter letzt noch Version 2, die (falls Sie dies bevorzugen) dasselbe mittels des 'spektakulären' Einzeilers macht:

call Ausgabe.text( Auswahl.Item( Auswahl.Select() ) || " " || strip( Eingabe.text() ) || "." )

So weit so gut. Wenn Sie Ihre REXX-Programmierungskenntnisse ausbauen, werden Sie strip() wahrscheinlich etwas häufiger über den Weg laufen. Lassen Sie uns aber nun auf das konzentrieren, was wir heute eigentlich besprechen wollten:

GUI Grundbestandteile

Wie ich letzten Monat bereits bemerkte, kann die Darstellung je nach Plattform unterschiedlich ausfallen. In den meisten Fällen werden Sie diese Komponenten aber immer daran wiedererkennen können, wie Darstellung und Verhalten miteinander 'verzahnt' sind... es handelt sich um:

Anm.: Wir werden hier absichtlich die englischen Begriffe verwenden, da innerhalb von DrDialog auch diese Bezeichnungen verwendet werden.

Natürlich gibt es eine Vielzahl weiterer Komponenten, aber diese hier stellen den absolut kleinsten 'gemeinsamen Nenner' dar, wenn man OS/2 Warp, Windows (3.x bis 2K) und die Macs in Betracht zieht. Für das Linux-GUI und BeOS kann ich es nicht mit Sicherheit sagen, da ich mich nie getraut habe, es mir so genau anzuschauen <g>, aber wenn's dort ein GUI gibt, hat es mit Sicherheit (auch) diese Bestandteile. Sogar in Java oder der 'Formulardarstellungen' Ihres Webbrowsers werden Sie diese Komponenten wiederfinden! Und zu Zeiten von DOS, als man begann, die  Bildschirmmasken von zeichenorientierten Programmen mit 'einer Art' von GUI auszustatten, waren sie bereits präsent in Produkten wie den Norton Utilities oder PCTools.

Die "HUI"s und "PFUI"s von GUI:

Nun, die meisten unter uns benutzen diese Komponenten schon sehr lange fast intuitiv, ohne sich darüber großartige Gedanken zu machen. Wahrscheinlich haben Sie sogar schon ein gutes "Gespür" dafür, welche Komponenten man einsetzen würde, um bestimmte Anforderungen umzusetzen. Aber lassen Sie mich Ihnen sagen, daß gesunder Menschenverstand in der Programmierung von grafischen Oberflächen scheinbar doch nicht jedem einfach so in die Wiege gelegt wird. ;) So gibt es da draußen einige lustige Zeitgenossen, die lustige Sachen mit GUI-Komponenten veranstalten und sich dabei nicht im geringsten durch die ungeschriebenen Gesetze der 'GUI-Ethik' einschüchtern lassen. Eines von vielen klassischen Beispielen dafür ist 'Optionbutton oder Checkbox'.
Im Grunde sind 'option buttons' dafür da, sich gegenseitig ausschließende Optionen zu kennzeichnen - solche also, bei denen man sich immer nur für eine entscheiden kann. Daher werden diese Komponenten auch RADIO BUTTONS genannt, in Anspielung an die Stations- oder Modulationsauswahlschalter an den alten Radios: Wenn man einen davon nach unten drückte, sprang der vorher gedrückte Knopf wieder zurück nach oben. Ein typisches Beispiel für den Einsatz von radio buttons wäre folgende Frage:

radio button example

Die 'checkbox' wiederum dient zur Kennzeichnung von Optionen, die man beliebig und unabhängig voneinander kombinieren kann, beispielsweise:

checkbox example

Was nun die angesprochenen Zeitgenossen so 'lustig' macht, ist Ihre totale Ignoranz hinsichtlich der eingebauten Logik von Verhalten, Aussehen und Benutzersteuerung, die sich bereits in den Komponenten verbirgt. Natürlich steht es Ihnen frei, sich sämtlicher Möglichkeiten zu bedienen, die Ihnen durch den Einsatz dieser Komponenten zur Verfügung stehen. Wenn Sie sich das Leben unnötig schwer machen wollen, können Sie auch eine Gruppe von radio buttons auf Basis von checkboxen zusammenstricken... dennoch gibt es Sachen, die man besser vermeiden sollte wie...

the don't example #1 links: Scheinbar ein Programmierer, der einer strengen Validierung den Vorzug gibt vor dem Einsatz der geeigneten Komponente, die das bereits in sich trägt. Zwei radio buttons, von denen einer standardmäßig vorgewählt ist, hätten einiges an 'code-Arbeit' erspart...

unten: Eine meiner bevorzugten 'Schwachsinns-GUI's. Um deren "Hirnrissigkeit" in Gänze verstehen zu können, habe ich noch nicht einmal den Einsatz einer kleinen Animation gescheut:

the don't #2 example

PUSHBUTTON -Aussehen und Verhalten

Ziemlich leicht zu benutzen - die Default-Option im Style-Dialog eines pushbuttons bewirkt, daß die Schaltfläche das Drücken der <ENTER>-Taste in einem Dialogfenster 'abfängt', auch wenn die Schaltfläche gar nicht das aktive control ist. No pointer focus verhindert, daß das kleine 'focus'-Rähmchen um die Aufschrift der Schaltfläche nicht gezeichnet wird, wenn man mit der Maus auf diese Schaltfläche geklickt hat. Wurde die Schaltfläche mittels <TAB>-Taste angewählt, wird der 'focus' nach wie vor angezeigt. No border bewirkt, daß die Schaltfläche fast wie eine Textbox aussieht - mit dem Unterschied, daß der 'Versatzeffekt' beim Anklicken bestehen bleibt.

PUSHBUTTON -Ereignisse und Methoden

Man glaubt es kaum: Es gibt tatsächlich ein click-Ereignis für pushbuttons! ;) Davon abgesehen gibt es das INIT-Ereignis, das wir bereits aus unserem Textbox-Beispiel kennen und ein Ereignis namens DROP, welches immer dann ausgelöst wird, wenn ein anderes DrDialog-Objekt auf die Schaltfläche gezogen und abgelegt wurde. Drag-und-Drop (Ziehen und Übergeben) erfordert allerdings noch ein paar andere Dinge und obwohl 'DnD' sehr nützlich und mit DrDialog leicht zu bewerkstelligen ist, werden wir uns seiner zu einem späteren Zeitpunkt widmen.

CHECKBOXES - Aussehen und Verhalten

checkbox style dialogMit DrDialog wirklich einfach zu benutzen: Im Grunde kann eine checkbox ("Ankreuzkästchen") sich in einem von 3 verschiedenen Zuständen befinden: unchecked (nicht angekreuzt), checked (angekreuzt) und undetermined (unbestimmt), bei dem die Ankreuzfläche grau schattiert dargestellt wird. In den meisten Fällen werden aber die zwei Zustände checked/unchecked reichen. Wenn Sie tatsächlich den dritten Zustand 'unbestimmt' benötigen, wählen Sie im Style-Dialog der checkbox die Option 3state aus. Die weitere Bearbeitung von Events (Ereignissen) gestaltet sich äußerst einfach (da nämlich keine nötig ist), wenn Sie die Option Auto aus dem Style-Dialog der checkbox verwenden, was standardmäßig auch der Fall ist.

Hierdurch bewegt sich die checkbox bei jedem Klick automatisch zwischen den Zuständen hin und zurück (bzw. bei 3 Zuständen immer reihum). Wenn Sie Auto deaktivieren, müssen Sie sich selbst um die benötigte Programmlogik auf Basis des Click-Ereignis bemühen. Beachten Sie, daß der Zustand undetermined nur dann zur Verfügung steht, wenn die Option 3state aktiviert wurde. Auch 'manuelle Anweisungen' im Programmcode können dies dann nicht bewerkstelligen - die Box wird dann schlicht angekreuzt. Der zu einer checkbox angezeigte Text wird entweder über die Auswahl TEXT im Kontextmenü zur Entwicklungszeit oder mittels der Funktion/Anweisung TEXT() zur Laufzeit festgelegt, wie wir das bereits im letzten Monat mit unserer Textbox kennengelernt haben.

CHECKBOXES - Ereignisse und Methoden

Wie alle anderen controls, so erzeugt auch die CHECKBOXES ein DROP Ereignis, wenn man ein Objekt darauf ablegt. Da wir Drag-und-Drop etwas später in dieser Serie besprechen werden, bleiben noch zwei Ereignisse übrig: INIT (kennen wir schon, oder?) und CLICK. Das CLICK-Ereignis ist dann sehr nützlich, wenn man eine bestimmte Abhängigkeit von Optionsgruppen darstellen will, wenn diese ansonsten zu unübersichtlich geraten würden... ich versuche mal, ein Beispiel anhand einer Animation zu geben:

gui effects sample

Sowohl das Abfragen als auch das Setzen des Status einer checkbox wird mittels der SELECT-Methode bzw. Eigenschaft erledigt. Um den Status einer checkbox abzufragen (also, ob Sie angekreuzt ist oder nicht), verwenden Sie einfach SELECT in der 'funktionalen' Schreibweise

zustand = meineCheckBox.select()

wodurch zustand dann entweder 0 (null) enthält, wenn die checkbox nicht angekreuzt ist, respektive 1 (eins), wenn sie es ist, - oder auch 2, wenn sie sich im 'unbestimmten' Zustand befindet (und dies mittels der Option 3state vorher auch ermöglicht wurde). Wenn Sie den Zustand sofort auswerten wollen, indem Sie z.B. etwas bestimmtes machen wollen, wenn die box angekreuzt ist, können Sie das im Rahmen einer IF-Anweisung tun wie z.B.:

if meineCheckBox.select() = 1 then say 'JA - wurde angekreuzt'

Um den Zustand einer checkbox aus dem Programm heraus zu setzen (z.B. anhand gespeicherter Einstellungen aus einer .INI-Datei), verwenden Sie 'Befehls'-Schreibweise:

call meineCheckBox.select 1

...wodurch die checkbox angekreuzt wird. Analog zu den Rückgabewerten der Funktion, verwenden Sie hier den Wert 0 (null) anstelle von 1 (eins) um die checkbox 'abzukreuzen' oder 2, wenn Sie den 'unbestimmten' Zustand setzen sollen. Letzteres geht wie gesagt nur dann, wenn Sie im Style-Dialog die Option 3state ausgewählt hatten. Das wär's schon zu den checkboxen. Natürlich gibt es noch mehr Möglichkeiten, checkboxen zur Laufzeit zu beeinflussen, wie die VISIBLE-Funktion zum Anzeigen/Verstecken oder das Aktivieren und Deaktivieren mittels der Anweisungen ENABLE, DISABLE oder die ENABLED-Funktion, aber dies betrifft alle Typen von controls und daher werden wir uns das am Ende dieses Artikels nochmals im Detail anschauen.

RADIO BUTTONS - Aussehen und Verhalten

Mit DrDialog ist das Verwenden von radio buttons spielend leicht. Alles, was Sie zur Entwicklungszeit machen müssen, um eine Gruppe von sich gegenseitig automatisch ausschließenden Optionen zu erstellen, ist, die gewünschten radio buttons in Reihe zu setzen - vorzugsweise untereinander, um eine bessere Übersichtlichkeit zu erreichen. Die Reihenfolge der Optionen (per <TAB>-Taste) wird von DrDialog zur Laufzeit automatisch anhand der IDs ermittelt.

radio group sample 1

Wenn Sie zwei (oder mehrere) unabhängige Gruppen von mehreren Optionen erreichen wollen, wird DrDialog dies aber nicht automatisch erkennen und alle radio buttons als Bestandteile einer einzelnen großen Gruppe ansehen... außer, Sie teilen ihm mit, wie sich die Gruppen jeweils zusammensetzen. Das erreichen Sie, indem Sie entweder

ein beliebiges anderes Element (wie eine einfache textbox) zwischen die Gruppen setzen oder indem Sie einen 'Gruppe'-Rahmen um die jeweiligen Optionen  ziehen, wenn Sie dies von seiner optischen Wirkung bevorzugen:
separating radio groups with label separating radio groups with frame

Auch bei den radio buttons können Sie die Auto-Option im Style-Dialog deaktivieren, wenn Sie es bevorzugen, die "Drecksarbeit" selbst zu übernehmen. Wenn also Auto deaktiviert ist, müssen Sie sich um das an- und abwählen der einzelnen Optionen innerhalb einer Gruppe selbst kümmern - speziell, was das gegenseitige Ausschließen angeht. Viel Spaß, sage ich nur. Ansonsten übernimmt DrDialog die Aufgabe, immer nur eine einzelne Option innerhalb einer Gruppe wählbar zu machen, d.h. eine evtl. vorher ausgewählte Option abzuwählen.

RADIO BUTTONS - Ereignisse und Methoden

Das läuft genau wie bei den checkboxen: Click, Init und Drop. Punkt. Die 'Zustände' sind aber noch einfacher zu kontrollieren als bei den checkboxen, da wir es hier wirklich nur mit zwei Arten zu tun haben, denn einen 'unbestimmten' Zustand gibt es bei den radio buttons nicht. Gott sei Dank - ich frage mich, was unsere lustige Zeitgenossen damit noch alles anstellen würden... um also den Zustand eines radio buttons abzufragen, bedienen wir uns wieder der Funktion SELECT:

zustand = meineOption1.select()

Luxus pur: Wird ein nicht ausgewählter radio button zur Laufzeit mittels SELECT angewählt, sorgt DrDialog dafür, daß ein vorher angewählter anderer radio button der selben Gruppe automatisch ABgewählt wird. Okay, macht Sinn. Wenn Sie aber mittels SELECT einen bis dato ANgewählten radio button ABwählen, wird nicht etwa automatisch ein anderer radio button angewählt. Im Grunde ist das aber auch logisch, denn DrDialog kann ja nicht ahnen, welcher radio button angewählt werden soll. Auch, wenn die Gruppe nur aus zwei Optionen besteht, erfolgt kein automatisches anwählen der anderen Option.... gut: Um den Zustand eines radio buttons zur Laufzeit zu beeinflussen, verwenden wir SELECT in der CALL-Notation und analog zu den checkbox-Zuständen gilt auch hier wieder einfach 0 = abgewählt, 1 = ausgewählt:

call meineOption1.select 1

Damit wird meineOption1 ausgewählt und alle anderen radio buttons, die sich in der selben Gruppe befinden, wie meinOption1, würden abgewählt. Eigentlich kümmert man sich meisten nie um den Zustand eines einzelnen radio buttons, sondern ist vielmehr daran interessiert, WELCHER radio button einer Gruppe jeweils ausgewählt ist, nicht wahr? Tja - dafür gibt es in DrDialog leider keinen eingebauten Weg, aber man kann z.B. allen Optionen einen eindeutigen Wert zuordnen und mittels einer Variable sich den Wert des jeweils gerade angeklickten radio button merken. Ein anderer Weg ist, dieses Verfahren mittels der focus()-Eigenschaft zu verfeinern, aber das nehmen wir später durch...

TEXTBOX - Aussehen und Verhalten

Na, die kennen wir doch schon, oder? Wenn man sich die Optionen zur Textausrichtung ("Alignment") im Style-Dialog anschaut, könnte man nicht auf die Idee kommen, daß es dort irgendwelche versteckte Geheimnisse gibt... es gibt allerdings etwas, das man beachten sollte: Die Abhängigkeiten zwischen der Option Word break und der vertikalen Ausrichtung. Wenn Sie eine Textbox anlegen, die eine mehrzeilige Anzeige verwendet, müssen Sie die vertikale Ausrichtung  TOP verwenden, sonst klappt es nicht. Schauen Sie sich einmal die beiden Abbildungen an, dann verstehen Sie was ich meine:

word wrap right

oben: Das ist korrekt - Text wird vollständig und mehrzeilig angezeigt  /  unten: Wegen des 'Vertical alignment'wird der Text nur auf einer Zeile (und somit unvollständig) angezeigt...

word wrap wrong

Die Option horizontal alignment hat allerdings keinen Einfluß auf word break und funktioniert wie erwartet.
Um ein control 'deaktiviert' erscheinen zu lassen, können Sie die Option Disabled in dessen Style-Dialog aktivieren. Hierdurch reagiert das jeweilige control dann nicht mehr auf benutzeraktionen und wird 'blass' dargestellt. Sie können aber auch hier wieder alle Prinzipien des GUI über Bord werfen ;-) und stattdessen die Option Halftone verwenden, die ebenfalls den selben optischen Effekt erzielt, das control selbst aber AKTIV lässt. Das wäre unter Umständen dann von Nutzen, wenn das control deaktiv aussehen, aber trotzdem auf die Aktion des Benutzers reagieren soll. Allerdings kennt die textbox aber nur eine Art von Benutzerereignis: Das Ablegen eines Objekts. Ich bin kein Freund solcher Dinge wie das Auslösen einer Aktion mittels des Ablegens eines Objekts auf ein deaktiviertes control, aber... vielleicht teilen Sie nicht meinen ethischen Standpunkt in GUI-Grundlagen. Vielleicht werden Sie aber auch irgendwann einmal mit einer Situation konfrontiert, wo nur DAS Ihnen hilft - und da ist es gut zu wissen, das so etwas zumindest möglich ist.

TEXTBOX - Ereignisse und Methoden

Im Gegensatz zu vergleichbaren controls in anderen Entwicklungsumgebungen, erzeugt die textbox in DrDialog kein click-Ereignis... wozu auch? Welchen Sinn soll es machen, auf einen Text zu klicken? Na gut - jemand könnte einen URL-Link simulieren, indem er einen unterstrichenen Text anzeigt und beim Klick darauf den Webbrowser startet, aber das kann man sicher auch anders bewerkstelligen. Bleibt also nur nur das INIT-Ereignis, das wir schon kennen und das DROP-Ereignis, welches wir später besprechen werden.

ENTRY FIELD - Aussehen und Verhalten

Zur Textausrichtung brauche ich - glaube ich - nichts zu sagen. Schauen wir uns lieber einmal die anderen Sachen an, mit denen man lustige Verhaltensweisen erreichen kann: Von der Option Auto scroll zum Beispiel sollte man meiner Meinung tunlichst die Finger lassen. Wenn Ihre Eingaben länger sind als die Anzeigegröße eines entry fields, dann sorgt diese Option in ihrem aktivierten Standardzustand nämlich dafür, daß der Inhalt eines entry fields immer so verschoben wird, daß man sehen kann, was man gerade tippt. Wird diese Option deaktiviert, müssen Sie Ihre Eingaben 'blind' tätigen. Lustig. ;)

Die Option read only ist relativ selbsterklärend, jedoch auch nennenswert: Wenn Sie ein entry field mittels 'disabled' deaktivieren, werden dessen Inhalte in 'halftone' dargestellt, was manchmal zu einer sehr schlechten Lesbarkeit führt. Wenn Sie also erreichen wollen, daß man in einem entry field zwar nichts eingeben, dessen Inhalte dafür aber zumindest vernünftig lesen kann, ist read only genau die Option Ihrer Wahl.

Margin (Rand) gibt lediglich an, ob ein Rand um das Eingabefeld gezogen werden soll und ist nicht zu verwechseln mit dem Begriff 'margin', der normalerweise Textränder betrifft (was der Grund dafür ist, daß ich denke, 'margin' war eine schlechte Wahl verglichen mit 'border'... aber jetzt wissen Sie ja, was es bedeutet).

Unreadable bewirkt, daß Sternchen anstelle der vom Anwender eingegebenen Zeichen angezeigt werden. Also der sogenannte 'Passworteingabe-Effekt'. Aber das ist noch nicht alles: Haben Sie schon einmal versucht, den Inhalt eines 'passwortfeldes' mittels Kopieren und Einfügen in - beispielsweise - den Editor zu übertragen? Das geht nicht. Glücklicherweise. Ich kenne einige 'handgestrickte' Dialoge, die das nicht berücksichtigten - was zu einer lächerlichen Farce von Sicherheit führte... glücklicherweise ist das mit DrDialog (und allen anderen Entwicklungstools, die mir begegnet sind) nicht so und das Kopieren eines eingegebenen Texts wird unterbunden, wenn die Option unreadable verwendet wird. Das Einfügen von Text in ein solch definiertes feld ist allerdings natürlich nach wie vor möglich.

Auto tab und Max length spielen auf bestimmte Art und Weise zusammen: Max length gibt die maximale Länge des eingebbaren Texts an. Wird hier beispielsweise 5 angegeben, kann der Anwender keine Eingabe machen, die mehr als 5 Zeichen lang ist (Leerzeichen eingeschlossen). Wenn zusätzlich Auto tab ausgewählt wurde, springt der Cursor automatisch in das nächste Feld oder das nächste Control, wenn die angegebene Höchstgrenze an Zeichen erreicht wurde. Beispiel:
Sie haben ein Bestellformular entwickelt. Im ersten Feld muß eine 5-stellige Artikelnummer eingegeben werden, dann eine Mengenanzahl und schließlich der Stückpreis. Wenn Sie für das Artikelnummerfeld die Option auto tab setzen, braucht der Anwender nach Eingabe der fünfstelligen Artikelnummer nicht mittels <TAB>-Taste oder Mausklick in das nächste Feld zu wechseln, sondern DrDialog steuert das automatisch anhand der ID-Nummer der Felder. Eine extrem nützliche Funktionalität für Datenerfassungsdialoge!

DBCS bedeutet 'double byte character set' und bezeichnet Zeichensätze, bei denen zwei Byte für die Speicherung eines Zeichens verwendet werden, wie z.B. für Chinesisch. SBCS (single byte character set) ist das, was wir im Allgemeinen gewohnt sind: Zeichensätze, die nur 1 Byte benötigen, um einen Buchstaben (oder ein beliebiges anderes Zeichen) zu speichern. Die SBCS/DBCS-Optionen werden wir später noch besprechen - vorausgesetzt ich finde jemanden, der erst einmal MIR beibringt, um was es da genau geht - sorry.

ENTRY FIELD - Ereignisse und Methoden

Abgesehen von den Ereignissen INIT und DROP gibt es noch andere Ereignisse, die durchaus interessant an den Eingabefeldern sind: OVERFLOW zum Beispiel wird dann ausgelöst, wenn der Anwender im Eingabefeld eine Taste gedrückt hat, durch die der Inhalt länger würde, als durch die Option Max Length (die wir gerade besprochen hatten) festgelegt.

Changed wird immer ausgelöst, wenn sich der Inhalt des Eingabefelds geändert hat. Das betrifft wohlgemerkt aber nur den Inhalt des Feldes - so würde dieses Ereignis nicht ausgelöst, wenn der Anwender beispielsweise nur einen Bereich des eingegebenen Textes markiert hätte.

Scrolling ist witzig: Dieses Ereignis tritt ein, wenn der Inhalt des Eingabefelds verschoben wird, um dem Anwender seine aktuelle Schreibposition ersichtlich zu machen. Witzig daran ist die Tatsache, daß das "scrollen" nicht zeichenweise ein ums andere mal geschieht, sondern in 'Häppchen' zu je drei Zeichen. Momentan habe ich keine Ahnung, wozu man dieses Ereignis nutzen könnte. Hm.

Für GetFocus und LoseFocus muss ich etwas weiter ausholen: Der focus ist eine Art systemeigener Kenner, der angibt, welches control gerade innerhalb eines Dialoges aktiv ist und somit die primäre Steuerung übernimmt. Vielleicht haben Sie schon einmal das kleine, aus einer gepunkteten Linie bestehende Rechteck bemerkt, welches sich z.B. um den Text einer Schaltfläche herum befindet... das ist die Kennzeichnung dafür, daß diese Schaltfläche das momentan aktive control ist ("den Fokus hat"). Das Ereignis GetFocus tritt nun auf, wenn Ihr Eingabefeld soeben zum aktiven control geworden ist, weil der Anwender entweder mit der <TAB>-Taste dorthin gewechselt hat oder den Mauszeiger auf das Feld bewegt und dann geklickt hat. Häufig wird dieses Ereignis dafür verwendet, den gesamten gerade enthaltenen Text des Feldes auszuwählen (das Drücken einer Taste wird dann zuerst den 'alten' Inhalt des Feldes löschen). Das LoseFocus-Ereignis wiederum tritt ein, sobald der Anwender per Tastatur oder Maustaste ein anderes control angewählt hat. Es wird normalerweise verwendet, um eine Prüfung der im Feld eingegebenen Daten vor deren weiterer Verarbeitung durchzuführen (z.B. Datumsformat prüfen).

Die Steuerung und Verwendung eines entry fields aus dem Programmcode heraus ist nicht allzu schwer, da Sie ohnehin meist nur die Funktion text() benutzen werden. Mittels der Funktion RANGE können Sie zur Laufzeit das machen, was Sie zur Entwicklungszeit mittels der Option Max length machen, nämlich die maximale Eingabelänge festlegen (oder abfragen). Dies ist ganz nützlich, denn ansonsten müssten Sie dies durch entsprechendes Setzen der Bits in der Style-Maske tun, was ein wenig unkomfortabel ist. Um beispielsweise zur Laufzeit den Wert für max length auf 12 zu setzen, geben Sie an:

call meineEingabe.RANGE 12

Aber es gibt noch eine weitere Funktion, die hier auf jeden Fall besprochen werden muß: Select. Hierbei handelt es sich um den Teil des Textfelds, der markiert wurde. Der Anwender kann einen Bereich des Eingabetextes (oder den ganzen Text) mittels der Umschalttaste markieren, wenn er gleichzeitig die Maus darüber bewegt oder die Cursortasten drückt. Und das ist es, worum es sich bei SELECT dreht - der Programmierer kann damit den markierten Bereich des Texts ermitteln, denn es werden zwei Werte geliefert: Der Index des ersten markierten Zeichens (1 ist der erste Buchstabe im Eingabefeld usw.) sowie die Gesamtanzahl der markierten Zeichen.
Wenn der Anwender beispielsweise den Teil 'all' aus dem Wort 'Hallo' markiert hätte, würde die Funktion SELECT zurückgeben: '2 3' (ohne die Hochkommata).
Wie immer, so verwenden Sie auch SELECT anhand seiner CALL-Aufrufart um den ausgewählten Bereich eines Eingabefeldes zu setzen. Alles, was Sie angeben müssen, sind die Stelle des ersten markierten Zeichens im Eingabefeld und die Gesamtanzahl der markierten Zeichen (= die Länge). Wenn Sie als Länge 0 (null) angeben, wird der komplette Inhalt de-markiert. Um den gesamten Inhalt eines entry fields namens meineEingabe zu markieren, verwenden Sie:

call meineEingabe 0, 9999

Beachten Sie, daß beim Übergeben der Werte im Rahmen des Aufrufs ein Komma verwendet werden muß, wohingegen die Rückgabe der beiden Werte kein Komma enthält. Die Parameter '0,9999' stammen aus dem Beispiel in DrDialogs Onlinehilfe. Gut, es funktioniert, aber eigentlich macht man so etwas anders, nämlich indem man die REXX-Funktion LENGTH()verwendet:

call meineEingabe.SELECT 1, length( meineEingabe.text() )

Hier wird beim Aufruf die Länge des Inhalts von meineEingabe als Längenangabe für die Markierung verwendet. So beginnt die Markierung auf Stelle 1 und ist immer genau so lang, wie der momentane Inhalt - kein Byte zu wenig, keins zu viel. ;)

MLE - Aussehen und Verhalten

MLE's ("multi line edit fields") sind eigentlich nur gewöhnliche Eingabefelder mit speziellen Zusätzen, damit Sie mit Zeilenumbrüchen und mehrzeiligen Texten umgehen können:

  1. Sie können scrollbars (Bildlaufleisten) verwenden, damit der Anwender durch den Text blättern kann.
  2. Das Drücken von <ENTER> bewirkt einen Zeilenumbruch (bzw. man verwendet <Strg+ENTER>, wenn es einen pushbutton gibt, der die Option DEFAULT verwendet).
  3. Sie erkennen Leerstellen, damit sie mit deren Hilfe an Wortgrenzen automatische Zeilenumbrüche einfügen können (wenn man dies aktiviert hat)

Beachten Sie, daß es mitunter Kombinationen gibt, die nicht unbedingt Sinn machen: Wenn man beispielsweise word wrap aktiviert, so wird der Inhalt des MLE immer so umgebrochen, daß er in dessen momentane Anzeigegröße paßt. In diesem Fall benötigt man also eigentlich keine horizontale Scrollbar. Aber egal, es gibt etwas wichtigeres für den Gebrauch von MLEs: Die Option ignore tab. Das MLE besitzt die Fähigkeit, Tabulatorzeichen einzusetzen, um den Text zu formatieren. Wurde diese Option aktiviert, wird das Drücken der <TAB>-Taste nicht mehr vom MLE zum Einfügen eines Tabulatorzeichens verwendet, sondern (standardgemäß) um von einem Control zum nächsten zu wechseln (den 'Fokus' verändern).

MLE -Ereignisse und Methoden

Da es für MLEs keine max length-Option gibt, existiert auch kein OVERFLOW-Ereignis. Und da MLEs primär zur Verarbeitung von mehrzeiligem Text dienen, haben sie von Hause aus Scrollbars und lösen somit kein SCROLL-Ereignis aus. Übrig bleiben also INIT, CHANGED, GetFocus, LoseFocus und DROP, die wir ja vom 'normalen' entry field kennen. Bei den Funktionen sieht es ebenfalls genau so aus, wie bei den entry fields, mit Ausnahme von RANGE und SELECT: Für MLEs gibt es sie nicht.

LISTBOX - Aussehen und Verhalten

Einer der wichtigsten Aspekte beim Arbeiten mit Listboxen ist ihr SELECTION-Style: Normalerweise kann man innerhalb einer Liste immer nur einen Eintrag auswählen. Das ist der Fall, wenn man die Option single angegeben hat. Die Option multiple ermöglicht es dem Anwender, mehr als nur einen Eintrag in der Liste auszuwählen, indem er die Einträge mittels Anklicken oder dem Drücken der Leertaste an- bzw. abwählt. Die Option extended ermöglicht es zusätzlich noch, ganze Bereiche von Einträgen mittels der Umschalttaste an/abzuwählen (oder einzelne Einträge ohne die vorherige Selektion zu verlieren mittels der Strg-Taste). Beachten Sie, daß beide Optionen sowohl einzeln als auch zusammen verwendet werden können.

Owner draw deaktiviert den Standardmodus von DrDialog, die Einträge der Liste darzustellen, wodurch die Liste selbst nach dem Hinzufügen von Einträgen immer noch leer erscheint. Das 'Anzeigen' von Einträgen bleibt nun dem Entwickler überlassen. Ich glaube, daß es sich hierbei um eine Funktionalität handelt, die erst in Zusammenhang mit anderen Entwicklungsumgebungen richtig nutzbar ist, denn DrDialog kann auch dazu eingesetzt werden, 'nur' die Dialogdefinitionen zu generieren, die dann von anderen Entwicklungstools benutzt werden können. Lassen wir diese Option erst einmal außer Acht... ;)

Eine horizontal scroll bar ist dann serh nützlich, wenn der freie Platz auf Ihrem Dialog nicht ausreicht, um die Liste so 'breit' zu gestalten, daß deren Einträge vollständig lesbar sind. Vertikale Bildlaufleisten werden von Listboxen grundsätzlich zur verfügung gestellt und sind aktiv, sobald mehr Einträge in der Liste sind, als gleichzeitig angezeigt werden können.

LISTBOX - Ereignisse und Methoden

Abgesehen von INIT, dem üblichen FOCUS-Kram und DROP, gibt es drei Ereignisse, die man mit Listboxen verwenden kann:

SCROLL
Wird ausgelöst, wenn in der Liste horizontal 'gescrollt' wird - nicht beim vertikalen Blättern!
SELECT
Tritt ein, wenn der Anwender den Auswahlstatus eines Eintrag (selektiert/deselektiert) geändert hat.
ENTER
Tritt auf, wenn der Anwender einen Doppelklick auf einen Eintrag gemacht oder die <ENTER>-Taste gedrückt hat.

Als Funktionen stehen in erster Linie ADD (hinzufügen) und DELETE (Löschen) zur Verfügung, mit denen der Inhalt der Listbox bestimmt werden kann. Beachten Sie, daß keine automatische Sortierung der Listeninhalte stattfindet. Um eine bestimmte Sortierreihenfolge zu erzielen, müssen beim Hinzufügen der Einträge die entsprechenden Parameter angegeben werden. Werden keine Sortierungsparameter angegeben, erfolgt die Reihenfolge genau so, wie die Einträge in die Liste eingefügt wurden.

Keine Sortierung call meineListe.ADD neuEintrag
Aufsteigend: call meineListe.ADD neuEintrag, 'A'
oder: call meineListe.ADD neuEintrag, 'Ascending'
Absteigend: call meineListe.ADD neuEintrag, 'D'
oder: call meineListe.ADD neuEintrag, 'Descending'

Außerdem können Einträge an einer beliebige Stelle der Liste eingefügt werden (bspw. 17. Platz) ungeachtet einer evtl. vorliegenden Sortierung, indem die gewünschte Position angegeben wird:

call meineListe.add neuerEintrag, 17

Oder um beispielsweise sicherzugehen, daß ein Eintrag als letzter in die Liste aufgenommen wird:


call meineListe.ADD neuEintrag, 'L'
or call meineListe.ADD neuEintrag, 'LAST'

Die Funktion bzw. der Befehl SELECT kann dazu verwendet werden, einen bestimmten Eintrag in der Liste aus- bzw. abzuwählen. Auf den ersten Blick sieht das ziemlich kompliziert aus, wenn man Listboxtypen mit Mehrfachauswahl betrachtet, aber es ist eigentlich relativ einfach. In einer Liste mit 'single selection' (Einfachauswahl) kann immer nur ein einziger Eintrag ausgewählt sein, daher bräuchte man in diesem Fall nur

nummer = meineListe.SELECT()

zu verwenden und das wär's. Entweder enthält nummer danach den Index des ausgewählten Eintrags (wobei 1 für den ersten Eintrag der Liste steht und so weiter) oder 0 (null), wenn kein Eintrag in der Liste ausgewählt ist. Der gleiche Aufruf gibt - wenn auf eine Listbox mit Mehrfachauswahl angewendet - den Index des ersten ausgewählten Eintrags zurück (oder wieder 0, falls keiner ausgewählt wurde). Dabei spielt es keine Rolle, ob die Mehrfachauswahl auf Basis von multiple oder extended definiert wurde - für SELECT macht das keinen Unterschied. Um die restlichen evtl. ausgewählten Einträge zu ermitteln, bewegt man sich in einer Schleife durch die Liste und beginnt jeweils beim Eintrag, der dem zuvor gefundenen folgt:

nummer = meineListe.SELECT(nummer + 1, 'NEXT')

Was eigentlich auch nichts anderes macht, als den ersten ausgewählten Eintrag in der Liste zu suchen... Allerdings fängt die Suche nicht am Listenanfang an, sondern bei dem Eintrag, der dem zuletzt gefundenen Eintrag folgt. Das macht man dann so lange, bis man 0 zurück bekommt - das Zeichen für 'keine (weiteren) selektierten Einträge da'. Im Vergleich zum Durcharbeiten der gesamten Liste mit Prüfung jedes einzelnen Eintrags liegt der Vorteil dieser hier beschriebenen Methode darin, daß sie einerseits viel schneller ist und sie zweitens auch dann immer funktioniert, wenn man gar nicht weiß, wie viele Einträge überhaupt in der Liste sind. Um nun einen bestimmten Eintrag zu wählen, verwendet man

call meineListe.SELECT nummer

um den 'nummerten' Eintrag zu markieren. Gut, aber wo wir gerade bei der Anzahl der Einträge einer Liste waren... wie bekommt man das heraus? Na, mit der Funktion ITEM einer Listbox:
Damit kann man Informationen zu einem einzelnen Eintrag abrufen oder - wenn man keine Parameter übergibt - die Anzahl der Einträge herausbekommen:

anzahl = meineListe.ITEM()

Wenn Sie nun wissen möchten, wie der erste ausgewählte Eintrag einer Liste heißt, kombinieren Sie SELECT() und ITEM() auf folgende Weise:

nummer = meineListe.SELECT()
name = meineListe.ITEM( nummer )

Oder als klassischen Einzeiler:

name = meineListe.ITEM( meineListe.SELECT() )

Eine sehr nützliche Erweiterung zu den Listboxen ist die Anweisung bzw. Funktion VALUE, mit der man einen zusätzlichen Wert zu einem Listeneintrag speichern kann. Sie können sich das als eine zusätzliche, unsichtbare Spalte der Liste vorstellen. Beim Hinzufügen eines Eintrags zu einer Liste wird mittels eines Folgeaufrufs der mitzuspeichernde Wert abgelegt. Das ist dann sehr nützlich, wenn man z.B. mit Querverweisen zwischen mehreren Listboxen arbeitet. In einer späteren Ausgabe werden wir uns damit näher beschäftigen, nur so viel sei gesagt: Dieser zusätzliche Wert wird auch mittels der hier beschriebenen Funktion ITEM() in Zusammenhang mit einem weiteren Parameter abgefragt.

COMBO BOX - Aussehen und Verhalten

Eigentlich sind diese combo boxes nichts anderes als Kombinationen aus eines listbox und einem entry field... aber das ist natürlich nicht alles. ;) Die Unterschiede beginnen bereits zur Entwicklungszeit: Combo boxes können entweder eine geöffnete Liste enthalten oder eine ausklappbare Liste, die zur Laufzeit zunächst wie ein Eingabefeld aussehen, an dessen rechtem Rand sich ein 'Ausklappschalter' befindet. Während man beim ersten Typ (mit der geöffneten Liste) zur Entwicklungszeit die tatsächliche Größe der Liste festlegt, ist das beim Typ mit der 'ausklappbaren' Liste anders: Zur Laufzeit wird diese Art der combo box zunächst in der Größe eines normalen Eingabefelds angezeigt, jedoch ist die Größe der 'ausgeklappten' Liste davon abhängig, wie groß man die Liste während der Entwicklungszeit festgelegt hat. Klar? Na, schauen Sie lieber einfach mal die beiden Abbildungen an:

combo box sizing at design time combo box size at run time
Festlegen der Größe (für eine drop down list)zur Entwicklungszeit Und so sieht's dann zur Laufzeit aus

Wenn Sie sich den Style-Dialog einer combo box anschauen, werden Sie drei verschiedene Typen finden: Simple, Drop down und Drop down list. Aber was ist jetzt der Unterschied zwischen diesen Typen? Ihr Verhalten natürlich. ;) Die Simple combobox ist ein Eingabefeld mit einer dazugehörigen Liste. Sie können entweder frei etwas darin eingeben, oder den Eingabetext in Kombination mit den Cursortasten auf/ab verwenden, um die Liste auf einen entsprechend lautenden Eintrag vorzupositionieren. Dieser Typ wird meistens dann verwendet, wenn der Anwender neben einer vordefinierten Auswahl auch eigene Eingaben machen dürfen soll. Das gilt auch für den zweiten Typ Drop down, nur daß der Listenteil anfänglich unsichtbar bleibt und erst auf Anforderung 'ausgeklappt' wird, wodurch man einiges an Platz im Dialogfenster spart. Nach wie vor darf der Anwender aber neben der Auswahl aus den Einträgen auch eigene Eingaben vornehmen.
Manchmal jedoch möchte man sicherstellen, daß der Anwender keine eigenen Eingaben machen können darf und lediglich aus einer vordefinierten Liste auswählen kann. Hier kommt der dritte typ ins Spiel: Die Drop down list. Obwohl diese Liste anfänglich wie ein Eingabefeld aussieht, können keine Eingaben darin gemacht werden. Stattdessen erfolgt beim Drücken eines Buchstabens eine Vorpositioniereung der Liste auf den ersten Eintrag, der mit dem gedrückten Buchstaben beginnt und der (falls es einen solchen gibt) dann in das Eingabefeld übernommen wird. Jetzt fragen Sie bloß nicht, was man macht, um eine vordefinierte "NUR-AUSWAHL"-Liste anzuzeigen, die nicht ausgeklappt wird sondern immer sichtbar ist, denn die Antwort darauf lautet einfach: Das ist eine Standardlistbox, Mensch! ;)
Über die horizontal scroll bar werden wir hier nicht sprechen - es ist identisch mit der bei den Listboxen.

COMBO BOX - Ereignisse und Methoden

Während ENTER und SELECT dasselbe bewirken, wie bei einer Listbox und INIT und DROP sich genauso verhalten, wie bei allen anderen controls, gibt es hier noch das CHANGED Ereignis, welches wir bereits vom entry field (Eingabefeld) kennen. Und genau wie es im entry field ein SCROLL-Ereignis gibt, gibt es bei der combo box das Gegenstück, welches hier allerdings SCROLLENTRY hei&szllig;t und auch dann auftritt, wenn der Eingabefeldbereich der combobox horizontal "gescrollt" wurde. Der Grund für die Abweichung im Namen ist schlicht, daß es bei den Comboboxen ein weiteres Ereignis gibt, welches sich ums 'Scrollen' dreht: SCROLLLIST tritt dann auf, wenn im Listenbereich einer Combobox geblättert (gescrollt) wurde. Dann gibt es noch das SHOWLIST-Ereignis, welches ausgelöst wird, wenn der Anwender bei einer ausklappbaren Liste selbiges angefordert hat, indem er auf die entsprechende Schaltfläche geklickt hat. Beachten Sie, daß das Ereignis SHOWLIST nur dann ausgelöst wird, wenn durch das Klicken auf die Schaltfläche die Liste aufgeklappt wurde, nicht, wenn die Liste durch erneutes Klicken auf die Schaltfläche wieder ausgeblendet wird.

Zu den Funktionen einer combo box gibt es nichts aufregendes mehr zu berichten, da es sich tatsächlich um das handelt, was wir bereits aus den listboxen oder dem entry field kennen, abgesehen von der Tatsache, daß es keine SELECT()-Funktion für den Eingabefeldbereich gibt. Es gibt zwar eine SELECT()-Funktion, die sich allerdings auf den Listenteil der combo box bezieht und genau so funktioniert, wie das Gegenstück der listbox. Andererseits gibt es aber etwas, das funktioniert, obwohl es nicht in der Onlinehilfe aufgelistet ist: Wie ich bereits erwähnte, sind combo boxes eine Kombination von Listbox und Eingabefeld. Obwohl die TEXT()-Funktion im Hilfetext der combobox fehlt, kann man Sie dennoch benutzen. Das ist gut zu wissen, denn damit könnte man eine 'nur Auswahl'-Liste mit einer nicht auswählbaren Überschrift machen, wie zum Beispiel mit

call meineListe.TEXT '- Betriebssystem auswählen -'

und das wär's (natürlich müssen Sie noch ADD()s einfügen, um die Liste zu füllen). Solange der Anwender keinen Eintrag der Liste ausgewählt hat, wird SELECT() eine 0 (null) zurückgeben, auch wenn die Überschrift in der Liste steht. Hat der Anwender erst einmal einen Eintrag ausgewählt, kann er nicht zur Überschrift '- Betriebs...' zurückkehren, da diese nie Bestandteil der Listeneinträge war und somit nicht (mehr) auswählbar ist. Ha! Na das ist pfiffig, oder? ;)

GROUP - Aussehen und Verhalten

Da gibt es nicht viel zu sagen, wenn wir von dem absehen, was wir bereits vom Thema radio button kennen: Hiermit können controls gruppiert werden. Zur Entwicklungszeit werden beim verschieben eines 'group'-Rahmens alle enthaltenen controls entsprechend mitverschoben. Das Setzen von Position und Größe zur Laufzeit hat allerdings nur Auswirkungen auf den Rahmen selbst - die enthaltenen controls bleiben unverändert. Halftone scheint nicht zu funktionieren - zumindest nicht bei mir, aber DISABLED klappt... abgesehen vom Umstand, daß damit wirklich nur der Rahmen (de)aktiviert wird, nicht die enthaltenen controls. - Ich sage das nur, damit Sie gewarnt sind, alles klar? ;)

GROUP - Ereignisse und Methoden

Na klar - INIT und DROP mal wieder, natürlich. Aber hey: ShowMenu ist ja mal was neues! Dieses Ereignis wird dann ausgelöst, wenn der Anwender ein Kontextmenü angefordert hat (durch Klick auf Maustaste 2). Dieses Ereignis wird meistens in Zusammenhang mit DrDialogs Befehl MenuPopup verwendet, mit dem selbstdefinierte Menüs als Kontextmenüs angezeigt und verwendet werden können. Ich muß Sie aber wieder enttäuschen und darauf hinweisen, daß wir uns zu einem späteren Zeitpunkt der Serie mit den Menüs beschäftigen werden.

(ein paar) GEMEINSAME FUNKTIONEN

Enable/Disable

Nichts besonderes: Damit können controls zur Laufzeit aktiviert bzw. deaktiviert werden wie z.B. mit

call meineListe.DISABLE
Enabled

Nicht verwechseln mit dem CALL-Aufruf ENABLE, denn diese Funktion hier kann auch zum Abfragen verwendet werden, ob ein control aktiv oder deaktiv ist, während die beiden obigen Vertreter lediglich den Status setzen, aber nicht abfragen können. Um den Zustand eines controls abzufragen verwenden Sie

zustand = meineListe.ENABLED()

Rückgabewert ist 1 (enabled) oder 0 (null; disabled). Zum Setzen des Status mittels ENABLED() verwenden Sie die gleichen Werte als Parameter für den CALL-Aufruf:

call meineListe.ENABLED 0
Visible

Versteckt ein control zur Laufzeit bzw. zeigt es wieder an und kann auch entsprechend zur Abfrage des Status verwendet werden. Ziemlich nützlich, wenn man wenig Platz auf der Dialogmaske hat - einfach die nicht benötigten Teile verstecken und die benötigten wieder anzeigen. Aber übertreiben Sie's nicht! ;) Die Statuswerte für die Sichtbarkeit eines controls sind leicht zu merken: 0=unsichtbar (versteckt), 1=sichtbar. Um eine Listbox zur Laufzeit beispielsweise zu Verstecken, nimmt man

call meineListe.VISIBLE 0

Und um zu erfahren, ob die gleiche Liste sichtbar ist oder nicht nimmt man entsprechend

zustand = meineListe.VISIBLE()
Bottom/Top

Wenn man hübsche Effekte erreichen will, wie pushbuttons, die in Grafiken eingebettet sind oder mehrere Bitmaps mit anderen controls kombiniert, kann es vorkommen, daß die controls manchmal in der falschen "Z-Reihenfolge" liegen, und daß ein control 'unter' einem anderen versteckt ist, obwohl es genau umgekehrt sein müßte. Um diese "Z-Reihenfolge" ("z-order", abgeleitet vom dreidimensionalen Koordinatenmodell X-Achse, Y-Achse und Z-Achse) zu ändern, können Sie jedem control mitteilen, ob es ganz oben (top) oder ganz unten (bottom) in der Z-Reihenfolge stehen soll. Der Aufruf sind dementsprechend entweder so aus

call meineListe.TOP

oder

call meineListe.BOTTOM
Show/Hide

Jo, das ist cool: Anfänglich denkt man, daß es sich hierbei nur um eine andere Variante von VISIBLE handelt, mit der man auch controls verstecken oder anzeigen kann. Aber obwohl das stimmt, steckt da einiges mehr unter der Haube als man vermutet, denn HIDE kann zusätzlich dazu verwendet werden, das 'Aktualisieren' eines controls temporär auszuschalten. Dieser Kniff ist extrem hilfreich, wenn Sie beispielsweise eine große Menge von Einträgen sortiert in eine Listbox füllen (z.B. beim INIT-Ereignis). Jede ADD-Anweisung führt zu einem Update der listbox, wodurch diese oder die Einträge darin unter Umständen flackern. Das läßt sich vermeiden, indem die Aktualisierung temporär ausgeschaltet, die Listbox gefüllt und die Aktualisierung danach wieder eingeschaltet wird. Dann findet einmalig eine Anzeige der Inhalte statt und Sie sind genau wieder da, wo Sie auch "normalerweise" wären - nur, daß das Füllen der Liste mit diesem 'Trick' um einen erheblichen Faktor beschleunigt wird! Beachten Sie, daß das control selbst nicht versteckt wird sondern lediglich nur die Aktualisierungen unterdrückt werden.
Um ein control unsichtbar zu machen (wie mit VISIBLE), verwenden Sie HIDE wie folgt:

call meinControl.HIDE

Um aber nur die Aktualisierung eines controls temporär zu unterdrücken, verwenden Sie

call meinControl.HIDE 'Noupdate'

(Sie können auch einfach 'N' anstelle von 'Noupdate' angeben, um es abzukürzen). Um die Aktualisierung wieder zu aktivieren oder ein verstecktes control wieder anzuzeigen nehmen Sie dann

call meinControl.SHOW

Uff! Eigentlich sollte der Beitrag für diesen Monat etwas kürzer ausfallen, aber es gibt so viel zu entdecken, zu erzählen, zu erklären und zu beachten... und ich habe hier nur die wichtigsten gemeinsamen controls genommen. Nun ja - es ist mal wieder an der Zeit Abschied zu nehmen, Leute.
Bis zum nächsten Monat!

Daten und Quellen:

GuiObjectREXX Yahoo!-Gruppe: http://groups.yahoo.com/group/GuiObjectREXX/
Newsgruppe zur GUI-Programmierung mit REXX: news://news.consultron.ca/jakesplace.warp.visualrexx
Download von Hobbes: http://hobbes.nmsu.edu/cgi-bin/h-search?key=drdialog&pushbutton=Search


[Artikelverzeichnis]
editor@os2voice.org
[Vorherige Seite] [Inhaltsverzeichnis] [Nächste Seite]
VOICE Homepage: http://de.os2voice.org