Verwendung SWin/VRuby
Erweiterungen
SWin und VRuby sind zwei
Grundbestandteilen des VisualuRuby's
Projektes. SWin ist ein
Ruby-Erweiterungsmodul, geschrieben in C,
welches vielen von Win32 API zu den
Ruby-Interpreter bereitsteht. VRuby ist
eine Bibliothek, die aus reinen Rubymodulen
besteht, bildet sich auf SWin auf, so dass
es eine Schnittstelle auf höchster Ebene
für Win32-Programmierung zur Verfügung
stellt. Wie es der Fall mit anderen
Ruby-Erweiterungen ist, gibt es meistens
die Dokumentaion für SWin und VRuby nur in
Japanisch. Auf der offizielen Seite des
VisualuRuby Proejktes kann man sich
Beispielprogramme besorgen, die man als
Musterprogramme für seine Ideen
ausprobieren und was eingentlich mit SWin
und VRuby machen kann, und dadurch können
Sie sich schon mit allgemeinen
Windowsprogrammierungsvorstellungen vetraut
machen. Dieser Abschnitt liefert genug
Information der VRuby(API) Schnittstelle um
unseres Beispielprogramm zu entwicklen,
aber für die tieferen Kenntnissen in
SWin/VRuby müssen sich gut genug mit den
Hintergründen der Windowsprogrammierung
auskennen. Es gibt einige hervorragende
Bücher in diesem Gebiet, und wenn auch sie
aus dem Blinkwinkel der C Programmierung
Win32 API besprechen, könnten sie durchaus
gut einige Lücken des nötigen Wissens mit
VRuby Programmierung auffüllen. Außerdem
gibt es auch auf anderer Seite eine sehr
nützbare Information der Win32 API Referenz
auf der Microsoft Developer Network Seite
auch als CD's erhältlich.
Installation
SWin und VRuby Module sind im
Ruby-Installer von der "Pragmatic
Programmers" Webseite enthalten. Also
heisst es, dass wenn man sich Ruby
installiert hat(es handelt sich natürlich
nur um Windows OS), kann man sich loslegen.
Man kann sich auch Sourcecode für SWin von
der VisiualuRuby Projekt Seite
herunterladen, und kann auch so gut schon
precompilierte Binäres finden.
VRuby Bibliothek Basis
Da es so wenig Dokumentaion in
Englisch für SWin und VRuby gibt, werden
wir an dieser Stelle zusätzliche
Information liefern, die Ihnen einen
Überblick von der VRuby Bibliothek und
ihren Klassen und Modulen verschafft. Um
mehr Information darüber herauszubekommen,
wäre es hilfreich, Kommentare von der
Sourcedateien zu studieren, welche selbst
allerdings ziemlich skizzenhaft sind, aber
das könnte Ihnen helfen, anzufangen, wenn
Sie beabsichtigen, mit VRuby zu arbeiten.
Die VRuby Bibliothek ist als eine Reihe der
Ruby Sourcedateien aufgebaut, und wird ins
vr Package-Verzeichnis
installiert. Die unten dargestellte Tabelle
1 listet einige der meistens wichtigen
Dateien, die Sie in ihren Programmen
verwenden werden, und entsprechend
require Statement. Dabei ist
es, anzumerken, dass die meiste oder alle
der nicht sozusagen "Kern-Dateien" von der
Kern-Klassen und Modulen aus
vr/vruby.rb abhähngig sind, so
dass es wahrscheinlich nicht notwendig ist,
diese Dateien zusätzlich zu
importieren.
Tabelle 1 Inhalt
der VRuby Bibliothek
|
Beschreibung |
Wie wird es
importiert |
| Kern-Klasse und
Module |
require
'vr/vruby' |
| Layout Manager |
require
'vr/vrlayout' |
| Standard
Steuerung |
require
'vr/vrcontrol' |
| Allgemeine
Steuerung |
require
'vr/vrcomctl' |
| Multipane
Windows |
require
'vr/vrtwopane' |
Die Kern-Klasse und Module für
VRuby(Tabelle 2) besteht aus allein
"High-Level" Basisklassen und
"mixin"-Modulen, die Sie aber nicht direkt
in meisten Programmen verwenden werden. Es
gibt aber zwei bemerkenswerte Ausnahmen,
wie auch immer, VRForm und
VRScreen. VRForm
ist die Basisklasse, die für die
"top-level" Fenster verwendet wird, solche,
wie in ihren Programmen Hauptfenster sind.
Wie Sie in unserem Beispielprogramm sehen
werden, muss man nur lediglich unseres
Hauptfenster von der VRForm
Klasse ableiten, eventuell auch eine andere
Verhalten des Fensters bringen, und werden
Sie es kennenlernen, wie in dieser Klasse
durch die construct Methode
nach ihren Bedürfnissen das Verhalten und
das Aussehen der Applikation handhaben
wird.
Tabelle 2
Kern-Klasse und Module für
VRuby
| Name von
Klasse/Modul |
Beschreibung |
|
VRMessageHandler |
Dieses Modul könnte in
irgendwelchen Klassen verwendet werden,
die Windows Nachrichten empfangen
müssen; das stellt
acceptEvents und
addHandler zur
Verfügung |
| VRParent |
Dieses Modul liefert die
Modulmethode, die von dem Vater-Fenster
verwendet wird(das Fenster kann als ein
Behälter für die anderen Kind-Fenster
sein), passt gut unter anderem mit
VRForm und
VRPanel Klassen
zusammen, weil sie die meist verwendete
"Behälterklasse", die man am häfigsten
verwendet wird |
| VRWinComponent |
Das ist die Basisklasse
von allen Fenster |
| VRControl |
Basisklasse für alle
Controlwidgets; eine Subklasse von
VRWinComponent |
| VRCommonDialog |
Dieses Modul bietet
mehrere passende Funktionen an, die für
allgemeinen Fensterdialogen verwendet
werden; liefert Modulmethoden wie
openFilenameDialog,
saveFilenameDialog,
chooseColorDialog und
chooseFontDialog |
| VRForm |
Das ist Basisklasse für
alle Hauptfenster, wie das Hauptfenster
von unseren Beispielprogramm, und kann
auch mit
VRMessageHandler,
VRParent und
VRCommonDialog Modulen
verwendet werden |
| VRPanel |
Das ist die Basisklasse
für alle Kind-Fenster(wie
ControlWidgets); eine Subklasse von
VRControl |
| VRDrawable |
Dieses Modul kann mit
einigen Klassen verwendet werden, die
man braucht, um "Bild-Nachrichten"
handzuhaben(ein Verweis, dass die
Fensterinhalte rekonstruiert werden);
diese Klasse kann die
self_resize Methode außer
Kraft setzen |
| VRResizeable |
Dieses Modul kann in
irgendwelchen Klassen benutzt werden,
um Ereignisse abzufangen, die die
Änderung der Fenstergröße handhaben;
diese Klasse kann die
self_resize Methode außer
Kraft setzen |
|
VRUserMessageUseable |
Dieses Modul kann in
irgendeiner Klasse verwendet werden, um
Benutzerdefinierte Nachrichten mit dem
Betriebsystem zu passen |
| VRScreen |
Diese Klasse stellt die
Fensteroberfläche dar, und bietet
Methoden an, um neue
Hauptfenster-Widgets zu erzeugen und zu
zeigen, und dazu kann dies die
Hauptereignisschleife zu steuern. VRuby
legt genau eine globale Instanz dieser
Klasse,
VRLocalScreen |
Einige der Window's Steuerungen
existierten seit der Zeiten, als noch
Windows 95 nocht nicht zur Welt geblickt
hat, was aber, wie man schon weiß, nicht
verhindern konnte, dass diese Steurungen
sich als standard Steurungen
etabliert haben. Die Standardsteurungen(wie
Buttons, Labels, Textfelder) sind
zugägnlich, wenn man
vr/vrcontrol.rb in
Anspruch nimmt. Die nachstehende Tabelle 3
listet die Klassen, die dieses Modul
präsentieren.
Tabelle 3 Standard
Steuerelemente für VRuby
| Klassen/Modul
Name |
Beschreibung |
| VRStdControl |
Diese Klasse(eine
Subklasse von
VRControl ist einfach
die Basisklasse von allen Standard
Steurungenselementen |
| VRButton |
Das ist ein Standard
Drück-Button; Man kann auch den
Button's Text zuweisen, dabei wird eine
caption Instanz-Methode
verwendet |
| VRGroupbox |
Die Gruppenbox |
| VRCheckbox |
Das ist eine Checkbox
Steurungseinheit. Man kann ein
sogennantes Häkchen setzen oder das
entfernen, gemacht wird das durch die
check Instanz-Methode, um
den aktuellen Zustand zu prüfen,
verwendet man die checked?
Instanz-Methode |
| VRRadioButton |
Das ist ein Radio-Button,
gewöhnlich wird es als eine Gruppe von
Radio-Buttons angezeigt, wird
verwendet, wenn nur eine Auswahl
getroffen werden muß. Da es besonderer
Fall(eine Subklasse) der
VRCheckbox ist, wird
auch hier die check und
checked? Instanz-Methoden
unterstützt |
| VRStatic |
Das ist ein statischer
Text-Steureungselement, welches einfach
eine nicht editierbare Textbeschriftung
anzeigt. Der Beschriftungstext kann
durch die caption
Instanz-Methode zugewiesen
werden |
| VREdit |
Das ist einzigzeilige
editierbare Text-Steurungseinheit. Die
liefert eine Zahl von Instanz-Methoden
zusammenhängend mit dem Editieren und
Eingeben vom Text, und sowie die
Bearbeitung des ausgewählten Textes und
auch die Übertragung von einem Text
zwischen der VREdit
und Windows
Clipboard(Zwischenspeicher) |
| VRText |
Das ist vielzeilige
editierbare Text-Sterugseinheit. Sie
ist ähnlich wie einzigzeilige
Darstellung (VREdit),
aber bietet eine Zahl von zusätzlichen
Instanz-Methoden an, die mit dem
Navigieren durch den Text
zusammenhängen |
| VRListbox |
Das ist eine
vertikalorientierte Liste von Strings,
von welchen der User sich einen oder
mehrere Einträge aussuchen
kann |
| VRCombobox |
Das ist eine "Drop-Down"
Liste von Strings, ähnlich wie
VRListbox, nur aber
mit dem Unterschied, dass man sich
lediglich einen Eintrag aussuchen
kann |
| VRMenu |
Das ist eine Menübar, die
mit pulldown Menüs ausgestattet ist,
und gewöhnlich erscheint entlang des
oberen Randes von
Hauptprogrammfenster |
| VRMenuItem |
Das ist ein einzelnen
Menüeintrag, welcher in
VRMenu Widget
erscheint(z.B. Speichern
als... Befehl in der
Datei Menü eines
Programmes). Sie werden im Allgemeinen
es implizit erzeugen, wenn Sie eine
Menü's set Befehl aufrufen |
| VRMenuUseable |
Dieses Modul könnte mit
anderen verschiedenen Klassen verwendet
werden, welche Menüs benutzen müssen;
das liefert die newMenu
und setMenu
Modulmethode |
| VRBitmapPanel |
Das ist eine besondere
Art von Panel, die verwendet wird, um
statische Bitmaps zu zeigen |
| VRCanvasPanel |
Das ist eien spezielle
Art von Panel, die benutzt wird, um
zeichengeeignete Bitmap Images zu
zeigen; Sie können die Größe und Höhe
von Panel und kann man auch GDI
Funktionen, um darauf zu zeichnen
|
Windows 95 hat sehr viele neue
Benutzerfreundlichen Steuereinheiten
eingeführt, die als
common(allgemeine)
Steuerelemente genannt werden. Diese
beinhalten solche Steuerelemente, die als
list views, tree
views bekannt sind und werden
umfassend in Windows Explorer verwendet.
Die VRuby Klassen stellen algemeine
Steuerelemente, die in der Tabelle 4
auflistet sind.
Tabelle 4
Allgemeine Steuerelemente für
VRuby
|
Klassenname |
Beschreibung |
|
VRNotifyControl |
Diese Klasse(eine
Subklasse von
VRControl) ist einfach
die Basisklasse fü alle allgemeine
Steuerelemente |
| VRListView |
Das ist eine steigende
"Listensteuerung", welche konfiguriert
werden kann, um Daten in verschiedenen
Formaten zeigen zu lassen(z.B. als
Icons mit einer einfachen Beschreibung,
oder in der mehr detalierten
Listenform). Meinstens wird diese
Steuerung, wie in Windows Explorer
bekannter Form verwendet. |
| VRTreeview |
Diese Steuerung, auch
gewöhnlich als Tree-Liste bekannt ist,
wird verwendet, um die
hierarchisch-strukturierte Daten zeigen
zu lassen. Das ist eine beliebte
Auswahl für meiste Windowsprogrammen,
wird zum Beispiel in Register Editor
Utility verwendet |
| VRProgressbar |
Diese Steuerung wird
während eines sozusagen
"zeitaufgebrauchten" Vorgehens
verwendet, damit wird den User eine
Rückmeldung angeboten, über die er
erfahren kann, wie weit irgendwelche
Operation vorangekommen ist und wieviel
Zeit übriggeblieben ist, bis die
Operation beendet wäre |
| VRTrackbar |
Dieses Steuerungselement
besteht aus einem sozusagen Schieber
oder einer Führung und optionalen
Markierungszeichen. Das kann benutzt
werden, wenn der User möchte, einen
diskreten Wert aus einer Reihe von
Werten auszuwählen |
| VRUpdown |
Diese Steurung besteht
aus ein Paar Pfeil-Buttons(gewöhnlich
ein nach oben und andere nach unten
gerichtet),die der User benutzen kann,
um eine Zunahme oder eine Abnahme
einigen Werten im Programm zu zeigen.
Die bildet fast immer ein Paar mit
"buddy" Fenster, wie mit
VREdit Steuerung, um
ihre aktuelle Einstellungen zu
zeigen |
| VRStatusbar |
Das ist ein horizontales
Streifen, welches am unteren Rand des
Hauptfensters erscheinen kann, um die
Statusinformation anzeigen zu lassen
|
|
VRStatusbarDockable |
Dieses Modul könnte mit
der VRForm Klasse
verwendet werden. Damit wird die
Statusbar-Steureung eingeschloßen.
Benutzt wird dabei eine
addStatusbar Methode, um
die Statusbar in den Widget
hinzuzufügen |
| VRTabControl |
Diese Steuerung zeigt ein
oder mehrere Tabs, welche man verwenden
kann, um als eine Basis für dei
Eigenschaftentabelle oder Tabspanel zu
benutzen |
| VRTabbedPanel |
Diese Steuerung
kombiniert
VRTabControl mit einer
Reihe von Panels, um "tabbed"
notebook Steuerungen zu
erzeugen |
Layout Manager
Im Gegensatz zu allen anderen
GUI Tookits, die wir bis jetzt gesehen
haben, bietet VRuby nicht so viel, was
Layout Manager betrifft. Das ist
hauptsächlich auf den Fakt zurückzuführend,
dass Win32 API, auf der SWin und VRuby
basirien, überhaupt keine irgendwelche
Layout Manager enthalten. Obwohl die Layout
Manager jetzt mit VRuby mitgeliefert
werden, sind sie etwas begrenzt, eins würde
in dieser Situation erwarten, als VRuby
ausgereifter auszubaeun. Es gibt für VRuby
drei Layout Manager und zwar
VRHorizLayoutManager,
VRVertLayoutManager und
VRGridLayoutManager. Diese
Layout Manager sind einfach Module, die man
mit einer Behälterklasse, wie
VRPanel, verwenden kann, und
die dienen nicht als
Standalone-Behälterklasse. Ähnlich wie ihre
Gegenstücke in Ruby/GTK und FXRuby ordnen
die erste zwei Layout Manager ihre
Kind-Widgets in der horizontalen oder
vertikalen Richtung. Um diese Layout
Manager zu benutzen, muss man erstens das
gewünschte Layout Manager-Modul mit seiner
Behälterklasse zusammenmischen:
require
'vr/vrlayout'
eclass
MyPanelClass < VRPanel
enjinclude
VRHorizLayoutManager
eend
Danach werden einen oder
mehrere Kind-Widgets (oder in der
"Windows-Sprache" als controls
(Steuerelemente)genannt) zum Behäterfenster
durch die addControl Methode
hinzugefügt:
aPanel =
MyPanelClass.new ...
eaPanel.addControl(VRButton,
"button1", "Überschrift für den ersten
Button")
eaPanel.addControl(VRButton,
"button2", "Überschrift für den zweiten
Button")
Die volle Argumentenliste für
unsere Layout Manager
VRHorizLayoutManager#addControl (oder
VRVertLayoutManager#addControl ist:
addControl(type, name,
caption, style=0)
wo type eine VRuby
Klasse fürs Steuerungselement ist,
name sein Name ist, und
caption ein Textstring ist,
der auf dem Steuerungselement
erscheint(natürlich für diejenige, die das
unterstützen). Das letzte Argument
style kann verwendet werden,
um zusätzlich "windows style flags" für
dieses Steuerelement zu übergeben. Die
Grundeinstellung dafür ist es, dass VRuby
eine Steuerung erzeugt, die nur "basis
style flags" enthält; zum Beispiel,
VRButton-Steuerungselemente werden durch
die WStyle::WS_VISIBLE oder
WStyle::BS_PUSHBUTTON flags
erzeugt. Im Gegensatz zu anderen GUI
Toolkits brauchen Sie tatsächlich keine
Steuerungen über die Parameter von
Kinder-Widgets, um deren Größe zu
beinflüssen. Zum Beispiel für
VRHorizLayoutManager ist es
so, dass die Höhe von Kinder-Widgets ebenso
gleich wie die Höhe des Vater-Widgets ist
und die Breite des Vater-Fensters wird
durch die Anzahl der Kinder-Steuerungen
dividiert. Ferner jeder Kind-Widget breitet
sich automatisch(horizontal oder vertikal)
aus, um seinen zugewiesenen Raum zu
füllen.
Der
VRGridLayoutManager entspricht
ungefähr dem Tk's grid Layout,
GTK's Gtk::Table und FOX's
FXMatrix, allerdings mit einer
Art der Beschränkung für die Größe der
Kind-Steuerungen, die wir schon bei den
VRHorizLayoutManager und
VRVertLayoutManager gesehen
haben. Bevor die Kind-Steuerungen zum
Behälter hinzugefügt werden, dabei wird
VRGridLayoutManager verwendet,
müssen wir zunächst eine Anzahl von Spalten
und Zeilen mit Hilfe der
setDimension Methode
festlegen:
require
'vr/vrlayout'
eclass MyPanel
< VRPanel
enjinclude
VRGridLayoutManager
eend
eaPanel =
MyPanel.new ...
eaPanel.setDimension(5,
3)
wo die zwei Argumente auf die
Anzahl der Zeilen beziehungsweise Spalten
hindeuten. Gleich danach kann man die
Kind-Steuerungen durch die
VRGridLayouManager#addControl
Methode hinzufügen.
addControl(type, name,
caption, x, y, w, h, style=0)
Hier sind die erste drei
Argumenten gleich den Argumenten, die wir
vorhin für die
VRHorizLayoutManager und
VRVertLayoutManager erläutert
haben. Die nächste zwei Argumente(x und y)
weisen auf eine Zelle hin, die sich oben
links in der Reihe von Zellen befindet,
diese Zelle wird die entsprechende
Steuerung belegt, und schließlich die "w"
und "h" Argumente weisen darauf hin,
wieviel die Breite und die Höhe der
insgesamt in der Reihe vorhandenen
Tabellenzellen beträgt. Für die Steuerung,
die nur eine Tabellenzelle einnimmt, werden
Sie lediglich die Breite und die Höhe einer
Zelle verwenden.
Handhabung von Ereignissen
VRuby verwendet
Callback-basierende Methode, um die
Ereignisse zu behandeln, die ganz anderes
als die Methoden von anderen GUI's ist, die
wir schon gesehen haben. Sie können
erstaunt sein, wie man den Namen für jede
Steuerung, die Sie zur einer Form
hinzufügen möchten, festlegt. Zum Beispiel,
wenn man ein Button(das ist natürlich ein
Steuerungselement) hinzufügen möchte, kann
man so vorgehen:/p>
aForm.addControl(VRButton,
"button1", "Beschriftung für Button",
...)
Das dritte Argument ist ein
Beschriftungsstring, der auf dem Button
angezeigt wird. Das allerdings nicht
heisst, dass dieser Namenstring überal
erscheinen kann, aber eingentlich,
jedesmal, wenn Sie neue Steuerung zu den
VRForm oder
VRPanel hinzufügen(die sind
übrigens im VRParent Modul
vorhanden), legt das Behälter-Objekt auch
eine neue Instanzvarible und
Zugriffsmethoden fest, und zwar mit den
Namen, den Sie durch den Aufruf die Methode
addControl vorher erzeugt
haben. Diese neue Instanz-Variable ist
einfach ein Verweis auf das
Kind-Steuerungselement. Also nachdem der
obengennante Zeilencode ausgeführt wird,
könnten Sie später die Beschriftung von
Button mit dem folgenden Code ändern:
aForm.button1.caption =
"Neue Beschriftung für den
Button"
Die Namen von
Steuerungselementen sind dafür da, um die
Callbacks zu erzeugen und diese
Callbacksmethoden müssen solche Namen
tragen, wie wir das an folgenden Coden
erkennen können:
def
controlname_eventname
en...Behandle
dieses Ereignis
eend
So zum Beispiel, wenn Sie
möchten, ein clicked Ereignis
für die button1 Steuerung
abzufangen, müssen Sie der Methode als Name
button1_clicked vergeben:
def button1_clicked
evputs
"Button1 wurde angeclickt!"
eend
Diese Callbacksmethoden müssen
als Instanzmethoden fürs Behälterfenster
festgelegt werden, und das heisst, wenn wir
button1 Steuerung als ein
Kind-Widget fÜr den aForm
erzeugt haben, muss die
button1_clicked Methode als
eine Instanzmethode vom aForm
Vater-Widget sein. Wir werden später es
sehen, wie das im unseren Beispielprogramm
funktioniert. Die folgende Tabellen 5 und 6
bieten eine Liste von Ereignisnamen für
alle VRuby's Steuerungselementen, die Sie
verwenden können.
Tabelle 5
Ereignisnamen für
Standard-Steuerungen
|
Steurungsklassen |
Ereignisname(n) |
| VRButton |
clicked,
dblclicked |
| VREdit |
Changed |
| VRListbox |
Selchange |
| VRCombobox |
Selchange |
Tabelle 6
Ereignisnamen für allgemeine
Steuerungselementen
|
Steuerungsklassen |
Ereignisname(n) |
| Alle allgemeine
Steuerungen |
clicked, dblclicked,
gotfocus, hitreturn, lostfocus,
rclicked, rdblclicked |
| VRListview |
itemchanged,
itemchanging, columnclick, begindrag,
beginrgrad |
| VRTreeview |
selchanged, itemexpanded,
deleteitem, begindrag,
beginrdrag |
| VRUpdown |
Changed |
| VRTabControl |
Selchanged |
VRuby Beispielprogramm
Der untenstehende Code zeigt
uns eine VRuby's Version unseres
Beispielprogrammes im seinen vollen Umfang.
Den können Sie selbsverständlich auch
herunterladen vruby-xmlviewer. Der
Code beginnt mit dem Importieren von
verschiedenen VRuby Bibliotheken, die wir
benötigen werden:
require 'vr/vruby'
erequire
'vr/vrcontrol'
erequire
'vr/vrcomctl'
erequire
'vr/vrtwopane'
Als Nächstes definieren wir
globale Konstanten, die benötigt werden, um
später im Programm Nachrichtenboxen zu
zeigen
# The values of
these constants were lifted from
"winuser.h"
eMB_OKenjoyenjoyenjoy =
0x00000000
eMB_ICONEXCLAMATION
= 0x00000030
eMB_ICONINFORMATION
= 0x00000040
Die Win32 Schnittstelle
verwendet eine lange Zahl für die Namen von
Konstanten(wie MB_OK, MB_ICONEXCLAMATION
und MB_ICONINFORMATION), um die "style
flags" für die Steuerungen festzulegen. In
unserem Fall legt das letzte Argument der
VRuby's messageBox Funktion
Optionen von der Nachrichtenbox fest,
solche wie gezeigte Buttons und Icons. Da
diese Konstanten nocht nicht gut bei
SWin/VRuby repräsentiert werden, müssen Sie
sozusagen in allen Windows Header Dateien
wühlen, um die aktuelle numerische Werte
für diese Konstanten festzusetzen. Wie Sie
schon bestimmt geahnt haben, ist das ein
Zeitpunkt, wo die Windowsprogrammierung
ihre Stelle einnehmen würde. Der nächste
bedeutunsvolle Block des Codes legt die
XMLViewerForm Klasse fest, und
damit auch ihre Instanzmethoden; das ist
sozusagen ein Brennpunkt der unseren
Applikation. Bevor wir uns damit
beschäftigen, lassen wir uns für eine kurze
Zeit einen Teil des Codes überfliegen und
werfen wir einen Blick auf letzte wenige
Zeilen des Programmes:
mainWindow =
VRLocalScreen.newform(nil, nil,
XMLViewerForm)
emainWindow.create
emainWindow.show
e# Start der
Nachrichtenschleife
eVRLocalScreen.messageloop
Nachdem wir die
XMLViewerForm Klasse definiert
haben(die ist einfach eine Subklasse von
VRForm, rufen wir
newform Methode auf, die zur
VRLocalScreen Klasse gehört,
damit erzeugen wir eine Instanz von der
XMLViewerForm Klasse. Zur
Erinnerung, VRLocalScreen ist
eine spezielle Variable in VRuby; das ist
einzige globale Instanz von
VRScreen Klasse und sie
entspricht locker dem Windows Desktop. Die
erste zwei Argumente für
newform Methode sind
Vater-Fenster und "style flags" für dieses
neuen Fenster. Im unseren Fall ist das das
Hauptfenster unseres Programmes und so
damit übergeben wir nil
als Argument an die newform
Methode. Letzendlich haben wir erreicht,
dass sozusagen "Stil"(style) "default"
wird. Danach rufen wir
mainWindow.create auf, die
eingentlich nichts Anderes macht, als das
wirkliche Fenster als Ruby Objekt erzeugt.
Von diesem Zeipunkt an ist das
Behälter-Fenster, der Aufruf dieser
Methode(create) löst den Aufruf der anderen
Methode aus, und zwar
construct Methode(wir werden
das später sehen), um Steuerungselemente
und Menüs zu erzeugen. Und schließlich wird
die show Methode aufgerufen,
damit wird das Hauptfenster sichtbar, bevor
die Hauptereignisschleife(main even loop)
eintritt.
Nun lassen wir uns zurückgehen,
und schauen wir uns den Code für unsere
"Formklasse" und zwar
XMLViewerForm. Wir beginnen
damit, dass wir zwei Module einbinden, die
sehr nützliche Funktionen von VRForm zur
Vefügung stellen:
include
VRMenuUseable
einclude
VRHorizTwoPane
Das VRMenuUseable
Modul liefert uns die newMenu
und setMenu, die dazu dienen,
dass man damit Pulldown's Menüs aufbauen
kann. Das VRHorizTwoPane Modul
fügt die addPanelControl
Methode hinzu, und ermöglicht einen
horizontal-gesplitterten Layout für den
Inhalt des Haupfensters. Als nächstes
definieren wir zur Form gehörige
construct Methode, die nichts
anderes macht, als die Menüs erzeugt und
Steuerugselemente zum Hauptfenster
hinzufügt:
endef
construct
enj# Set
caption for application main window
enjself.caption =
"XML Viewer"
enj# Create
the menu bar
enj@menu =
newMenu()
enj@menu.set([
["&File", [ ["&Open...", "open"],
["Quit", "quit"] ] ],
enjoyenjoyenj["&Help",
[ ["About...", "about"] ] ] ])
enjsetMenu(@menu)
enj# Tree view
appears on the left
enjaddPanedControl(VRTreeview,
"treeview", "")
enj# List view
appears on the right
enjaddPanedControl(VRListview,
"listview", "")
enj@listview.addColumn("Attribute
Name", 150)
enj@listview.addColumn("Attribute
Value", 150)
enend
Der Aufruf der
newMenu Methode erzeugt
einfach eine leere Menü und weist die
danach zur unseren @menu
Instanzvarible zu; und gleich danach der
Aufruf der set Methode legt
einfach den Inhalt des Menüs fest. Das
sieht ein wenig kompliziert aus, muss aber
nicht sein, weil set Methode
ein Argument hat, welches ein Array von
Array's ist, ein pro Pulldown Menü. Das für
jede Pulldown Menü Subarray ist selbst ein
zweielemengites Array. Betrachten wir das
erste Array, welches der File Menü
entspricht:
[ ["&File", [
["&Open...", "open"], ["Quit", "quit"]
] ]
Das erste Arrayelement ist der
Name des Pulldown Menü. Durch die
Platzierung "ampersand"("&") vor der
Buchstabe "F" in "File" wird es erreicht,
dass die Alt+F
Shortkey-Kombination verwendet kann, um das
"File" Menü aufzuklappen. Das zweite
Element in diesem Array ist auch ein
anderes Array, diesmal ein Array, das einen
Eintrag im "File" Menü darstellt. Jedes
Element solches Array's ist entweder ein
zweielementiges Array, das für den
Menüentrag eine Beschriftung und einen
Namen anbietet, oder soeben die
Beschriftung und noch ein anderes Array
eines Menüeintrages um ein weiteres
"cascasding" sozusagen Submenü zu
präsentieren. Solche Submenüs machen
unseren Author(M.Neumann) ein bisschen
"verrückt", und so bleibt der Author weiter
hin mit Single-Level Menü zu beschäftigen.
Einen Kapiter zuvor haben wir das Thema
"Ereignisbehandlung" unterrichtet und haben
gesehen, dass Namen von Steuerungselementen
sehr wichtig sind, weil sie in den Namen
für VRuby's Callback's Methoden verwendet
werden. Auf gleicherweise sind auch von
Ihnen zugewiesenen Namen von Menüeinträgen
wichtig; wenn der Anwender auf einen
solchen Menüeintrag klickt, wird VRuby nach
der Callbackmethode suchen, die den Namen
name_clicked trägt. Bald
werden wir sehen, dass die
XMLViewerForm Klasse die
Callback's Methoden
open_clicked,
quit_clicked,
about_clicked definiert, um
diese drei Menübefehle festzusetzen.
Nachdem wir mit der Hilfe der
construct Methode die
Applikationsmenü's definiert haben,
f&uugen wir genau zwei
Steuerungselemente zum unseren horizontalen
"Schauplatz"(pane):
e# Tree view appears
on the left
eaddPanedControl(VRTreeview,
"treeview", "")
e# List view
appears on the right
eaddPanedControl(VRListview,
"listview", "")
Die Namen von
Kinder-Steuerungselementen, die man zu
VRParent hinzufügte, werden
als Namen Instanzvariablen. Wir werden
daraus einen Vorteil nutzen, um weiter den
Listview Widget mit dem Namen
listview zu konfigurieren:
e@listview.addColumn("Attribute
Name", 150)
e@listview.addColumn("Attribute
Value", 150)
Als nächstes lassen wir uns auf
drei Callback's Methoden konzentrieren. Die
behandeln Open...,
Quit und
About Menüsbefehle. Da der
Name fürs Menüeintrag
Open... open
war, wurde seine Callback-Methode als
open_clicked gennant:
endef
open_clicked
enjfilters =
[["All Files (*.*)", "*.*"],
enjoyenjoy["XML
Documents (*.xml)", "*.xml"]]
enjfilename =
openFilenameDialog(filters)
enjloadDocument(filename)
if filename
enend
Die
openFilenameDialog Methode ist
eine bequeme Funktion um einen üblichen
Windows Dateidialog zu zeigen. Das ist eine
Modulmethode, die im
VRCommonDialog Modul
integriert ist. Die kann genauso gut auch
in der VRForm Klasse verwendet
werden, so dass man diese Methode für
irgendwelche Form benutzen. Als Argument
erwartet diese Methode ein Array von
Dateinamen's Mustern(oder wie in unserem
Fall filters), welches im
Dateidialog angezeigt wird und danach den
Namen der ausgesuchten Datei
zurückliefert(oder nil,
wenn der Anwender den Dialog abbricht). Der
Callback für den About...
Menübefehl wird durch die "about_clicked"
Methode gehandelt:
endef
about_clicked
enjmessageBox("VRuby
XML Viewer Example", "About XMLView",
enjoyMB_OK|MB_ICONINFORMATION)
enend
Die messageBox
Methode ist eine andere Art der
"bequem"-Funktion, und sie ist einfach eine
Instanzmethode SWin::Window
Klasse(eine weit entfernte Vorfahrklasse
von unserer Form). Wie Sie schon
wahrscheinlich vermutet haben, sind die
drei Argumente die Nachricht selbst, die
auf der Oberfläche des Fensters erscheint,
der Titel des Fensters und "style flags",
das darauf hinweist, welche Icons und
Buttons(in der Regel zum Beenden) angezeigt
werden. Der Callback für den
Quit Menübefehl ist am
leichtesten zu verstehen, weil der nur
einfach Ruby's exit Methode
aufruft:
endef
quit_clicked
enjexit
enend
Die folgende Abbildung zeigt
eine VRuby Version unseres
Beispielprogrammes, das unter Window XP
ausprobiert wurde:
Und hier ist der vollständige
Code unseres Beispielprogrammes:
require
'vr/vruby'
erequire
'vr/vrcontrol'
erequire
'vr/vrcomctl'
erequire
'vr/vrtwopane'
erequire
'nqxml/treeparser'
e# The values
of these constants were lifted from
"winuser.h"
eMB_OKenjoyenjoyenjoy =
0x00000000
eMB_ICONEXCLAMATION
= 0x00000030
eMB_ICONINFORMATION
= 0x00000040
eclass
XMLViewerForm < VRForm
eninclude
VRMenuUseable
eninclude
VRHorizTwoPane
endef
construct
enj# Set
caption for application main window
enjself.caption =
"XML Viewer"
enj# Create
the menu bar
enj@menu =
newMenu()
enj@menu.set([
["&File", [ ["&Open...", "open"],
["Quit", "quit"] ] ],
enjoyenjoyenj["&Help",
[ ["About...", "about"] ] ] ])
enjsetMenu(@menu)
enj# Tree view
appears on the left
enjaddPanedControl(VRTreeview,
"treeview", "")
enj# List view
appears on the right
enjaddPanedControl(VRListview,
"listview", "")
enj@listview.addColumn("Attribute
Name", 150)
enj@listview.addColumn("Attribute
Value", 150)
enend
endef
populateTreeList(docRootNode,
treeRootItem)
enjentity =
docRootNode.entity
enjif
entity.instance_of?(NQXML::Tag)
enjoytreeItem
= @treeview.addItem(treeRootItem,
entity.to_s)
enjoy@entities[treeItem]
= entity
enjoydocRootNode.children.each
do |node|
enjoyenjpopulateTreeList(node,
treeItem)
enjoyend
enjelsif
entity.instance_of?(NQXML::Text)
&&
enjoyenjentity.to_s.strip.length
!= 0
enjoytreeItem
= @treeview.addItem(treeRootItem,
entity.to_s)
enjoy@entities[treeItem]
= entity
enjend
enend
endef
loadDocument(filename)
enj@document =
nil
enjbegin
enjoy@document
=
NQXML::TreeParser.new(File.new(filename)).document
enjrescue
NQXML::ParserError => ex
enjoymessageBox("Couldn't
parse XML document", "Error",
enjoyenjMB_OK|MB_ICONEXCLAMATION)
enjend
enjif
@document
enjoy@treeview.clearItems()
enjoy@entities
= {}
enjoypopulateTreeList(@document.rootNode,
@treeview.root)
enjend
enend
endef
open_clicked
enjfilters =
[["All Files (*.*)", "*.*"],
enjoyenjoy["XML
Documents (*.xml)", "*.xml"]]
enjfilename =
openFilenameDialog(filters)
enjloadDocument(filename)
if filename
enend
endef
quit_clicked
enjexit
enend
endef
about_clicked
enjmessageBox("VRuby
XML Viewer Example", "About XMLView",
enjoyMB_OK|MB_ICONINFORMATION)
enend
endef
treeview_selchanged(hItem, lParam)
enjentity =
@entities[hItem]
enjif entity
and
entity.kind_of?(NQXML::NamedAttributes)
enjoykeys =
entity.attrs.keys.sort
enjoy@listview.clearItems
enjoykeys.each_index
{ |row|
enjoyenjoy@listview.addItem([
keys[row], entity.attrs[keys[row]] ])
enjoy}
enjend
enend
eend
emainWindow =
VRLocalScreen.newform(nil, nil,
XMLViewerForm)
emainWindow.create
emainWindow.show
e# Start the
message loop
eVRLocalScreen.messageloop