home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-07-12 | 491.7 KB | 20,013 lines |
- WGVISION 1.0
-
-
-
-
-
- Klassenbibliothek zur Ausstattung von Turbo- und Borland-
- Pascal-Programmen mit einer Windows-ähnlichen grafischen
- Nutzeroberfläche
-
- -----------------------------------------------------------
- Copyright (c) 1992/93 Dipl.Phys. Mathias Scholz
-
- 02763 Zittau/Sa.
- Bergstr. 7
- -----------------------------------------------------------
-
- WW WW GGGGGG
- WW WW GG GG
- WW WW GG
- WW WW GG ========
- WW WW WW GG GGGGG ========
- WW WWWW WW GG GG
- WW WW GG GG
- WW WW GGGGGGGG
-
-
- VV VV ii SSSSSS ii OOOOOOO NN NN
- VV VV ii SS ii OO OO NNN NN
- VV VV ii SS ii OO OO NNNN NN
- VV VV ii SSSSSS ii OO OO NN NN NN
- VV VV ii SS ii OO OO NN NN NN
- VV VV ii SS ii OO OO NN NNNN
- VVV ii SS ii OO OO NN NNN
- V ii SSSSSS ii OOOOOOO NN NN
-
-
- Version 1.0
-
-
-
-
-
-
-
- WG-Vision ist eine Weiterentwicklung der Klassenbibliothek
- WGRAPH 1.0
-
-
-
- WG-Vision I
-
-
-
-
-
-
-
- Eingetragene Warenzeichen
-
- Microsoft, MS-DOS und Windows sind eingetragene Warenzeichen
- der Microsoft Corp., USA
-
- Turbo Pascal und Borland Pascal sind eingetragene Waren-
- zeichen von Borland International Inc., USA
-
-
-
- WG-Vision verwendet einen VESA-BGI-Treiber der Firma W&B
- Software, Dresden
-
- Aus Gründen des Copyrights liegen diesem Programmpaket nur
- die Shareware-Versionen der VESA-Treiber von W&B Software
- bei. Die Treiber, die sich im Verzeichnis PDVESA befinden,
- sind Public Domäin und können zusammen mit den mit WG-Vision
- entwickelten Anwendungen beliebig weitergegeben werden.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- WG-Vision II
-
-
-
-
-
-
-
- Inhaltsverzeichnis
-
-
- 1. Programmieren mit WG-Vision ........................... 1
-
- 2. Aufbau von WG-Vision .................................. 2
-
- 3. Programmierung des Desktops ........................... 4
- 3.1. Aufbau des Desktops ................................... 6
- 3.2. Gestaltung des Rahmens ................................ 6
- 3.3. Gestaltung des Arbeitsbereiches (Hintergrund) ........ 11
- 3.4. Aufbau eines Menüs ................................... 16
- 3.4.1. Farbeinstellungen .................................... 22
- 3.4.2. Laden von Menüs aus Ressourcen ....................... 23
- 3.4.3. Verarbeitung von Menü-Kommandos, der Event-Handler ... 26
- 3.4.4. Verschieben des Menüs in der Menüzeile ............... 32
- 3.5. Grafikmodus einstellen ............................... 33
- 3.6. Wechseln der Desktop-Farben zur Laufzeit ............. 37
- 3.7. Umschalten in den Alpha-Modus ........................ 40
-
- 4. Heap- und EMS-Überwachung ............................ 41
-
- 5. Schöne neue Fensterwelt .............................. 43
- 5.1. Programmierung ....................................... 46
- 5.1.1. Eigenschaften eines Fensters festlegen ............... 48
- 5.1.2. Hintergrundinformationen zur Fenstertechnik .......... 63
- 5.1.3. Fenster mit Rollbalken ............................... 69
- 5.1.3.1. Farbgestaltung der Rollbalken und des Scrollbereichs . 76
- 5.1.3.2. Programmierung des Scrollers ......................... 77
- 5.1.3.3. Bedienung des Rollbalkens mit der Tastatur ........... 80
- 5.1.3.4. Verwendung der Sonderzeichensätze .................... 80
- 5.1.3.4. Grafiken in einem Scrollfenster darstellen ........... 82
- 5.2. Programmierung von Dialogen .......................... 85
- 5.2.1. Pushbuttons (Drucktasten) ............................ 86
- 5.2.1.1. Farbgestaltung ....................................... 90
- 5.2.1.2. Verändern der Textposition ........................... 91
- 5.2.2. Statische Texte ...................................... 96
- 5.2.3. Rahmen, Gruppenrahmen ............................... 101
- 5.2.3.1. Farbgestaltung ...................................... 102
-
-
-
- WG-Vision III
-
-
-
-
-
-
-
- 5.2.4. Icons ............................................... 103
- 5.2.5. Aktive Dialogelemente in WG-Vision .................. 104
- 5.2.6. Radio-Buttons (Optionsschaltflächen) ................ 106
- 5.2.7. Checkbuttons (Kontrollfelder) ....................... 118
- 5.2.7.1. Farbgestaltung von Radio- und Checkbutton ........... 120
- 5.2.8. Textfelder (Edit-Controls) .......................... 120
- 5.2.8.1. Datenübergabe von und in Eingabefelder .............. 122
- 5.2.8.2. Farbgestaltung von TInputLine-Objekten .............. 128
- 5.2.8.3. Aufbau von Eingabemasken ............................ 143
- 5.2.9. Zählschalter ........................................ 144
- 5.2.10. Listboxen ........................................... 148
- 5.2.10.1.Farbpalette ......................................... 152
- 5.2.11. Zusammenfassung Dialogelemente ...................... 152
- 5.3. Child-Fenster ....................................... 155
- 5.4. Programmierung einer Iconleiste ..................... 163
- 5.5. Mitteilungsboxen .................................... 185
- 5.6. Anzeigen von Fehlermeldungen ........................ 186
- 5.7. Kontextsensitive Hilfe .............................. 189
- 5.8. Statuszeile ......................................... 193
- 5.9. Zweisprachige Programmierung ........................ 194
-
- 6. Objekte im Detail ................................... 195
- 6.1. Unit WDriver ........................................ 195
- 6.1.1. Ansteuerung der Grafikkarte - TVideoDevice .......... 195
- 6.1.2. Ansteuerung eines Spielhebels - TJoyStickDevice ..... 199
- 6.1.3. Tastatur - TKeyboardDevice .......................... 202
- 6.1.4. Maus - TMouseDevice ................................. 212
- 6.1.4.1. Erstellung von Mauszeiger-Ressourcen ................ 218
- 6.1.4.2. Einige Hinweise zur Benutzung des Mausobjektes ...... 224
- 6.1.5. SummaSketch-Digitizer - TSSDigiDevice ............... 226
- 6.2. Unit WText .......................................... 232
- 6.2.1. Standard-VGA: Sonderzeichensätze .................... 232
- 6.3. Unit WFont .......................................... 237
- 6.3.1. ROM- und Userzeichensätze in WG-Vision - TPixelFont . 237
- 6.3.2. Fontmania ........................................... 237
- 6.3.3. Font-Ressourcen ..................................... 239
- 6.3.4. Objekt TPixelFont ................................... 239
- 6.3.5. Verwendung der Vektorzeichensätze - TVektorFont ..... 256
- 6.3.5.1. Skalierung der BGI-Zeichensätze ..................... 256
-
-
-
- WG-Vision IV
-
-
-
-
-
-
-
- 6.4. Unit WEMS - Die Verwaltung des Expanded Memory ...... 259
- 6.4.1. Ein paar Worte zur Funktionsweise ................... 260
- 6.5. Schwelgen in Farben - Die Unit WPalette ............. 272
- 6.5.1. Farbmodelle ......................................... 283
- 6.5.1.1. RGB-Modell .......................................... 283
- 6.5.1.2. HSV-Modell .......................................... 284
-
- 7. Die Kern-Units von WG-Vision ........................ 285
- 7.1. Unit WAPP ........................................... 285
- 7.1.1. Aufbau eines WG-Vision-Programms .................... 285
- 7.2. Unit WViews ......................................... 291
- 7.2.1. Objekt TView ........................................ 291
- 7.2.2. Objekt TGroup ....................................... 293
- 7.2.2.1. Aufbau einer doppelt verketteten Liste .............. 295
- 7.2.3. Speicherobjekte ..................................... 302
- 7.2.4. Das Rahmenobjekt .................................... 303
- 7.3. Unit WDlg ........................................... 305
- 7.3.1. Das Standard-Fenster - TWindow ...................... 305
- 7.3.2. Dialogfenster - TDlgWindow .......................... 308
- 7.3.2.1. Dialogelemente ...................................... 311
-
- 8. WG-Vision und der Coprozessor ....................... 313
- 8.1. Erweiterte Funktionen des Coprozessors .............. 313
-
- 9. Verwendung von Overlays ............................. 315
-
- 10. Tips und Tricks ..................................... 318
-
- 10.1. Wir basteln uns einen Screensaver ................... 318
-
-
-
-
-
-
-
-
-
-
-
-
-
- WG-Vision V
-
-
-
-
-
-
-
- Anhang Interfacedokumentation der Units
-
- WDECL ........................................................ 325
- WAPP ......................................................... 334
- WVIEWS ....................................................... 337
- WDRIVER ...................................................... 344
- WDLG ......................................................... 349
- WEVENT ....................................................... 357
- WERROR ....................................................... 359
- WTEXT ........................................................ 360
- WEMS ......................................................... 362
- WUTILS ....................................................... 363
- WFONT ........................................................ 364
- WHELP ........................................................ 366
- WPCX ......................................................... 368
- W256PCX ...................................................... 369
- WCPROC ....................................................... 371
- WFILEDLG ..................................................... 372
- WPRINT ....................................................... 374
- WICNEDIT ..................................................... 377
- WCALC ........................................................ 379
- WUHR ......................................................... 381
- WPALETTE ..................................................... 383
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- WG-Vision VI
-
-
-
-
-
-
-
- Objekt-Hierarchie WG-VISION Unit
-
-
- Objekte
- - TObject [WDECL]
- - TView [WVIEWS]
- - TGroup [WVIEWS]
- - TBackground [WVIEWS]
- - TCalcBackground [WCALC]
- - TColorBar [WPALETTE]
- - TDruckBgrd [WPRINT]
- - TDsktpBgrd [WAPP]
- - TIconEditBgrd [WICNEDIT]
- - TIDlgBgrd [WFILEDLG]
- - TODlgBgrd [WFILEDLG]
- - TOptionBgrd [WPRINT]
- - TPWorkshopBgrd [WPALETTE]
- - TScaleBgrd [WPALETTE]
- - TUhrBgrd [WUHR]
- - TButton [WDLG]
- - TGroupFrame [WDLG]
- - TIcon [WDLG]
- - TInputLine [WDLG]
- - TNumButton [WDLG]
- - TPushButton [WDLG]
- - TRadioButton [WDLG]
- - TCheckButton [WDLG]
- - TScroller [WDLG]
- - THelpScroller [WHELP]
- - TListBox [WDLG]
- - TDateiListBox [WFILEDLG]
- - TDesktop [WVIEWS]
- - TFrame [WVIEWS]
- - TLine [WVIEWS]
- - TMemory [WVIEWS]
- - TEMS [WVIEWS]
- - THardDisk [WVIEWS]
- - THeap [WVIEWS]
-
-
-
-
- WG-Vision VII
-
-
-
-
-
-
-
- - TProgram [WAPP]
- - TApp [WAPP]
- - TWindow [WDLG]
- - TDlgWindow [DLG]
- - TCalculator [WCALC]
- - TDigitalUhr [WUHR]
- - TDruckOptionen [WPRINT]
- - TIconEdit [WICNEDIT]
- - TInputDialog [WFILEDLG]
- - TOutputDialog [WFILEDLG]
- - TPalWorkShop [WPALETTE]
- - TPrintOptionWindow [WPRINT]
- - TScale [WPALETTE]
- - TGrayBar [WPALETTE]
- - THelpWindow [WHELP]
- - TMainMenu [WVIEWS]
- - TSubMenu [WVIEWS]
- - TScrollBar [WDLG]
- - TObject [WDECL]
- - TJoyStickDevice [WDRIVER]
- - TKeyboardDevice [WDRIVER]
- - TMouseDevice [WDRIVER]
- - TPixelFont [WFONT]
- - TSSDigiDevice [WDRIVER]
- - TVektorFont [WFONT]
- - TVideoDevice [WDRIVER]
- - TLinePrint [WPRINT]
- - TPalette [WPALETTE]
- - TPCXImage [WPCX]
- - TPoint [WDECL]
- - TRect [WDECL]
- - TText [WTEXT]
-
-
-
-
-
-
-
-
-
-
- WG-Vision VIII
-
-
-
-
-
-
-
- Leistungsmerkmale von WG-VISION
-
- Allgemeine Angaben
-
- - 65 Objekte in 21 Units
- - 12000 Zeilen Quelltext in der Profiversion
-
- Hardware
-
- WG-Vision unterstützt
-
- - Maus
- - Tastatur
- - Joystick
- - Digitizer (Summagraphic MM-Serie)
-
- Grafik
-
- - Standard-VGA und EGA (VGA wird empfohlen)
- - Super-VGA's mit VESA-Unterstützung (VESA-Treiber für die
- meisten Grafikcontroller verfügbar), 256 Farben in allen
- unterstützten Auflösungen (nur Voll- und Profiversion)
-
- Oberfläche
-
- - WG-Vision erlaubt die Erstellung von Programmen mit einer
- stark an Windows angelegten Nutzeroberfläche (GUI)
- - SAA-konformes Menüsystem. Unterstützung von Menü-
- Ressourcendateien.
- - Programmierung von Statuszeile und Iconleisten problemlos
- möglich.
- - Kontextsensitives Hilfesystem
-
-
-
-
-
-
-
-
-
-
- WG-Vision IX
-
-
-
-
-
-
-
- - voll fensterorientiert
- * Verschiebbare und in ihrer Größe veränderbare Fenster
- * Dialogboxen mit - Druckschalter (mit und ohne Icons)
- - Radio- und Checkbuttons
- - Eingabefelder mit Editierfunktionen
- und Rollen
- - Eingabemasken
- - Zählschalter
- - Listboxen mit horizontalen und
- vertikalen Rollbalken
- - Statische Texte, Unterstützung von
- 9 Vektorzeichensätzen
- - Gruppenrahmen und Icons
- * Mitteilungsfenster (Messageboxen)
- * Fenster mit Rollbalken
- * Childfenster
-
- Die Bedienung eines WG-Vision-Programmes kann mit der Maus
- und mit der Tastatur erfolgen
-
- Speicher
-
- - Verwendung von EMS zur Auslagerung von Fenster-
- Untergrundbereichen und Daten. Wenn kein EMS vorhanden
- ist, werden Bildschirmbereiche in tempöräre Swapdateien
- gerettet.
- - Speicherobjekte für Heap, Festplatte und EMS
-
- Zusätzlich zu den Kernroutinen enthält WG-Vision Objekte für
-
- - Datei Ein- und Ausgabedialoge
- - Paletteneditor für die 256-farbigen VESA-Modi
- - IconEditor
- - Digitaluhr
- - Erweiterte Funktionen des Coprozessors (ab INTEL 80387)
- - VGA-Fonts im Grafikmodus, 6 Sonderzeichensätze für
- Standard-VGA
- - Laden und Speichern von PCX-Bildern mit 16 und 256 Farben
-
-
-
-
- WG-Vision X
-
-
-
-
-
-
-
- Hinweise zur Arbeit mit der Klassenbibliothek
-
- 1. Units
-
- In den Programmbeispielen des Handbuchs werden die einzu-
- bindenden Units i.R. explizit nicht angegeben. Schauen Sie
- deshalb in der Tabelle der Objekte nach, in welcher Unit das
- betreffende Objekt implementiert ist.
-
- 2. Verzeichnisse
-
- Für ein Pascal-Projekt hat sich folgende Verzeichnisstruktur bewährt:
-
- - Projekt - EXE {EXE und TPU's}
- - UNITS {Projekt- und WG-VISION-Units}
- - INC {COMPILER.INC, INC-Dateien}
- - OBJ {Objektdateien}
-
- Wenn Sie mit Borland Pascal 7.0 und nur mit den TPU's
- von WG-VISION arbeiten, dann sollten Sie diese TPU's in
- das Verzeichnis BIN von BP7 kopieren. Andernfalls müssen Sie
- in einem separaten Verzeichnis oder im Verzeichnis EXE des
- Projekts zugänglich sein. Nicht vergessen, in der IDE
- Directories einstellen !
-
- 3. IDE
-
- - Linkpuffer auf "Disk" stellen
- - TP6/7: EMS verwenden
- - Directories einstellen
- - Kompilieren auf DISK
- - Einstellungen in <Projektname>.TP retten
-
- 4. Compileroptionen
-
- Die Compileroptionen befinden sich in der Include-Datei
- COMPILER.INC. Sie werden beim Compilieren der Bibliothek
- über den Include-Befehl in die Units mit eingebunden. Wenn
- Sie die Quellen von WG-Vision besitzen, dann sollten Sie in
-
-
-
- WG-Vision XI
-
-
-
-
-
-
-
- der Testphase Ihres Programms die Präprozessorkonstante
- Debug einschalten, damit Sie mit dem Debugger auch innerhalb
- der Units von WG-Vision herumstöbern können. COMPILER.INC
- hat folgenden Aufbau:
-
- (************************************************
- * *
- * COMPILER-Optionen für WG-Vision 1.0 *
- * *
- *---------------------------------------------- *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- ************************************************)
-
- { Die Optionen sind auf maximale Geschwindigkeit ausgelegt}
-
- {$DEFINE Debug} { Nur in der Testphase setzen! }
-
- {$IFDEF Debug} { Debugging eingeschaltet }
-
- {$A+,B-,D+,F-,G+,I+,L+,O-,P-,Q+,R+,S+,T-,V+,X-,Y+}
-
- {$ELSE}
-
- {$A+,B-,D-,F-,G+,I-,L-,O-,P-,Q-,R-,S-,T-,V+,X-,Y+}
-
- {$ENDIF}
-
- { Checking, ob Coprozessor vorhanden ist }
-
- {$IFDEF CPU87}
-
- {$N+,E-}
-
- {$ELSE}
-
- {$N+,E+}
-
- {$ENDIF}
-
-
-
-
- WG-Vision XII
-
-
-
-
-
-
-
- Unterschiede zwischen Shareware- und Vollversion
-
- WG-VISION wird in drei Varianten angeboten:
-
- 1. Sharewareversion : Darf frei kopiert und vervielfältigt werden,
- wenn der Inhalt der Diskette dabei nicht
- verändert wird. Für den Kopierservice dürfen
- maximal 15.- DM verlangt werden.
-
- 2. Vollversion : Enthält das Programmpaket in Form von TPU's
- für die Borland-Compiler TP6 / TP7 und BP7.
- Der Preis beträgt 59.- DM + Porto und Verpackung.
-
- 3. Profiversion : Enthält alle Quellen von WG-VISION.
- Der Preis beträgt 149.- DM + Porto und Verpackung.
-
- In der Shareware-Version werden nur die 16-farbigen EGA- und VGA-Modi
- unterstützt. Außerdem erscheint am Ende eines mit WG-VISION kompilierten
- Programms ein Registrierhinweis. Beim Anklicken des ENDE-Buttons vom
- Desktop wird ein Copyright-Fenster aufgeblendet. Weitere Einschränkungen
- sind nicht vorhanden.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- WG-Vision XIII
-
-
-
-
-
-
-
- Aus der Szene ...
-
-
- Fachhochschule für Technik und Wirtschaft Reutlingen
-
- ... unsere Studenten sind von Ihrem Produkt beeindruckt.
-
- JDS-Report 5/93 (Rainer Nausedat)
-
- ... Mit WGRAPH 2.0 stellt der Autor Dipl.Phys. Mathias Scholz
- nun eine objektorientierte Klassenbibliothek für Turbo- und
- Borland-Pascal vor, die jedem fleißigen Turbo-Vision-Nutzer
- die Tränen der Freude in die Augen treiben dürfte.
-
- ... Die mit WGRAPH erzeugten Fenster, Messageboxen, Menüs etc.
- sind optisch höchst ansprechend und zeugen von der Liebe des
- Programmierers zum Detail. Bei der Gestaltung der Fenster,
- Menüs etc. wurde auch auf absolute Kleinigkeiten geachtet.
- Das Outfit der mit WGRAPH erzeugten Programme ist professionell.
-
- ... Ich empfehle bei Gefallen unbedingt den Kauf der Quelltext-
- version: Der Autor gestattet auch die lizenzfreie Nutzung von
- Programmteilen (z.B. PCX-Bilder lesen und schreiben) und weiterhin
- ist WGRAPH auch gut als Lehrstück geeignet. Anstatt sich bei einem
- Massenverlag ein Buch für rund 100.- DM über Turbo Pascal und die
- objektorientierte Programmierung zu kaufen, sollte man sich lieber
- seine Handbücher schnappen und den Quelltext von einem Produkt wie
- WGRAPH durchackern. Der Nutzen ist wesentlich größer und zudem hat
- man auch noch eine vollständige, ansprechende Bibliothek.
-
-
-
-
-
-
-
-
-
-
-
-
-
- WG-Vision XIV
-
-
-
-
-
-
-
- Mit WG-Vision wurden vom Autor bis jetzt folgende größere Projekte
- erstellt:
-
- SBG 1.0 Digitale Bildverarbeitung für ST4-CCD-Kameras (diese Kamera
- wird von Amateurastronomen zur Fotografie von kosmischen
- Objekten eingesetzt). Die Demo-Version liegt der Klassen-
- bibliothek bei (SBGDEMO.EXE)
-
- IMOD Berechnung der Schadstoffausbreitung nach dem Gauß-Modell
- unter Berücksichtigung komplizierter orographischer und
- meteorologischer Verhältnisse
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 1 -
-
-
-
-
-
-
- 1. Programmieren mit WG-Vision
-
- Der Aufbau einer grafischen Oberfläche für ein Programm ist
- eine zeitraubende und fehleranfällige Angelegenheit. Das
- gilt besonders dann, wenn man näherungsweise die Funktiona-
- lität und Flexibilität von Windows als Prototyp einer grafi-
- schen Betriebssystem-Erweiterung anstrebt. Eine ausgefeilte
- Fenstertechnik in Verbindung mit einer ereignisgesteuerten
- Programmarchitektur läßt sich am komfortabelsten mit Hilfe
- objektorientierter Programmiermethoden realisieren. Borlands
- Spitzenprodukte Turbo-Vision und Object Windows können dabei
- als Vorbild dienen.
- WG-Vision besteht aus einer Anzahl von Kernbibliotheken, die
- in ihrer Einheit und Komplexität den Aufbau von Tastatur-
- und Maus-gesteuerten Programmen ermöglichen, die sich im ge-
- wohnten Windows-Look dem Nutzer präsentieren. Ein "klassi-
- scher" Pascal-Programmierer muß bei der Arbeit mit WG-Vision
- in vielerlei Hinsicht umdenken. An erster Stelle ist die Be-
- herrschung objektorientierter Programmiertechniken zu nen-
- nen. Sie sind Voraussetzung, um mit WG-Vision ansprechende
- und fehlerfreie Programme zu erstellen. Da es bereits eine
- ganze Anzahl guter Bücher gibt, die sich mit objektorien-
- tierter Programmierung beschäftigen, soll hier nicht weiter
- auf dieses Thema eingegangen werden. Trotzdem möchte ich
- keinen Leser abschrecken, der noch nie etwas über diese neue
- Art von Programmieren gehört hat. WG-Vision ist durchaus ge-
- eignet, um OOP (object oriented programming) zu erlernen.
- Vor der Verwendung einzelner Units aus WG-Vision als her-
- kömmliche Bibliotheken möchte ich warnen (mit Ausnahme viel-
- leicht von WDRIVER, WFONT und WEMS), da sie nur als Einheit
- ihre Fähigkeiten entfalten können. Da die Objekte der
- Toolbox hierarchisch geordnet sind, macht es auch wenig
- Sinn, sie aus ihrem ganz spezifischen Zusammenhang zu
- reißen. Ein WG-Vision Programm wird entweder ganz aus WG-
- Vision heraus entwickelt oder man läßt es bleiben. Einen
- Mittelweg gibt es nicht. Das bedeutet keine Einschränkung in
- den Möglichkeiten von WG-Vision. So gesehen bildet diese
- Klassenbibliothek ein festes Fundament, auf das sich mehr
- oder weniger komplexe Programme aufbauen lassen.
-
-
-
- Programmierhandbuch WG-Vision - 2 -
-
-
-
-
-
-
-
- 2. Aufbau von WG-Vision
-
- Der Kern von WG-Vision besteht aus folgenden Units:
-
- WDECL : Enthält grundlegende Deklarationen und einige
- Standardobjekte wie TRect und TObject
-
- WAPP : Applikationsobject
-
- WVIEWS : Objektverwaltung (TView, TGroup, Menü und
- Desktop)
-
- WDLG : Fenster- und Dialogobjekte
-
- WEVENT : Event-Verwaltungsroutinen
-
- WDRIVER : Treiber für Bildschirm, Tastatur, Maus, Joystick
- und Summagraphic-Digitizer
-
- WEMS : Verwaltungsroutinen für Expanded Memory
-
- WERROR : Fehlermitteilungen
-
- Der Kern verwendet wiederum einige Objekte, die in folgenden
- Units zusammengefaßt sind:
-
- WUTILS : Allgemeine Hilfsroutinen
-
- WTEXT : Textausgabe und Texthandling
-
- WFONT : Zusatzzeichensätze im Grafikmodus, ROM-Zeichen-
- sätze und BGI-Vektorzeichensätze
-
- Folgende Bibliotheken wurden bereits mit WG-Vision
- entwickelt und dienen speziellen Aufgaben. Da Sie als Quell-
- text vorliegen, können sie als Beispiele für die Programm-
- entwicklung mit WG-Vision dienen:
-
- WPCX : Laden und Speichern von 16-farbigen PCX-Bildern
-
-
-
- Programmierhandbuch WG-Vision - 3 -
-
-
-
-
-
-
-
- W256PCX : Laden und Speichern von 256-farbigen PCX-Bildern
- (nur Voll- und Profi-Version)
-
- WPALETTE : Palettenmanipulation (VESA), Paletteneditor
-
- WFILEDLG : Dialoge zum Laden und Speichern von Dateien
-
- WHELP : kontextsensitives Hilfesystem
-
- WCALC : Taschenrechner
-
- WPRINT : Druckdialoge (Text)
-
- WICNEDIT : Icon-Editor für WG-VISION
-
- WCPROC : Erweiterte Funktionen des Coprozessors
- (ab 80387), Mathematische Standardfunktionen
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 4 -
-
-
-
-
-
-
-
- 3. Programmierung des Desktops
-
- Das Desktop stellt die Arbeitsfläche unseres Programms dar.
- Es hat das Aussehen eines einzigen großen Fensters, welches
- im Normalfall den gesamten Bildschirm überdeckt. Standard-
- mäßig besteht es aus folgenden Teilen:
-
- - Doppelrahmen
-
- - Titelleiste (Panel)
-
- - Menüleiste mit den Hauptmenüeintragungen
-
- - Arbeitsfläche
-
- Außerdem kann es noch mit einer Statuszeile ausgestattet
- werden.
- Das Panel besitzt in der linken Seite ein Quadrat mit einem
- kleinen Rechteck im Zentrum. Dieses Zeichen wird als Ende-
- Icon bezeichnet. Wir finden es auch bei den von WG-Vision
- generierten Fenstern wieder. Dort verbirgt sich darunter ein
- kleines Pull-Down-Menü, welches in Anlehnung an Windows als
- "Systemmenü" bezeichnet werden soll. Wenn mit der Maus das
- Ende-Icon des Desktop angeklickt wird, dann wird das Pro-
- gramm geschlossen. Im Klartext bedeutet das, daß WG-Vision
- ein cmCloseApplication-Kommando (verpackt in einem Ereignis-
- Rekord) generiert, welches das Programm beendet und die
- Steuerung wieder dem Betriebssystem übergibt. Natürlich kann
- der Programmierer diese Botschaft abfangen und sie z.B. be-
- nutzen, um eine Abfrage der Form "Wollen Sie dieses Programm
- wirklich beenden, ja/nein" zu realisieren. Eine weitere Mög-
- lichkeit zum Schließen einer Applikation besteht in der Ta-
- stenkombination <alt><x>.
- Das Desktop wird von einem der grundlegensten Objekte von
- WG-Vision, TApp, zur Verfügung gestellt. Jedes Programm, das
- Sie mit WG-Vision entwickeln, muß ein Nachkomme von diesem
- Objekt sein.
- Um das Standard-Desktop auf dem Bildschirm zu zaubern, sind
- nur folgende Programmzeilen notwendig:
-
-
-
- Programmierhandbuch WG-Vision - 5 -
-
-
-
-
-
-
-
- program Desktop;
-
- uses WApp;
-
- type TApplication=object(TApp)
- end;
-
- var MyApp:TApplication;
-
- begin
- MyApp.Init('Standard-Desktop'); {Initialisierung + Paneltext}
- MyApp.Run; {Abarbeitungsschleife}
- MyApp.Done; {Aufräumen und Beenden}
- end.
-
- MyApp hat als Instanz von TApplication alle Eigenschaften
- von TApp geerbt. Natürlch hätte man auch gleich eine Instanz
- von TApp bilden können. In diesem Fall wäre aber eine Wei-
- terentwicklung des Programms nicht mehr möglich gewesen.
- Erst die Ableitung eines neuen Objektes erlaubt die Eigen-
- schaften dieses Objektes gezielt zu verändern. Das kann
- entweder durch das Überschreiben bereits vorhandener virtu-
- eller Methoden oder durch die Implementierung von neuen Me-
- thoden geschehen. Doch bevor wir näher darauf eingehen,
- schauen wir uns noch einmal das Desktop in seiner Grundein-
- stellung an:
-
- - Grafik VGA (640x480x16)
- - Graugemusterter Arbeitsbereich
- - Blaues Panel mit Überschrift
- - Hellgrauer Doppelrahmen
- - Leere weiße Menüzeile
- - Mauszeiger bei installierten Maustreiber
-
- Das Aussehen des Desktops läßt sich leicht verändern. Das
- betrifft die Größe, den Grafikmodus und die farbliche Ge-
- staltung.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 6 -
-
-
-
-
-
-
-
- 3.1. Aufbau des Desktop
-
- Das Desktop besteht im Wesentlichen aus zwei Bestandteilen,
- dem Rahmen (Frame) und dem Hintergrund. Um Mißverständnissen
- vorzubeugen, soll folgende Sprachregelung gelten. Der Hin-
- tergrund ist immer der Bereich zwischen dem Rahmen, der auf
- dem Bildschirm zu sehen ist. Im Fall des Desktops ist das
- der graugemusterte Arbeitsbereich. Als Untergrund soll der
- rechteckige Bereich des Bildschirms bezeichnet werden, der
- vom Rahmen und dem Hintergrund abgedeckt wird. Im Fall eines
- Fensters lagert WG-Vision den Untergrund in eine Datei bzw.
- in den EMS aus, während der Hintergrund und der Rahmen des
- darüberliegenden Fensters angezeigt wird. Erst beim Schlie-
- ßen des Fensters erfolgt eine Restauration des Untergrundes,
- wobei das gerade aufgeblendete Fenster verschwindet.
- Rahmen und Hintergrund sind zwei separate Objekte mit ganz
- speziellen Eigenschaften. Bei der Initialisierung des Desk-
- tops werden zwei Pointer auf Instanzen dieser Objekte er-
- zeugt und in eine Liste mit dem Namen List eingefügt. Das
- geschieht für Sie unsichtbar in der Unit WApp mittels der
- Methode InsertItem. List ist wie alle Listenobjekte in WG-
- Vision eine Instanz von TGroup. Dieses wirklich grundlegende
- Objekt stellt eine doppelt verkettete Liste einschließlich
- einer großen Anzahl von Methoden zu deren Verwaltung zur
- Verfügung.
- Damit Sie den Rahmen und den Hintergrund des Desktops nach
- Ihrem Ermessen gestalten können, stellt Ihnen TApp die vir-
- tuellen Methoden SetDesktopFrame und SetDesktopBackground
- zur Verfügung. Diese Methoden sind virtual deklariert und
- lassen sich bei Bedarf überschreiben. Wie das konkret
- gemacht wird, zeigt eines der nächsten Beispiele.
-
- 3.2. Gestaltung des Rahmens
-
- Der Desktop-Rahmen besteht aus einem Außenrahmen, dem Panel
- mit Text und dem Ende-Icon. Er ist ein eigenständiges Objekt
- mit der Bezeichnung TFrame (alle Objekte in WG-Vision begin-
- nen mit einem großen T, alle Typen mit einem kleinen t und
- alle Zeiger auf Objekte mit einem großen P etc.). Der Rahmen
-
-
-
- Programmierhandbuch WG-Vision - 7 -
-
-
-
-
-
-
-
- ist sehr komplex. Er muß sich nicht nur selbst darstellen,
- sondern auch auf Maus- und Tastaturereignisse reagieren kön-
- nen. Diese Eigenschaften werden aber erst bei frei ver-
- schieb- und skalierbaren Fenstern benötigt. Der Desktop-
- Rahmen ist statisch. Es läßt sich lediglich seine Größe, die
- Form (Einfach- oder Doppelrahmen) und die Färbung ändern.
- Um einen neuen Rahmen zu gestalten, muß die Methode SetDesk-
- topFrame überschrieben werden:
-
- ...
- type TApplication=object(TApp)
- procedure SetDesktopFrame(Titel:string); virtual;
- end;
-
- ...
-
- procedure TApplication.SetDesktopFrame(Titel:string);
- var R:TRect;
- begin
- with Desktop^ do
- begin
- GetBounds(R);
- Frame:=new(PFrame, Init(R,R,Titel,winDouble+winPanel+winMenu));
- Frame^.Palette:=Pal(palRed);
- List^.InsertItem(Frame):
- end;
- end;
-
- Welche Informationen benötigt nun das Rahmenobjekt, um sich
- eine neue Form zu geben. Als Erstes seine Größe. Da der
- Desktop-Rahmen im Allgemeinen den gesamten Bildschirm um-
- faßt, benötigt er die Pixelmaße des Bildschirms. Diese wie-
- derum hängen von der Auflösung des gerade aktiven
- Grafikmodus ab. Da WG-Vision diese Maße bekannt sind (sie
- ergeben sich bei der Initialisierung des Grafikmodus), brau-
- chen Sie nur explizit aus den entsprechenden Variablen aus-
- gelesen zu werden. Das geschieht mittels der Methode
- GetBounds(R). Dabei ist R ein TRect-Objekt (d.h. nichts an-
- deres als ein Rechteck mit den Diagonalpunkten A und B), in
-
-
-
- Programmierhandbuch WG-Vision - 8 -
-
-
-
-
-
-
-
- dem nach Abarbeitung von GetBounds die Eckpunktkoordinaten
- des Bildschirms gespeichert sind. Eine weitere Information
- betrifft das Aussehen des Rahmens, Es wird durch folgende
- vordefinierte Konstanten festgelegt:
-
- winSingle / winDouble Rahmenform
- winPanel mit Titelleiste
- winMenu mit Ende-Icon
-
- Diese Konstanten lassen sich additiv verknüpfen und werden
- zusammen mit R und dem Títeltext dem Konstruktor von TFrame
- übergeben. Der Rahmen selbst wird im Heap angelegt und ein
- Pointer darauf (Frame) in die Elementeliste des Desktop's
- eingefügt. Um eine andere Rahmenform zu erhalten, müssen die
- Rahmenkonstanten entsprechend kombiniert werden. Wünschen
- Sie z.B. einen einfachen Desktop-Rahmen mit Titelleiste aber
- ohne Ende-Icon, dann lautet die entsprechende Zeile im
- Quelltext:
-
- Frame:=new(PFrame, Init(R,R,winSingle+winPanel));
-
- Wenn Sie auf eine Titelzeile verzichten, dann wird die Menü-
- zeile an die Position der Titelzeile gesetzt.
- Das Rechteck R beschreibt, wie bereits erwähnt, die Außmaße
- des Desktops. Es enthält als TRect-Objekt nach Aufruf von
- GetBounds die Koordinaten des linken oberen (Punkt A) und
- des rechten unteren Eckpunktes (Punkt B) des Bildschirms. Um
- das Desktop zu verkleinern, muß lediglich R verändert wer-
- den. TRect-Objekte verfügen zu diesem Zweck die Methoden
- Grow(a,b) und Move(dx,dy). Mit Grow verändert man die Größe
- des Rechtecks, indem zu den Koordinaten der rechten unteren
- Ecke a und b addiert wird. Move verschiebt das Rechteck um
- dx und dy auf dem Bildschirm. Um das Desktop zu verkleinern
- und anschließend zu zentrieren sind demnach zwei Schritte
- notwendig:
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 9 -
-
-
-
-
-
-
-
- ...
- GetBounds(R); {Dektop-Größe holen}
- R.Grow(-200,-80); {R verkleinern}
- R.Move(100,40); {R verschieben}
- ...
-
-
- Durch die Größenänderung wird auch der Arbeitsbereich klei-
- ner. Dem muß man Rechnung tragen, indem man die Größe des
- Workareas (d.h. der Arbeitsfläche) an die neuen Verhältnisse
- anpaßt:
-
- WorkArea.Assign(R.A.x+4,R.A.y+46,R.B.x-4,R.B.y-4);
-
- Das Workarea beschreibt jenen Bereich des Desktops, inner-
- halb dessen Fenster verschoben oder in ihrer Größe geändert
- werden können.
- Wenn Sie möchten, können Sie jetzt noch die Farbe des Rah-
- mens ändern. In unserem Beispiel geschieht das durch die Zu-
- weisund der Standard-Palette palRed. Sie können natürlich
- auch jedes Rahmenelement separat einfärben. In WG-Vision
- werden Farbpaletten als Strings definiert. Jedes Zeichen
- stellt einen Farbeintrag dar. Dabei werden die Turbo-Pascal-
- Farbnummern mit einem vorangestellten Doppelkreuz (z.B. #12
- für Hellrot) verwendet. Das ist nichts weiter als die Defi-
- nition eines ASCII-Zeichens über dessen Ordinalzahl.
- Die Rahmen-Palette (Palette1) hat folgenden Aufbau:
-
- Eintrag Bedeutung Standard
-
- 1 Außenrahmen #0 Schwarz
- 2 Zwischenrahmen #7 Hellgrau
- 3 Innenrahmen #0 Schwarz
- 4 Panelmischfarbe 1 #1 Blau
- 5 Panelmischfarbe 2 #9 Hellblau
- 6 Textfarbe Titelzeile #15 Weiß
-
-
- Palette1:=#0#7#0#1#9#15{...};
-
-
-
- Programmierhandbuch WG-Vision - 10 -
-
-
-
-
-
-
-
- Die Einträge in geschwungenen Klammern werden von anderen
- Objekten benutzt.
- Neben der Zuweisung einer Standardpalette stehen noch fol-
- gende Möglichkeiten zur Palettenmanipulation zur Verfügung:
-
- ...
- with Desktop^ do
- begin
- GetBounds(R);
- Frame:=new(PFrame, Init(R,R,Titel,winDouble+winPanel));
- Frame^.Palette:=#15#11#0#1#9#15; {1. Möglichkeit}
- Frame^.Palette:=Pal[palGray]; {2. Möglichkeit}
- Frame^.Palette[4]:=#14; {3. Möglichkeit}
- Frame^.Palette[2]:=#12;
- ...
- end;
- ...
-
- Pal ist ein array of string, wobei die Konstanten palStan-
- dard, palRed, palGray und palGreen Indizes in diesem Feld
- sind.
- Wichtig ist, daß Sie die Farbmanipulation vor dem Einfügen
- von Frame in List ausführen.
- Die in diesem Abschnitt beschriebene Art der Farbmanipulati-
- on gilt übrigens auch für andere Objekte innerhalb von WG-
- Vision. Jeder sich selbst darstellbare Objekttyp (z.B. Fen-
- ster oder einzelne Dialogelemente) besitzt eine eigene vor-
- definierte Farbpalette, die nachträglich leicht manipu-
- lierbar ist. Zum Teil stellt WG-Vision sogar spezielle
- Methoden zur Manipulation von Farbeinträgen zur Verfügung.
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 11 -
-
-
-
-
-
-
-
- 3.3. Gestaltung des Arbeitsbereiches (Hintergrund)
-
- Für das Aussehen des Arbeitsbereiches ist das Objekt
- TDsktpBgrd zuständig. Standardmäßig stellt es nichts weiter
- als eine graugemusterte Fläche dar. Um Änderungen vorzuneh-
- men, müssen Sie entweder die Draw-Methode des TDsktpBgrd-Ob-
- jekts überschreiben oder, wenn Ihnen nur die Farbe stört,
- die entsprechenden Paletteneinträge ändern.
- Beginnen wir mit dem einfachsten Fall. Genauso wie der Rah-
- men verwendet auch das Hintergrund-Objekt die Standardpalet-
- te 1. Es benutzt jedoch nur die Einträge 7 und 8. Eintrag 7
- legt den Hintergrund des Hauptmenü-Bereichs fest. Voreinge-
- stellt ist die Farbe Weiß. Eintrag Nr. 8 ist für den Ar-
- beitsbereich zuständig. Neben der Grundfarbe (standardmäßig
- Weiß) wird immer die Farbe Schwarz dazugemischt. Damit erge-
- ben sich zwangsläufig sehr dunkle Farben. Wenn das nicht
- ausdrücklich gewünscht wird, dann sollten Sie sich überle-
- gen, ob Sie nicht gleich den Hintergrund neu gestalten
- sollten. Dazu muß lediglich die Draw-Methode des Hinter-
- grund-Objekts überschrieben werden.
- Folgendes Beispiel zeigt wie Sie vorgehen müssen, um den Ar-
- beitsbereich mit einem grünen HatchFill-Muster zu versehen:
-
- 1. Neues Hintergrundobjekt ableiten
-
- ...
- type PNewDTBgrd=^TNewDTBgrd;
- TNewDTBgrd=object(TDsktpBgrd)
- procedure Draw; virtual;
- end;
- ...
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 12 -
-
-
-
-
-
-
-
- 2. Hintergrundobjekt in das Desktop einfügen
-
- procedure TApplication.SetDesktopBackground;
- var R:TRect;
- NBgrd:PNewDTBgrd;
- begin
- with Desktop^ do
- begin
- R:=Frame^.Area; {Bereich innerhalb des Rahmens bestimmen}
- NBgrd:=new(PNewDTBgrd, Init(R)); {Instanz auf dem Heap erzeugen}
- with NBgrd^ do
- begin
- Palette[7]:=#14; {Farben neu definieren}
- Palette[8]:=#10;
- end;
- List^.InsertItem(NBgrd); {In Desktop-Liste einfügen}
- end;
- end;
-
- Beachten Sie, daß im Konstruktor das neue Hintergrundobjekt
- angegeben wird. Das ist notwendig, da zur Hintergrundgestal-
- tung eine neue Draw-Methode implementiert werden muß:
-
- 3. Neue Draw-Methode
-
- procedure TNewDTBgrd.Draw;
- begin
-
- Border enthält die Koordinaten des Bereichs innerhalb des Rahmens.
-
- with Border do
- begin
-
- Menübereich, Hintergrund Gelb
-
- SetFillStyle(SolidFill, GetPalColor(7));
- Bar(A.x,A.y,B.x,A.y+20);
-
-
-
-
-
- Programmierhandbuch WG-Vision - 13 -
-
-
-
-
-
-
-
- Arbeitsbereich, Hatchfill
-
- SetFillStyle(HatchFill, GetPalColor(8));
- Bar(A.x,A.y+22,B.x,B.y);
- end;
- end;
-
- Die Variable Border enthält als TRect-Objekt die Koordinaten
- des Bereichs innerhalb des dazugehörigen Fenster-Objekts.
- Sie kann immer dann Verwendung finden, wenn der Hintergrund
- eines Fensters (oder hier des Desktops) frei gestaltet wer-
- den soll. Die Prozedur Draw verwendet die Punkte A und B, um
- den zu füllenden Bereich konkret festzulegen. Natürlich ist
- es Ihnen überlassen, was für Grafik-Befehle Sie zwischen
- begin und end schreiben. Beispielsweise ist es auch möglich,
- hier ein Hintergrundbild von Windows aufzublenden. Bedingung
- ist, daß Sie die Windows-Bitmap zuvor in ein PCX-Bild umge-
- wandelt haben. Sie können zu diesem Zweck natürlich auch je-
- des x-beliebige PCX-Bild verwenden, eben das, welches Ihnen
- gefällt und zu Ihrem Programm paßt. Sie müssen lediglich be-
- achten, in welchem Grafikmodus WG-Vision gerade arbeitet.
- PCX-Bilder mit 16 Farben unterscheiden sich eben doch von
- PCX-Bildern mit 256 Farben. WG-Vision trägt dem Rechnung,
- indem es zwei verschiedene Units zum Laden und Speichern
- derartiger Bildern zur Verfügung stellt. WPCX arbeitet in
- den 16-farbigen Standardmodi der VGA- bzw. EGA-Karte.
- W256PCX erlaubt das Laden und Speichern von 256-farbigen
- PCX-Bildern. Diese Unit ist natürlich nur sinnvoll, wenn ein
- 256-Farb-Modus aktiv ist. Außerdem muß beachtet werden, daß
- WG-Vision die ersten 16 Einträge der Farbpalette für sich
- selbst benötigt und diese nicht unbedingt mit den Eintragun-
- gen in der Palette der PCX-Datei übereinstimmen. Das ist
- aber fast immer der Fall. Es bleibt also nichts anderes üb-
- rig, als eine Farbreduktion und "Freilenken" der ersten 16
- Paletteneintragungen vorzunehmen. Einige wenige Bildbearbei-
- tungsprogramme sind dazu in der Lage (z.B. das Sharewarepro-
- gramm IMPROCES).
- Was muß man tun, um z.B. das 16-farbige PCX-Bild "WETT.PCX"
- als Hintergrundbild für das Desktop zu laden ?
-
-
-
- Programmierhandbuch WG-Vision - 14 -
-
-
-
-
-
-
-
- 1. Neues Hintergrundobjekt ableiten
-
- ...
- type PNewDTBgrd=^TNewDTBgrd;
- TNewDTBgrd=object(TDsktpBgrd)
- BgImage:TPCXImage; {Instanz von TPCXImage}
- procedure Draw; virtual; {Draw-Methode}
- end;
- ...
-
- 2. Hintergrundobjekt in das Desktop einfügen
-
- procedure TApplication.SetDesktopBackground;
- var R:TRect;
- NBgrd:PNewDTBgrd;
- begin
- with Desktop^ do
- begin
- R:=Frame^.Area; {Bereich innerhalb des Rahmens bestimmen}
- NBgrd:=new(PNewDTBgrd, Init(R)); {Instanz auf dem Heap erzeugen}
- with NBgrd^ do
- begin
- Palette[7]:=#14; {Farben neu definieren}
- Palette[8]:=#9;
- end;
- List^.InsertItem(NBgrd); {In Desktop-Liste einfügen}
- end;
- end;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 15 -
-
-
-
-
-
-
-
- 3. Neue Draw-Methode
-
- procedure TNewDTBgrd.Draw;
- var R:TRect;
- begin
- TDsktpBgrd.Draw; {Standard-Untergrund zeichnen}
- R.Copy(Border); {Bereich innerhalb des Rahmens in R kopieren}
- R.A.y:=R.A.y+21; {Menübereich freihalten}
- BgImage.Init(R,'WETT.PCX'); {Bild initialisieren}
- BgImage.LoadPCXImage(0); {Bild laden}
- end;
-
- Als Erstes wird der Standard-Untergrund gezeichnet. Das ge-
- schieht, in dem die Draw-Methode des Vorgängers (alse
- TDsktpBgrd) aufgerufen wird. Als Nächstes wird der Bereich
- festgelegt, in welches das Bild gezeichnet werden soll. Da-
- bei müssen Sie darauf achten, daß die Menüzeile freigehalten
- wird. Das erreicht man durch eine Neuzuweisung der y-Koordi-
- nate der oberen linken Ecke des Ausschnitts (Punkt A). Jetzt
- braucht nur noch das Bild von der Platte geladen und auf dem
- Bildschirm dargestellt werden. Diese Arbeit übernehmen die
- Routinen der Unit WPCX.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 16 -
-
-
-
-
-
-
-
- 3.4. Aufbau eines Menüs
-
- Der Aufbau einer Menüstruktur ist mit WG-Vision spielend
- einfach. Drei Schlüsselbefehle, MainMenu, SubMenu und New-
- Line reichen aus, um ein komplexes Pull-Down-Menü zu erstel-
- len, welches in Gestaltung und Bedienung weitgehend dem SAA-
- Standard entspricht. Wem selbst das zu viel ist, hat noch
- die Möglichkeit den Menübaum über eine Ressourcen-Datei zu
- laden. Dieser Weg hat den Vorteil, daß man die Menüstruktur
- einfach durch Austausch der entsprechenden Menüdatei ändern
- kann ohne das Programm neu kompilieren zu müssen. Anpassun-
- gen an andere Sprachen sind dadurch problemlos möglich.
- WG-Vision-Menüs können genauso wie Windows-Menüs bedient
- werden. Die <F10>-Taste aktiviert und deaktiviert das Haupt-
- menü. Mit den Kursortasten kann man Untermenüs öffnen, Menü-
- punkte auswählen und sich durch den Menübaum bewegen. Ein
- Druck auf die <ESC>-Taste schließt ein gerade aktives Unter-
- menü. Mit <ENTER> wird der gewünschte Menüpunkt ausgewählt.
- Wer gerne mit Shortkeys arbeitet, wird auch nicht im Stich
- gelassen. Die <alt>-Taste in Verbindung mit dem unterstri-
- chenen Buchstaben öffnet das gewünschte Untermenü. Jetzt
- braucht nur noch der entsprechende Buchstabe gedrückt wer-
- den, um einen Menüpunkt aufzurufen.
- Für besonders oft benötigte Funktionen können auch Hotkeys
- vergeben werden. Mit ihrer Hilfe lassen sich Menüpunkte un-
- ter Umgehung des Aufblendens des Menübaums aktivieren. Als
- Hotkeys finden besonders die Funktionstasten Verwendung.
- Am schnellsten und am Einfachsten gestaltet sich die Menü-
- auswahl mit der Maus. Einfach Anklicken und fertig !
- Von der Komplexität der Menüroutinen bemerken Sie als WG-Vi-
- sion Programmierer praktisch nichts. Sie sind lediglich für
- die Gestaltung des Menübaums zuständig.
- Die zur Menüdefinition zuständige virtuelle Methode hat den
- Namen InitMenuBar. Indem Sie diese Methode überschreiben,
- bauen Sie nach und nach Ihr Desktop-Menü auf. Für ein einfa-
- ches Malprogramm könnte es beispielsweise folgendermaßen
- aussehen:
-
-
-
-
-
- Programmierhandbuch WG-Vision - 17 -
-
-
-
-
-
-
-
- {Konstantendefinitionen für die Menü-Kommandos}
-
- const cmNew = 101; cmRestore = 201;
- cmLoad = 102; cmCut = 202;
- cmSave = 103; cmCopy = 203;
- cmPrint = 104; cmMove = 204;
- cmErase = 105; cmTurn = 204;
-
- cmMagni = 301; cmRoman = 401;
- cmGrid = 302; cmScript = 402;
- cmPencel = 303; cmTimes = 403;
- cmBrush = 304; cmNormal = 404;
- cmBold = 405;
- cmItalic = 406;
- cmUnderline = 407;
- ...
-
- type TApplication=object(TApp)
- procedure SetDesktopFrame(Titel:string);virtual;
- procedure SetDesktopBackground; virtual;
- procedure InitMenuBar; virtual;
- end;
- ...
-
- procedure TApplication.InitMenuBar;
- begin
-
- {Farbanpassung an das Desktop}
-
- Palette[1]:=#14; {Hauptmenüzeile Hintergrundfarbe}
- Palette[5]:=#14; {Untermenü,Hintergrundfarbe}
- Palette[4]:=#4; {Hauptmenüzeile,Auswahlbalken}
- Palette[12]:=#4; {Auswahlbalken}
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 18 -
-
-
-
-
-
-
-
- {Menüdefinition}
-
- MainMenu('~D~atei',1);
- SubMenu('~N~eues Bild',cmNew,0,0,false,false);
- SubMenu('Bild ~L~aden F3',cmLoad,0,kbF3,false,false);
- SubMenu('Bild ~S~peichern F2',cmSave,0,kbF2,false,false);
- NewLine;
- SubMenu('~D~rucken',cmPrint,0,0,false,false);
- SubMenu('Lös~c~hen',cmErase,0,0,false,false);
- NewLine;
- SubMenu('~B~eenden Alt-X,cmCloseApplication,0,altX,false,false);
- MainMenu('~B~earbeiten',2);
- SubMenu('~R~ückgängig',cmRestore,0,0,false,false);
- NewLine;
- SubMenu('~S~chnitt',cmCut,0,0,true,false);
- SubMenu('~K~opieren',cmCopy,0,0,true,false);
- SubMenu('~V~erschieben',cmMove,0,0,true,false);
- SubMenu('~D~rehen',cmTurn,0,0,true,false);
- MainMenu('~W~erkzeuge',3);
- SubMenu('~V~ergrößern',cmMagni,0,0,false,false);
- NewLine;
- SubMenu('~R~aster',cmGrid,0,0,false,false);
- NewLine;
- SubMenu('~P~insel ändern',cmPencel,0,0,false,false);
- SubMenu('~S~pray ändern',cmBrush,0,0,false,false);
- MainMenu('~S~chrift',4);
- SubMenu('~R~oman',cmRoman,0,0,false,true);
- SubMenu('~S~cript',cmScript,0,0,false,false);
- SubMenu('~T~imes',cmTimes,0,0,false,false);
- NewLine;
- SubMenu('~N~ormal',cmNormal,0,0,false,true);
- SubMenu('~F~ett',cmBold,0,0,false,false);
- SubMenu('~K~ursiv',cmItalic,0,0,false,false);
- SubMenu('~U~nterstrichen',cmUnderline,0,0,false,false);
- end;
-
- Jeder Hauptmenüpunkt wird durch den Befehl MainMenu defi-
- niert. Als erster Parameter folgt der Bezeichner, wobei der
- "Shortkey" in Tilde-Zeichen eingeschlossen wird. Über diesen
-
-
-
- Programmierhandbuch WG-Vision - 19 -
-
-
-
-
-
-
-
- Buchstaben in Kombination mit der Alt-Taste kann das dazuge-
- hörige Untermenü aufgeklappt werden. Danach folgt eine von
- ihnen festzulegende Zahl, der Help-Index. Er ist nur von Be-
- deutung, wenn Sie ihr Programm mit einer Online-Hilfe-Funk-
- tion ausstatten wollen.
- Hauptmenüpunkte können keine Kommandos aussenden. Deshalb
- ist eine direkte Steuerung des Programms durch Anklicken
- bzw. Aktivieren eines Hauptmenüpunktes nicht möglich.
- Zu jedem Hauptmenüpunkt gehört ein Untermenü mit möglichst
- mehr als einem Eintrag. Es ist als Pull-Down-Menü gestaltet,
- d.h. es wird nach Aktivierung des zugehörigen Hauptmenüpunk-
- tes "aufgeklappt". In unserem Beispiel besitzt das Hauptmenü
- "Datei" Untermenüs mit den Eintragungen "Neues Bild", "Bild
- Laden", "Bild Speichern", "Drucken", "Löschen" und
- "Beenden". Jedem Eintrag im Untermenü müssen Sie eine ein-
- deutige Zahl zuordnen. Diese Zahl wird als Kommando bezeich-
- net und im Konstantenteil ihrer Applikation vereinbart.
- Kommandobezeichner werden in WG-Vision immer mit dem Präfix
- "cm" versehen. Machen Sie es am besten genauso wie im Bei-
- spiel. Wählen Sie als Kommandos einfach die Submenü-Bezeich-
- ner mit einem vorangestellten "cm". Diese Kommandos
- benötigen Sie später zur Identifizierung des ausgewählten
- Menüpunktes.
- Verwenden Sie als Kommandos bitte immer Zahlen >=100, da ei-
- nige Kommandos, wie z.B. cmCloseApplication in WG-Vision be-
- reits definiert sind. Folgende Vorgehensweise hat sich
- bewährt: Die einzelnen Submenü-Punkte erhalten als Hunderter
- die Nummer des dazugehörigen Hauptmenüs. Dazu addieren Sie
- einfach die Untermenü-Nummern, sodaß sich beispielsweise für
- das Menü "Bearbeiten" folgende Kommandofolge ergibt:
-
- const cmRestore = 201;
- cmCut = 202;
- cmCopy = 203;
- cmMove = 204;
- cmTurn = 204;
-
- Neben der Aufruftaste (sie ist vorgeschrieben) können Sie
- jedem Submenü-Punkt einen speziellen Hotkey zuordnen (z.B.
-
-
-
- Programmierhandbuch WG-Vision - 20 -
-
-
-
-
-
-
-
- <F2> oder <alt><A>). Er wird als vierter Parameter in der
- Parameterliste von SubMenu übergeben. Erlaubt sind alle
- Scancodes. Bitte verwenden Sie die in der Unit WDecl vorde-
- finierten Konstanten, z.B.
-
- kbF1..kbF12
- ShiftF1..ShiftF12
- altF1..altF12
-
- Beachten Sie dabei, das <F10> bereits zur Aktivierung des
- Hauptmenüs vorgesehen ist. Weiterhin ist <F1> belegt, wenn
- das Hilfesystem aktiv ist.
- Natürlich können Sie auch für die Untermenüs eine Online-
- Hilfe vorsehen. Der dritte Parameter stellt den Help-Index
- dar. In unserem Beispiel ist er durchgängig auf 0 gesetzt
- (keine Hilfe verfügbar).
- Oftmals ist es günstig, einen Menüpunkt zu sperren, weil es
- keinen Sinn macht, ihn zu einem bestimmten Zeitpunkt auszu-
- führen. Solange z.B. in unserem fiktiven Malprogramm kein
- Ausschnitt definiert ist, macht es wenig Sinn, die Bearbei-
- tungsfunktionen "Verschieben", "Kopieren" usw. auszuführen.
- Indem Sie den Parameter Akt auf true setzen, kann der Menü-
- punkt bei Betätigung kein Kommando mehr absetzen. Auf dem
- Bildschirm wird der Bezeichner in der Farbe, der durch den
- Paletteneintrag 9 bzw. 10 vorgegeben ist (standardmäßig
- Hellgrau), dargestellt.
- Menüpunkte, die Alternativen darstellen (Ein-Aus), können
- mit einem Häkchen versehen werden. Dafür ist der Parameter
- Kennz zuständig.
- Mit NewLine trennen Sie Gruppen von Menüeintragungen ab.
-
- Syntax
-
- MainMenu(Eintrag:str25;Help:byte);
-
- Eintrag Menübezeichner. Der Aufrufbuchstabe ist in Tilde-
- Zeichen eingeschlossen
-
-
-
-
-
- Programmierhandbuch WG-Vision - 21 -
-
-
-
-
-
-
-
- Help HelpIndex. Dient zur Identifizierung des Hilfe-
- Textes einer On-Line-Hilfe.
-
- Beispiel:
-
- MainMenu('Ein~f~ügen',10);
-
- SubMenu(Eintrag:str25;Kommando:word;Help,Key:byte;
- Akt,Kennz:boolean);
-
- Eintrag Menübezeichner. Der Aufrufbuchstabe ist in Tilde-
- Zeichen eingeschlossen
-
- Kommando Kommando, welches bei Aktivierung abgesetzt wird
-
- Help HelpIndex. Dient zur Identifizierung des Hilfe-
- Textes einer On-Line-Hilfe.
-
- Key Spezial-Key. Dient dem schnellen Aufruf eines
- Menüs über die Tastatur. Es sind nur ScanCodes
- erlaubt.
-
- Akt Menüpunkt deaktiviert (true) ?
-
- Kennz Häkchen gesetzt (true) ?
-
- Beispiel:
-
- SubMenu('~N~eues Bild',cmNew,0,0,false,false);
- SubMenu('Bild ~L~aden F3',cmLoad,0,kbF3,false,false);
- SubMenu('Bild ~S~peichern F2',cmSave,0,kbF2,false,false);
-
- NewLine
-
- Trennt Menübereiche ab.
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 22 -
-
-
-
-
-
-
-
- 3.4.1. Farbeinstellungen
-
- Das Menü als Bestandteil des Applikationsobjekts verwendet
- standardmäßig eine Kopie der Palette2 aus der Unit WView.
- Innerhalb der Methode InitMenuBar können Sie die Standard-
- farben der einzelnen Menübestandteile leicht verändern, z.B.
-
- ...
- Palette[1]:=#14; {Hauptmenüzeile Hintergrundfarbe}
- Palette[4]:=#4; {Hauptmenüzeile,Auswahlbalken}
- Palette[5]:=#14; {Untermenü,Hintergrundfarbe}
- Palette[12]:=#4; {Auswahlbalken}
- ...
-
- Die Positionen (Index) innerhalb des Palettenstrings haben
- folgende Bedeutung:
-
- 1 Hauptmenü, Hintergrundfarbe
- 2 Hauptmenü, Schrift normal
- 3 Hauptmenü, Schriftfarbe innerhalb des Auswahlbalkens
- 4 Hauptmenü, Farbe des Auswahlbalkens
- 5 Untermenü, Hintegrundfarbe
- 6 Rahmenfarbe des Untermenüs
- 7 Farbe des Menü-Trennstrichs
- 8 Untermenü, Schrift normal
- 9 Untermenü, Schriftfarbe inaktiv (Grayed=true)
- 10 Untermenü, Schriftfarbe innerhalb des
- Auswahlbalkens,inaktiv
- 11 Untermenü, Schriftfarbe innerhalb des
- Auswahlbalkens,aktiv
- 12 Untermenü, Farbe des Auswahlbalkens
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 23 -
-
-
-
-
-
-
-
- 3.4.2. Laden von Menüs aus Ressourcen
-
- WG-Vision unterstützt in der vorliegenden Version noch keine
- Streams. Trotzdem können Sie Menüressourcen aufbauen, die
- ihr Anwendungsprogramm zur Laufzeit lädt und damit das Menü
- initialisiert. Auf diese Weise lassen sich leicht Programme
- in andere Sprachen portieren, da es ausreicht, die Ressour-
- cendatei zu übersetzen.
- Menüressourcen sind einfache ASCII-Dateien wie folgendes
- Beispiel zeigt:
-
- {Menü-Ressource für WG-Vision}
-
- ~F~ile,1
- ~N~ew Picture,101,0,0,f,f
- ~L~oad F3,102,0,61,f,f
- ~S~ave F2,103,0,60,f,f
- NewLine
- ~P~rint,104,0,0,f,f
- ~C~lear,105,0,0,f,f
- NewLine
- ~E~xit Alt-X,1,0,45,f,f
- ~E~dit,2
- ~U~ndo,201,0,0,f,f
- NewLine
- ~C~ut,202,0,0,t,f
- C~o~py,203,0,0,t,f
- ~M~ove,204,0,0,t,f
- ~T~urn,205,0,0,t,f
- ~T~ools,3
- ~Z~oom,301,0,0,f,f
- NewLine
- ~G~rid,302,0,0,f,f
- NewLine
- ~P~encel change,303,0,0,f,f
- ~B~rush change,304,0,0,f,f
- ~T~ext,4
- ~R~oman,401,0,0,f,t
- ~S~cript,402,0,0,f,f
-
-
-
- Programmierhandbuch WG-Vision - 24 -
-
-
-
-
-
-
-
- ~T~imes,403,0,0,f,f
- NewLine
- ~N~ormal,404,0,0,f,t
- ~B~old,405,0,0,f,f
- ~I~talic,406,0,0,f,f
- ~U~nderline,407,0,0,f,f
- END
-
- Die Reihenfolge der Parameter einer Zeile entspricht genau
- dem WG-Vision-Befehl. Folgendes ist jedoch zu beachten:
-
- - Kommandos werden als Nummern eingetragen. Die Nummern
- müssen mit der Konstantenliste des Programms
- übereinstimmen
-
- - Codes für Hotkeys (z.B. <F2>) sind als Scancodes
- einzutragen. Kürzel sind unzulässig
-
- - true wird mit t und false mit f abgekürzt
-
- Das Einbinden der Menüressource erfolgt mit dem Befehl:
-
- LoadMenu('<Name der Ressourcendatei>');
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 25 -
-
-
-
-
-
-
-
- Beispiel:
-
- procedure TApplication.InitMenuBar;
- begin
-
- {Farbanpassung an das Desktop}
-
- Palette[1]:=#14; {Hauptmenüzeile Hintergrundfarbe}
- Palette[5]:=#14; {Untermenü,Hintergrundfarbe}
- Palette[4]:=#4; {Hauptmenüzeile,Auswahlbalken}
- Palette[12]:=#4; {Auswahlbalken}
-
- {Menüdefinition}
-
- LoadMenu('BSP8.MNU'); {das ist schon alles}
-
- end;
-
- Ist die Ressourcendatei offensichtlich fehlerhaft, dann
- bricht das Programm während des Ladevorgangs mit einer Feh-
- lermeldung ab:
-
- WG-Vision-Fehler : Menüdatei nicht gefunden !
-
- WG-Vision-Fehler : Zeile xxx in Menüdatei fehlerhaft !
- Falscher Scancode für Shortkey
-
- WG-Vision-Fehler : Zeile xxx in Menü-Datei fehlerhaft !
- Menübezeichner zu lang (maximal 25
- Zeichen
-
- Die ersten beiden Zeilen der Ressourcendatei sind für Kom-
- mentare vorgesehen.
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 26 -
-
-
-
-
-
-
-
- 3.4.3. Verarbeitung von Menü-Kommandos, der Event-Handler
-
- WG-Vision bildet das Fundament eines ereignisgesteuerten
- Programms. Solch ein Ereignis wird als Event bezeichnet. Das
- Programm muß sicherstellen, daß es auf ein Ereignis reagie-
- ren kann. Ein Event kann über die Tastatur oder mittels der
- Maus, aber auch durch das Programm selbst ausgelöst werden.
- Wenn z.B. ein Menüpunkt angeklickt wird, dann wird ein Er-
- eignis generiert, d.h. in der Struktur Event (dem Event-Re-
- cord) wird das Feld Command mit dem Menü-Kommando (z.B.
- cmRestore) besetzt. Innerhalb der Abfrageschleife des Pro-
- gramms (MyApp.Run) kann dieses Kommando abgefangen und zur
- Steuerung des Programms verwendet werden. Die virtuelle Me-
- thode, die dafür verantwortlich ist, wird als Event-Handler
- bezeichnet. Für die Auswertung von Menü-Ereignissen ist die
- Methode HandleEvent von TApp zuständig:
-
- type TApplication=object(TApp)
- ...
- procedure HandleEvent; virtual;
- ...
- end;
- ...
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 27 -
-
-
-
-
-
-
-
- procedure TApplication.HandleEvent;
- begin
- TProgram.HandleEvent; {Nicht vergessen !}
- case Event.Command of
- cmNew : begin {Programmteil Neues Bild}
- end;
- cmLoad : begin {Programmteil Bild laden}
- end;
- cmSave : begin {Programmteil Bild sichern}
- end;
- ...
-
- cmExit : Event.Command:=cmCloseApplication;
- ...
-
- end; {case}
- end;
-
- Die Schlüsselstruktur dieser Methode ist eine case-Anwei-
- sung. Als Selektoren dienen die zu den Untermenüpunkten ge-
- hörenden Kommandos. Für jeden Menüpunkt müssen Sie diesem
- Handler die entsprechende Aktion zur Verfügung stellen. Das
- kann z.B. das Aufblenden eines Dialogfensters oder die Ver-
- anlassung eines Ausdrucks sein.
- Bei der Implementation des Event-Handlers darf auf keinem
- Fall vergessen werden, den Vorgänger (TProgram.HandleEvent)
- aufzurufen. Er ermöglicht erst die Benutzung des Menüs und
- verwaltet auch alle Ereignisse, die sich auf bereits aufge-
- blendete und aktive Fenster beziehen. Ein Weglassen dieser
- Methode hätte fatale Folgen, d.h. das Programm würde auf
- Eingaben nicht mehr reagieren.
- Der Event-Record ist das Behältnis, mit dem Informationen
- von einem Programmteil in einen anderen Programmteil über-
- tragen werden. Er ist in der Unit WEvent implementiert und
- hat folgende Struktur:
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 28 -
-
-
-
-
-
-
-
- type pEvent=^tEvent;
- tEvent=record
- What : byte;
- Command : word;
- Message : word;
- Info : word;
- case word of
- 0 : (InfoPtr:Pointer);
- 1 : (InfoLong:LongInt);
- 2 : (InfoWord:word);
- 3 : (InfoByte:byte);
- 4 : (InfoChar:char);
- 5 : (InfoString:string);
- end;
-
- Das Feld What kann benutzt werden, um das Ereignis genauer
- zu spezifizieren. Folgende Fälle sind möglich:
-
- evNothing = 0 kein Ereignis
- evMouse = 1 Mausereignis
- evKeyboard = 2 Keyboard-Ereignis
- evMessage = 3 Mitteilung oder Botschafts-
- Ereignis
- evCommand = 4 Befehlsereignis (Kommando)
- evBroadcast = 5 Rundruf-Ereignis
-
- Das What-Feld wird übrigens nur dann besetzt, wenn es wirk-
- lich von Interesse ist, um was für ein Ereignis es sich han-
- delt.
- Command ist das wichtigste Feld des Event-Records. Es ent-
- hält den jeweils letzten Befehl. Befehle oder Kommandos wer-
- den in WG-Vision mit dem Präfix cm versehen, um sie leicht
- von anderen Ereignissen (z.B. Mitteilungen) zu unterschei-
- den.
- Einige Kommandos sind bereits definiert. Sie haben eine
- große Bedeutung für die interne Funktion der Klassenbiblio-
- thek und sollten nicht anderweitig verwendet werden:
-
-
-
-
-
- Programmierhandbuch WG-Vision - 29 -
-
-
-
-
-
-
-
- cmNothing = 0 kein Kommando (Normalzustand)
- cmCloseApplication = 1 Anwendungsprogramm schließen
- cmCloseWindow = 2 aktives Fenster schließen
- cmWindowNewSize = 3 aktives Fenster skalieren
- cmSelectWindow = 4 neues Fenster selektieren
- cmScrollBarChanged = 5 Rollbalken verändert, intern
-
- cmExit = 6 Programm beenden (ohne Reaktion)
- cmOK = 7 Dialogfenster schließen
- cmCancel = 8 Dialog löschen (Abbrechen)
-
- cmYes =10; Message-Box, intern
- cmNo =11;
-
- cmUp =12; Rollbalken, intern
- cmDown =13;
-
- Kommandos, die mit intern gekennzeichnet sind, sollten im
- Programm nicht verwendet werden.
- Mitteilungen werden oft im Zusammenhang mit Kommandos ver-
- wendet und zwar immer dann, wenn neben dem Kommando eine
- weitere Information übertragen werden muß. Mitteilungen wer-
- den in der Regel vom Programmierer formuliert und sind am
- Präfix msg leicht zu erkennen. Bitte verwenden Sie zur Co-
- dierung von Mitteilungen nur Zahlen >= 10.
- Um noch komplexere Informationen zu übertragen, müssen Sie
- das Feld Info verwenden. Es kann gemäß der Definition eines
- varianten Record mit beliebigen Datentypen besetzt werden.
- Im Zusammenhang mit dem Event-Record sind noch folgende Pro-
- zeduren von Interesse:
-
- procedure GetEvent; holt Tastatur- und Mausereignisse
-
- procedure ClearEvent; setzt What auf evNothing und löscht
- die Felder Keyb.ScanCode und
- Keyb.KeyCode. Außerdem wird
- Mouse.DoubleKlick auf false gesetzt
-
-
-
-
-
- Programmierhandbuch WG-Vision - 30 -
-
-
-
-
-
-
-
- procedure ClearMessage; Event.Message wird auf msgNothing gesetzt
-
- Um das Wechselspiel zwischen Menü und Eventhandler etwas ge-
- nauer zu betrachten, soll im folgenden Beispiel gezeigt wer-
- den, wie man zur Laufzeit ein Menü auswechseln kann.
- Die beiden Menüs liegen jeweils als Ressourcendateien vor:
-
- {Menü-Ressource für Programm MTEST, Menü 1}
-
- ~A~uswahl,0
- ~N~eues Menü laden,101,0,0,f,f
- NewLine
- E~x~it <alt><x>,1,0,45,f,f
-
- {Menü-Ressource für Programm MTEST, Menü 2}
-
- ~A~uswahl,0
- Altes ~M~enü laden,111,0,0,f,f
- NewLine
- E~x~it <alt><x>,1,0,45,f,f
-
- Man beachte, daß die Kommandos, die abgesetzt werden, unter-
- schiedlich sind. Das ist zwar nicht immer zwingend notwen-
- dig, hilft aber, die Übersicht zu bewahren. In diesem
- Beispiel sind das die Kommandos 101 und 111. Sie erscheinen
- nochmals im Konstanten-Deklarationsteil des Hauptprogramms:
-
- program MenuTest;
-
- uses WApp,
- WEvent;
-
- const cmLoadNewMenu = 101; {Menü-Kommandos}
- cmLoadOldMenu = 111;
-
- type TApplication=object(TApp) {Neues Applikations-Objekt}
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- end;
-
-
-
- Programmierhandbuch WG-Vision - 31 -
-
-
-
-
-
-
-
- var MyApp:TApplication;
-
- {Implementation TApplication}
-
- procedure TApplication.InitMenuBar; {erstes Menü laden}
- begin
- LoadMenu('MTEST1.MNU');
- end;
-
- procedure TApplication.HandleEvent;
- begin
- TProgram.HandleEvent;
- case Event.Command of
- cmLoadNewMenu : begin
- ClearMenu; {altes Menü löschen}
- LoadMenu('MTEST2.MNU'); {Menü 2 laden}
- DrawMainMenu; {Menü 2 auf den Bildschirm}
- end; {zeichnen}
- cmLoadOldMenu : begin
- ClearMenu;
- LoadMenu('MTEST1.MNU');
- DrawMainMenu;
- end;
- end; {case}
- end;
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Menü-Test');
- MyApp.Run;
- MyApp.Done;
- end.
-
- Der Befehl ClearMenu löscht die Eintragungen des gerade ak-
- tiven Menüs vom Heap und macht damit Platz für das neue Me-
- nü, welches mit LoadMenu geladen wird. DrawMainMenu schreibt
- danach das neue Hauptmenü auf den Bildschirm.
- Die Abarbeitungsschleife, die sich hinter dem Befehl
-
-
-
- Programmierhandbuch WG-Vision - 32 -
-
-
-
-
-
-
-
- MyApp.Run verbirgt, hat jetzt folgende Struktur:
-
-
- ┌─────> repeat
- │ │
- │ GetEvent
- │ │
- │ │ HandleEvent (allgemein)
- │ HandleEvent ──> HandleEvent (Menü)
- │ HandleEvent (Applikation) - Menü laden
- │ │
- │ ClearEvent <──────────────┘
- │ │
- │ │
- └ until Event.Command=cmCloseApplication
-
- Wie Sie sehen, wird jeweils der Event-Handler des gerade ak-
- tiven Elements (Menü, Dialogfenster, Dialogelement etc.) in
- die Ereignisabarbeitungskette eingefügt. Das bedeutet, daß
- die Funktionalität eines ereignisgesteuerten Programms in
- den entsprechenden Event-Handler (z.B. eines Dialogfensters)
- gelegt werden muß.
-
- 3.4.4. Verschieben des Menüs in der Menüzeile
-
- Die linke Position des ersten Hauptmenüeintrags läßt sich
- über die Variable MPos frei festlegen. Um beispielsweise das
- gesamte Hauptmenü um ca 100 Pixel nach rechts zu verschie-
- ben, muß die Prozedur InitMenuBar um folgenden Eintrag er-
- gänzt werden:
-
- procedure TApplication.InitMenuBar;
- begin
- MPos:=100; {erst das}
- LoadMenu('MTEST1.MNU'); {dann das}
- end;
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 33 -
-
-
-
-
-
-
-
- 3.5. Grafikmodus einstellen
-
- Eine besondere Stärke von WG-Vision ist die Unterstützung
- einer großen Anzahl von Super-VGA-Karten. Das Stichwort dazu
- heißt VESA-Kompatibilität. Für die meisten heute im Handel
- befindlichen Super-VGA's gibt es sogenannte VESA-Erweiterun-
- gen, wenn die Karten nicht schon bereits BIOS-seitig VESA-
- kompatibel sind. Für die meisten Grafik-Chipsätze findet man
- im PD-Bereich VESA-Treiber, die als TSR-Programme geladen,
- eine Super-VGA VESA-kompatibel machen. Für den Programment-
- wickler ergibt sich damit die angenehme Situation, daß ein
- einziger BGI-Treiber ausreicht, um eine große Zahl verschie-
- dener Grafikkarten zu unterstützen. Und das noch bei allen
- vom jeweiligen VESA-Treiber unterstützten Auflösungen und
- mit 256 Farben !
- Um auch Grafikkarten mit dem IBM8514-Chip zu unterstützen,
- wurde auch der 8514-BGI-Treiber implementiert. Nur kann es
- hier zu Schwierigkeiten mit der Maus kommen.
-
- WG-Vision unterstützt folgende Grafikkarten
-
- EGA 16 Farben
- VGA 16 Farben (Voreinstellung)
- VESA 256 Farben (VESA-Treiber muß geladen sein)
- IBM8514 256 Farben
-
- Die unterstützten Auflösungen hängen im konkreten Fall vom
- installierten Grafikadapter bzw. vom installierten VESA-
- Treiber ab. Folgende Auflösungen sind möglich:
-
- M640x350
- M640x480 (Voreinstellung)
- M800x600 (nur VESA)
- M1024x768 (VESA und IBM8514)
-
- Um den Grafikmodus einzustellen, müssen Sie die virtuelle
- Methode InitVideoDevice überschreiben:
-
-
-
-
-
- Programmierhandbuch WG-Vision - 34 -
-
-
-
-
-
-
-
- procedure TApplication.InitVideoDevice;
- begin
- Video.Init(VESA,M800x600);
- end;
-
- Das Programm schaltet beim Starten in den 800x600x256 Modus.
- Zur Initialisierung verwenden Sie bitte die vordefinierten
- Konstanten. Wenn ein Umschalten in den Grafikmodus nicht
- möglich ist, erfolgt eine Fehlermeldung und das Programm
- bricht ab. Aufgrund eines Bugs in der GRAPH-Unit erscheint
- beim Fehlen eines resident geladenen VESA-Treibers bei man-
- chen Grafikkarten die mißverständliche Ausschrift "No
- Error".
- Der Grafikmodus läßt sich prinzipiell auch während der Lauf-
- zeit eines Programms ändern. Bedingung ist, daß nur die Auf-
- lösung und nicht der Treiber gewechselt wird. Ein Umschalten
- von VGA auf VESA ist ausgeschlossen. Ist aber beispielsweise
- der VESA-Treiber installiert, dann kann zwischen allen von
- diesem Treiber unterstützten Auflösungen hin und hergeschal-
- ten werden.
- Das folgende Beispiel zeigt die Vorgehensweise. Das Menü
- wird um den Punkt "Grafik-Mode wechseln" ergänzt. Beim An-
- klicken soll das Kommando "cmChangeGMode" abgesetzt werden.
- Im Eventhandler erfolgt dann das Umschalten in die neue Auf-
- lösung:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 35 -
-
-
-
-
-
-
-
- procedure TApplication.HandleEvent;
- var i:integer;
- begin
- TProgram.HandleEvent;
- case Event.Command of
- cmChangeGMode : begin
- Mouse.HideMouse;
- if Video.GetGrafikMode=M640x480 then
- Video.ChangeGraficMode(M800x600)
- else Video.ChangeGraficMode(M640x480);
- Draw;
- Mouse.ShowMouse;
- end;
- ...
-
- end; {case}
- end;
-
- Das Objekt, welches für die eingestellten Grafikparameter
- zuständig ist, hat den Namen TVideoDevice und ist in der
- Unit WDriver implementiert. Eine Instanz davon ist Video.
- Video wird beim Programmstart innerhalb von MyApp.Init
- iniialisiert. Zu diesem Zweck wird die virtuelle Methode
- InitVideoDevice abgearbeitet. Standardmäßig wird in den VGA-
- Modus mit einer Auflösung von 640x480x16 geschaltet. Wie be-
- reits behandelt, können Sie diese Methode überschreiben und
- damit andere Grafikadapter oder Modi aktivieren. Um während
- der Laufzeit die Auflösung zu ändern, müssen Sie jetzt nur
- noch die Methode ChangeGraficMode von TVideoDevice aufrufen.
- Übergabeparameter ist die gewünschte Auflösung.
- Sie sollten vor Aufruf dieser Methode nicht vergessen, die
- Maus auszuschalten. Ansonsten kann der Mausinterrupt den Um-
- schaltvorgang empfindlich stören, was sich durch Fehler beim
- Aufblenden des Desktops bemerkbar macht.
- Der letzte Schritt besteht in der Rekonstruktion des vor dem
- Umschaltvorgangs vorhandenen Bildschirms. Dazu braucht nur
- die Draw-Methode des Applikationsobjekts abgearbeitet wer-
- den. Sie stellt das Desktop und alle aktiven Fenster neu auf
- dem Bildschirm dar.
-
-
-
- Programmierhandbuch WG-Vision - 36 -
-
-
-
-
-
-
-
- Während es beim Übergang von einer geringeren Auflösung zu
- einer höheren Auflösung keine Probleme gibt, ist der umge-
- kehrte Weg etwas mit Vorsicht zu geniesen. WG-Vision kann im
- Gegensatz zu Windows oder Turbo-Vision nur Fenster verwal-
- ten, die vollständig auf dem Bildschirm dargestellt sind
- (deshalb auch die Begrenzung von Resize- und des Move-
- Bereichs auf das Workarea). Beim Umschalten auf geringere
- Auflösung kann es vorkommen, daß ein Fenster nicht mehr auf
- den Bildschirm paßt (das Workarea hat sich verkleinert). Das
- führt zwangsläufig zu einer fehlerhaften Darstellung.
- Außerdem funktionieren die Routinen zur Restauration des
- Untergrunds nicht mehr. Deshalb folgende Empfehlung:
- Realisieren Sie Ihr Programm so, daß ein Umschalten in einen
- anderen Grafikmodus nur möglich ist, wenn sich keine Fenster
- auf dem Bildschirm befinden, das Desktop also leer ist.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 37 -
-
-
-
-
-
-
-
- 3.6. Wechseln der Desktop-Farben zur Laufzeit
-
- Dadurch, daß man durch Abarbeitung der Draw-Methode des Ap-
- plikationsobjekts alle Objekte auf dem Bildschirm restaurie-
- ren kann, ist eine Änderung der Desktop-Farben (z.B.
- gesteuert durch einen Farbauswahl-Dialog entsprechend Win-
- dows) zur Laufzeit relativ leicht möglich.
- Was muß man zu diesem Thema wissen ? Das Desktop-Objekt ver-
- waltet in der Struktur List (doppelt verkettete Liste, Nach-
- komme von TGroup) seine einzelnen Bestandteile in der
- Reihenfolge ihrer Implementation:
-
- 1.Position Rahmen (Index in der Liste=1)
- 2.Position Hintergrund (Index in der Liste=2)
-
- Jedes dieser Objekte besitzt eine eigene Farbpalette. Das
- Rahmenobjekt verwendet standardmäßig die Eintragungen 1 bis
- 6 und das Hintergrundobjekt die Paletteneintragungen 7 und 8
- der Palette1 (Unit WViews). Es hat jedoch keinen Zweck, etwa
- die Standardpalette 1 zu verändern oder zu überschreiben.
- Vielmehr muß die objekteigene Palette verändert werden. Dazu
- sind folgende Schritte notwendig:
-
- Einen Pointer auf das erste Element von List setzen:
-
- with DeskTop^ do {"Eigentümer" von List}
- begin
- LfdPtr:=List^.GetItems(1);
- ...
-
- LfdPtr ist ein Pointer vom Typ PGroup. Mit GetItems wird die
- Adresse des ersten Eintrags der doppelt verketteten Liste
- List geholt und LfdPtr zugewiesen.
- Um auf das Feld Palette zuzugreifen, ist noch ein Typecast
- notwendig (woher soll denn sonst der Rechner wissen, um was
- für einen Objekttyp es sich konkret bei LfdPtr handelt ?):
-
- with PFrame(LfdPtr)^ do
- Palette:=#2#13#2#10#3#0;
-
-
-
- Programmierhandbuch WG-Vision - 38 -
-
-
-
-
-
-
-
- Jetzt können Sie die Rahmenpalette nach Ihren eigenen Vor-
- stellungen verändern. Wie diese Palette aufgebaut ist, steht
- im Kapitel "Gestaltung des Rahmens".
- Ganz analog wird auch die Farbe des Hintergrundobjektes ge-
- ändert:
-
- LfdPtr:=List^.GetItems(2);
- with PDsktpBgrd(LfdPtr)^ do
- begin
- Palette[7]:=#14; {Menübereich auf Gelb}
- Palette[8]:=#9; {Hintergrund auf Hellblau}
- end;
-
- Zum Schluß muß nur noch die Farbe des Menüs angepaßt werden.
- Da das Menü die gleiche Palette benutzt wie das Applikati-
- onsobjekt, braucht lediglich die Variable Palette auf neue
- Werte gesetzt werden:
-
- Palette:=#14#0#15#4#9#15#15#11#7#15#7#4;
-
- oder, wenn Sie z.B. nur die Hintergrundfarbe der Hauptme-
- nüzeile ändern möchten:
-
- Palette[1]:=#14;
-
- Eine komplette Farbumschaltung könnte innerhalb des Event-
- Handlers des Applikationsobjekts etwa so aussehen:
-
- ...
-
- case Event.Command of
- cmChangeDTColor : begin
- Mouse.HideMouse;
- with DeskTop^ do
- begin
- LfdPtr:=List^.GetItems(1); {Rahmen}
- with PFrame(LfdPtr)^ do
- Palette:=#2#13#2#10#3#0;
- LfdPtr:=List^.GetItems(2); {Hintergrund}
-
-
-
- Programmierhandbuch WG-Vision - 39 -
-
-
-
-
-
-
-
- with PDsktpBgrd(LfdPtr)^ do
- begin
- Palette[7]:=#14;
- Palette[8]:=#9;
- end;
- end;
- Palette:=#14#0#15#4#9#15#15#11#7#15#7#4; {Menü}
- Draw;
- Mouse.ShowMouse;
- end;
- ...
-
- Mit diesem Wissen ist es dann nicht mehr sonderlich schwie-
- rig, einen Dialog zur freien Gestaltung der Desktop-Farben
- zu entwickeln.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 40 -
-
-
-
-
-
-
-
- 3.7. Umschalten in den Alpha-Mode
-
- WG-Vision merkt sich beim Initialisieren der Grafik den ur-
- sprünglich aktiven Alphamodus. Mit dem Befehl Video.SetText-
- Mode kann dann problemlos von der graphischen Oberfläche in
- den Textmodus zurückgeschalten werden. Folgendes Programm-
- fragment, welches in den Eventhandler der Applikation einge-
- baut werden muß, zeigt, wie man einen solchen Vorgang
- programmiert:
-
- ...
-
- case Event.Command of
- cmRestoreCRTMode : begin
- Mouse.HideMouse;
- Video.SetTextMode;
- ...
-
- {Hier kommt der Programmteil im Textmodus}
-
- ...
-
- Video.ChangeGraphicMode(M640x480);
- Draw; {Desktop neu darstellen}
- Mouse.ShowMouse;
- end;
- ...
-
- Noch besser ist es, wenn Sie bevor Sie in den Alphamodus
- wechseln, den gesamten Grafikbildschirm in den EMS oder in
- eine Swapdatei retten. Anstelle der Abarbeitung der Draw-
- Methode brauchen Sie dann nur noch den Grafikbildschirm
- rekonstruieren. Das geht bedeutend schneller, als wenn Sie
- alle Objekte inklusive Desktop neu zeichnen lassen.
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 41 -
-
-
-
-
-
-
-
- 4. Heap-und EMS-Überwachung
-
- Bei der objektorientierten Programmierung erzeugt man In-
- stanzen, die man als ordentlicher Programmierer möglichst
- auf dem Heap ablegt. Da kann es sehr schnell vorkommen, daß
- man Objekte zwar initialisiert, man aber vergißt, sie wieder
- vom Heap zu entfernen. Solchen Fehlern ist sehr schwer auf
- die Schliche zu kommen. Ergebnis ist ein immer kleiner wer-
- dender und mehr und mehr fragmentierter Heap. Damit es nicht
- zu solchen Fehlern kommt, stellt ihnen WG-Vision einen Heap-
- wächter zur Verfügung, der ihnen den noch freien Heap und
- den größten freien Speicherblock anzeigt. Diesen Heapwächter
- sollten Sie während der Entwicklungsphase Ihres Programms
- immer in die Methode HandleEvent einbauen:
-
- procedure TApplication.HandleEvent;
- begin
- Heap^.ShowHeapStatus(523,8,White); {Position und Schriftfarbe}
- TProgram.HandleEvent;
- ...
-
- end;
-
- In der Titelzeile des Desktops an der Position (523,8) kön-
- nen Sie jetzt den jeweiligen Zustand des Heaps ablesen. Wenn
- Sie z.B. ein Untermenü aufklappen, sehen Sie, wie das Pro-
- gramm Speicher für den Untergrund allokiert. Beim Deaktivie-
- ren geht der Wert für den freien Speicher wieder auf seinen
- alten Wert zurück. Wenn das nicht der Fall sein sollte, ha-
- ben Sie vergessen, irgendein Objekt vom Heap wieder zu ent-
- fernen. Das kann u.U. zu einer lustigen und kurzweiligen
- Sucherei nach den Ursachen führen.
- Wenn Sie mit EMS-Speicher arbeiten, ist natürlich dessen
- Status auch sehr interessant. Mit folgender Zeile
-
- EMS^.ShowEMSStatus(x,y,Farbe);
-
- können Sie sich zu jeden Zeitpunkt über den noch freien EMS-
- Speicher und der Anzahl noch freier Pages informieren.
-
-
-
- Programmierhandbuch WG-Vision - 42 -
-
-
-
-
-
-
-
- Hier noch ein Achtung für alle, die mit Borland-Pascal ar-
- beiten. Trotz nach Ihrer Meinung reichlich vorhandenen EMS-
- Speicher zeigt ShowEMSStatus immer Null freie Pages an. Der
- Grund dafür ist, daß Borland Pascal einen DPMI-Server nutzt,
- damit die Entwicklungsumgebung im Protected Mode arbeiten
- kann. Dieser Server allokiert standardmäßig den gesamten Er-
- weiterungsspeicher und deaktiviert somit auch den EMS-Trei-
- ber.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 43 -
-
-
-
-
-
-
-
- 5. Schöne neue Fensterwelt
-
- Beginnen wir etwas akademisch. Fenster sind für den Compu-
- terfreak nicht nur Öffnungen in der Wand, wo nachts der Mond
- hineinscheint. Fenster sind vielmehr Bildschirmbereiche, die
- durch einen Rahmen begrenzt sind und in deren Innern Infor-
- mationen dargestellt werden. Ein richtiges Fenster läßt sich
- obendrein noch mit der Maus beliebig auf dem Bildschirm ver-
- schieben und sich vergrößern bzw. verkleinern.
- Folgendes Minimalprogramm zaubert genau solch ein Fenster
- auf Ihren Computerbildschirm:
-
- program Fenstertest;
-
- uses WDecl,
- WEvent,
- WApp,
- WDlg;
-
- const cmNewWindow=101;
-
- type TApplication=object(TApp)
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- procedure NewWindow;
- end;
-
- {Implementation TApplication}
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~F~enster',0);
- SubMenu('~T~estfenster',cmNewWindow,0,0,false,false);
- SubMenu('E~x~it Alt-X',cmCloseApplication,0,altX,false,false);
- end;
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 44 -
-
-
-
-
-
-
-
- procedure TApplication.HandleEvent;
- begin
- TProgram.HandleEvent;
- case Event.Command of
- cmNewWindow:NewWindow;
- end; {case}
- end;
-
- {und hier unser Fensterlein ...}
-
- procedure TApplication.NewWindow;
- var R:TRect;
- Window:PWindow;
- begin
- R.Assign(60,80,400,280);
- Window:=new(PWindow,Init(R,'Testfenster',winDouble+winPanel+winMenu
- +winKey));
- InsertDesktop(Window);
- end;
-
- var MyApp:TApplication;
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Fenster-Test');
- MyApp.Run;
- MyApp.Done;
- end.
-
- Probieren Sie bitte dieses Programm einmal aus. Das Fenster,
- welches nach Anklicken des Menüpunktes "Testfenster" auf dem
- Bildschirm erscheint, hat fast alle Eigenschaften, die ein
- Fenster unter Windows auch hat:
- Es kann beliebig innerhalb des Workareas verschoben wer-
- den.Ein Herausschieben aus dem Bildschirm wie bei Windows
- oder Turbo-Vision ist jedoch nicht möglich. Dazu Klicken Sie
- das Panel an und bewegen die Maus bei gedrückter linker
- Maustaste. Sie können das Fenster aber auch mit Hilfe der
-
-
-
- Programmierhandbuch WG-Vision - 45 -
-
-
-
-
-
-
-
- Tastatur bewegen. Einmal <ESC> drücken öffnet das Systemme-
- nü. Daraus wählen Sie den Menüpunkt Verschieben (bzw. Move).
- Anschließend können Sie mit Hilfe der Kursortasten das Fen-
- ster neu auf dem Bildschirm positionieren. <ENTER> beendet
- die Prozedur.
- Die Fenstergröße kann verändert werden (Skalierung). Wenn
- die Maus den Rahmen des Fensters berührt, ändert sich in Ab-
- hängigkeit von der momentanen Position die Form des Mauszei-
- gers. Wenn Sie jetzt mit gedrückter linker Maustaste die
- Maus bewegen, verändert sich (dargestellt durch ein farbiges
- Rechteck) die Größe des Fensters. Einschränkend muß noch er-
- wähnt werden, daß eine freie Skalierung über die Tastatur
- nicht möglich ist. Alle skalierbaren Fenster besitzen in der
- rechten oberen Ecke der Titelzeile zwei Schalter. Wenn Sie
- auf den rechten Schalter drücken, verändert sich das Fenster
- auf die Größe des aktiven Workareas. Der linke Schalter ver-
- kleinert es wieder auf die Größe, wie es im Programm defi-
- niert wurde (Unterschied zu einem Windows-Fenster). Die
- gleichen Aktionen können Sie auch über die Tastenkombinatio-
- nen <Ctrl><PgUp> und <Ctrl><PgDn> erreichen.
- Wenn ein Standardfenster aufgeblendet wird, bleibt weiterhin
- das Hauptmenü aktiv. Solch ein Fenster wird als nicht-modal
- bezeichnet. Sie können jetzt das Fenster verschieben und an-
- schließend ein weiteres Fenster aufblenden usw. Diesen Vor-
- gang können Sie solange wiederholen, bis Ihr Programm wegen
- Speichermangels abbricht (hier bewährt sich zum Test wieder
- der Heapwächter). Wie Sie sehen, können Sie quasi beliebig
- viele Fenster erzeugen. Das jeweils vorletzte wird deakti-
- viert, was man an der Farbänderung des Rahmens beobachten
- kann. Man sagt auch, daß es seinen Fokus verliert. Nur das
- gerade aktive Fenster ist fokussiert und reagiert auf Ereig-
- nisse.
- Wenn Sie ein deaktiviertes Fenster anklicken, wird es wieder
- aktiviert. Wenn es durch Teile von anderen Fenstern verdeckt
- war, werden die Fenster so umsortiert, daß es wieder "oben"
- zu liegen kommt.
- Um ein Fenster zu schließen, brauchen Sie nur das Ende-Icon
- zweimal mit der Maus kurz anzuklicken. Auch die Tastenkombi-
- nation <ESC><ENTER> oder <ESC><S> bzw. <ESC><C> (englische
-
-
-
- Programmierhandbuch WG-Vision - 46 -
-
-
-
-
-
-
-
- Variante) entfernt das Fenster vom Bildschirm.
-
- 5.1. Programmierung
-
- Alle Fenster leiten sich vom Objekt TWindow ab, welches in
- der Unit WDlg implementiert ist. Wenn Sie ein Fenster mit
- Leben erfüllen wollen, müssen Sie von diesem Objekt einen
- Nachkommen erzeugen und ihn mit allen gewünschten Eigen-
- schaften ausstatten. Im obigen Beispiel wurde direkt auf
- TWindow zurückgegriffen. Es zeigt also ein Fenster in seinem
- "Urzustand".
- Das Einfügen des Fensters in die Window-Liste des Desktops
- erfolgt innerhalb einer neuen Methode des Applikationsob-
- jekts (procedure NewWindow) mit dem Befehl InsertDesktop.
- Zuvor werden über den Konstruktor von TWindow die Eigen-
- schaften des Fensters festgelegt. Das sind
-
- - Position und Größe
- - Eigenschaften (ergibt sich aus dem Rahmentyp)
-
- ...
- R.Assign(60,80,440,280); {Größe und Position des Fensters}
- Window:=new(PWindow,
- │ Init(R,'Testfenster',winDouble+winPanel+winMenu+winKey));
- ... │ │ │ │
- │ │ │ └─ Rahmenform
- │ │ └─ Paneltext
- │ └─ Position und Größe (TRect)
- └─ Zeiger auf Fenstertyp
-
-
- In WG-Vision werden die Eigenschaften der Fenster durch die
- Art des Rahmens bestimmt. So lassen sich z.B. alle Fenster
- mit Panel verschieben. Fenster mit Resize-Schalter sind in
- ihrer Größe veränderbar.
- Die Rahmenform wird als Parameter im Konstruktor übergeben.
- Zur Vereinfachung stellt WG-Vision folgende additiv ver-
- knüpfbare Konstanten zur Verfügung:
-
-
-
-
- Programmierhandbuch WG-Vision - 47 -
-
-
-
-
-
-
-
- winSingle einfacher Rahmen
- winDouble Doppelrahmen
- winPanel Fenster mit Titelleiste (verschiebbar)
- winMenu Fenster mit Systemmenü
- winKey Fenster mit Resize-Schalter (skalierbar)
-
- Folgende Kombinationen sind sinnvoll:
-
- winSingle
- Stationäres Fenster mit einfachen Rahmen. Rahmengröße nach
- unten nicht begrenzt.
-
- winDouble
- Stationäres Fenster mit Doppelrahmen. Rahmengröße nach unten
- nicht begrenzt.
-
- Folgende Rahmen besitzen das Minimalmaß 100x86 Pixel. Sie
- lassen sich nicht weiter verkleinern. Wenn ein Rahmenbereich
- kleiner als diese Größe festgelegt wird, dann wird es von
- WG-Vision automatisch auf dieses Maß vergrößert.
-
- winSingle+winPanel
- Verschiebbares Fenster mit einfachen Rahmen und Titelleiste
-
- winDouble+winPanel
- Verschiebbares Fenster mit Doppelrahmen und Titelleiste
-
- winSingle+winPanel+winMenu
- Verschiebbares Fenster mit einfachen Rahmen,Panel und Sys-
- temmenü
-
- winDouble+winPanel+winMenu
- Verschiebbares Fenster mit Doppelrahmen, Panel und System-
- menü
-
- winSingle+winPanel+winMenu+winKey
- Verschiebbare Fenster mit einfachen Rahmen, Panel, System-
- menü und Resize-Schalter
-
-
-
-
- Programmierhandbuch WG-Vision - 48 -
-
-
-
-
-
-
-
- winDouble+winPanel+winMenu+winKey
- Verschiebbare Fenster mit Doppelrahmen, Panel, Systemmenü
- und Resize-Schalter
-
- Fenster ohne Sytemmenü lassen sich explizit nicht schließen.
-
- 5.1.1. Eigenschaften eines Fensters festlegen
-
- Ein Fenster wird erst dann interessant, wenn es irgendetwas
- tut, z.B. Informationen anzeigt oder einen Text aufblendet.
- Diese Eigenschaften müssen Sie als Programmierer selbst
- festlegen. Leiten Sie dazu von TWindow einen Nachfahren ab
- und geben Sie ihm einen Namen, der in etwa seine Funktion
- (z.B. TDigitalUhr, TDrawWindow etc.) bezeichnet:
-
- PNewWindow=^TNewWindow;
- TNewWindow=object(TWindow)
- ... {überschriebene bzw. neue Methoden}
- end;
-
- Bei größeren Projekten empfehle ich, daß diese neuen Objekt-
- definitionen nicht im Hauptprogramm, sondern in themenbezo-
- genen Units implementiert werden. Die Unit WFileDlg von WG-
- Vision ist z.B. eine solche themenbezogene Unit.
-
- - Modalität des Fensters ändern
-
- TWindow-Objekte sind von Haus aus nicht-modal. Das kann sich
- in Anwendungsfällen als ungünstig erweisen. Durch Aufruf der
- Methode
-
- SetWindowAttrib(false)
-
- kann man jedoch die Modalität erzwingen. Wird ein derartiges
- Fenster aufgeblendet, dann werden sofort das Menü und alle
- anderen Fenster deaktiviert, indem deren Eventhandler aus
- der Abarbeitungsschleife ausgeklingt werden. Das Hauptmenü
- erscheint beispielsweise in dezenten Grau und ist nicht mehr
- ansprechbar.
-
-
-
- Programmierhandbuch WG-Vision - 49 -
-
-
-
-
-
-
-
- constructor TNewWindow.Init;
- var R:TRect;
- begin
- R.Assign(60,80,440,280); {Größe und Position des Fensters}
- Init(R,'Test-Fenster',winDouble+winPanel+winMenu+winKey);
- SetWindowAttrib(false);
- end;
-
- Der Aufruf innerhalb des Applikationsobjekts sieht jetzt
- folgendermaßen aus:
-
- procedure TApplication.NewWindow;
- var Window:PNewWindow;
- begin
- Window:=new(PNewWindow, Init);
- InsertDesktop(Window);
- end;
-
- - Fensterfarbe änden
-
- Die Farbgestaltung eines Fensters erfolgt analog der Farbge-
- bung des Desktops. Da der Rahmen die Farbe des Fensters be-
- stimmt (der Hintergrund wird durch ein separates Objekt
- verwaltet), wird standardmäßig auch hier Palette1 verwendet.
- Die Zuordnung erfolgt innerhalb der virtuellen Methode Set-
- Palette. Diese Methode kann leicht überschrieben werden, so
- daß Sie selbst festlegen können, in welcher Farbkombination
- Ihr Fenster erscheinen soll:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 50 -
-
-
-
-
-
-
-
- procedure TNewWindow.SetPalette; {einfarbig Grün}
- begin
- Palette:=#2#2#2#2#2#15#15#15#15#8#0#15#7
- end; │ │ │ │ │ │ │ │ │ │ │ │
- │ │ │ │ │ │ │ │ │ │ │ └─ Textfarbe Feld gesperrt
- │ │ │ │ │ │ │ │ │ │ └─ Textfarbe Auswahlbalken
- │ │ │ │ │ │ │ │ │ └─ Textfarbe normal
- │ │ │ │ │ │ │ │ └─ Auswahlbalken
- │ │ │ │ │ │ │ └─ Menü-Hintergrund
- │ │ │ │ │ │ └─ reserviert
- │ │ │ │ │ └─ Textfarbe Titelzeile
- │ │ │ │ └─ Panelmischfarbe 2
- │ │ │ └─ Panelmischfarbe 1
- │ │ └─ Innenrahmen
- │ └─ Zwischenrahmen
- └─ Außenrahmen
-
-
- In diesem Beispiel wurde die ganze Palette neu gesetzt. Wenn
- Sie nur einige wenige Paletteneintragungen verändern möch-
- ten, empfiehlt sich folgende Vorgehensweise:
-
- procedure TNewWindow.SetPalette;
- begin
- TWindow.SetPalette; {Vorgänger aufrufen}
- Palette[2]:=#12; {Innenrahmen auf Rot}
- Palette[6]:=#14; {Titelzeile in Gelb}
- end;
-
- oder für ein gelbes Fenster:
-
- procedure TNewWindow.SetPalette;
- var i:integer;
- begin
- TWindow.SetPalette; {Vorgänger aufrufen}
- for i:=2 to 5 do Palette[i]:=#14;
- Palette[3]:=#7;
- Palette[6]:=#1;
- end;
-
-
-
- Programmierhandbuch WG-Vision - 51 -
-
-
-
-
-
-
-
- Ansonsten können Sie natürlich alle Register der Stringmani-
- pulation zur Festlegung der Farbpalette nutzen.
- Eine weitere Möglichkeit besteht in der Wahl einer der vor-
- definierten und speziell für WG-Vision-Fenster ausgelegten
- Spezialpaletten. Sie werden über einen Index angesprochen,
- für die Sie folgende Konstanten-Bezeichner verwenden können:
-
- palStandard
- palRed
- palGray
- palGreen;
-
- procedure TNewWindow.SetPalette;
- begin
- Palette:=Pal[palGreen];
- end;
-
- - Fensterhintergrund
-
- Ein Standard-Fenster besteht aus drei verschiedenen Schich-
- ten, die in einer doppelt verketteten Liste verwaltet wer-
- den. Diese Schichten sind
-
- a) der Untergrund
- Der Untergrund ist der Bereich des Bildschirms, welcher vom
- Fenster abgedeckt wird. Dieser Untergrund muß bevor ein Fen-
- ster aufgeblendet wird (d.h. dessen Draw-Methode abgearbei-
- tet) gerettet werden. Das geschieht übrigens völlig
- automatisch. Ist beispielsweise genügend EMS-Speicher vor-
- handen, dann wird der Untergrund in den Expanded Memory ge-
- schrieben. Diesen Vorgang können Sie übrigens sehr schön
- beobachten, wenn Sie den EMS-Wächter installiert haben und
- das Programm nicht gerade unter Borland Pascal 7 starten.
- Reicht der EMS-Speicher nicht mehr aus oder ist gar keiner
- vorhanden, dann schreibt WG-Vision den Untergrund in eine
- temporäre Datei (Zufallszahl+Extension ".$$$") auf den gera-
- de aktiven Datenträger (i.A. die Festplatte),
-
-
-
-
-
- Programmierhandbuch WG-Vision - 52 -
-
-
-
-
-
-
-
- b) der Rahmen
- Der Rahmen ist halt nur ein Rahmen, obwohl das Objekt recht
- intelligent ist. Es muß ja immerhin auf die Lage des Maus-
- kursors reagieren und gegebenenfalls die Form des Mauskursor
- verändern. Außerdem ist er noch für Verschiebungen und Ska-
- lierungen sowie für das Systemmenü zuständig. Alle diese
- Vorgänge laufen innerhalb des Eventhandlers des Frame-Objek-
- tes ab.
-
- c. der Hintergrund
- Der Hintergrund ist der Teil des Fensters, der sich inner-
- halb des Rahmens befindet. Er ist so wichtig, daß er durch
- ein eigenes Objekt verwaltet wird. Es ist das gleiche Ob-
- jekt, welches auch für den Hintergrund des Desktops verant-
- wortlich ist: TBackGround.
-
- Später werden wir zu diesen drei Schichten noch eine weitere
- hinzufügen, den Scrollbereich mit Rollbalken.
- Der Hintergrund ist in der Voreinstellung eine weiße Fläche.
- Um das zu ändern, muß ein neues Objekt von TBackground abge-
- leitet und in die Liste mit den Fensterbestandteilen einge-
- fügt werden:
-
- PNewBackGround=^TNewBackGround;
- TNewBackGround=object(TBackGround)
- procedure Draw; virtual;
- end;
-
- WG-Vision verwendet dann zum Aufblenden des Fensterhinter-
- grundes nicht mehr die Draw-Methode von TBackGround, sondern
- die von TNewBackground.
- Bei der Implementation von TNewBackGround.Draw muß man wis-
- sen, wie groß der Bereich innerhalb des Rahmens ist. Sie
- brauchen jetzt aber nicht zum Zollstock zu greifen, denn WG-
- Vision stellt Ihnen die Größe des Hintergrundobjektes mund-
- gerecht als TRect-Objekt in der Variablen Border zur Verfü-
- gung:
-
-
-
-
-
- Programmierhandbuch WG-Vision - 53 -
-
-
-
-
-
-
-
- procedure TNewBackGround.Draw;
- begin
- with Border do
- FBar(A.x,A.y,B.x,B.y,LightBlue);
- end;
-
- Border enthält im Punkt A (TPoint-Objekt) die Koordinaten
- der linken oberen Ecke und im Punkt B die Koordinaten der
- rechten unteren Ecke des Hintergrundbereiches.
- Die Prozedur FBar wird durch die Unit WUtils zur Verfügung
- gestellt und zeichnet einen durch die Punkte A und B gegebe-
- nen gefüllten rechteckigen Bereich. Der letzte Parameter ist
- die Füllfarbe.
-
- Komplexbeispiel Ausgabe der momentan verfügbaren
- Speicherressourcen des Systems
-
- Aufgabenstellung:
- In einem Fenster soll der momentan freie Arbeitsspeicher
- (Heap), der freie Expansionsspeicher und die noch vorhandene
- freie Kapazität der Festplatte C ausgegeben werden.
-
- program Komplexbeispiel_1;
-
- uses WDecl,
- WEvent,
- WUtils,
- WApp,
- WViews,
- WDlg,
- graph;
-
-
- const cmGetMemory=101; {Kommando zum Aufblenden des Info-Fensters}
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 54 -
-
-
-
-
-
-
-
- type TApplication=object(TApp) {Applikationsobjekt}
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- procedure GetMemoryStatus;
- end;
-
- PMemoryInfo=^TMemoryInfo; {Info-Fenster}
- TMemoryInfo=object(TWindow)
- constructor Init;
- procedure InitBackground; virtual;
- end;
-
- PMemoryInfoBgrd=^TMemoryInfoBgrd; {Fenster-Hintergrund}
- TMemoryInfoBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
-
- var MyApp:TApplication;
-
-
- {Implementation TApplication}
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~F~enster',0);
- SubMenu('~S~peicher-Ressourcen',cmGetMemory,0,0,false,false);
- SubMenu('E~x~it
- Alt+X',cmCloseApplication,0,altX,false,false);
- end;
-
- procedure TApplication.HandleEvent;
- begin
- TProgram.HandleEvent;
- case Event.Command of
- cmGetMemory:GetMemoryStatus;
- end; {case}
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 55 -
-
-
-
-
-
-
-
- procedure TApplication.GetMemoryStatus; {Mit diesem "Zweizeiler" wird}
- var Window:PMemoryInfo; {das Info-Fenster in die Window-}
- begin {Liste des Desktops eingefügt}
- Window:=new(PMemoryInfo, Init);
- InsertDesktop(Window);
- end;
-
- Die Implementation von TMemoryInfo und TMemoryInfoBgrd kann natürlich
- auch in einer eigenen Unit stehen und ist dann ohne Änderungen allgemein
- verwendbar
-
- {Implementation TMemoryInfo}
-
- constructor TMemoryInfo.Init; {... und hier das eigentliche Fenster}
- var R:TRect;
- begin
- R.Assign(60,80,450,320);
- TWindow.Init(R,'Speicher-Ressourcen',winDouble+winPanel+winMenu);
- SetWindowAttrib(false); {modal-machen, damit keine weiteren}
- end; {Fenster aufgeblendet werden können und das Menü gesperrt wird}
-
- procedure TMemoryInfo.InitBackground;
- var R:TRect;
- begin
- R:=Frame^.Area; {hier wird die Größe innerhalb des Rahmens geholt}
- Bgrd:=new(PMemoryInfoBgrd, Init(R)); {und jetzt kennt auch}
- {└─TMemoryInfoBgrd diesen Wert (Border)}
- List^.InsertItem(Bgrd);
- end;
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 56 -
-
-
-
-
-
-
-
- {Implementation TMemoryInfoBgrd}
-
- procedure TMemoryInfoBgrd.Draw;
- var z:string;
- EMS:PEMS; {diese Speicherverwaltungsobjekte werden von der}
- HD:PHardDisk; {Unit WViews zur Verfügung gestellt}
- begin
- with Border do
- begin
- FillBar(A.x,A.y,B.x,B.y,Yellow,White,SolidFill);
-
- {ist doch hübsch,oder?}
-
- str(MemAvail:8,z); SetColor(Red); {freier Heap}
- OutTextXY(A.x+10,A.y+25,'Hauptspeicher');
- OutTextXY(A.x+10,A.y+100,'Expanded Memory');
- OutTextXY(A.x+10,A.y+160,'Festplatte C');
- SetColor(Blue);
- OutTextXY(A.x+10,A.y+45,'freier RAM (Heap) : '+z+'
- Byte');
- str(MaxAvail:8,z);
- OutTextXY(A.x+10,A.y+65,'größter zusammenhängender');
- OutTextXY(A.x+10,A.y+75,'freier Speicherblock : '+z+'
- Byte');
- EMS:=new(PEMS, Init(Border));
- str(EMS^.FreeMemory:8,z);
- OutTextXY(A.x+10,A.y+120,'verfügbarer Speicher : '+z+'
- Byte');
- str(EMS^.FreeMemory div 16384:8,z);
- OutTextXY(A.x+10,A.y+140,'verfügbare Seiten : '+z+'
- Pages');
- dispose(EMS, Done); {Adios Amigos !}
- HD:=new(PHardDisk, Init(Border));
- str(HD^.FreeMemory:8,z);
- OutTextXY(A.x+10,A.y+180,'verfügbare Plattenkapazität : '+z+'
- Byte');
- dispose(HD, Done); {Adios Amigos !}
- end;
- end;
-
-
-
- Programmierhandbuch WG-Vision - 57 -
-
-
-
-
-
-
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Speicher-Ressourcen');
- MyApp.Run;
- MyApp.Done;
- end.
-
- Dieses kleine Programm, das fast völlig ohne Schnörkel aus-
- kommt, zeigt deutlich die Vorgehensweise bei der Programmie-
- rung eines Anwendungsprogramms mit WG-Vision. Hier noch
- einmal die wesentlichsten Schritte:
-
- 1. Ableitung eines Applikationsobjektes von TApp und
- Anpassung des Desktops (Farben, Hintergrundgestaltung
- etc.)
-
- 2. Menü definieren und Eventhandler einrichten
-
- 3. Fenster in das Desktop einfügen und ihren Aufruf über den
- Eventhandler sicherstellen
-
- 4. Neue Fensterobjekt ableiten und ihre Eigenschaften der
- Problemstellung anpassen
-
- Nun noch einige Worte zum obigen Programm. Es mag etwas be-
- fremdlich erscheinen, daß zur Initalisierung der Speicher-
- verwaltung eine TRect-Variable übergeben werden muß. Der
- Grund dafür ist recht einfach. Die Speicherobjekte von WG-
- Vision (TEMS, THardDisk und THeap) sind so ausgelegt, daß
- sie rechteckige Ausschnitte des Grafikbildschirms über ihre
- Save-Methoden speichern können. Die im Konstruktor übergebe-
- nen Koordinaten legen diese Ausschnitte fest. In unserem
- obigen Beispiel sind diese Koordinaten jedoch völlig belang-
- los, da lediglich abgefragt wird, wieviel Speicher denn noch
- verfügbar sei. Anstatt Border hätten wir deshalb zur Initia-
- lisierung auch jedes x-beliebige TRect-Objekt verwenden
- können. Der Bequemlichkeit halber wird jedoch auf Border zu-
- rückgegriffen.
-
-
-
- Programmierhandbuch WG-Vision - 58 -
-
-
-
-
-
-
-
- Achten Sie bei der Implementation der Draw-Methode eines
- Hintergrundobjekts immer darauf, daß Sie mit Koordinaten re-
- lativ zu Border arbeiten (also "A.x + Irgendwas" und nicht
- "Irgendwas"). Nur so kann sichergestellt werden, daß WG-Vi-
- sion bei einer Verschiebung oder Skalierung eines Fensters
- die Koordinaten richtig transformiert. Bei der Hintergrund-
- gestaltung eines skalierbaren Fensters muß außerdem auf ein
- ordentliches Clipping entlang des Innenrahmens geachtet wer-
- den (SetViewPort) wenn man nicht möchte, daß beim Verklei-
- nern eines Fensters die Schrift über den Rand hinausschießt.
- Im nächsten Beispiel soll gezeigt werden, wie man es errei-
- chen kann, daß sich der Inhalt des Hintergrundes permanent
- verändert. Kurz gesagt, wir wollen eine Digitaluhr program-
- mieren. Auf den ersten Blick erscheint das Unterfangen als
- recht schwierig. Denn ein permanentes Öffnen und Schließen
- eines Fensters nur zur permanenten Aktualisierung des Fen-
- sterhintergrundes dürfte selbst bei einem sehr schnellen
- Rechner wenig akzeptabel sein.
- Die Lösung des Problems besteht darin, die Anzeige der Uhr-
- zeit gänzlich vom Fensterhintergrund abzutrennen und immer
- nur die Ziffern zu aktualisieren, die sich wirklich gerade
- ändern. Dieser Mechanismus muß in einem Programmteil unter-
- gebracht werden, der ständig durchlaufen wird. Solch ein
- Programmteil ist der Eventhandler eines Fensters, der, nach-
- dem das Fenster aufgeblendet und fokussiert wurde, in die
- Ereignisabarbeitungsschleife des Hauptprogramms eingehangen
- wird (MyApp.Run).
- Damit wir unsere Digitaluhr ohne große Probleme auch in an-
- deren Programmen verwenden können, werden alle Routinen in
- einer neuen Unit, WUhr, zusammengefaßt. Diese Unit kann auch
- als Overlay deklariert werden was den Vorteil hat, daß die
- darin enthaltenen Objekte erst zur Laufzeit Speicher allo-
- kieren.
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 59 -
-
-
-
-
-
-
-
- UNIT WUhr;
-
- INTERFACE
-
- uses WDecl,
- WViews,
- WDlg,
- WDriver,
- dos,
- graph;
-
- type PDigitalUhr=^TDigitalUhr; {Unsere Uhr}
- TDigitalUhr=object(TWindow)
- constructor Init(x,y:integer);
- procedure SetPalette; virtual;
- procedure InitBackground; virtual;
- procedure HandleEvent; virtual;
- end;
-
- PUhrBgrd=^TUhrBgrd; {Uhren-Hintergrund}
- TUhrBgrd=object(TBackground)
- Stunde : word; {Warum das ? --> siehe Text !}
- Minute : word;
- Sekunde : word;
- procedure Draw; virtual;
- end;
-
- IMPLEMENTATION
-
- {Implementation TDigitalUhr}
-
- constructor TDigitalUhr.Init(x,y:integer); {Neuer Konstruktor, x und y}
- var R:TRect; {dienen der Positionierung des Fensters}
- begin
- R.Assign(x,y,x+190,y+105);
- TWindow.Init(R,'Uhr',winDouble+winPanel+winMenu);
- SetWindowAttrib(false); {Modal machen ! (warum nur ?)}
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 60 -
-
-
-
-
-
-
-
- procedure TDigitalUhr.SetPalette;
- begin
- Palette:=Pal[palRed]; {eine Uhr mit roten Rahmen ..}
- end;
-
- procedure TDigitalUhr.InitBackground;
- var R:TRect;
- begin
- R:=Frame^.Area;
- Bgrd:=new(PUhrBgrd, Init(R));
- List^.InsertItem(Bgrd);
- end;
-
- procedure TDigitalUhr.HandleEvent;
- var Std,Min,Sek,HSek, {aktuelle Zeit}
- StdOld,MinOld,SekOld : word; {alte Zeit}
- LfdPtr:PGroup;
-
- procedure WriteTime(Nr,x,y:integer;Zeit1,Zeit2:word);
- var zz:string[2];
- begin
- Mouse.HideMouse; {Zeitanzeige aktualisieren}
- str(Zeit1:2,zz);
- SetColor(Blue);
- OutTextXY(x,y,zz); {alte Zeit überschreiben}
- str(Zeit2:2,zz);
- SetColor(LightCyan);
- OutTextXY(x,y,zz); {neue Zeit}
- if Nr<3 then OutTextXY(x+38,y,':'); {Zeitbegrenzer (:) setzen}
- Mouse.ShowMouse;
- end;
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 61 -
-
-
-
-
-
-
-
- {------}
-
- begin
- TWindow.HandleEvent; {nicht vergessen !}
- SetTextStyle(TriplexFont,HorizDir,4);
- GetTime(Std,Min,Sek,HSek); {Onkel DOS fragen, wie spät es ist}
- LfdPtr:=List^.GetItems(3); {hier wird es interessant, siehe Text}
- with PUhrBgrd(LfdPtr)^ do
- begin
- StdOld:=Stunde;
- MinOld:=Minute;
- SekOld:=Sekunde;
- end;
- if StdOld<>Std then WriteTime(1,Origin.x+30,Origin.y+40,StdOld,Std);
- if MinOld<>Min then WriteTime(2,Origin.x+80,Origin.y+40,MinOld,Min);
- if SekOld<>Sek then WriteTime(3,Origin.x+130,Origin.y+40,SekOld,Sek);
- with PUhrBgrd(LfdPtr)^ do
- begin
- Stunde:=Std;
- Minute:=Min;
- Sekunde:=Sek;
- end;
- SetTextStyle(DefaultFont,HorizDir,0);
- end;
-
- {Implementation TUhrBgrd}
-
- procedure TUhrBgrd.Draw;
- begin
- Stunde:=0; Minute:=0; Sekunde:=0;
- with Border do
- begin {Blau ist eine schöne Farbe (Himmel, Meer etc.)}
- SetFillStyle(SolidFill,Blue);
- Bar(A.x,A.y,B.x,B.y);
- end;
- end;
-
- END.
-
-
-
-
- Programmierhandbuch WG-Vision - 62 -
-
-
-
-
-
-
-
- Im Objekt TUhrBgrd wird die jeweils aktuelle Zeit gespei-
- chert. Wenn das Fenster beispielsweise bewegt wird (das soll
- ja ab und an mal vorkommen), wird die Zeit wieder auf Null
- gesetzt, damit die entsprechende Routine im Eventhandler die
- gesamte Zeichenkette mit der Uhrzeit neu im Fenster dar-
- stellt.
- Der Zugriff auf die Daten im TUhrBgrd-Objekt erfolgt über
- einen Typecast. Zuvor wird der Zeiger auf dieses Objekt aus
- der doppelt verketteten Elementenliste mit dem Namen List
- ausgelesen:
-
- LfdPtr:=List^.GetItems(3);
-
- List enthält, wie Sie bereits wissen, alle Elemente eines
- Fensters in der Reihenfolge Untergrund, Rahmen und
- Hintergrund. Da der Hintergrund immer das dritte Objekt in
- dieser Liste ist, wird als Parameter für GetItems 3
- übergeben. Um jetzt auf die Datenfelder zugreifen zu können,
- ist noch ein Typecast notwendig:
-
- with PUhrBgrd(LfdPtr)^ do
- begin
- StdOld:=Stunde;
- MinOld:=Minute;
- SekOld:=Sekunde;
- end;
-
- Eine Typüberprüfung entsprechend
-
- if TypeOf(LfdPtr^)=TypeOf(PUhrBgrd) then ...
-
- ist nicht erforderlich, da das Ergebnis eindeutig ist.
- Auf die gleiche Weise wird die aktualisierte Zeit in das Ob-
- jekt TUhrBgrd zurückgeschrieben.
- Und noch etwas, der Triplex-Font muß für das Programm ver-
- fügbar sein sonst brauchen Sie eventuell eine Brille zum
- Lesen der Zeitanzeige.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 63 -
-
-
-
-
-
-
-
- 5.1.2. Hintergrundinformationen zur Fenstertechnik
-
- Alle sichtbaren Elemente des Bildschirms wie Rahmen, Fen-
- ster, Dialogelemente usw. werden in doppelt verketteten Li-
- sten verwaltet. Diese Listen sind Instanzen des Objektes
- TGroup. TGroup enthält Methoden, um derartige Listen zu ver-
- walten:
-
- TGroup=object(TView)
- First : PGroup; {erstes Element der Liste}
- Last : PGroup; {letztes Element der Liste}
- Current : PGroup; {gerade aktives Element}
- CurrNo : word; {Index des gerade aktiven Elements}
- AnzElem : word; {Anzahl der Elemente in der Liste}
- constructor Init;
- destructor Done; virtual;
- ...
- procedure InsertItem(Item:PGroup); {Element in die Liste einfügen}
- procedure DeleteItems; {Alle Elemente löschen}
- function GetItems(Nr:word):PGroup; {Pointer auf das Element mit}
- {dem Index i}
- procedure DelItem(N:PGroup); {Element N löschen}
- procedure DelLastItem; {Letztes Element der Liste}
- {löschen}
- procedure Draw; virtual; {alle Elemente auf dem}
- {Bildschirm darstellen}
- procedure Hide; virtual; {Alle Elemente vom Bildschirm}
- {löschen}
- ...
-
- end;
-
- Das Objekt TDesktop verwaltet z.B. den Rahmen und den
- Hintergrund in der Liste List. Deshalb müssen Sie auch einen
- neuen Hintergrund mit dem Befehl
-
- List^.InsertItem(Bgrd);
-
-
-
-
-
- Programmierhandbuch WG-Vision - 64 -
-
-
-
-
-
-
-
- in diese Liste einbauen. Auf die gleiche Art und Weise wer-
- den auch Fenster in das Desktop eingefügt. Nur das hier die
- Liste WinList für die Verwaltung zuständig ist. Zur Verein-
- fachung stellt TApp dafür die Methode InsertDesktop zur Ver-
- fügung:
-
- InsertDesktop(Window);
-
- Seine Implementation sieht folgendermaßen aus:
-
- procedure TProgram.InsertDesktop(Item:PGroup);
- begin
- with Desktop^ do
- begin
- WinList^.InsertItem(Item);
- inc(WinCount); {Window-Zähler}
- end;
- end;
-
- Die Variable WinCount enthält die Anzahl der z.Z. instal-
- lierten Fensterobjekte.
- Ein Fenster, d.h. ein Nachfahre oder eine Instanz von TWin-
- dow, verwaltet seine Elemente analog. Auch hier heißt die
- Elementeliste List.
- Zur Darstellung auf dem Bildschirm werden jeweils die Draw-
- Methoden der einzelnen Listenelemente aufgerufen. Zum Ent-
- fernen verwendet man die dazugehörigen Hide-Methoden.
- Mit folgendem Programm können Sie durch einfaches Drücken
- der <F8>-Taste beliebig viele Fenster auf dem Desktop erzeu-
- gen ("beliebig" bedeutet weniger als 256 oder bis sich ihr
- Programm mangels Heap von selbst verabschiedet ...):
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 65 -
-
-
-
-
-
-
-
- program ZufallsFenster;
-
- uses WApp,
- WDecl,
- WEvent,
- WViews,
- WDlg,
- graph;
-
- const cmStandard = 101;
- cmCloseAllWindows = 102;
-
- type TApplication=object(TApp)
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- procedure NewWindow;
- procedure CloseAllWindows;
- end;
-
- var MyProg:TApplication;
-
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~F~enster',0);
- SubMenu('~Z~ufalls-Fenster F8',cmStandard,0,kbF8,false,false);
- SubMenu('~F~enster schließen',cmCloseAllWindows,0,0,false,false);
- SubMenu('E~x~it Alt-X',cmCloseApplication,0,altX,false,false);
- end;
-
- procedure TApplication.HandleEvent;
- begin
- Heap^.ShowHeapStatus(523,8,White);
- TProgram.HandleEvent;
- case Event.Command of
- cmStandard : NewWindow;
- cmCloseAllWindows : CloseAllWindows;
- end; {case}
- end;
-
-
-
- Programmierhandbuch WG-Vision - 66 -
-
-
-
-
-
-
-
- procedure TApplication.NewWindow;
- var R:TRect;
- x,y:integer;
- Window:PWindow;
- begin
- x:=Random(480)+4;
- y:=Random(328)+48;
- R.Assign(x,y,x+150,y+100);
- Window:=new(PWindow, Init(R,'ZufallsFenster',
- winDouble+winPanel+winMenu+winKey));
- InsertDesktop(Window);
- end;
-
- procedure TApplication.CloseAllWindows;
- var i:integer;
- LfdPtr:PGroup;
- begin
- with Desktop^ do
- begin
- for i:=WinCount downto 1 do {WinList von hinten nach vorn abbauen}
- begin
- LfdPtr:=WinList^.GetItems(i); {Pointer holen über Index}
- LfdPtr^.Hide; {Fenster schließen, Untergrund restaurieren}
- WinList^.DelLastItem; {Pointer aus der Liste entfernen und}
- end; {Speicherplatz freigeben}
- WinCount:=0; WinAnz:=0; {Das wars !}
- end;
- end;
-
- {Hauptprogramm}
-
- begin
- MyProg.Init('Zufallsfenster');
- MyProg.Run;
- MyProg.Done;
- end.
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 67 -
-
-
-
-
-
-
-
- Damit Sie nicht jedes Fenster zwecks Löschung einzeln an-
- klicken müssen, wurde der Menüpunkt "Fenster schließen" in
- das Programm integriert. Die eigentliche Arbeit übernimmt
- die Prozedur CloseAllWindows, die wir uns hier noch etwas
- genauer ansehen wollen:
-
- procedure TApplication.CloseAllWindows;
- var i:integer;
- LfdPtr:PGroup;
- begin
- with Desktop^ do
- begin
- for i:=WinCount downto 1 do { --> A }
- begin
- LfdPtr:=WinList^.GetItems(i); { --> B }
- LfdPtr^.Hide; { --> C }
- WinList^.DelLastItem; { --> D }
- end;
- WinCount:=0; WinAnz:=0; { --> E }
- end;
- end;
-
- WinCount und WinAnz sind zwei Zähler, die beide gleich Null
- sind, wenn sich keine Fenster auf dem Desktop befinden.
- Ansonsten enthalten sie die Anzahl der geöffneten Fenster.
-
- A : Alle geöffneten Fenster sind in der Liste WinList, die
- ein Bestandteil des Desktop ist, enthalten. Da die
- Fenster in der entgegengesetzten Richtung ihrer
- Implementation wieder abgebaut werden müssen, muß auch
- der Index i entsprechend laufen.
-
- B : Einem Pointer wird die Adresse des i-ten Eintrages der
- Windowliste zugeordnet
-
- C : Schließen des Fensters. Die Hide-Methode eines
- Standardfensters sieht folgendermaßen aus (Unit WDlg):
-
-
-
-
-
- Programmierhandbuch WG-Vision - 68 -
-
-
-
-
-
-
-
- procedure TWindow.Hide;
- var LfdPtr:PGroup;
- i:integer;
- begin
- Mouse.HideMouse;
- with List^ do
- for i:=AnzElem downto 1 do {Hintergrund, Rahmen, Untergrund}
- begin
- LfdPtr:=GetItems(i);
- LfdPtr^.Hide; {Adios Amigos !}
- end;
- Mouse.ShowMouse; {jetzt darf ich wieder ...}
- end;
-
- Eine verblüffende Ähnlichkeit, nicht wahr ?
-
- D : Letztes Element der Windowliste löschen und
- Speicherfreigabe. Wenn Sie diesen Befehl vergessen,
- funktioniert das Programm trotzdem. Der von der Liste
- im Heap beanspruchte Speicher wird jedoch nicht
- freigegeben und ist damit verloren. An dieser Stelle
- erweist sich übrigens die Nützlichkeit des Heap-
- Wächters.
-
- E : Fensterzähler auf Null setzen
-
- Sie werden verstehen, daß ich im Rahmen dieses Handbuches
- keine erschöpfende Abhandlung über verkettete Listen schrei-
- ben kann. Alle glücklichen Besitzer der Profiversion sollten
- in diesem Zusammenhang ruhig einmal einen Nachmittag lang
- den Quelltext des Objekts TGroup durchforsten. Wenn dann im-
- mer noch nicht der Groschen fällt (und ich nehme das nieman-
- den übel), dann hilft nur noch das Studium von Arne Schäpers
- Klassiker "Turbo Pascal 6.0 - Konzepte, Analysen, Tips &
- Tricks" Seite 574 ff. Und für alle die Trost brauchen : als
- WG-Vision Programmierer kommen Sie (man ist geneigt, "Gott-
- seidank" zu sagen) mit den eigentlichen Listen-Innereien
- kaum in Berührung.
-
-
-
-
- Programmierhandbuch WG-Vision - 69 -
-
-
-
-
-
-
-
- 5.1.3. Fenster mit Rollbalken
-
- Rollbalken sind Elemente, die sich genauso wie der Rahmen
- oder der Hintergrund bei Bedarf in die Liste der Fensterele-
- mente einfügen lassen. Der Hintergrundbereich des Fensters
- wird dann nicht mehr durch ein TBackground-Objekt bestimmt,
- sondern durch ein TScroller-Objekt. Das TScroller-Objekt
- kann auf Ereignisse reagieren, welche die Rollbalken abset-
- zen. Als Programmierer müssen Sie lediglich festlegen, wie
- das TScroller-Objekt auf diese Ereignisse reagieren soll.
- Bevor wir näher auf den Mechanismus eingehen, möchte ich Ih-
- nen folgenden kleinen Quelltextlister vorstelle:
-
- program Lister;
-
- uses WApp,
- WEvent,
- WDecl,
- WViews,
- WDriver,
- WDlg,
- graph;
-
- const cmList = 101;
-
- type TApplication=object(TApp)
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- procedure NewWindow;
- end;
-
- PNewScroller=^TNewScroller;
-
- PScrollWindow=^TScrollWindow;
- TScrollWindow=object(TWindow)
- Scroller:PNewScroller;
- procedure InitWindowScroller; virtual;
- destructor Done; virtual;
- end;
-
-
-
- Programmierhandbuch WG-Vision - 70 -
-
-
-
-
-
-
-
- TNewScroller=object(TScroller) {Scroll-Bereich}
- procedure CreateData; {Daten bereitstellen (hier Textstrings)}
- procedure ScrollDraw; virtual; {Scrollbereich darstellen}
- end;
-
-
- var MyApp:TApplication;
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~F~enster',0);
- SubMenu('~Q~elltext-Lister',cmList,0,0,false,false);
- SubMenu('E~x~it Alt-X',cmCloseApplication,0,altX,false,false);
- end;
-
- procedure TApplication.HandleEvent;
- begin
- Heap^.ShowHeapStatus(523,8,White);
- TProgram.HandleEvent;
- case Event.Command of
- cmList : NewWindow;
- end; {case}
- end;
-
- procedure TApplication.NewWindow;
- var R:TRect;
- Window:PScrollWindow;
- begin
- R.Assign(60,80,440,280);
- Window:=new(PScrollWindow, Init(R,'ScrollWindow / Quelltext-Lister',
- winDouble+winPanel+winMenu+winKey));
- InsertDesktop(Window);
- end;
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 71 -
-
-
-
-
-
-
-
- {Implementation TScrollWindow}
-
- procedure TScrollWindow.InitWindowScroller;
- var R:TRect;
- SBH1,SBV1:PScrollBar;
- begin
- R:=Frame^.Area;
- SBH1:=new(PScrollBar, Init(R,HorizDir)); {horizontaler Rollbalken}
- SBV1:=new(PScrollBar, Init(R,VertDir)); {vertikaler Rollbalken}
- Scroller:=new(PNewScroller, Init(R,SBH1,SBV1)); {Scroller-Objekt}
- Scroller^.CreateData; {Daten für die Anzeige bereitstellen}
- List^.InsertItem(Scroller); {und jetzt in List einfügen}
- end;
-
- destructor TScrollWindow.Done;
- begin
- TWindow.Done; {natürlich muß jetzt auch der Scroller aus dem}
- dispose(Scroller, Done); {Heap verschwinden}
- end;
-
- {Implementation TNewScroller}
-
- Mit dieser Prozedur werden die Zeilen des Quelltextes von LIST.PAS in
- die Struktur TLine eingelesen, die nichts anderes als eine Pointerliste
- darstellt. Ein Nachteil dieser Methode ist, daß mit dem Text der Heap
- belastet wird, was nicht immer gut sein muß. Aber letztendlich bleibt es
- ja dem Programmierer überlassen, wie er seinem Rollfenster die Daten
- überläßt. Im Abschnitt über den EMS zeige ich Ihnen eine Möglichkeit,
- wie Sie Texte im Expanded Memory ablegen können,
-
- procedure TNewScroller.CreateData;
- var dat:text;
- LfdPtr:PLine;
- begin
- assign(dat,'B:LIST.PAS');
- reset(dat);
- while not EOF(dat) do
- begin
- LfdPtr:=new(PLine, Init);
-
-
-
- Programmierhandbuch WG-Vision - 72 -
-
-
-
-
-
-
-
- readln(dat,LfdPtr^.Eintrag);
- Liste^.InsertItem(LfdPtr); {rein in die bereits vorbereitete Liste}
- end;
- SetLimit(25,Liste^.AnzElem-1,8,16); {sehr wichtig ! --> Beschreibung}
- end;
-
- Draw-Bereich aktualisieren. Diese Methode erhält ihre Informationen
- direkt von den Rollbalken (Delta.y, WDelta.y, Delta.x, Zeilen).
-
- procedure TNewScroller.ScrollDraw;
- var i:integer;
- LfdPtr:PGroup;
-
- function clip(p,n:byte;z:string):string; {Zeile so zusammenstutzen, daß}
- begin {sie in das Fenster paßt}
- clip:=copy(z,p,n);
- end;
-
- begin
- Mouse.HideMouse;
- with Border do
- begin
- SetFillStyle(SolidFill,GetPalColor(1));
- SetColor(GetPalColor(2));
- for i:=Delta.y to WDelta.y do
- begin
- LfdPtr:=Liste^.GetItems(i); {i-te Zeile aus der Textliste holen}
- Bar(A.x,A.y+(i-Delta.y)*Py+10,B.x,A.y+(i-Delta.y)*Py+10+Py);
- OutTextXY(A.x+20,A.y+(i-Delta.y)*Py+10,clip(Delta.x,
- Spalten*8 div 8-5,PLine(LfdPtr)^.Eintrag));
- end;
- if VertiScrollBar<>nil then
- for i:=(WDelta.y-Delta.y)+1 to Zeilen do
- Bar(A.x,A.y+i*Py+10,B.x,A.y+i*Py+10+Py);
- end;
- Mouse.ShowMouse;
- end;
-
-
-
-
-
- Programmierhandbuch WG-Vision - 73 -
-
-
-
-
-
-
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Beispiel : LISTER');
- MyApp.Run;
- MyApp.Done;
- end.
-
- - Fenster mit Rollbalken ausstatten
-
- Das Objekt TWindow soll um die Fähigkeit, Rollbalken darzu-
- stellen und zu verwalten, erweitert werden. Dazu müssen Sie
- auf der Grundlage von TWindow ein neues Objekt erzeugen und
- die virtuelle Methode InitWindowScroller überschreiben.
- Außerdem benötigen Sie noch ein TScroller-Objekt, da Sie ja
- irgendetwas im Fenster darstellen wollen:
-
- PScrollWindow=^TScrollWindow;
- TScrollWindow=object(TWindow)
- Scroller:PNewScroller;
- procedure InitWindowScroller; virtual;
- destructor Done; virtual;
- end;
-
- Der Scroller ist der Bereich auf dem Bildschirm, der sich
- innerhalb der Rollbalken befindet. Die wesentlichsten Felder
- dieses Objekts sind:
-
- HorizScrollBar Zeiger auf einen horizontalen Rollbalken
-
- VertiScrollBar Zeiger auf einen vertikalen Rollbalken
-
- Delta,WDelta relative Position des Scrollobjekts in
- bezug (TPoint) auf die Einstellung der
- Rollbalken
-
- Limit (TPoint) Ausmaße des im Scroller sichtbaren Daten-
- bereichs in Zeilen (Limit.x) und Spalten
- (Limit.y)
-
-
-
- Programmierhandbuch WG-Vision - 74 -
-
-
-
-
-
-
-
- Px,Py Anzahl der Pixel, die jeweils einer Zeilen-
- und Spaltenbreite entsprechen
-
- Zeilen Anzahl der Zeilen im Scrollfenster
-
- Spalten Anzahl der Spalten im Scrollfenster
-
- Liste verkette Liste, welche Strings aufnehmen
- kann
-
- Für den Programmierer ist nur die Methode SetLimit wichtig.
- Die anderen Felder, welche sich auf die momentane Lage des
- Scrollbereiches beziehen, werden innerhalb des Eventhandlers
- von TScroller durch die Rollbalken bedient. Jede Änderung
- der Rollbalkenposition führt damit automatisch zu einer
- neuen Anzeige des Scrollers (TScroller.Draw) mit ent-
- sprechend verschobenen Datenausschnitt. Wie sieht das nun
- konkret aus. Im Eventhandler von TScroller werden als Erstes
- die Eventhandler der Rollbalken abgearbeitet. Im Normalfall
- passiert dabei nichts bis ein Rollbalken verändert wird. In
- diesem Fall wird das interne Kommando cmScrollBarChanged
- gesendet und außerdem das Feld Event.Info mit einer
- Identifikationsnummer gefüllt, welches dem Eventhandler von
- TScroller erlaubt, die Werte Delta und WDelta den neuen
- Gegebenheiten anzupassen. Anschließend wird die Draw-Methode
- aufgerufen, wodurch der Inhalt des Scrollfensters
- aktualisiert wird.
- Das ist jedoch noch lange nicht alles, was das TScroller-
- Objekt können muß um richtig zu funktionieren. Da sich auch
- skalierbare Fenster mit Scrollbalken versehen lassen, muß es
- natürlich auch auf Änderungen der Fenstergröße reagieren.
- Das führt zu einigen sehr komplizierten Programmabläufen,
- auf die hier aus verständlichen Gründen nicht näher einge-
- gangen werden kann (ich möchte es nicht verhelen, selbst der
- Autor brauchte eine ganze Weile, bis er die Funktionsweise
- wieder verstanden hat. Die Scrollbalkengeschichte hat ihm
- nicht umsonst einige Wochen Arbeit gekostet ...).
-
-
-
-
-
- Programmierhandbuch WG-Vision - 75 -
-
-
-
-
-
-
-
- - Rollbalken einbauen und Scroller initialisieren
-
- procedure TScrollWindow.InitWindowScroller;
- var R:TRect;
- SBH1,SBV1:PScrollBar;
- begin
- R:=Frame^.Area;
- SBH1:=new(PScrollBar, Init(R,HorizDir));
- SBV1:=new(PScrollBar, Init(R,VertDir));
- Scroller:=new(PNewScroller, Init(R,SBH1,SBV1));
- Scroller^.CreateData;
- List^.InsertItem(Scroller);
- end;
-
- TScrollBar ist der eigentliche Rollbalken. Er tritt in zwei
- Formen auf, als horizontaler und als vertikaler Rollbalken.
- Seine Position wird durch das Rechteck R festgelegt. Die
- linke untere Ecke des horizontalen Rollbalken hat z.B. die
- Koordinaten R.A.x und R.B.y.
- In unserem Beispiel schmiegen sich die Rollbalken unten und
- rechts an den Innenrahmen des Fensters. Es steht nichts im
- Wege, die Rollbalken beliebig im Fenster zu positionieren.
- Sie müssen dazu nur R entsprechend verändern. Erlaubt ist
- das jedoch nur bei Windows, deren Größe sich nicht ändern
- läßt und die sich nicht verschieben lassen. Das sind alle
- Windows ohne Resize-Schalter und bei denen die Variable
- DragMode auf dmNoMove gesetzt ist:
-
- procedure TApplication.NewWindow;
- var R:TRect;
- Window:PScrollWindow;
- x,y:integer;
- begin
- R.Assign(60,80,540,380);
- Window:=new(PScrollWindow, Init(R,'ScrollWindow / Quelltext-
- Lister',winDouble+winPanel+winMenu));
- with Window^ do Frame^.DragMode:=dmNoMove;
- InsertDesktop(Window);
- end;
-
-
-
- Programmierhandbuch WG-Vision - 76 -
-
-
-
-
-
-
-
- ...
-
- procedure TScrollWindow.InitWindowScroller;
- var R:TRect;
- SBH1,SBV1:PScrollBar;
- begin
- R:=Frame^.Area; {Größe des Bereichs innerhalb des Rahmens holen}
- R.Grow(-120,-30); {Größe ändern}
- R.Move(30,15); {Verschieben}
- SBH1:=new(PScrollBar, Init(R,HorizDir)); {Rollbalken einbauen}
- SBV1:=new(PScrollBar, Init(R,VertDir));
- Scroller:=new(PNewScroller, Init(R,SBH1,SBV1)); {Scroller initialis.}
- Scroller^.CreateData; {Daten bereitstellen}
- List^.InsertItem(Scroller); {und einbauen}
- end;
-
- 5.1.3.1. Farbgestaltung der Rollbalken und des Scrollbereichs
-
- Die farbliche Gestaltung der Rollbalken und des Scrollerbe-
- reichs erfolgt wieder bequem über die Manipulation der dazu-
- gehörigen Palette.
- Standardmäßig ist Palette3 für Rollbalken und Scroller zu-
- ständig. Sie wird bereits bei der Initialisierung dieser Ob-
- jekte geladen.
-
- Palettenlayout
-
- Eintrag Bedeutung Standard
-
- 1 Hintergrund Scrollbereich #15 Weiß
- 2 Schriftfarbe Scroller #0 Schwarz
- 3 Tastenfarbe #7 Hellgrau
- 4 Balkenfarbe (Gray50) #7 Hellgrau
- 5 Randfarbe Taste #15 Weiß
- 6 Begrenzungslinien #0 Schwarz
- 7 Pfeile #8 Dunkelgrau
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 77 -
-
-
-
-
-
-
-
- Beispiel
-
- ...
-
- SBH1:=new(PScrollBar, Init(R,HorizDir));
- SBV1:=new(PScrollBar, Init(R,VertDir));
- with SBH1^ do
- begin
- Palette[3]:=#2;
- Palette[4]:=#14;
- Palette[5]:=#14;
- Palette[7]:=#4;
- end;
- with SBV1^ do
- begin
- Palette[3]:=#2;
- Palette[4]:=#14;
- Palette[5]:=#14;
- Palette[7]:=#4;
- end;
- Scroller:=new(PNewScroller, Init(R,SBH1,SBV1));
- Scroller^.CreateData;
- Scroller^.Palette[1]:=#11; {muß mit Fensterhintergrund harmonieren !}
- List^.InsertItem(Scroller);
- ...
-
- 5.1.3.2. Programmierung des Scrollers
-
- Der Scroller ist gewissermaßen das Fenster, durch das man
- ein Teil eines größeren Datenbereiches betrachten kann. Es
- ist allein für den Inhalt des Scrollbereiches zuständig und
- muß vom Programmierer für die jeweilige Aufgabe angepaßt
- werden. Zwei Methoden, CreateData und ScrollDraw stehen da-
- für zur Verfügung.
- In unserem Beispiel werden alle Zeilen des Quelltextes von
- LIST.PAS in eine Liste, deren Elemente durch Objekte vom Typ
- TLine repräsentiert werden, übertragen. Diese Liste wird im
- Heap angelegt. Was Sie konkret in diese Liste einlesen,
- hängt davon ab, was für Texte Sie auf den Bildschirm dar-
-
-
-
- Programmierhandbuch WG-Vision - 78 -
-
-
-
-
-
-
-
- stellen wollen. Um z.B. alle Dateien im aktuellen Verzeich-
- nis aufzulisten, müssen Sie CreateData folgendermaßen
- implementieren:
-
- procedure TNewScroller.CreateData;
- var SRec:SearchRec;
- LfdPtr:PLine;
- begin
- FindFirst('*.*',Archive,SRec);
- if SRec.Name<>'' then
- repeat
- LfdPtr:=new(PLine, Init);
- LfdPtr^.Eintrag:=SRec.Name;
- Liste^.InsertItem(LfdPtr);
- FindNext(SRec);
- until DOSError=18;
- SetLimit(12,Liste^.AnzElem-1,CharLength,CharHeight);
- end;
-
- Da die Dateinamen maximal eine Länge von 12 Zeichen
- aufweisen, lohnt sich ein horizontaler Rollbalken nicht.
- Deshalb setzen Sie ihn bei der Implementation einfach auf
- nil:
-
- Scroller:=new(PNewScroller, Init(R,nil,SBV1));
- │
- └─ horiz. Rollbalken
-
- Sehr wichtig ist die Methode
-
- SetLimit(x,y,Pxx,Pyy:integer)
-
- Sie legt die horizontale und die vertikale Schrittweite bei
- einem Scrollschritt fest.
-
- x horizontale Ausdehnung des Datenobjekts (Länge der
- Zeichenkette)
-
-
-
-
-
- Programmierhandbuch WG-Vision - 79 -
-
-
-
-
-
-
-
- y vertikale Ausdehnung des Datenobjekts = Anzahl der
- Elemente in der Liste
-
- Pxx horizontale Schrittweite = Buchstabenbreite (+Offset)
-
- Pyy vertikale Schrittweite = Buchstabenhöhe (+Offset)
-
- Die Darstellung der Daten im Scrollbereich erfolgt mittels
- der virtuellen Methode ScrollDraw:
-
- procedure TNewScroller.ScrollDraw;
- var i:integer;
- LfdPtr:PGroup;
-
- function clip(p,n:byte;z:string):string; { --> A }
- begin
- clip:=copy(z,p,n);
- end;
-
- begin
- Mouse.HideMouse;
- with Border do
- begin
- SetFillStyle(SolidFill,GetPalColor(1));
- SetColor(GetPalColor(2));
- for i:=Delta.y to WDelta.y do
- begin
- LfdPtr:=Liste^.GetItems(i);
- Bar(A.x,A.y+(i-Delta.y)*Py+10,B.x,A.y+(i-Delta.y)*Py+10+Py);
- OutTextXY(A.x+20,A.y+(i-Delta.y)*Py+10,clip(Delta.x,
- Spalten*8 div 8-5,PLine(LfdPtr)^.Eintrag));
- end;
- if VertiScrollBar<>nil then
- for i:=(WDelta.y-Delta.y)+1 to Zeilen do
- Bar(A.x,A.y+i*Py+10,B.x,A.y+i*Py+10+Py);
- end;
- Mouse.ShowMouse;
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 80 -
-
-
-
-
-
-
-
- Die Hilfsfunktion clip dient der Anpassung der darzustellen-
- den Zeichenkette an den horizontalen Fensterbereich. {-->A}
- Delta.y und WDelta.y werden bei Betätigung eines Rollbalkens
- jeweils aktualisiert. Danach erfolgt ein Kommando (cmScroll-
- BarChanged), welches dazu führt, daß der Eventhandler des
- Scroller die Methode ScrallDraw aufruft und damit den
- Scrollbereich neu darstellt.
-
- 5.1.3.3. Bedienung des Rollbalkens mit der Tastatur
-
- Wenn die Taste ScrollLock (Rollen) eingeschaltet ist, können
- Sie mit den Kursortasten den Rollbalken bedienen. <PgUp> und
- <PgDn> sind in der vorliegenden Version von WG-Vision noch
- nicht implementiert. Es ist aber möglich, den Eventhandler
- von TScroller zu überschreiben und weitere Funktionen
- einzubauen.
-
- 5.1.3.4. Verwendung der Sonderzeichensätze
-
- In der Unit WText sind z.Z. 6 Sonderzeichensätze enthalten,
- die Sie in den 16-Farben-Modi der Klassenbibliothek verwen-
- den können. Arbeiten Sie mit 256 Farben, dann passiert auch
- nicht viel. Die Toolbox verwendet in diesem Fall wieder den
- normalen 8x16 Zeichensatz via OutTextXY.
- Wenn Sie jedoch mit diesen Zusatzzeichensätzen arbeiten wol-
- len, dann müssen Sie die Prozedur OutTextXY durch WriteText
- ersetzen. Standardmäßig wird der Zeichensatz Wndw19 verwen-
- det. Der eigentliche Vorteil dieser Zeichensätze liegt in
- ihrer Schreibgeschwindigkeit. Die Prozedur WriteText ist die
- einzige Stelle in WG-Vision, wo ich von meinem Vorsatz, kei-
- nen Assembler zu verwenden, abgewichen bin.
- Um den aktiven Zeichensatz zu wechseln, müssen Sie den Be-
- fehl
-
- SetFont(<Bezeichner>)
-
- in den Quelltext einfügen.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 81 -
-
-
-
-
-
-
-
- Folgende Bezeichner können Sie verwenden. Die dazugehörigen
- Zeichensätze liegen als OBJ-Dateien WG-Vision bei:
-
- Thin8 / Thin14 / Thin16 / Brdwy19 / Wndw19 / Sans19 / VGAF
-
- VGAF ist der VGA-Standardzeichensatz von Turbo/Borland -
- Pascal.
-
- Beispiel
-
- procedure TNewScroller.ScrollDraw;
- ...
-
- begin
- SetFont(Brdwy19); {Neuen Zeichensatz aktivieren}
- ...
- {statt OutTextXY}
- WriteText(...)
- ...
-
- end;
-
- Um die Parameter CharLength und CharHeight in der Methode
- SetLimit brauchen Sie sich nicht zu kümmern. Sie werden beim
- Laden des Zusatzzeichensatzes automatisch auf die richtigen
- Werte gesetzt.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 82 -
-
-
-
-
-
-
-
- 5.1.3.5. Grafiken in einem Scrollfenster darstellen
-
- Das folgende Beispiel zeigt, wie man in einem Scrollfenster
- ein PCX-Bild aufblenden kann. Dieses Beispiel hat vorerst
- nur akademisches Interesse, da in einem realen Anwendungs-
- fall auch die Routinen, welche das Bild letztendlich auf dem
- Bildschirm bringen, angepaßt werden müssen. In diesem Bei-
- spiel verwenden wir die Unit WPCX (Achtung ! --> funktio-
- niert nur im VGA-Standardmodus mit 16 Farben, da diese Unit
- direkt in den Bildwiederholspeicher schreibt !), welche aber
- immerhin schon erlaubt, ein Bild in y-Richtung zu verschie-
- ben (Parameter AddY in der Methode LoadPCXImage). Auf einen
- Nachteil möchte ich schon hier hinweisen. Bei jedem Scroll-
- vorgang wird das Bild neu von der Festplatte geladen, ein
- Fakt, den man in einem realen Malprogramm natürlich umgehen
- muß. In einem solchen Anwendungsfall sollte man das Bild
- vollständig in einen Puffer (Heap oder EMS) laden und auf
- dessen Grundlage eine geeignete Aufblend-Methode entwickeln.
- In unserem Beispiel kommen wir mit einem Rollbalken aus, da
- wir das Bild aus den genannten Einschränkungen heraus sowie-
- so nur vertikal verschieben können:
-
- {Implementation TScrollWindow}
-
- procedure TScrollWindow.InitWindowScroller;
- var R:TRect;
- SBV1:PScrollBar;
- begin
- R:=Frame^.Area;
- SBV1:=new(PScrollBar, Init(R,VertDir));
- Scroller:=new(PNewScroller, Init(R,nil,SBV1));
- Scroller^.CreateData; {└─ wir benötigen nur einen}
- {vertikalen Rollbalken}
- List^.InsertItem(Scroller);
- end;
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 83 -
-
-
-
-
-
-
-
- destructor TScrollWindow.Done;
- begin
- TWindow.Done;
- dispose(Scroller, Done);
- end;
-
- {Implementation TNewScroller}
-
- {In die Typdeklaration des Objekt TNewScroller muß als neues Feld eine
- Instanz von TPCXImage eingefügt werden: Image : TPCXImage}
-
- procedure TNewScroller.CreateData;
- begin
- Image.Init(Border,'WETT.PCX'); {TPCXImage-Objekt Bild initialisieren}
- SetLimit(640,480 div 16,8,16);
- end;
-
- SetLimit bewirkt, daß ein Rollschritt genau 16 Pixel umfaßt. Wenn Sie
- möchten, können Sie diesen Parameter auch ändern. Die Werte für die x-
- Richtung sind ohne Bedeutung. Sie dürfen aber nicht auf Null gesetzt
- werden, weil es sonst innerhalb der Toolbox zum berühmten Division by
- Zero -Fehler kommt. Das 640x480 die Größe des zu ladenden Bildes ist,
- dürfte wohl klar sein.
-
- procedure TNewScroller.ScrollDraw;
- var i:integer;
- LfdPtr:PGroup;
-
- begin
- Mouse.HideMouse;
- with Border do
- begin
- Image.T:=Border; {aktuelle Bildgröße an den Rahmen des}
- Image.T.Move(-4,0); {Scrollfensters anpassen und Korrektur}
- Image.LoadPCXImage(Delta.y); {PCX-Bild um Delta.y versetzt laden}
- end;
- Mouse.ShowMouse;
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 84 -
-
-
-
-
-
-
-
- Dadurch, daß die Routinen innerhalb der Unit WPCX direkt in
- den Bildwiederholspeicher schreiben, kann ein PCX-Bild nur
- entlang von Scanlines, die um jeweils 4 Pixel versetzt in x-
- Richtung angeordnet sind, gezeichnet werden. Da sich das
- Scrollfenster aber pixelgenau verschieben läßt, kann es zu
- Versetzungen des PCX-Bildes innerhalb des Scrollbereiches
- kommen. Das macht sich an einem schmalen Rand bemerkbar. Da-
- mit u.U. nicht ein Teil des Rollbalkens überschrieben wird,
- erfolgt mit T.Move(-4,0) eine kleine Korrektur. T ist inner-
- halb des TPCXImage-Objekts der Bildschirm-Bereich, in wel-
- ches das PCX-Bild linksbündig gezeichnet wird.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 85 -
-
-
-
-
-
-
-
- 5.2. Programmierung von Dialogen
-
- Dialogfenster dienen der Kommunikation zwischen dem Nutzer
- des Programms und dem Programm selbst. Sie enthalten in der
- Regel verschiedene Eingabefelder, Buttons zur Programmsteue-
- rung oder auch Bereiche, wo Informationen dargestellt wer-
- den. Kurz gesagt, ein Dialogfenster ist ein spezialisiertes
- Fensterobjekt, mit dessen Hilfe Sie dem Programm Daten und
- Informationen übermitteln können, die es zu einer fehler-
- freien Ausführung benötigt.
- Es hat sich bewährt, daß man im Menü einer Applikation dem
- Menüpunkt, welcher ein Dialogfenster öffnet, immer drei
- Punkte nachstellt (z.B. Optionen ...). Auf diese Weise wird
- der Nutzer vorgewarnt, daß u.U. jetzt noch einige Eingaben
- folgen.
- Ein Dialogfenster ist ein direkter Nachkomme von TWindow und
- erbt damit alle seine Eigenschaften. Lediglich eine Skalie-
- rung ist nicht mehr möglich weil auch nicht sinnvoll. Außer-
- dem wird ein Dialogfenster immer modal dargestellt, d.h.
- nach dem Aufblenden einer Dialogbox werden alle anderen auf
- dem Bildschirm aktiven Elemente (einschließlich Menü) deak-
- tiviert.
- Dialogboxen können weitere Fenster, sogenannte Childfenster,
- enthalten. Dabei gilt folgende Regel: In ein Dialogfenster
- lassen sich beliebig viele Childfenster implementieren. Zu
- einem konkreten Zeitpunkt darf jedoch nur eines davon aktiv
- sein. Ein Childfenster darf kein weiteres Fenster aufblenden
- (in diesem Fall wäre der Eventhandler des TApp-Objekts maß-
- los überfordert und es würde zu Fehlern kommen. Vielleicht
- baue ich mir einmal in einer ruhigen Minute einen rekursiven
- Algorithmus zusammen, der eine Liste der Form Dialogfenster
- - Childfenster - Child-Childfenster etc. verdauen kann. Nur
- ist die Sache leider nicht trivial ...).
- In ein Dialogfenster lassen sich in beliebiger Anzahl und
- Reihenfolge aktive und passive Dialogelemente einbauen. WG-
- Vision unterstützt in der vorliegenden Version folgende Dia-
- logelemente:
-
-
-
-
-
- Programmierhandbuch WG-Vision - 86 -
-
-
-
-
-
-
-
- Element Objekt Typ Bemerkung
-
- Drucktasten TPushButton passiv kann Kommandos
- absetzen
- Optionsschaltflächen TRadioButton aktiv
- Kontrollfelder TCheckButton aktiv
- Textfelder TInputLine aktiv Texteingabe
- Numerische Eingabefelder TNumButton aktiv Zälschalter mit
- Eingebe
- Listenfelder TListBox aktiv
- Rollbalken TScrollBar aktiv
-
- Gruppenrahmen TGroupFrame passiv
- Sinnbilder (Icons) TIcon passiv 32x32 und 16x16 Icons
- Statischer Text TStaticText passiv
-
-
- Weitere Dialogelemente können bei Beachtung aller Konventio-
- nen leicht programmiert werden (i.A. benötigen Sie dafür
- aber die Quelltexte der Profi-Version).
-
- 5.2.1. Pushbuttons (Drucktasten)
-
- Pushbuttons haben die Eigenschaft, daß sie bei Betätigung
- Kommandos absetzen, die im Feld Command des Event-Records
- verpackt werden. Sie können innerhalb des Eventhandlers des
- Dialogfensters oder auch außerhalb der Dialogbox von anderen
- Objekten abgefangen werden. Das Standard-Kommando cmClose-
- Window schließt z.B. das gerade aktive Fenster.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 87 -
-
-
-
-
-
-
-
- Beispiel
-
- Dialogfenster mit drei Pushbuttons
-
- procedure TApplication.DialogWindow;
- var R:TRect;
- Window:PDlgWindow;
- begin
- R.Assign(60,80,440,280);
- Window:=new(PDlgWindow, Init(R,'Dialogfenster',
- winDouble+winPanel+winMenu));
- with Window^ do
- begin
- SetPushButton(15,40,80,22,'OK',cmCloseWindow);
- SetPushButton(15,70,80,0,'#ICON.I32/1',cmNothing);
- SetPushButton(15,120,80,22,'Piep-Ton',99);
- end; └─ modulinternes Kommando
- InsertDesktop(Window);
- end;
-
- Ein Dialogfenster leitet sich vom Objekt TDlgWindow ab. Die-
- ses Objekt besitzt alle Eigenschaften, um die unter-
- schiedlichsten Dialogelemente zu verwalten. In unserem
- Beispiel werden drei Druckschalter implementiert, bei denen
- nur das Erste eine Reaktion zeigt. Die anderen beiden sind
- "Dummys", erkennbar am Kommando cmNothing. Das zweite Push-
- buttons wurde an Stelle einer Beschriftung mit einem Icon
- versehen. Die Schalterbreite kann in diesem Fall getrost auf
- Null gesetzt werden, da sich das Pushbutton selbständig an
- die Größe des Icons anpaßt. In diesem speziellen Fall ist
- das ein Icon der Größe 32x32 Pixel (erkennbar an der Exten-
- sion .I32). Icon werden in speziellen Icon-Dateien seriell
- gespeichert. Die Zeichenkette "#ICON .I32/1" bedeutet, daß
- die Draw-Methode des Pushbuttons die Icon-Datei ICON.I32
- öffnen und daraus das 1.Icon laden soll.
- Dialogelemente werden in der Reihenfolge ihrer Implementati-
- on angesprochen (fokussiert). Ein fokussiertes Pushbutton
- erkennen Sie an der breiten Umrandung. Den Fokussierzustand
- können Sie entweder durch Anklicken mit der Maus oder durch
-
-
-
- Programmierhandbuch WG-Vision - 88 -
-
-
-
-
-
-
-
- Betätigung der Tabulatator- bzw. Shift-Tabulatortaste än-
- dern. Es ist selbstverständlich, daß sich neben dem Pushbut-
- ton nur aktive und nicht gesperrte Dialogelemente
- fokussieren lassen. Das "Anklicken" erfolgt über die Tasta-
- tur mit der <Space>-Taste.
-
- Syntax
-
- SetPushButton(x,y,xl,yl:integer;Bez:str25;Kommando:word);
-
- x,y Position der linken oberen Ecke relativ zum
- Fenster (!)
- xl,yl Länge und Breite der Drucktaste
- Bez Bezeichner, wird standardmäßig zentriert in die
- Mitte der Drucktaste geschrieben. Wenn Sie Short-
- cuts zur Fokussierung verwenden möchten, müssen
- Sie den entsprechenden Buchstaben in Tilde-Zeichen
- einschließen.Drucktasten können auch mit einem
- Icon versehen werden. Dazu geben Sie als Be-
- zeichner den Dateinamen der Icondatei (mit Exten-
- sion) und dahinter, durch einen Schrägstrich ge-
- trennt, die Nummer des Icons an. Dem Dateinamen
- muß ein Doppelkreuz (#) vorangestellt werden.
- Kommando Wird bei Betätigung der Taste abgesetzt
-
- Ein Dialogfenster, welches sich wie bei unserem Beispiel di-
- rekt von TDlgWindow ableitet, ist in der Regel zu nichts zu
- gebrauchen, weil es einfach nicht flexibel genug ist. Des-
- halb immer einen Nachkommen von TDlgWindow erzeugen und ihn
- mit den gewünschten Eigenschaften ausstatten.
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 89 -
-
-
-
-
-
-
-
- Beispiel
-
- Verbessertes Dialogfenster
-
- type PNewDialog=^TNewDialog;
- TNewDialog=object(TDlgWindow)
- constructor Init(x,y:integer);
- procedure HandleEvent; virtual;
- end;
-
- {Implementation TNewDialog}
-
- constructor TNewDialog.Init(x,y:integer);
- var RR:TRect;
- begin
- RR.Assign(x,y,x+380,yy+200);
- TDlgWindow.Init(RR,'Dialogfenster',
- winDouble+winPanel+winMenu));
- SetPushButton(15,40,80,22,'OK',cmCloseWindow);
- SetPushButton(15,70,80,0,'#ICON.I32/1',cmNothing);
- SetPushButton(15,120,80,22,'Piep-Ton',99);
- end;
-
- procedure TNewDialog.HandleEvent;
- begin
- TDlgWindow.HandleEvent;
- if Event.Command=99 then
- begin
- Beep(100);
- Event.Command:=cmNothing;
- end;
- end;
-
- Diese Dialogbox braucht jetzt nur noch in die Fensterliste
- des Applikationsobjekts eingefügt werden:
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 90 -
-
-
-
-
-
-
-
- procedure TApplication.DialogWindow;
- var Window:PNewDialog;
- begin
- Window:=new(PNewDialog, Init(60,80));
- InsertDesktop(Window);
- end;
-
- Dieses Beispiel zeigt in stark vereinfachter Form auch, wie
- Ereignisse, die eine Dialogbox generiert, sofort verarbeitet
- werden können. Immer dann, wenn Sie die Taste mit der Auf-
- schrift "Piep-Ton" drücken, wird das Kommando "99" abgesetzt
- (von TDlgWindow.HandleEvent). Dieses Kommando wird im Event-
- handler der Dialogbox "herausgefischt" und daraufhin ein
- Piep-Ton generiert. Zum Abschluß wird ein ordentlicher Pro-
- grammierer Event.Command wieder auf cmNothing setzen.
-
- 5.2.1.1. Farbgestaltung
-
- Damit Sie bei Ihren Programmierversuchen nicht nur auf Ta-
- sten in dezenten Mausgrau zurückgreifen müssen, wurde dem
- TDlgWindow-Objekt die Methode ChangePalColor mitgegeben, mit
- deren Hilfe sie die Farben der meisten Dialogelemente den
- eigenen Wünschen anpassen können.
- Den Pushbuttons wird die Farbpalette 4 (Palette4 in WView)
- zugeordnet:
-
- Eintrag Bedeutung Standard
-
- 1 Außenrahmen #0 Schwarz
- 2 Hintergrund #15 Weiß
- 3 Taste aktiv #7 Hellgrau
- 4 Taste, unten und rechts #0 Schwarz
- 5 Taste, inaktiv #15 Weiß (Gray50)
- 6 Beschriftung #0 Schwarz
- 7 Focus-Bereich #0 Schwarz
- 8 Fenster-Hintergrund #15 Weiß
-
- Die Änderung der Paletteneinträge erfolgt mit dem Befehl
- ChangePalColor(Eintrag, Farbe:byte). Dieser Befehl bzw. eine
-
-
-
- Programmierhandbuch WG-Vision - 91 -
-
-
-
-
-
-
-
- Folge von derartigen Befehlen muß sofort nach dem Befehl
- SetPushButton implementiert werden (einrücken):
-
- ...
- SetPushButton(15,120,80,22,'Farbtest',cmNothing);
- ChangePalColor(3,Red);
- ChangePalColor(6,White);
- ChangePalColor(4,Blue);
- ChangePalColor(1,Blue);
- ChangePalColor(2,LightCyan);
- SetPushButtons(15,160,80,22,'Fonts',cmNothing);
- ChangePalColor(3,Green);
- ChangePalColor(6,White)
- ...
-
- 5.2.1.2. Verändern der Textposition
-
- Mit dem Befehl SetTextPosition können Sie die Lage des Be-
- zeichners relativ zur Tastenmitte verändern:
-
- ...
- SetPushButton(150,40,80,22,'OK',cmCloseWindow);
- SetTextPosition(0,22); {22 Pixel nach unten}
- SetPushButton(150,120,80,0,'#ICON.I32/2',cmNothing);
- ...
-
- Hinweis: Icons lassen sich nicht verschieben !
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 92 -
-
-
-
-
-
-
-
- Komplexbeispiel "Klavier-Simulator"
-
- Das folgende Beispiel soll Ihnen zeigen, wie man sich sein
- eigenes Tasteninstrument programmieren kann. Es ist gewis-
- sermaßen eine minimale Minimalversion, die Sie, wenn Sie
- Zeit haben, bis zu einer High-End-Soundblaster-Ansteuerungs-
- software "auf-blastern" können. Hier verwenden wir zur Ton-
- erzeugung einfach den PC-Piepser, was auch erklärt, warum
- die "Herz-Routine" dieses Simulationsprogramms "Pieps"
- heißt.
- Die Bedienung des "Klavier-Simulators" erfolgt durch Ankli-
- ken der Tasten mit der Maus. Eine Tastaturunterstützung wäre
- natürlich auch noch möglich gewesen, hätte das Programm aber
- etwas komplizierter gemacht. Deshalb wurde darauf verzich-
- tet.
-
- program Klavier;
-
- uses WApp,
- WEvent,
- WDecl,
- WViews,
- WDlg,
- WUtils,
- crt;
-
- const cmKlavier=101;
-
- type TApplication=object(TApp)
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- procedure PlayWindow;
- end;
-
- PPiano=^TPiano; {Unser "Klavier"}
- TPiano=object(TDlgWindow)
- constructor Init(x,y:integer);
- procedure HandleEvent; virtual;
- end;
-
-
-
- Programmierhandbuch WG-Vision - 93 -
-
-
-
-
-
-
-
- var MyApp:TApplication;
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~F~enster',0);
- SubMenu('~K~lavier',cmKlavier,0,0,false,false); {etwas übertrieben}
- SubMenu('E~x~it Alt-X',cmCloseApplication,0,altX,false,false);
- end;
-
- procedure TApplication.HandleEvent;
- begin
- Heap^.ShowHeapStatus(523,8,White); {wir testen noch}
- TProgram.HandleEvent;
- case Event.Command of
- cmKlavier : PlayWindow;
- end; {case}
- end;
-
- procedure TApplication.PlayWindow; {was es alles für Fenster gibt ...}
- var Window:PPiano;
- begin
- Window:=new(PPiano, Init(60,80));
- InsertDesktop(Window);
- end;
-
- {Implementation TPiano}
-
- constructor TPiano.Init(x,y:integer);
- var RR:TRect;
- begin
- RR.Assign(x,y,x+184,y+102);
- TDlgWindow.Init(RR,'Klavier',winDouble+winPanel+winMenu);
- SetPushButton(6,26,22,70,'C',90);
- ChangePalColor(8,LightGray); {nur eine Oktave}
- SetPushButton(31,26,22,70,'D',91);
- ChangePalColor(8,LightGray);
- SetPushButton(56,26,22,70,'E',92);
- ChangePalColor(8,LightGray);
-
-
-
-
- Programmierhandbuch WG-Vision - 94 -
-
-
-
-
-
-
-
- SetPushButton(81,26,22,70,'F',93);
- ChangePalColor(8,LightGray);
- SetPushButton(106,26,22,70,'G',94);
- ChangePalColor(8,LightGray);
- SetPushButton(131,26,22,70,'A',95);
- ChangePalColor(8,LightGray);
- SetPushButton(156,26,22,70,'H',96);
- ChangePalColor(8,LightGray);
- end;
-
- procedure TPiano.HandleEvent;
-
- procedure Pieps(Frequenz:integer);
- begin {der PC-Piepser kann halt nur piepsen}
- sound(Frequenz);
- delay(100);
- nosound;
- end;
-
- {-------}
-
- begin
- TDlgWindow.HandleEvent;
- case Event.Command of {und hier wird in der 4.Oktave gepiepst !}
- 90 : Pieps(262);
- 91 : Pieps(294);
- 92 : Pieps(330);
- 93 : Pieps(349);
- 94 : Pieps(392);
- 95 : Pieps(440);
- 96 : Pieps(494);
- end; {case}
- end;
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 95 -
-
-
-
-
-
-
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Klavier-Simulation'); {klingt bombastisch, nicht ?}
- MyApp.Run;
- MyApp.Done;
- end.
-
- Zu diesem Programm gibt es eigentlich nicht viel zu sagen.
- Es zeigt sehr schön, wie man Pushbutton-Kommandos abfangen
- und damit Aktionen steuern kann. In Perfektion können Sie
- die Vorgehensweise innerhalb des Taschenrechner-Objekts
- TCalc studieren, welches Bestandteil von WG-Vision ist.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 96 -
-
-
-
-
-
-
-
- 5.2.2. Statische Texte
-
- In ein Dialogfenster können an jeder beliebigen Stelle sta-
- tische Texte eingefügt werden. Mit der Methode SetStaticText
- legen Sie fest, was für ein Text an welcher Stelle in wel-
- cher Justierung ausgegeben werden soll. Außerdem können Sie
- bei Verwendung einer der Vektorzeichensätze noch die
- Schriftgröße und den Zeichensatz auswählen (mit dem Befehl
- SetTextParameters). Statische Texte werden von WG-Vision wie
- Dialogelemente verwaltet. Sie sind jedoch nicht fokussierbar
- (warum auch ?). Dieser Befehl ist deshalb nicht geeignet,
- einen Text auf ein Hintergrundobjekt zu schreiben. Dort
- sollten Sie die normalen, von Turbo-Pascal unterstützten
- Textausgabebefehle verwenden.
-
- Syntax
-
- SetStaticText(x,y:integer;Bez:string;RichPos:byte);
-
- x,y Bezugspunkt des Textes
- Bez auszugebender Text
- RichPos Ausrichtung relativ zu x und y. Folgende
- vordefinierten
- Konstanten können verwendet werden:
-
- LeftText linksbündig
- RightText rechtsbündig
- Centertext zentriert
-
- Eine Anwendung zeigt folgendes Beispiel:
-
- procedure TApplication.DialogText;
- var R:TRect;
- Window:PDlgWindow;
- begin
- R.Assign(60,80,440,280);
- Window:=new(PDlgWindow, Init(R,'Textausgabe im Dialogfenster',
- winDouble+winPanel+winMenu));
-
-
-
-
- Programmierhandbuch WG-Vision - 97 -
-
-
-
-
-
-
-
- with Window^ do
- begin
- SetPushButton(15,40,80,22,'OK',cmCloseWindow);
- SetStaticText(150,40,'Standard-Zeichensatz',LeftText);
- end;
- InsertDesktop(Window);
- end;
-
- Für die Textfarbe ist der Paletteneintrag 10 zuständig. Soll
- z.B. die Zeichenkette in Rot ausgegeben werden, dann ist der
- Quelltext um den Befehl ChangePalColor zu ergänzen:
-
- ...
-
- SetStaticText(150,40,'Standardzeichensatz',LeftText);
- ChangePalColor(10, Red);
- ...
-
- Mit dem Befehl SetTextParameters können Sie den Zeichensatz,
- die Größe der Buchstaben und die Ausrichtung des Textes
- beeinflussen.
- Unterstützt werden neben dem Standardzeichensatz DefaultFont
- folgende 9 Vektorzeichensätze:
-
- TriplexFont TRIP.CHR
- SmallFont LITT.CHR
- SansSerifFont SANS.CHR
- GothicFont GOTH.CHR
- ScriptFont SCRI.CHR
- SimpleFont SIMP.CHR
- TSCRFont TSCR.CHR
- LCOMFont LCOM.CHR
- EuroFont EURO.CHR
-
- Die in einem Programm verwendeten Zeichensätze müssen zur
- Laufzeit im Verzeichnis des Programms vorhanden sein. Aus
- Speicherplatzgründen wurde auf eine Einbindung als Objektda-
- tei in WG-Vision verzichtet.
-
-
-
-
- Programmierhandbuch WG-Vision - 98 -
-
-
-
-
-
-
-
- Für die Textausrichtung verwenden Sie bitte die Konstanten
- HorizDir und VertDir.
-
- Syntax
-
- SetTextParameters(Fnt,Direct:word;CharSz:byte);
-
- Fnt Zeichensatz (DefaultFont ... EuroFont)
- Direct Ausrichtung (HorizDir, VertDir)
- CharSz Buchstabengröße
-
- Beispiel
-
- ...
-
- SetStaticText(150,40,'Gotischer Zeichensatz',LeftText);
- SetTextParameters(GothicFont,HorizDir,1);
- SetStaticText(150,65,'Triplex - Zeichensatz',LeftText);
- SetTextParameters(TriplexFont,HorizDir,1);
- SetStaticText(150,90,'Small - Zeichensatz',LeftText);
- SetTextParameters(SmallFont,HorizDir,6);
- ...
-
- Folgendes Beispiel zeigt alle verfügbaren Vektorzeichensätze
- in einem Dialogfenster an:
-
- program ShowFonts;
-
- uses WDecl,
- WEvent,
- WViews,
- WDlg,
- WApp,
- graph;
-
- const cmDialog = 101;
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 99 -
-
-
-
-
-
-
-
- type TApplication=object(TApp)
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- procedure DialogWindow;
- end;
-
- var MyApp:TApplication;
-
- {Implementation TApplication}
-
- procedure TApplication.InitMenuBar;
- begin
- Palette[1]:=#14; {diesmal ein etwas bunteres Menü}
- Palette[5]:=#14;
- Palette[4]:=#4;
- Palette[12]:=#4;
- MainMenu('~F~enster',0);
- SubMenu('~D~ialogfenster',cmDialog,0,0,false,false);
- SubMenu('E~x~it Alt-X',cmCloseApplication,0,altX,false,false);
- end;
-
- procedure TApplication.HandleEvent;
- begin
- Heap^.ShowHeapStatus(523,8,White);
- TProgram.HandleEvent;
- case Event.Command of
- cmDialog : DialogWindow;
- end; {case}
- end;
-
- procedure TApplication.DialogWindow;
- var R:TRect;
- Window:PDlgWindow;
- begin
- R.Assign(60,80,440,360);
- Window:=new(PDlgWindow, Init(R,'Beispiel 18 : Vektor-Zeichensätze',
- winDouble+winPanel+winMenu+winKey));
-
-
-
-
-
- Programmierhandbuch WG-Vision - 100 -
-
-
-
-
-
-
-
- with Window^ do {die Zeichensätze müssen natürlich verfügbar sein}
- begin
- SetPushButton(15,40,80,22,'Schließen',cmCloseWindow);
- SetStaticText(150,40,'Gotischer Zeichensatz',LeftText);
- SetTextParameters(GothicFont,HorizDir,1);
- SetStaticText(150,65,'Triplex - Zeichensatz',LeftText);
- SetTextParameters(TriplexFont,HorizDir,1);
- SetStaticText(150,90,'Small - Zeichensatz',LeftText);
- SetTextParameters(SmallFont,HorizDir,6);
- SetStaticText(150,110,'Sanserif - Zeichensatz',LeftText);
- SetTextParameters(SansSerifFont,HorizDir,1);
- SetStaticText(150,125,'Script - Zeichensatz',LeftText);
- SetTextParameters(5,HorizDir,1);
- SetStaticText(150,147,'Simple - Zeichensatz',LeftText);
- SetTextParameters(6,HorizDir,1);
- SetStaticText(150,168,'TSCR - Zeichensatz',LeftText);
- SetTextParameters(7,HorizDir,1);
- SetStaticText(150,185,'LCOM - Zeichensatz',LeftText);
- SetTextParameters(8,HorizDir,1);
- SetStaticText(60,210,'Euro - Zeichensatz',LeftText);
- SetTextParameters(9,HorizDir,1);
- SetStaticText(40,140,'Vertical - Small',RightText);
- SetTextParameters(SmallFont,VertDir,4);
- end;
- InsertDesktop(Window);
- end;
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Zeichensätze im Dialogfenster');
- MyApp.Run;
- MyApp.Done;
- end.
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 101 -
-
-
-
-
-
-
-
- 5.2.3. Rahmen, Gruppenrahmen
-
- Ein wichtiges passives Dialogelement ist der Gruppenrahmen.
- Er dient der übersichtlichen Gestaltung eines Dialogfen-
- sters. Mit Gruppenrahmen werden funktional zusammengehörende
- Dialogelemente (z.B. eine Gruppe von Radiobuttons) versehen,
- um ihre Zusammengehörigkeit hervorzuheben.
- Gruppenrahmen müssen immer vor den Dialogelementen implemen-
- tiert werden, die der Rahmen einfassen soll (bei den Grup-
- penrahmen handelt es sich um Rahmen mit "Füllung").
-
- Syntax
-
- SetGroupFrame(x,y,xl,yl:integer;Bez:str25;FrameTyp:word);
-
- x,y linke obere Ecke
- xl,yl Länge und Breite des Rahmens
- FrameTyp Rahmentyp. Folgende Rahmentypen sind verfügbar:
-
- NormWidth normale Linienstärke
- ThickWidth dreifache Linienstärke
-
- Der Bezeichner wird, wie bei Windows üblich, links oben in
- den Rahmen eingefügt. Er kann aber auch beliebig positio-
- niert werden, indem ihm mit SetTextPosition eine neue Posi-
- tion im Dialogfenster zugeordnet wird. In diesem Fall
- schließt sich der Rahmen zu einem vollständigen Rechteck.
- Die Positionierung des Bezeichners erfolgt absolut innerhalb
- des durch den Rahmen des Dialogfensters gegebenen Koordina-
- tensystems (siehe Beispiel).
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 102 -
-
-
-
-
-
-
-
- 5.2.3.1. Farbgestaltung
-
- Für die farbliche Gestaltung des Gruppenrahmens ist Palette
- 5 zuständig:
-
- Palettenlayout
-
- Eintrag Bedeutung Standard
-
- 1 Rahmenfarbe #0 Schwarz
- 2 Hintergrund #15 Weiß
- 4 Bezeichner #0 Schwarz
-
- Beispiel
-
- procedure TApplication.DialogWindow;
- var R:TRect;
- Window:PDlgWindow;
- begin
- R.Assign(60,80,440,360);
- Window:=new(PDlgWindow, Init(R,'Beispiel 19 :
- Gruppenfenster',winDouble+winPanel+winMenu));
- with Window^ do
- begin
- SetPushButton(15,40,80,22,'OK',cmCloseWindow);
- SetGroupFrame(130,40,210,60,'Gruppenfenster 1',NormWidth);
- SetGroupFrame(130,120,210,60,'Gruppenfenster 2',ThickWidth);
- SetGroupFrame(130,200,210,60,'Gruppenfenster 3',ThickWidth);
- ChangePalColor(1,Blue); {Rahmen}
- ChangePalColor(2,Yellow); {Hintergrund}
- ChangePalColor(4,Green); {Text}
- SetGroupFrame(15,160,80,60,'Rahmen 4',ThickWidth);
- SetTextPosition(15,145); {neue Textposition relativ zum}
- {Fenster}
- ChangePalColor(4,Magenta);
- ChangePalColor(2,LightRed);
- end;
- InsertDesktop(Window);
- end;
-
-
-
- Programmierhandbuch WG-Vision - 103 -
-
-
-
-
-
-
-
- 5.2.4. Icons
-
- Seitdem es Windows gibt, werden Icons immer beliebter. Dem
- will auch WG-Vision nicht nachstehen. Im Gegensatz zu Win-
- dows werden aber nur statische Icons unterstützt. Das sind
- Sinnbilder, die als passives Dialogelement fest (und nicht
- mit der Maus verschiebbar) in einem Dialogfenster angeordnet
- werden. Außerdem lassen sie sich sehr gut zur Ausschmückung
- von Pushbuttons (z.B. für eine Icon-Leiste) verwenden.
- Die von WG-Vision verwendeten Icons sind nicht Windows-kom-
- patibel. Sie werden, nachdem sie in einem Icon-Editor er-
- stellt worden sind, mit GetImage ausgelesen und via
- BlockWrite in eine Datei geschrieben. Solch eine Datei kann
- beliebig viele Icons gleicher Größe (z.B. 32x32 Pixel) ent-
- halten und wird als Icon-Ressource bezeichnet. Der Aufruf
- eines Icons erfolgt über seinen Index (d.h. Position) inner-
- halb dieser Datei.
- WG-Vision verwendet Icons der Größe 16x16 und 32x32 Pixel.
- Eine Icon-Ressource kann nur Icons eines Typs (erkenntlich
- an den Extensionen .I16 und .I32) enthalten. Außerdem muß
- noch beachtet werden, daß Icons für EGA- und VGA-Grafikkarte
- nicht in den VESA-Super-VGA-Modi verwendet werden können
- (andere Organisation des Bildwiederholspeichers und der
- Farbcodierung).
-
- Syntax
-
- SetIcon(x,y:integer;Bez:str25);
-
- x,y Koordinate der linken oberen Ecke
- Bez Dateiname + Iconnummer
-
- Beispiel
-
- SetIcon(100,120,'#ICON.I32/5');
- │ │ └─ Icon Nr. 5
- │ └─ Extension I32, 32x32 Pixel-Icon
- └─ Dateiname, das Doppelkreuz muß
- zusätzlich angegeben werden
-
-
-
- Programmierhandbuch WG-Vision - 104 -
-
-
-
-
-
-
-
- 5.2.5. Aktive Dialogelemente in WG-Vision
-
- Der eigentliche Sinn von Dialogboxen besteht in der Eingabe
- von Informationen, auf die i.A. andere Programmteile zugrei-
- fen sollen. Das bedeutet, daß die Daten, die Sie in ein Dia-
- logfenster eingeben, auch außerhalb dieses Dialogfensters
- verfügbar sein müssen. Um diese Forderung zu erfüllen, be-
- nutzt WG-Vision spezielle Datenrecords (Dialog-Record), die
- für jedes Dialogfenster individuell erstellt werden. Die Re-
- cordvariablen sind Programm- bzw. Modul-global. Ihr Inhalt
- kann damit von beliebigen Programmteilen gelesen werden.
-
- Prinzipielles Herangehen
-
- 1. Deklaration eines Programm- bzw. Modul-globalen
- Datenrecords für jedes Dialogfenster
-
- type tFontDataRec=record
- Schalter:string[9];
- end; └─ Dialogbox enthält 9 Dialogelemente
-
- Bei einer Modul-globalen Deklaration ist der Dialogrecord
- nur innerhalb einer Unit verfügbar. Die Deklaration erfolgt
- innerhalb des Implementationsteils der Unit (Beispiel siehe
- Unit WPalette.pas).
-
- 2. Record-Variable deklarieren
-
- var FontDataRec:tFontDataRec;
-
- 3. Record-Variable mit Anfangswerten belegen (nicht
- vergessen!)
-
- Die Initialisierung der Datenrecords erfolgt innerhalb der
- virtuellen Methode SetDialogData. Innerhalb dieser Methode
- werden die Datenrecords aller im Programm vorkommenden Dia-
- logfenster mit Anfangswerten belegt. Bei Modul-internen De-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 105 -
-
-
-
-
-
-
-
- klarationen ist diese Vorgehensweise nicht notwendig. In
- solch einem Fall belegen Sie den Dialogrecord am Besten
- innerhalb des Konstruktors des Dialogfensters.
-
- procedure TApplication.SetDialogData;
- begin
- with FontDataRec do Schalter:='TGrrrrRrG';
- end;
-
- An dieser Stelle ist besondere Sorgfalt angesagt. Ein klei-
- ner Fehler kann schnell zu unvorhergesehenen Programmabläu-
- fen führen. Die Variable Schalter enthält in der Reihenfolge
- der Implementation die Kennbuchstaben der im Dialogfenster
- implementierten Dialogelemente. Die Anzahl der Zeichen in
- diesem String muß genauso groß sein wie die im Datenrecord
- vorgegebene Stringlänge.
- Innerhalb von WG-Vision gelten folgende Kennbuchstaben für
- die einzelnen Dialogelemente:
-
- T Pushbutton
- R gesetztes Radiobutton
- r nichtgesetztes Radiobutton
- C gesetztes Checkbutton
- c nichtgesetztes Checkbutton
- L Eingabezeile, Zählschalter
- B Listbox
- G Gruppenrahmen
- I Icon
- S statischer Text
-
- Hinweis: Dialogfenster, welche nur passive Dialogelemente
- enthalten, benötigen keinen Datenrecord zum
- Datenaustausch.
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 106 -
-
-
-
-
-
-
-
- 5.2.6. Radio-Buttons (Optionsschaltflächen)
-
- Radio-Buttons verdanken ihren Namen den Frequenzwahltasten
- an Radios, deren Funktionsweise sie nachahmen. Betätigt man
- z.B. mit der Maus ein Radiobutton, dann wird der bisher ak-
- tive Radiobutton deaktiviert. Daraus wird ersichtlich, daß
- mindestens zwei Radiobuttons eine Gruppe bilden. Ein Radio-
- button für sich allein ergibt keinen Sinn.
- Da Radiobuttons innerhalb eines Programms verschiedene Funk-
- tionseinheiten repräsentieren können, ist eine Gruppenbil-
- dung unerläßlich. Die Gruppenzugehörigkeit eines Radiobut-
- tons wird durch den Parameter PGruppe festgelegt.
- Das Einfügen von Radiobuttons in ein Dialogfenster ist sehr
- einfach, wie folgendes Beispiel zeigt:
-
- constructor TSetFontWindow.Init(x,y:integer);
- var RR:TRect;
- begin
- RR.Assign(x,y,x+455,y+265);
- TDlgWindow.Init(RR,'Zeichensätze', winDouble+winPanel+winMenu);
- SetPushButton(55,210,80,22,'OK',cmCloseWindow);
- SetGroupFrame(25,55,150,125,'Zeichensätze',NormWidth);
- SetRadioButton(45,80, '~T~hin8 8x12',1); {Gruppe 1}
- SetRadioButton(45,95, 'T~h~in14 8x14',1);
- SetRadioButton(45,110,'Th~i~n16 8x16',1);
- SetRadioButton(45,125,'~B~rdwy19 8x19',1);
- SetRadioButton(45,140,'~W~ndw19 8x19',1);
- SetRadioButton(45,155,'~S~ans19 8x19',1);
- SetData(FontDataRec); {Dialogrecord mit Anfangswerten übergeben}
- end;
-
- Mit SetData werden dem Dialogfenster die Anfangswerte zu-
- gänglich gemacht. Die Variable Schalter in FontDataRec hat
- folgende Belegung:
-
- Schalter:='TGrrrrRrG';
-
- Das Radiobutton mit der Bezeichnung Wndw19 ist beim Aufblen-
- den des Dialogfensters aktiv. Das wird durch den Buchstaben-
-
-
-
- Programmierhandbuch WG-Vision - 107 -
-
-
-
-
-
-
-
- kürzel "R" (im Gegensatz zu "r") erreicht. Wenn ein anderes
- Radiobutton angeklickt wird (z.B. Thin14), dann ändert sich
- Schalter simultan in
-
- 'TGrRrrrrG'
-
- Durch die Analyse dieser Zeichenkette kann man nach dem
- Schließen des Dialogfensters (oder simultan innerhalb dessen
- Eventhandlers) die neue Schalterstellung auswerten, z.B. mit
-
- if Schalter[4]:'R' then ...
-
- Oft versieht man ein Dialogfenster mit dem Schalter "Abbre-
- chen". Damit nach einem Abbruch der Ursprungszustand des
- Dialogrecords wieder hergestellt werden kann, empfiehlt es
- sich, eine Zwischenvariable für den Dialogrecord als Feld
- innerhalb des Dialogfenster-Objekts einzurichten. Innerhalb
- des Konstruktors wird in diesem Feld der Dialogrecord zwi-
- schengespeichert. Sendet das Dialogfenster das Kommando
- cmCancel, dann läßt sich innerhalb des Eventhandlers der
- Originalzustand leicht wieder herstellen.
-
- Komplexbeispiel Quelltext-Lister mit Zeichensatzänderung
-
- Das folgende Beispiel zeigt die Verwendung von Radiobuttons
- in einem konkreten Anwendungsfall. Außerdem werden einige
- spezielle Programmiermethoden (Abfangen von Mitteilungen,
- Sperren und Freigabe von Menüpunkten, Änderung des Fenster-
- hintergrundes ohne Verwendung des TBackground-Objekts)
- behandelt.
-
- Aufgabenstellung
- Es soll ein einfacher Quelltextlister (Erweiterung des
- Programms Lister.pas) entwickelt werden, bei dem sich zur
- Laufzeit der Zeichensatz wechseln läßt. Die verfügbaren
- Zeichensätze sollen sich aus einem Dialogfenster unter
- Verwendung von Radiobuttons auswählen lassen.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 108 -
-
-
-
-
-
-
-
- Der Quelltextlister mit Veränderung des Zeichenfonts
- funktioniert nicht in den Super-VGA-Modi.
-
- program Lister;
-
- uses WApp,
- WEvent,
- WDecl,
- WViews,
- WDriver,
- WDlg,
- WFileDlg,
- WUtils,
- WText,
- graph;
-
-
- const cmOpen = 101;
- cmSetFont = 102;
-
- msgDraw = 100; {Mitteilung, Scrollbereich mit neuem}
- {Zeichensatz darstellen}
-
- type TApplication=object(TApp)
- procedure InitMenuBar; virtual;
- procedure SetDialogData; virtual;
- procedure HandleEvent; virtual;
- procedure LoadFile;
- procedure ListWindow;
- procedure SetFont;
- end;
-
- PNewScroller=^TNewScroller;
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 109 -
-
-
-
-
-
-
-
- PScrollWindow=^TScrollWindow;
- TScrollWindow=object(TWindow)
- Scroller:PNewScroller;
- procedure InitWindowScroller; virtual;
- procedure HandleEvent; virtual;
- destructor Done; virtual;
- end;
-
- TNewScroller=object(TScroller)
- procedure CreateData;
- procedure ScrollDraw; virtual;
- end;
-
- {Dialogfenster zur Auswahl der Zeichensätze}
-
- PSetFontWindow=^TSetFontWindow;
- TSetFontWindow=object(TDlgWindow)
- DFont:GraficFont;
- constructor Init(x,y:integer);
- procedure DrawClientArea; virtual;
- procedure HandleEvent; virtual;
- end;
-
- {Dialog-Record}
-
- tFontDataRec=record
- Schalter:string[8];
- end;
-
-
- var MyApp:TApplication;
- FontDataRec:tFontDataRec;
-
- Der Menüpunkt "Zeichensatz wechseln" ist beim Programmstart gesperrt
- (vorletzter Parameter=true). Da es in diesem konkreten Beispiel wenig
- sinnvoll ist, den Zeichensatz vor dem Aufblenden des Listfensters zu än-
- dern (das List-Objekt stellt bei seiner Initialisierung selbst einen
- Zeichensatz ein), wird dieser Menüpunkt einfach gesperrt. Erst wenn sich
- ein List-Fenster auf dem Bildschirm befindet, wird er freigegeben (siehe
-
-
-
- Programmierhandbuch WG-Vision - 110 -
-
-
-
-
-
-
-
- TApplication.HandleEvent)
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~F~enster',0);
- SubMenu('~D~atei Laden',cmOpen,0,0,false,false);
- SubMenu('~Z~eichensatz wechseln',cmSetFont,0,0,true,false);
- NewLine;
- SubMenu('E~x~it Alt-X',cmCloseApplication,0,altX,false,false);
- end;
-
- Dialogrecord initialisieren. Das Radiobutton Nr.5 ist aktiv
-
- procedure TApplication.SetDialogData;
- begin
- FontDataRec.Schalter:='TGrrrrRr';
- end;
-
- Das Objekt TInputDialog (Unit WFileDlg) ist eine komplette Dateiaus-
- wahlbox. Diese Auswahlbox sendet die Message msgLoadFile, wenn daraus
- ein gültiger Dateiname ausgewählt wurde. Dieser Dateiname wird in
- Event.InfoString mit kompletten Pfad gespeichert und damit letztendlich
- zu seinem Empfänger transportiert (TNewScroller.CreateData). Das pas-
- siert beim Aufruf von ListWindow. Dieses Objekt ist für die Darstellung
- eines Textes in einem Scrollfenster zuständig. Danach darf auf keinem
- Fall vergessen werden, die Message zu löschen. Andernfalls würden weite-
- re Listfenster im Heap (und auf dem Bildschirm) erzeugt bis leztendlich
- der Speicher voll ist.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 111 -
-
-
-
-
-
-
-
- procedure TApplication.HandleEvent;
- begin
- Heap^.ShowHeapStatus(523,8,White);
- TProgram.HandleEvent;
- case Event.Command of
- cmOpen : LoadFile;
- cmSetFont : SetFont;
- end; {case}
- if Event.Message=msgLoadFile then
- begin
- ListWindow;
- ClearMessage;
- end;
-
- Jeder Untermenüeintrag verfügt als Instanz von TSubMenu Methoden, um
- sich zu sperren (Aktiviere) und sich wieder freizugeben (DeAktiviere).
- Ein gesperrter Untermenüpunkt wird standardmäßig auf dem Bildschirm mit
- hellgrauer Schrift dargestellt. Er kann dann keine Kommandos mehr abset-
- zen. Ein zu sperrendes Untermenü erreicht man über die Pointerkette MMe-
- nu[Nr des Hauptmenü-eintrags]^.SBMenu[Position im Pull-Down-Menü]^.
- NewLine zählt dabei auch als Eintrag. In diesem Beispiel wird das Menü
- immer dann gesperrt, wenn sich kein Listfenster (WinAnz=0) auf dem Bild-
- schirm befindet.
-
- if WinAnz=0 then MMenu[1]^.SbMenu[2]^.Aktiviere
- else MMenu[1]^.sbMenu[2]^.DeAktiviere;
- end;
-
- Hier sieht man die Vorteile, die ein ordentlich ausgetestetes Fenster-
- objekt, verpackt in einer Unit (hier WFileDlg), den Programmierer bietet
- (oder wie lange würden Sie zur Programmierung eines Eingabedialogs benötigen ?
-
- procedure TApplication.LoadFile;
- var Window:PInputDialog;
- begin
- Window:=new(PInputDialog, Init('Dateiauswahl','*.PAS'));
- InsertDesktop(Window);
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 112 -
-
-
-
-
-
-
- procedure TApplication.ListWindow;
- var R:TRect;
- Window:PScrollWindow;
- begin
- R.Assign(20,60,616,446);
- Window:=new(PScrollWindow, Init(R,'ScrollWindow / Quelltext-Lister',
- winDouble+winPanel+winMenu+winKey));
- InsertDesktop(Window);
- end;
-
- procedure TApplication.SetFont;
- var Window:PSetFontWindow;
- begin
- Window:=new(PSetFontWindow, Init(60,80));
- InsertDesktop(Window);
- end;
-
- {Implementation TScrollWindow}
-
- procedure TScrollWindow.InitWindowScroller;
- var R:TRect;
- SBH1,SBV1:PScrollBar;
- begin
- R:=Frame^.Area;
- SBH1:=new(PScrollBar, Init(R,HorizDir));
- SBV1:=new(PScrollBar, Init(R,VertDir));
- Scroller:=new(PNewScroller, Init(R,SBH1,SBV1));
- Scroller^.CreateData;
- List^.InsertItem(Scroller);
- end;
-
- procedure TScrollWindow.HandleEvent;
- begin
- TWindow.HandleEvent;
- if Event.Message=msgDraw then {Scrollbereich neu darstellen}
- begin
- Scroller^.ScrollDraw;
- ClearMessage;
- end;
- end;
-
-
-
- Programmierhandbuch WG-Vision - 113 -
-
-
-
-
-
-
-
- destructor TScrollWindow.Done;
- begin
- TWindow.Done;
- dispose(Scroller, Done);
- end;
-
- {Implementation TNewScroller}
-
- procedure TNewScroller.CreateData;
- var dat:text;
- LfdPtr:PLine;
- begin
- SetFont(Wndw19);
-
- An dieser Stelle wird der InfoString ausgelesen. Rückgesetzt wird die
- Mitteilung aber erst im Eventhandler der Applikation
-
- assign(dat,Event.InfoString);
- reset(dat);
- while not EOF(dat) do
- begin
- LfdPtr:=new(PLine, Init);
- readln(dat,LfdPtr^.Eintrag);
- Liste^.InsertItem(LfdPtr);
- end;
- SetLimit(25,Liste^.AnzElem-1,8,16);
- end;
-
- procedure TNewScroller.ScrollDraw;
- var i:integer;
- LfdPtr:PGroup;
-
- function clip(p,n:byte;z:string):string;
- begin
- clip:=copy(z,p,n);
- end;
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 114 -
-
-
-
-
-
-
-
- begin
- SetFontColor(White,Blue); {Farbgestaltung des gerade}
- {aktiven Zeichensatzes}
- Mouse.HideMouse;
- with Border do
- begin
- SetFillStyle(SolidFill,GetPalColor(1));
- SetColor(GetPalColor(2));
- for i:=Delta.y to WDelta.y do
- begin
- LfdPtr:=Liste^.GetItems(i);
- Bar(A.x,A.y+(i-Delta.y)*Py+10,B.x,A.y+(i-Delta.y)*Py+10+Py);
- WriteText(A.x+20,A.y+(i-Delta.y)*Py+10,clip(Delta.x,
- Spalten*8 div 8-5,PLine(LfdPtr)^.Eintrag));
- end;
- if VertiScrollBar<>nil then
- for i:=(WDelta.y-Delta.y)+1 to Zeilen do
- Bar(A.x,A.y+i*Py+10,B.x,A.y+i*Py+10+Py);
- end;
- Mouse.ShowMouse;
- end;
-
- {Implementation TSetFontWindow}
-
- constructor TSetFontWindow.Init(x,y:integer);
- var RR:TRect;
- i:integer;
- begin
- RR.Assign(x,y,x+455,y+265);
- TDlgWindow.Init(RR,'Zeichensätze',winDouble+winPanel+winMenu);
- SetPushButton(55,210,80,22,'OK',cmCloseWindow);
- SetGroupFrame(25,55,150,125,'Zeichensätze',NormWidth);
- SetRadioButton(45,80, '~T~hin8 8x12',1);
- SetRadioButton(45,95, 'T~h~in14 8x14',1);
- SetRadioButton(45,110,'Th~i~n16 8x16',1);
- SetRadioButton(45,125,'~B~rdwy19 8x19',1);
- SetRadioButton(45,140,'~W~ndw19 8x19',1);
- SetRadioButton(45,155,'~S~ans19 8x19',1);
-
-
-
-
- Programmierhandbuch WG-Vision - 115 -
-
-
-
-
-
-
-
- Dialogrecord dem Fensterobjekt bekannt machen
-
- SetData(FontDataRec);
-
- Da nicht vorausgesetzt werden kann, welcher Zeichensatz gerade aktiv
- ist, wird der aktive Zeichensatz aus der Stellung der Radiobuttons be-
- stimmt. Nur beim allerersten Aufblenden der Dialogbox steht der in TAp-
- plication.SetDialogData initialisierte Dialogstring zur Verfügung.
- Später kann er durchaus verändert worden sein.
-
- for i:=3 to 8 do
- if FontDataRec.Schalter[i]='R' then
- case i of
- 3 : DFont:=Thin8;
- 4 : DFont:=Thin14;
- 5 : DFont:=Thin16;
- 6 : DFont:=Brdwy19;
- 7 : DFont:=Wndw19;
- 8 : DFont:=Sans19;
- end; {case}
-
- Font-Typ und Font-Farbe setzen
-
- SetFont(DFont);
- SetFontColor(White,Green);
- end;
-
- Wie in diesem Handbuch schon mehrfach erläutert wurde, stellt der Fen-
- sterhintergrund ein eigenständiges Objekt dar. Das bringt den Nachteil
- mit sich, daß eine Veränderung des Fensterinhalts ohne Abarbeitung der
- Draw-Methoden aller Fensterelemente nur umständlich zu realisieren ist.
- Aus diesem Grund wurde innerhalb des TWindow-Objekts die leere Methode
- DrawClientArea implementiert. Mit dieser Methode läßt sich der Hinter-
- grund eines Fenster sehr leicht überschreiben. In diesem Programm wird
- die Prozedur zur Anzeige eines Zeichenblocks im Dialogfenster genutzt.
- Sie wird im Eventhandler immer dann abgearbeitet, wenn ein neues Radio-
- button ausgewählt wird. In diesem Beispiel wird für die Positionierung
- der Rahmen und der Zeichenketten der Nullpunkt des Fensters (Origin)
- verwendet.
-
-
-
- Programmierhandbuch WG-Vision - 116 -
-
-
-
-
-
-
-
- procedure TSetFontWindow.DrawClientArea;
- var z:array[1..6] of string;
- i:integer;
- begin
- z[1]:='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
- z[2]:='abcdefghijklmnopqrstuvwxyz';
- z[3]:='ÄÖÜäöü?=)(/&%$"!^°²ⁿ{[]}\';
- z[4]:='12345678901234567890123456';
- z[5]:='{}[]\~ÇüéâäàåçêëèïîìÄÅÉæôö';
- z[6]:='òûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼─«';
- with Origin do
- begin
- SetColor(Black);
- Mouse.HideMouse;
- FBar(x+205,y+60,x+425,y+188,White);
- SetLineStyle(SolidLn,0,ThickWidth);
- RectAngle(x+200,y+55,x+427,y+190);
- SetLineStyle(SolidLn,0,NormWidth);
- for i:=1 to 6 do WriteText(x+215,y+45+i*20,z[i]);
- Mouse.ShowMouse;
- end;
- end;
-
- Setzen eines neuen Zeichensatzes. Der Zeichensatz wird je nach Schal-
- terstellung innerhalb einer case-Auswahl bestimmt. Hat sich gegenüber
- dem letzten Aufruf der Font verändert, dann wird der neue Zeichensatz
- aktiviert und der Zeichenblock mittels der Methode DrawClientArea neu
- dargestellt. Außerdem wird die Message msgDraw ausgesendet, die vom
- Eventhandler des Scrollers abgefangen wird und ein Neu-Zeichnen des
- Scrollbereichs bewirkt. Da der Scroller solange deaktiv ist wie das Dia-
- logfenster aufgeblendet ist (ein Dialog ist immer modal), kann er erst
- auf diese Message reagieren, wenn das Font-Auswahlfenster mit cmClose-
- Window geschlossen wird (deshalb wird TDlgWindow.HandleEvent erst am
- Ende der Prozedur aufgerufen).
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 117 -
-
-
-
-
-
-
-
- procedure TSetFontWindow.HandleEvent;
- var i:byte;
- begin
- with FontDataRec do
- for i:=3 to 8 do
- if Schalter[i]='R' then
- begin
- case i of
- 3 : DFont:=Thin8;
- 4 : DFont:=Thin14;
- 5 : DFont:=Thin16;
- 6 : DFont:=Brdwy19;
- 7 : DFont:=Wndw19;
- 8 : DFont:=Sans19;
- end; {case}
- end;
- if DFont<>Font then {Font gewechselt ?}
- begin
- SetFont(DFont); {neuen Font aktivieren}
- DrawClientArea; {Testblock zeichnen}
- Event.Message:=msgDraw; {Message an Scroller}
- end;
- TDlgWindow.HandleEvent;
- end;
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Beispiel : LISTER mit Fontwechsel');
- MyApp.Run;
- MyApp.Done;
- end.
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 118 -
-
-
-
-
-
-
-
- 5.2.7. Checkbuttons (Kontrollfelder)
-
- Eine Checkbutton repräsentiert jeweils eine Option, die ein-
- oder ausgeschalten sein kann. Durch Anklicken des Buttons
- wird entweder ein Kreuz in das Auswahlquadrat gezeichnet
- oder gelöscht. Im Gegensatz zu den Radiobuttons gibt es in-
- nerhalb einer Gruppe von Chekbuttons keine Verbindung zwi-
- schen den einzelnen Elementen. Deshalb können Sie ein
- einzelnes Checkbutton unabhängig von den anderen Checkbut-
- tons der Gruppe ein- und ausschalten.
- Die Programmierung von Checkbuttons erfolgt in der gleichen
- Art und Weise wie die Programmierung der Radiobuttons. Mit
- dem Befehl
-
- SetCheckButton(x,y:integer; Bez:str25);
-
- erzeugen Sie ein Checkbutton. Die Angabe einer Gruppennummer
- ist natürlich nicht notwendig, da alle Checkbuttons völlig
- unabhängig voneinander sind.
-
- Beispiel
- Einfacher Druckerdialog mit Radio- und Checkbuttons
-
- ...
- type PDruckerDlg=^TDruckerDlg;
- TDruckerDlg=object(TDlgWindow)
- constructor Init(x,y:integer);
- ...
- end;
-
- ...
-
- procedure TApplication.SetDialogData;
- begin
- PrintDialogData.Schalter:='TTGRrrrrGrRrCGcccS';
- end;
- ...
-
-
-
-
-
- Programmierhandbuch WG-Vision - 119 -
-
-
-
-
-
-
-
- procedure TApplication.DruckerDialog;
- var Window:PDruckerDlg;
- begin
- Window:=new(PDruckerDlg, Init(60,80));
- InsertDesktop(Window);
- end;
-
- {Implementation TDruckerDlg}
-
- constructor TDruckerDlg.Init(x,y:integer);
- var RR:TRect;
- begin
- RR.Assign(x,y,x+380,y+310);
- TDlgWindow.Init(RR,'Drucker-Dialog',winDouble+winPanel));
- SetPushButton(190,270,80,22,'OK',cmCloseWindow);
- SetPushButton(285,270,80,22,'Abbrechen'),cmCancel);
- SetGroupFrame(20,40,180,140,'Druckertyp',NormWidth);
- SetRadioButton(40,70,'~M~atrixdrucker',1); {1.Gruppe}
- SetRadioButton(40,90,'~L~aserdrucker',1);
- SetRadioButton(40,110,'~T~ypenraddrucker',1);
- SetRadioButton(40,130,'~B~ubble-Jet',1);
- SetRadioButton(40,150,'T~h~ermodrucker',1);
- SetGroupFrame(220,40,135,90,'Auflösung',NormWidth);
- SetRadioButton(240,70,'~3~00 dpi',2); {2.Gruppe}
- SetRadioButton(240,90,'~1~60 dpi',2);
- SetRadioButton(240,110,' ~7~5 dpi',2);
- SetCheckButton(225,165,'~E~inzelblatt');
- SetGroupFrame(20,200,155,88,'',ThickWidth);
- SetCheckButton(40,225,'~F~ett');
- SetCheckButton(40,245,'~K~ursiv');
- SetCheckButton(40,265,'~U~nterstrichen');
- SetStaticText(195,210,'Drucker-Dialog',LeftText);
- SetTextParameters(TSCRFont,HorizDir,1);
- ChangePalColor(10,Red);
- SetData(PrintDialogData);
- end;
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 120 -
-
-
-
-
-
-
-
- Die Abfrage, ob ein Checkbutton gesetzt ist oder nicht,
- erfolgt genauso wie bei den Radiobuttons:
-
- if Schalter[13]='C' then
-
- 5.2.7.1. Farbgestaltung von Radio- und Checkbuttons
-
- Für die Farben der Radio- und Checkbuttons ist die Standard-
- palette Palette5 zuständig. Es gilt folgendes Palettenlay-
- out:
-
- Eintrag Bedeutung Standard
-
- 1 Markierungskreis/-kästchen #0 Schwarz
- 2 Hintergrund #15 Weiß
- 3 Kreisscheibe / Kreuz #8 Dunkelgrau
- 4 Text, aktiv #0 Schwarz
- 5 Text, inaktiv #7 Grau
- 6 Aktiv-Rahmen #8 Dunkelgrau
-
- Der Aktivrahmen wird punktiert um den Bezeichner eines fo-
- kussierten Dialogelements (außer Pushbuttons) gezeichnet.
- Zur Änderung eines Paletteneintrags kann auch hier die Me-
- thode ChangePalColor verwendet werden.
-
- 5.2.8. Textfelder (Edit-Controls)
-
- Die Eingabe von Zeichenketten (Wörter, Zahlen) in
- Maskenfelder wird sehr oft benötigt. WG-Vision stellt mit
- SetInputLine eine Methode zur Verfügung, mit der sehr leicht
- Eingabemasken aufgebaut werden können. Mit diesem Befehl
- erzeugen Sie ein Rechteck, das Ihre Eingaben aufnehmen kann.
- Innerhalb der Maske stehen Ihnen die wichtigsten
- Editierfunktionen zur Verfügung:
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 121 -
-
-
-
-
-
-
-
- ^H, Backspace Zeichen links vom Kursor löschen
- ^Y gesamte Eingabezeile löschen
- ^T ab Kursorposition bis Zeilenende löschen
- ^G, Del Zeichen an der Kursorposition löschen
-
- End, Ende Kursor hinter den letzten Buchstaben der
- Eingabezeile setzen
- Home, Pos1 Kursor an den Anfang der Eingabezeile setzen
-
-
- Syntax
-
- SetInputLine(x,y,xl:integer;Bez:str25;MaxLen:byte;Zeich:ZMenge);
-
- x,y Position der linken oberen Ecke der Eingabemaske
- xl Länge der Eingabemaske in Zeichen
- MaxLen Maximallänge der einzugebenden Zeichenkette. Dieser
- Wert muß mit der im Dialogrecord definierten
- Stringlänge übereinstimmen (s.u.).
- Zeich Erlaubte Zeichen (nur diese können eingegeben
- werden)
-
- Ziffern = ['0'..'9','.','-']
- ASCII = [' '..'■']
- Character = ['A'..'Z',á'..'z','Ä','Ö',
- 'Ü','ä','ö','ü','ß']
-
- Wenn MaxLen>xl ist, erfolgt innerhalb der Maske ein Rollen.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 122 -
-
-
-
-
-
-
-
- 5.2.8.1. Datenübergabe von und in Eingabefelder
-
- Eingabefelder benutzen zum Datenaustausch mit ihrer Umgebung
- den Dialogrecord. Dieser Record muß um die Definitionen der
- Übergabefelder ergänzt werden. Für einen einfachen Adressen-
- erfassungs-Dialog könnte er beispielsweise folgendermaßen
- aussehen:
-
- ...
-
- type tAdressData=record
- Schalter : string[7];
- Firma : string[40];
- PLZ : string[5];
- Ort : string[25];
- Strasse : string[30];
- Telefon : string[20];
- end;
-
- var Adresse:tAdressData;
- ...
-
- Wichtig für die Funktionalität ist, daß die Stringlängen,
- wie sie im Dialogrecord definiert sind, mit dem Parameter
- MaxLen von SetInputLine übereinstimmen.
- Die Initialisierung der Adress-Variablen erfolgt bei Objekt-
- übergreifender Nutzung innerhalb von TApplication.SetDialog-
- Data:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 123 -
-
-
-
-
-
-
-
- procedure TApplication.SetDialogData;
- begin
- with Adresse do
- begin
- Schalter:='TTLLLLLS';
- FillChar(Firma,SizeOf(Firma),' ');
- FillChar(PLZ,SizeOf(PLZ),' ');
- FillChar(Ort,SizeOf(Ort),' ');
- FillChar(Strasse,SizeOf(Strasse),' ');
- FillChar(Telefon,SizeOf(Telefon),' ');
- end;
- end;
-
- Bei der Initialisierung eines Dialogrecords sind folgende
- Punkte zu beachten:
-
- - "Schalter" muß immer als Erstes Element implementiert
- werden !
-
- - Zeichenketten müssen vollständig aufgefüllt sein:
- Def. z:string5; z:='ab'; (falsch) z:=' ab'; (richtig)
-
- - lange Zeichenketten zuerst mit Leerzeichen füllen, dann
- erst Zuweisung eines Anfangswertes
- z.B. FillChar(Ort,SizeOf(Ort),' '); Ort:='Zittau';
-
- Ein Dialogrecord wird von der Leseroutinen eines aktiven
- Dialogelements direkt aus dem Speicher gelesen: Das Objekt
- TInputLine benutzt dafür folgende Routine (Unit WDlg):
-
- procedure TInputLine.SetData(var Rec);
- var i:integer;
- begin
- Data:='';
- for i:=1 to DataLen do Data:=Data+char(mem[SSeg:ofs(Rec)+i] );
- for i:=DataLen downto 1 do
- if Data[i]=' ' then delete(Data,i,1) else Exit;
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 124 -
-
-
-
-
-
-
-
- Data ist das Feld in TInputLine, in dem die editierbare Zei-
- chenkette aufgebaut wird. Der untypisierte Record wird zur
- Laufzeit von TDlgWindow.SetData zur Verfügung gestellt. In-
- nerhalb dieser Routine wird aus dem Dialogrecord gemäß der
- Typdefinition des Records und der Reihenfolge der Implemen-
- tierung der Dialogelemente ein Teilrecord erzeugt, der TIn-
- putLine.SetData übergeben wird. Daraus extrahiert die
- Routine den Anfangswert für die Eingabezeile, die letztend-
- lich in Data gespeichert wird. Da das Längenbyte eines
- Strings in diesem Zusammenhang nicht zu gebrauchen ist, wer-
- den die Leerzeichen am Ende der Zeichenkette zur Identifika-
- tion nicht benötigter Zeichen verwendet. Die Verwendung
- nullterminierter Strings hätte die Datenübergabe vom Dialog-
- record in ein Dialogfenster stark vereinfacht. Aus Kompati-
- bilitätsgründen zu Turbo-Pascal 6.0 konnte diese Art von
- Strings (sie werden erst ab BP7 unterstützt) jedoch nicht
- verwendet werden.
- Das Auslesen der Datenfelder aus den Dialogelementen zurück
- in den Dialogrecord wird von der Methode GetDataRec
- (TDlgWindow) gewährleistet.
-
- Lesen des Dialogrecords
-
- procedure TDlgWindow.SetData(var Rec);
- var LfdPtr:PGroup;
- i,j,k:integer;
- Wert:string;
- ch:char;
- begin
- RecAdr:=ofs(Rec); {Offsett-Adresse von Rec merken}
- k:=0; Wert:=0;
- with DlgList^ do {gesamte Liste der Dialogelemente abackern}
- begin
- for i:=1 to AnzElem (= Anzahl implementierter Dialogelemente}
- begin
- ch:=char(mem[DSeg:ofs(Rec)+i]); {"Schalter" auslesen}
- Wert:=Wert+ch; {Zeichenkette "DlgElemente" zusammenbasteln}
-
-
-
-
-
- Programmierhandbuch WG-Vision - 125 -
-
-
-
-
-
-
-
- {Radio- oder Checkbutton ?}
-
- if (UpCase(ch)='R') or (UpCase(ch)='C') then
- begin
- LfdPtr:=GetItems(i); {Radio- oder Checkbutton holen}
- LfdPtr^.SetData(ch); {Daten überhelfen}
- end;
- DlgElemente:=Wert; {ist identisch mit "Schalter"}
-
- {Offsett-Index für das Erste Zeichen des nächsten Dialogrecord-Eintrags}
-
- k:=AnzElem+1;
- for i:=1 to DlgList^.AnzElem do
-
- {Eingabezeile, Zählschalter (L) oder Listbox (B) ?}
-
- case DlgElemente[i] of
- 'L' : begin
- Wert:='';
- LfdPtr:=GetItems(i); {Pointer auf Dialog-Element}
- Anz:=PInputLine(LfdPtr)^.DataLen; {wieviele Zeichen}
- {lesen ?}
-
- {Übergaberecord zusammenbasteln}
-
- for j:=1 to Anz do
- Wert:=Wert+char(mem[DSeg:ofs(Rec)+k+j]);
- k:=Anz+k+1; {neuer Offsett-Index}
- LfdPtr^.SetData(Wert); {Daten übergeben}
- end;
- 'B' : begin
- Wert:='';
- LfdPtr:=GetItems(i); {Pointer auf Dialog-Element}
- Anz:=PListBox(LfdPtr)^.DataLen; {wieviele Zeichen}
- {lesen ?}
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 126 -
-
-
-
-
-
-
-
- {Übergaberecord zusammenbasteln}
-
- for j:=1 to Anz do
- Wert:=Wert+char(mem[DSeg:ofs(Rec)+k+j]);
- k:=Anz+k+1; {neuer Offsett-Index}
- LfdPtr^.SetData(Wert); {Daten übergeben}
- end;
- end; {case}
- end;
- end;
- end;
-
- Schreiben des Dialogrecords
-
- procedure TDlgWindow.GetDataRec;
- var LfdPtr:PGroup;
- i,j,k,l:integer;
- ch:char;
- Wert:string;
- Anz:word;
- begin
- if not DlgInput then Exit; {nur passive Dialogelemente}
- with DlgList^ do
- for i:=1 to AnzElem do
- begin
- LfdPtr:=GetItems(i);
- ch:=DlgElemente[i];
-
- {Status der Radio- und Checkbuttons auslesen}
-
- if (UpCase(ch)='R') or (UpCase(ch)='C') then
- begin
- if TypeOf(LfdPtr^)=TypeOf(TRadioButton) then
- if PRadioButton(LfdPtr)^.Gesetzt then DlgElemente[i]:='R'
- else DlgElemente[i]:='r';
- if TypeOf(LfdPtr^)=TypeOf(TCheckButton) then
- if PCheckButton(LfdPtr)^.Gesetzt then DlgElemente[i]:='C'
- else DlgElemente[i]:='c';
- end;
-
-
-
- Programmierhandbuch WG-Vision - 127 -
-
-
-
-
-
-
-
- mem[DSeg:RecAdr+1]:=byte(DlgElemente[i]); {zurück in den}
- {Dialogrecord}
- end;
-
- {Eingabewerte der Eingabezeilen, Zählschalter und Listboxen
- zurückschreiben}
-
- k:=DlgList^.AnzElem+1;
- for i:=1 to DlgList^.AnzElem do
- case DlgElemente[i] of
- 'L' : begin
- LfdPtr:=DlgList^.GetItems(i);
- Wert:=PInputLine(LfdPtr)^.Data;
- l:=length(Wert);
- Anz:=PInputLine(LfdPtr)^.DataLen;
- for j:=l+1 to Anz do Wert:=Wert+' ';
- for j:=1 to Anz do mem[DSeg:RecAdr+k+j]:=byte(Wert[j]);
- k:=Anz+k+l;
- end;
- 'B' : begin
- LfdPtr:=DlgList^.GetItems(i);
- Wert:=PListBox(LfdPtr)^.Data;
- l:=length(Wert);
- Anz:=PListBox(LfdPtr)^.DataLen;
- for j:=l+1 to Anz do Wert:=Wert+' ';
- for j:=1 to Anz do mem[DSeg:RecAdr+k+j]:=byte(Wert[j]);
- k:=Anz+k+l;
- end;
- end; {case}
- end;
-
- Bei der Erweiterung der Toolbox um neue aktive Dialogelemen-
- te müssen diese beiden Methoden u.U. angepaßt werden.
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 128 -
-
-
-
-
-
-
-
- 5.2.8.2. Farbgestaltung von TInputLine-Objekten
-
- Für die Farben der Eingabezeilen ist die Standardpalette
- Palette5 zuständig. Es gilt folgendes Palettenlayout:
-
- Eintrag Bedeutung Standard
-
- 1 Rechteck um das Eingabefeld #0 Schwarz
- 2 Hintergrund #15 Weiß
- 3 wird nicht verwendet
- 4 Text, aktiv (Bezeichner) #0 Schwarz
- 5 Text, inaktiv (Bezeichner) #7 Grau
- 6 Aktiv-Rahmen um Bezeichner #8 Dunkelgrau
- 7 Text im Eingabefeld #0 Schwarz
-
- Zur Änderung eines Paletteneintrags kann auch hier die
- Methode ChangePalColor verwendet werden.
-
- Komplexbeispiel Mini-Adreßdatenbank
-
- Das Programm MiniDB zeigt am Beispiel einer einfachen Adreß-
- Datenbank die Programmierung von Eingabemasken aus TInputLi-
- ne-Objekten. Besondere Aufmerksamkeit wird dem Austausch von
- Messages zwischen einzelnen Programmteilen (z.B. Datenerfas-
- sungsfenster und Browse-Fenster) gelegt. Außerdem zeigt das
- Programm exemplarisch, wie mit Dateien in WG-Vision-Program-
- men umgegangen werden muß.
-
- Aufgabenstellung
- Das Programm MiniDB soll in der Lage sein, Adreßdaten zu er-
- fassen und sie in einem Browse-Fenster darstellen. Die Daten
- werden in einer Datei mit wahlfreien Zugriff verwaltet. Be-
- reits erstellte Adreßdateien sollen geladen und neue Adreß-
- dateien erzeugt werden. Die Eingabe ist über einen Eingabe-
- Dialog zu realisieren.
- Weiterhin sind alle Menüpunkte und Dialogelemente zu sper-
- ren, wenn ihre Funktion nicht sinnvoll ist.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 129 -
-
-
-
-
-
-
-
- {Mini-Adressdatenbank zur Demonstration der Arbeit mit TInputLine-
- Objekten}
-
- program Mini_Adressdatenbank;
-
- uses WApp,
- WEvent,
- WDecl,
- WViews,
- WDriver,
- WDlg,
- WFileDlg,
- WUtils,
- WText,
- dos,
- graph;
-
-
- const cmOpen = 101;
- cmSave = 102;
- cmErfassen = 201;
- cmBlaettern = 202;
- cmBrowse = 203;
-
- {Diese Konstanten werden nur innerhalb des Objekts TErfassen benötigt}
-
- cmLeft = 90; {zum Blättern innerhalb des Anzeige-Fenster}
- cmRight = 91;
-
- msgDraw = 100;
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 130 -
-
-
-
-
-
-
-
- type TApplication=object(TApp)
- FName : PathStr;
- procedure InitMenuBar; virtual;
- procedure SetDialogData; virtual;
- procedure HandleEvent; virtual;
- procedure LoadFile; {Adreßdatei laden}
- procedure NewFile; {Neue Adreßdatei erstellen}
- procedure BrowseWindow; {Scrollfenster zum "browsen"}
- procedure Erfassen(Mode:boolean); {Eingabemaske}
- end;
-
- {Browse-Fenster}
-
- PNewScroller=^TNewScroller;
-
- PScrollWindow=^TScrollWindow;
- TScrollWindow=object(TWindow)
- Scroller:PNewScroller;
- procedure InitWindowScroller; virtual;
- procedure HandleEvent; virtual;
- destructor Done; virtual;
- end;
-
- TNewScroller=object(TScroller)
- procedure CreateData;
- procedure ScrollDraw; virtual;
- end;
-
- {Eingabemaske für die Adreßdaten und Anzeige für den Menüpunkt Blättern}
-
- PErfassen=^TErfassen;
- TErfassen=object(TDlgWindow)
- PosIndex:word;
- constructor Init(DInput:boolean);
- destructor Done; virtual;
- procedure DeleteDataRecord;
- procedure HandleEvent; virtual;
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 131 -
-
-
-
-
-
-
- {Datenrecord für Datei}
-
- tAdressData =record
- Firma : string[40];
- PLZ : string[5];
- Ort : string[25];
- Strasse : string[30];
- Telefon : string[15]
- end;
-
- {Dialog-Record}
-
- tAdressDataRec=record
- Schalter : string[9];
- Adr : tAdressData; {hilft wirtschaften ...}
- end;
-
- var MyApp:TApplication;
- AdressData:tAdressDataRec; {Dialogrecord}
- Adresse:tAdressData; {Adressen-Record}
- dat:file of tAdressData; {Datenbank-Datei}
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~D~atei',0);
- SubMenu('~A~dressen laden',cmOpen,0,0,false,false);
- SubMenu('~N~eue Adreßdatei',cmSave,0,0,false,false);
- NewLine;
- SubMenu('E~x~it Alt-X',cmCloseApplication,0,altX,false,false);
-
- Alle Menüpunkte unter "Bearbeiten" sind beim Programmstart gesperrt
- (Parameter true). Das ist sinnvoll, weil dem Programm zu diesem Zeit-
- punkt noch nicht bekannt ist, welche Datei konkret bearbeitet werden
- soll
-
- MainMenu('~B~earbeiten',0);
- SubMenu('~A~dressen Erfassen',cmErfassen,0,0,true,false);
- SubMenu('~B~lättern',cmBlaettern,0,0,true,false);
- SubMenu('B~r~owse',cmBrowse,0,0,true,false);
- end;
-
-
-
- Programmierhandbuch WG-Vision - 132 -
-
-
-
-
-
-
-
- {Initialisierung der Werte für die Eingabemaske}
-
- procedure TApplication.SetDialogData;
- begin
- with AdressData do
- begin
- Schalter:='TTTLLLLLS';
- FillChar(Adr.Firma,SizeOf(Adr.Firma),' ');
- FillChar(Adr.PLZ,SizeOf(Adr.PLZ),' ');
- FillChar(Adr.Ort,SizeOf(Adr.Ort),' ');
- FillChar(Adr.Strasse,SizeOf(Adr.Strasse),' ');
- FillChar(Adr.Telefon,SizeOf(Adr.Telefon),' ');
- end;
- end;
-
- procedure TApplication.HandleEvent;
- var i:integer;
- begin
- Heap^.ShowHeapStatus(523,8,White);
- TProgram.HandleEvent;
- case Event.Command of
- cmOpen : LoadFile;
- cmSave : NewFile;
- cmErfassen : Erfassen(true);
- cmBlaettern : Erfassen(false);
- cmBrowse : BrowseWindow;
- end; {case}
-
- Die Fenster LoadFile und NewFile senden die Messages msgLoadFile und
- msgSaveFile sowie in Event.InfoString den jeweils ausgewählten bzw. ein-
- gegebenen Dateinamen inklusive vollständiger Pfadangabe. Diese Messages
- werden hier abgefangen um den Applikationsobjekt den Dateinamen zu über-
- geben.
-
- if Event.Message=msgLoadFile then
- begin
- FName:=Event.InfoString;
-
-
-
-
-
- Programmierhandbuch WG-Vision - 133 -
-
-
-
-
-
-
-
- Sobald ein gültiger Dateiname verfügbar ist, kann die Sperrung des Menüs
- "Bearbeiten" aufgehoben werden
-
- for i:=1 to 3 do MMenu[2]^.SbMenu[i]^.DeAktiviere;
- ClearMessage;
- end;
- if Event.Message=msgSaveFile then
- begin
-
- Wurde bei der Eingabe des Dateinamens keine Extension angegeben, dann
- wird sie hier angehängt. Die Adreßdateien bekommen die Extension .DBS
-
- if Pos('.',Event.Infostring)=0 then FName:=Event.InfoString+'.DBS'
- else FName:=Event.InfoString;
- MMenu[2]^.SbMenu[1]^.DeAktiviere;
- ClearMessage;
- end;
- end;
-
- Die Objekte TInputDialog und TOutputDialog werden aus der Unit WFileDlg
- importiert. Diese Unit ist Bestandteil von WG-Vision
-
- procedure TApplication.LoadFile;
- var Window:PInputDialog;
- begin
- Window:=new(PInputDialog, Init('Dateiauswahl','*.DBS'));
- InsertDesktop(Window);
- end;
-
- procedure TApplication.NewFile;
- var Window:POutputDialog;
- begin
- Window:=new(POutputDialog, Init('Neue Adreß-Datei'));
- InsertDesktop(Window);
- end;
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 134 -
-
-
-
-
-
-
-
- procedure TApplication.BrowseWindow;
- var R:TRect;
- Window:PScrollWindow;
- begin
- R.Assign(20,60,616,446);
- Window:=new(PScrollWindow, Init(R,'BROWSE-Fenster',
- winDouble+winPanel+winMenu+winKey));
- InsertDesktop(Window);
- end;
-
- In diesem Programm wird das Fenster Erfassen für zwei verschiedene
- Zwecke benutzt. Einmal dient es zur Verwaltung der Eingabemaske für die
- Adreßdaten und zum anderen wird es zum "Blättern" innerhalb der Adreß-
- datenbank verwendet. Die Unterscheidung zwischen diesen beiden Funktio-
- nen geschieht über die logische Variable Mode. Sie wird an das Objekt
- TErfassen weitergeleitet (im Konstruktor)
-
- procedure TApplication.Erfassen(Mode:boolean);
- var Window:PErfassen;
- i:integer;
- begin
- Window:=new(PErfassen, Init(Mode));
- InsertDesktop(Window);
-
- Sobald eine Datei eröffnet ist, können dem Nutzer auch die Menüpunkte
- "Blättern" und "Browse" zugänglich gemacht werden
-
- for i:=2 to 3 do MMenu[2]^.SbMenu[i]^.DeAktiviere;
- end;
-
- {Implementation TScrollWindow}
-
- procedure TScrollWindow.InitWindowScroller;
- var R:TRect;
- SBH1,SBV1:PScrollBar;
- begin
- R:=Frame^.Area;
- SBH1:=new(PScrollBar, Init(R,HorizDir));
- SBV1:=new(PScrollBar, Init(R,VertDir));
-
-
-
- Programmierhandbuch WG-Vision - 135 -
-
-
-
-
-
-
-
- Scroller:=new(PNewScroller, Init(R,SBH1,SBV1));
- Scroller^.CreateData;
- List^.InsertItem(Scroller);
- end;
-
- procedure TScrollWindow.HandleEvent;
- begin
- TWindow.HandleEvent;
-
- Da das Browse-Fenster nichtmodal ist, kann während es aufgeblendet ist
- auch die Eingabemaske aktiv sein, d.h. es sind weitere Adreßeingaben
- möglich. Sobald die Erfassung abgeschlossen ist, muß das Browse-Fenster
- aktualisiert werden. Um das zu erreichen, wird zuerst die Datenliste im
- Heap gelöscht und danach wieder neu aufgebaut (in CreateData). Anschlie-
- ßend wird der Scroller mit den aktualisierten Daten neu aufgeblendet
- (Draw). Ausgelöst wird dieser Vorgang durch die Message msgDraw, welche
- das Erfassungsfenster sendet, wenn es geschlossen wird
-
- if Event.Message=msgDraw then
- begin
- with Scroller^ do
- begin
- Createdata;
- Draw;
- end;
- ClearMessage; {wichtig !}
- end;
- end;
-
- destructor TScrollWindow.Done;
- begin
- TWindow.Done;
- dispose(Scroller, Done);
- end;
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 136 -
-
-
-
-
-
-
-
- {Implementation TNewScroller}
-
- procedure TNewScroller.CreateData;
- var LfdPtr:PLine;
- begin
- SetFont(Wndw19);
-
- Erst einmal nachschauen, ob eine Datenliste bereits vorhanden ist (wegen
- Aktualisierung !) und wenn ja, dann Inhalt löschen
-
- if Liste<>nil then Liste^.DeleteItems;
-
- Datei zum Lesen öffnen
-
- assign(dat,MyApp.FName);
- reset(dat);
-
- Adreßdaten in die Liste einlesen. Da die Liste nur Strings aufnehmen
- kann und deren Länge bekanntlich begrenzt ist (256 Zeichen), paßt die
- Telefonnummer nicht mehr hinein.
-
- while not EOF(dat) do
- begin
- LfdPtr:=new(PLine, Init);
- read(dat,Adresse);
- with Adresse do
- LfdPtr^.Eintrag:=Firma+' │ '+PLZ+' │ '+Ort+' │ '+Strasse;
- Liste^.InsertItem(LfdPtr);
- end;
- SetLimit(25,Liste^.AnzElem,8,16);
- close(dat);
- end;
-
- procedure TNewScroller.ScrollDraw;
- var i:integer;
- LfdPtr:PGroup;
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 137 -
-
-
-
-
-
-
-
- function clip(p,n:byte;z:string):string;
- begin
- clip:=copy(z,p,n);
- end;
-
- begin
- SetFontColor(White,Blue);
- Mouse.HideMouse;
- with Border do
- begin
- SetFillStyle(SolidFill,GetPalColor(1));
- SetColor(GetPalColor(2));
- for i:=Delta.y to WDelta.y do
- begin
- LfdPtr:=Liste^.GetItems(i);
- Bar(A.x,A.y+(i-Delta.y)*Py+10,B.x,A.y+(i-Delta.y)*Py+10+Py);
- WriteText(A.x+20,A.y+(i-Delta.y)*Py+10,clip(Delta.x,
- Spalten*8 div 8-5,PLine(LfdPtr)^.Eintrag));
- end;
- if VertiScrollBar<>nil then
- for i:=(WDelta.y-Delta.y)+1 to Zeilen do
- Bar(A.x,A.y+i*Py+10,B.x,A.y+i*Py+10+Py);
- end;
- Mouse.ShowMouse;
- end;
-
- {Implementation Erfassen}
-
- constructor TErfassen.Init(DInput:boolean);
- var RR:TRect;
- begin
- PosIndex:=0; {Position des Satzzeigers in der Datei}
- RR.Assign(60,80,440,350); {Position und Größe des Fensters}
-
- An dieser Stelle muß die Datei geöffnet werden. Der Konstruktor wird
- immer nur einmal, nämlich in dem Augenblick, wo das Fenster geöffnet
- wird, durchlaufen. Das Schließen der Datei erfolgt dann logischerweise
- im Destructor Done des Fensters. Aus diesem Grund muß der Destructor
- auch überschrieben werden, da diese Arbeit aus begreiflichen Gründen der
-
-
-
- Programmierhandbuch WG-Vision - 138 -
-
-
-
-
-
-
-
- Destruktor des TDlgWindow-Objektes nicht übernehmen kann. Beim Öffnen
- der Datei muß weiterhin untersucht werden, ob die Adressendatei bereits
- existiert (Öffnen zum Anhängen von neuen Datensätzen) oder ob eine neue
- Datei erst erzeugt werden muß. Diese Frage läßt sich in diesem Beispiel-
- programm eindeutig durch Überprüfung von IOResult beantworten.
-
- assign(dat,MyApp.FName);
- {$I-}
- reset(dat);
- {$I+}
- if IOResult=0 then {Existiert Datei ?}
- begin
- if not DInput then {Blättern}
- begin
-
- Ersten Datensatz lesen, und AdressData damit initialisieren, damit
- sofort der erste Datensatz aufgeblendet wird.
-
- read(dat,Adresse); {1. Datensatz lesen}
- AdressData.Adr:=Adresse; {Dialogrecord initialisieren}
- SetData(AdressData); {Dialogrecord setzen}
- end
- else
- begin
-
- Datensatzzeiger an das Ende der Datei positionieren und leere Eingabe-
- maske vorbereiten.
-
- DeleteDataRecord;
- seek(dat,FileSize(dat));
- end;
- end
- else rewrite(dat); {neue Datei anlegen}
-
- Fensterobjekt initialisieren und gestalten
-
- TDlgWindow.Init(RR,'Erfassen von Adressen',winDouble+winPanel);
- SetPushButton(134,225,100,22,'OK',cmCloseWindow);
-
-
-
-
- Programmierhandbuch WG-Vision - 139 -
-
-
-
-
-
-
-
- Die Methode SetDisabled schaltet ein Dialogelement gewissermaßen ab. Das
- bedeutet, daß solch ein Dialogelement aus dem Eventhandler des Fensters
- ausgeschlossen ist und damit nicht mehr auf Ereignisse reagieren kann.
- Es ist gewissermaßen totgelegt. Auf dem Bildschirm wird es durch seine
- farbliche Gestaltung besonders hervorgehoben.
-
- SetPushButton(260,225,40,22,'<<',cmLeft);
- if DInput then SetDisabled;
- SetPushButton(310,225,40,22,'>>',cmRight);
- if DInput then SetDisabled;
- SetInputLine(140,90,25,'~F~irma :',40,ASCII);
- if not DInput then SetDisabled;
- SetInputLine(140,115,5,'~P~LZ :',5,ZIFFERN);
- if not DInput then SetDisabled;
- SetInputLine(140,140,20,'~O~rt :',25,ASCII);
- if not DInput then SetDisabled;
- SetInputLine(140,165,20,'~S~traße :',30,ASCII);
- if not DInput then SetDisabled;
- SetInputLine(140,190,15,'~T~elefon :',15,ZIFFERN);
- if not DInput then SetDisabled;
-
- Statischer Text in Rot unter Verwendung des Triplex-Fonts.
-
- if DInput then SetStaticText(40,35,'Adressenerfassung',LeftText)
- else SetStaticText(40,35,'Blättern in der Datei',LeftText);
- SetTextParameters(TriplexFont,HorizDir,2);
- ChangePalColor(10,Red);
-
- Anfangswerte des Diaslogrecords an das Fenster übergeben.
-
- SetData(AdressData);
- end;
-
- destructor TErfassen.Done;
- begin
- close(dat); {Adressendatei schließen}
- TDlgWindow.Done;
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 140 -
-
-
-
-
-
-
-
- Dialogrecord mit Leerzeichen belegen. Da die Eingabezeilen direkt auf
- die Werte im Dialogrecord zugreifen, ist es zum Aufblenden einer leere
- Maske unumgänglich, den Dialogrecord zu "löschen".
-
- procedure TErfassen.DeleteDataRecord;
- begin
- with AdressData do
- begin
- FillChar(Adr.Firma,SizeOf(Adr.Firma),' ');
- FillChar(Adr.PLZ,SizeOf(Adr.PLZ),' ');
- FillChar(Adr.Ort,SizeOf(Adr.Ort),' ');
- FillChar(Adr.Strasse,SizeOf(Adr.Strasse),' ');
- FillChar(Adr.Telefon,SizeOf(Adr.Telefon),' ');
- end;
- SetData(AdressData); {nicht vergessen !}
- end;
-
- Und hier eine der wichtigsten Routinen. Innerhalb des Eventhandlers des
- Erfassungsfensters erfolgt die eigentliche Datenübernahme in die Datei.
-
- procedure TErfassen.HandleEvent;
-
- Hilfsroutine zum Lesen eines Datensatzes aus der Adressendatei. Diese
- Routine wird zum Blättern benötigt.
-
- procedure ReadDataRecord;
- begin
- seek(dat,PosIndex); {Satzzeiger positionieren}
- read(dat,Adresse); {Adresse auslesen}
- AdressData.Adr:=Adresse; {Dialogrecord mit Adresse füllen}
- SetData(AdressData); {Dialogrecord dem Fenster bekannt machen}
- DrawMask; {Maske neu zeichnen}
- Event.Command:=cmNothing; {Kommando löschen}
- end;
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 141 -
-
-
-
-
-
-
-
- begin
- TDlgWindow.HandleEvent;
-
- Die Message msgNewMask wird direkt von WG-Vision gesendet. Immer wenn
- eine Eingabemaske nach unten mit <Cursor><Down> verlassen wird, wird
- diese Message auf die Reise geschickt. Dadurch kann der Programmierer
- auf den Fakt reagieren, daß die Maske ausgefüllt ist und die Daten über-
- nommen werden können. In unserem Beispiel wird nach Speicherung des
- Adress-Records in der Datei sofort eine leere Maske aufgeblendet und die
- Eingabe der nächsten Adresse kann erfolgen.
-
- if Event.Message=msgNewMask then
- begin
- Adresse:=AdressData.Adr; {Adresse aus dem Dialogrecord übernehmen}
- write(dat,Adresse); {Adresse in die Datei schreiben}
- DeleteDataRecord; {Dialogrecord mit Leerzeichen füllen}
- DrawMask; {neue Eingabemaske aufblenden}
-
- An dieser Stelle sendet das Fenster eine Mitteilung an das Browse-Fen-
- ster. Da dieses Fenster durchaus auf dem Bildschirm präsent sein kann
- (es ist jedoch deaktiviert, da ein Dialogfenster immer modal ist), muß
- es sich nach dem Schließen des Erfassungsfenster an die neuen Daten an-
- passen, d.h. es muß jetzt auch ohne Zutun des Nutzers die neu eingegebe-
- nen Datensätze richtig anzeigen. Da sein Eventhandler erst nach dem
- Schließen des Erfassungsfenster auf Messages reagieren kann, erfolgt na-
- türlich auch erst dann die Neuanpassung des Scrollbereiches.
-
- Event.Message:=msgDraw; {Mitteilung an das Browse-Fenster}
- end;
-
- Diese Kommandos können nur im Blätter-Modus abgesetzt werden.
-
- if Event.Command=cmRight then
- if FilePos(dat)<FileSize(dat) then
- begin
- inc(PosIndex); {nach Rechts blättern}
- ReadDataRecord;
- end;
- if Event.Command=cmLeft then
-
-
-
- Programmierhandbuch WG-Vision - 142 -
-
-
-
-
-
-
-
- if PosIndex>0 then
- begin
- dec(PosIndex); {nach links blättern}
- ReadDataRecord;
- end;
- end;
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Adressen-Datenbank');
- MyApp.Run;
- MyApp.Done;
- end.
-
- Das Program MiniDB ist natürlich vollausbaufähig. Wenn Sie
- eine kleine Adressenverwaltung benötigen, dann sollten Sie
- diesem Programm weitere Funktionen hinzufügen. Es dürfte
- beispielsweise nicht schwierig sein, eine Editier- und
- Druckfunktion einzubauen.
-
- Hinweis:
- Beobachten Sie bitte bei der Abarbeitung dieses Programms
- einmal den Heapwächter. Sie werden feststellen, das 8888
- Bytes nicht wieder freigegeben werden. Der Grund liegt in
- diesem Fall nicht in einer fehlerhaften Programmierung son-
- dern in dem Umstand, daß WG-Vision den Vektorzeichensatz
- TriplexFont in den Heap geladen hat. Dieser Font kann in der
- jetzigen Version von WG-Vision nicht mehr aus dem Speicher
- entfernt werden. Das ist zwar traurig, aber wahr.
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 143 -
-
-
-
-
-
-
-
- 5.2.8.3. Aufbau von Eingabemasken
-
- Eingabemasken haben insbesonders bei Datenbankanwendungen
- eine zentrale Bedeutung. Um die Programmierung von Eingabe-
- masken zu vereinfachen, besitzt WG-Vision intern bereits ei-
- nige Routinen, die die Verwaltung von Eingabemasken
- unterstützen. Ob sie genutzt werden, hängt von der jeweili-
- gen Aufgabenstellung ab.
- Eine Eingabemaske unter WG-Vision besitzt folgende Eigen-
- schaften:
-
- - Jedes Eingabefeld ist voll editierbar. Das wird dadurch
- gewährleistet, daß ein Eingabefeld in WG-Vision ein
- TInputLine-Objekt ist
-
- - Die Eingabefelder einer Eingabemaske sind unabhängig von
- anderen Dialogelementen (Druckschalter, Radio- und
- Checkbuttons) fokussierbar. In WG-Vision erfolgt die
- Fokussierung eines Dialogelementes mittels der Tabulator-
- Taste (bzw. <Shift><Tab>). Zusätzlich dazu lassen sich
- Maskenfelder mittels der Tasten <Cursor><Up> und
- <Cursor><Down> zyklisch (also von den anderen Dialog-
- elementen entkoppelt) fokussieren.
-
- - Eine Eingabemaske muß unabhängig vom Fenster neu
- darstellbar sein (Methode DrawMask).
-
- - Wenn eine Eingabemaske nach unten verlassen wird, sendet
- WG-Vision die Message msgNewMask aus (unabhängig davon, ob
- in die Maske Daten eingegeben wurden oder nicht). Diese
- Mitteilung kann genutzt werden, um die Maskendaten
- abzuspeichern und eine neue leere Maske aufzublenden
- (siehe Komplexbeispiel MINIDB).
-
- - In einem Dialogfenster werden alle TInputLine-Objekte zu
- einer Maske vereinigt. Mehrere individuelle Masken in
- einem Dialogfenster sind nicht möglich.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 144 -
-
-
-
-
-
-
-
- 5.2.9. Zählschalter
-
- Ein direkter Nachkomme von TInputLine ist der sogenannte
- Zählschalter (TNumButton). Mit dem Zählschalter können Zah-
- len in festzulegenden Grenzen und Schrittweiten herauf- und
- herabgezählt werden. Außerdem lassen sich Zahlen auch direkt
- eingeben und genauso wie Zeichenketten editieren.
- Ein Zählschalter unterscheidet sich von einer Eingabezeile
- durch zwei Schalter, die entweder übereinander oder rechts
- oder links vom Eingabefeld angeordnet sein können. Indem Sie
- diese Schalter betätigen, können Sie einen Wert im Eingabe-
- feld herauf- oder herunterzählen. Die Schalter werden dazu
- entweder mit der Maus angeklickt oder mit den Tasten <Cur-
- sor><Up> und <Cursor><Down> bedient (natürlich nur, wenn der
- Zählschalter fokussiert ist). Die Fokussierung erfolgt ent-
- weder mittels der Tabulator-Taste, dem Shortkey (in Verbin-
- dung mit <alt>) oder durch Anklicken des Eingabebereichs mit
- der Maus.
-
- Syntax
-
- SetNumButton(x,y,xl:integer;Bez:str25;MaxLen,TTyp:byte;
- Min,Max,Step,Format:real);
-
- x,y Position der linken oberen Ecke der Eingabemaske
- xl Länge der Eingabemaske in Zeichen
- Bez Bezeichner
- MaxLen Maximallänge der einzugebenden Zeichenkette. Dieser
- Wert muß mit der im Dialogrecord definierten
- Stringlänge übereinstimmen
-
- TTyp Anordnung der Tasten: 1 übereinander
- 2 nebeneinander
-
- Min Minimalwert, bis auf den heruntergezählt wird
- Max Maximalwert, bis auf den heraufgezählt wird
- Step Schrittweite
- Format legt die Anzahl der Vor- und Nachkommastellen fest
-
-
-
-
- Programmierhandbuch WG-Vision - 145 -
-
-
-
-
-
-
-
- Der Anfangswert für den Zählschalter wird im Dialogrecord
- festgelegt. Im String "Schalter" wird ein TNumButton-Objekt
- genauso wie die Eingabezeile mit L codiert.
- Das folgende kleine Programmfragment könnte einem Drucker-
- dialog entnommen sein. Durch die Eingaben über drei
- Zählschalter soll angegeben werden von und bis zu welcher
- Seite ein Dokument ausgedruckt werden soll und in wieviel
- Exemplaren:
-
- Dialogrecord deklarieren
-
- ...
-
- type tPrintPages=record
- Schalter:string[4];
- VonSeite:string[3];
- BisSeite:string[3];
- Exemplare:string[2];
- end;
-
- var PPages:tPrintPages;
-
- Dialogrecord mit Anfangswerten belegen
-
- procedure TApplication.SetDialogData;
- begin
- with PPages do
- begin
- Schalter:='SLLL';
- VonSeite:=' 1'; {unbedingt Leerzeichen mit angeben !}
- BisSeite:=' 1';
- Exemplare:=' 1';
- end;
- end;
- ...
-
- Neues Dialogfenster in die Windowliste einfügen
-
-
-
-
-
- Programmierhandbuch WG-Vision - 146 -
-
-
-
-
-
-
-
- procedure TApplication.NewWindow;
- var Window:PNewWindow;
- begin
- Window:=new(PNewWindow, Init);
- InsertDesktop(Window);
- end;
- ...
-
- Dialogfenster mit einem statischen Text und drei Zählschal-
- tern
-
- constructor TNewWindow.Init;
- var RR:TRect;
- begin
- RR.Assign(60,80,300,280);
- TDlgWindow.Init(RR,'Fenster mit Zählschalter',
- winDouble+winPanel+winMenu+winKey);
- SetStaticText(20,40,'Dokument drucken',LeftText);
- ChangePalColor(10,Red);
- SetNumButton(20,100,3,'~V~on',3,1,1,999,1,3.0);
- SetNumButton(135,100,3,'~B~is',3,1,1,999,1,3.0);
- SetNumButton(40,155,2,'~E~xemplare',2,2,1,99,1,2.0);
- SetData(PPages); │ │ │ │ │ └─ 2 Vorkommastellen
- end; │ │ │ │ └─ Schrittweite
- ... │ │ │ └─ Maximalwert
- │ │ └─ Minimalwert
- │ └─ Schaltertyp
- └─ Maximallänge
-
- Bei den ersten beiden Zählschaltern werden die Tasten über-
- einander rechts neben das Eingabefeld gezeichnet (TTyp 1).
- Beim Dritten Zählschalter befindet sich jeweils rechts und
- links neben dem Eingabefeld ein Schalter. Der Text wird auch
- hier rechts daneben geschrieben. Sie können übrigens die Po-
- sition des Bezeichners relativ zum Fenster beliebig mit dem
- Befehl
-
- SetTextPosition(x,y:integer)
-
-
-
-
- Programmierhandbuch WG-Vision - 147 -
-
-
-
-
-
-
-
- verändern. Bedingung ist, daß Sie diesen Befehl gleich un-
- terhalb von SetNumButton anordnen bzw. vor dem nächsten neu-
- en Dialogelement (analog ChangePalColor im obigen Beispiel).
-
- Für die Farbgestaltung sind die Paletten 4 (Drucktasten) und
- 5 (eigentlicher Zählschalter) zuständig.
- Ein Beispiel für die Anwendung von Zählschaltern ist das
- Objekt TPalWorkShop in der Unit WPalette.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 148 -
-
-
-
-
-
-
-
- 5.2.10. Listboxen
-
- Listboxen sind rechteckige Bereiche innerhalb eines Dialog-
- fensters, die mit einem oder zwei Rollbalken ausgestattet
- sind. Sie enthalten zeilenweise Zeichenketten (z.B. Dateina-
- men), die sich mit einem Auswahlbalken auswählen lassen.
- Zur Implementation in ein Dialogfenster reicht es nicht aus,
- mit dem Befehl SetListBox(...) einen Zeiger auf die Stan-
- dard-Listbox in die Dialogelementeliste DlgList des Dialog-
- fensters einzufügen. Die Methode SetListbox ist als virtual
- deklariert und muß in einem konkreten Anwendungsfall über-
- schrieben werden. Das ist deshalb notwendig, um der Listbox
- zu sagen, was sie eigentlich auflisten soll. Bevor wir in
- einem kleinen Beispiel die Vorgehensweise näher beleuchten,
- hier erst einmal die Syntax des Befehls:
-
- Syntax
-
- SetListBox(x,y,xl,yl:integer;Bez:str25;LScroller:word);
-
- x,y Koordinaten der linken oberen Ecke der Listbox
- xl,yl Breite und Länge der Listbox
- Bez Bezeichner (wird standardmäßig linksbündig über
- die Listbox geschrieben. Position läßt sich aber
- mit SetTextPosition relativ zum Dialogfenster
- verändern
-
- LScroller Rollbalken: VScrBar nur vertikaler Rollbalken
- HScrBar nur horizontaler Rollbalken
- DScrBar beide Rollbalken
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 149 -
-
-
-
-
-
-
-
- Beispiel: Fenster mit einer Listbox, in der alle Dateien des
- Hauptverzeichnisses aufgelistet werden
-
- Da wir die Listbox mit Daten (hier Dateinamen) füllen
- wollen, müssen wir von TListBox ein neues Objekt ableiten:
-
- type PDateiListBox=^TDateiListBox;
- TDateiListBox=object(TListBox)
- procedure CreateDataList;
- end;
- ...
-
- Außerdem muß die Methode SetListBox überschrieben werden:
-
- type PNewWindow=^TNewWindow;
- TNewWindow=object(TDlgWindow)
- constructor Init;
- procedure SetListBox(x,y,xl,yl:integer;Bez:str25;
- LScroller:word); virtual;
- end;
- ...
-
- Zum Schluß müssen wir für das Fenster TNewWindow noch einen
- Dialogrecord zur Verfügung stellen:
-
- type tLBoxData=record
- Schalter:string[2];
- DName:string[12];
- end;
-
- var LBoxData:tLBoxData;
-
- Die Variable DName enthält nach dem Schließen des Dialogfen-
- sters den Dateinamen in der Listbox, auf welchem der Aus-
- wahlbalken zuletzt gestanden hat.
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 150 -
-
-
-
-
-
-
-
- Dialogdaten setzen:
-
- procedure TApplication.SetDialogData;
- begin
- with LBoxData do
- begin
- Schalter:='TB';
- FillChar(DName,SizeOf(DName),' ');
- end;
- end;
-
- Eine Listbox wird in der Stringvariablen Schalter mit dem
- Buchstaben `B' codiert.
-
- SetListBox überschreiben:
-
- procedure TNewWindow.SetListBox(x,y,xl,yl:integer;
- Bez:str25;LScroller:word);
- var LBox:PDateiListBox; {neues TListBox-Objekt}
- begin
- TDlgWindow.SetListBox(x,y,xl,yl,Bez,LScroller);
- LBox:=new(PDateiListBox, Init(R,Bez,SBH,SBV));
- with LBox^ do
- begin
- CreateDataList;
-
- Koordinaten in P merken, damit bei Verschiebungen des Fensters die
- Listbox wieder an die richtige relative Position gezeichnet werden kann.
-
- P.x:=x; P.y:=y;
- end;
- DlgList^.InsertItem(LBox);
- end;
-
- In der Methode CreateDataList werden der Listbox die Daten
- übergeben, die sie konkret auflisten soll. Zu diesem Zweck
- mußte ein neues Objekt von TListBox abgeleitet werden, deren
-
-
-
-
-
- Programmierhandbuch WG-Vision - 151 -
-
-
-
-
-
-
-
- Methode CreateDataList dann die Daten bereitstellt. Wir ver-
- wenden wieder eine Liste im Heap, um die Dateinamen abzu-
- speichern:
-
- procedure TDateiListBox.CreateDataList;
- var SRec:SearchRec;
- LfdPtr:PLine;
- begin
- FindFirst('\*.*',Archive,SRec);
- if SRec.Name<>'' then
- repeat
- LfdPtr:=new(PLine, Init);
- LfdPtr^.Eintrag:=SRec.Name;
- Liste^.InsertItem(LfdPtr);
- FindNext(SRec);
- until DOSError=18;
-
- DataLen:=12; {Sehr wichtig ! Dieser Wert wird in TDlgWindow.SetData}
- {benötigt. Er ist identisch mit der Stringlänge in der}
- {Deklaration von DName im Dialogrecord}
-
- SetLimit(12,Liste^.AnzElem,8,11);
- end;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 152 -
-
-
-
-
-
-
-
- 5.2.10.1. Farbpalette
-
- Die Listbox verwendet die Standardpalette Palette5. Folgende
- Einträge sind von Bedeutung:
-
- Eintrag Bedeutung Standard
-
- 1 Rahmen der Listbox #0 Schwarz
- 2 Hintergrund #15 Weiß
- 3 wird nicht verwendet
- 4 Text in der Listbox (normal) #0 Schwarz
- Bezeichner, aktiv
- 5 Bezeichner, inaktiv #7 Grau
- 6 Aktiv-Rahmen um Bezeichner #8 Dunkelgrau
- 7 wird nicht verwendet #0 Schwarz
- 8 Farbe des Auswahlbalkens #8 Dunkelgrau
- 9 Text im AuswahlbalkenS #15 Weiß
-
-
- Zur Darstellung der Rollbalken wird die Standardpalette
- Palette3 verwendet.
- Wie bei jedem Dialogelement läßt sich ein Paletteneintrag
- mit ChangePalColor verändern.
-
- 5.2.11. Zusammenfassung Dialogelemente
-
- Folgende Methoden von TDlgWindow stehen zur Programmierung
- eines Dialogs zur Verfügung:
-
- SetPushButton Druckschalter passiv
- SetRadioButton Optionsschaltfläche aktiv
- SetCheckButton Kontrollfeld aktiv
- SetInputLine Eingabezeile aktiv
- SetNumButton Zählschalter aktiv
- SetListBox Listbox aktiv
- SetGroupFrame Gruppenrahmen passiv
- SetStaticText Statischer Text passiv
- SetIcon Icon passiv
-
-
-
-
- Programmierhandbuch WG-Vision - 153 -
-
-
-
-
-
-
-
- Alle Fenster mit aktiven Dialogelementen benötigen einen
- Dialogrecord, der entweder global (innerhalb des gesamten
- Programms, initialisiert in SetDialogData) oder Objekt-lokal
- (implementiert im Konstruktor des Fensterobjekts) implemen-
- tiert sein muß.
- Folgende Methoden beeinflussen einige Eigenschaften der Dia-
- logelemente:
-
- ChangePalColor ändert einen Paletteneintrag
- SetDisabled deaktiviert ein Dialogelement
- SetTextParameters ändert die Font-Eigenschaften eines
- statischen Textes
- SetTextPosition verändert die Position eines Bezeichners.
- Druckschalter: relativ zur Tastenmitte
- übrige Elemente: relativ zum Fenster
-
-
- Diese Befehle müssen unterhalb der Implementationsbefehle
- angeordnet werden:
-
- Beispiel
- ...
-
- SetInputLine(20,40,80,22,'OK',cmCloseWindow);
- ChangePalColor(3,Yellow);
- SetTextPosition(-10,-20);
- SetDisabled;
- SetStaticText(20,80,'Statischer Text in Rot',LeftText);
- ChangeColor(10,Red);
- ...
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 154 -
-
-
-
-
-
-
-
- Spezialmethoden
-
- DrawMask zeichnet eine Eingabemaske neu
- SetData übergibt einen Dialogrecord an das
- Fenster
-
- InsertChildWindow Einfügen eines Child-Fensters
- GetFocElem übergibt den Index des gerade
- fokussierten Dialogelements
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 155 -
-
-
-
-
-
-
-
- 5.3. Child-Fenster
-
- In ein Dialogfenster können weitere Fenster, sogenannte
- Childfenster, eingehangen werden. Childfenster werden beim
- Aufbau von Dialogen oft benötigt. Wenn Sie z.B. aus einem
- Drucker-Setup-Dialog einen Drucker aus einer Listbox ausge-
- wählt haben, möchten Sie ihn vielleicht konfigurieren. Zu
- diesem Zweck programmieren Sie ein weiteres Dialogfenster,
- das Sie z.B. über ein Pushbutton aufblenden. Dieses Fenster
- ist dann aber kein Bestandteil der Windowliste des Desktops
- (wie das "Parent"-Fenster), sondern ein dem aufrufenden Fen-
- ster untergeordnetes Window, welches als "Child" nur inner-
- halb des "Parent"-Fensters definiert ist.
- Zum "Einhängen" des Childwindows wird die Methode Insert-
- ChildWindow verwendet.
- In ein Parent-Fenster können beliebig viele Child's einge-
- hangen werden. Ein Child-Fenster selbst darf jedoch keine
- Child-Fenster enthalten. Sonst kommt der Eventhandler von
- WG-Vision gehörig durcheinander, da er nicht für rekursive
- Aufrufe ausgelegt ist.
- Für die Implementierung eines Childfensters gelten die glei-
- chen Regeln wie für jedes normale Dialogfenster. Es lassen
- sich natürlich auch Objekte vom Ausgangstyp TWindow als
- Child's verwenden.
-
- Prinzipielle Vorgehensweise
-
- Deklaration des Parent-Fensters
-
- type PParentWindow=^TParentWindow;
- TParentWindow=object(TDlgWindow)
- ...
- procedure SetChildWindow; {in dieser Methode erfolgt das}
- {Einhängen des Childfensters}
- end;
-
- Deklaration des Child-Fensters
-
-
-
-
-
- Programmierhandbuch WG-Vision - 156 -
-
-
-
-
-
-
-
- type PChildWindow=^TChildWindow;
- TChildWindow=object(TDlgWindow);
- constructor Init;
- ... {Eventhandler, Hintergrund etc.}
- end;
-
- Implementation von SetChildWindow
-
- procedure TParentWindow.SetChildWindow;
- var CWindow:PChildWindow;
- begin
-
- Zunächst benötigen wir einen Zeiger auf unser Childwindow
-
- CWindow:=new(PChildWindow, Init);
-
- Bevor das Childwindow aufgeblendet werden kann, muß das Parentwindow
- deaktiviert werden. Das passiert automatisch (das Childwindow als Nach-
- fahre von TDlgWindow ist ja von Haus aus modal). Lediglich der Rahmen
- muß in Verantwortung des Programmierers neu gezeichnet werden, damit das
- Fenster auch optisch "deaktiviert" ist. Zu diesem Zweck wird die Varia-
- ble FrameDeaktivated auf true gesetzt und das Parentfenster veranlaßt,
- sich selbst neu zu zeichnen.
-
- FrameDeaktivated:=true;
- DrawNewFrame;
-
- Und jetzt muß sich nur noch das Childfenster aufblenden.
-
- CWindow^.Draw;
-
- Damit auch alle Ereignisse, die dieses Fenster betreffen, vom
- Eventhandler auch richtig ausgewertet werden können, muß das
- Childfenster in die entsprechende Liste des Parentfensters eingebaut
- werden.
-
- InsertChildWindow(CWindow);
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 157 -
-
-
-
-
-
-
-
- Das Childfenster muß innerhalb des Eventhandlers des Parent-
- fensters als Reaktion auf ein Kommando (z.B. von einem
- Pushbutton) aufgerufen werden:
-
- ...
-
- if Event.Command=cmHelp then SetChildWindow;
- ...
-
- Zur Laufzeit kann über die logische Variable ChildPresent
- abgetestet werden, ob ein Childfenster gerade aufgeblendet
- ist oder nicht.
-
-
- Komplexbeispiel Dialog zur Änderung des Systemdatums und der
- Systemzeit
-
- Aufgabenstellung:
- Ein Dialogfenster, in dem das Systemdatum und die Systemzeit
- editiert werden können, soll mit einer Hilfe-Funktion ausge-
- stattet werden. Dazu ist ein Pushbutton mit der Aufschrift
- "Hilfe" anzulegen und die Ereignisbehandlung so zu gestal-
- ten, daß eine Aktivierung dieses Schalters ein Childwindow
- mit der Hilfe-Information aufblendet.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 158 -
-
-
-
-
-
-
-
- program Datum_und_Zeiteingabe;
-
- uses WDecl,
- WApp,
- WEvent,
- WDlg,
- graph,
- dos;
-
- const cmDate=101;
-
- type TApplication=object(TApp)
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- procedure SetDate;
- end;
-
- Die Methode SetDialogData wird nicht benötigt, da die Initialisierung
- des Dialogrecords erst im Augenblick des Aufblendens des TDateiWindow's
- innerhalb des Konstruktors erledigt wird. Alles andere hätte auch keinen
- Sinn, da ja nicht die Uhrzeit bei Programmstart, sondern die aktuelle
- Uhrzeit editiert werden soll.
-
- PDateWindow=^TDateWindow; {Parent-Window}
- TDateWindow=object(TDlgWindow)
- constructor Init;
- procedure HandleEvent; virtual;
- procedure SetHelp;
- end;
-
- PHilfe=^THilfe; {Child-Window}
- THilfe=object(TDlgWindow)
- constructor Init;
- end;
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 159 -
-
-
-
-
-
-
-
- tSetDateTime=record
- Schalter:string[5];
- Datum:string[10];
- Zeit:string[8]
- end;
-
- var MyApp:TApplication;
- DT:tSetDateTime;
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~F~enster',0);
- SubMenu('~E~instellungen',cmDate,0,0,false,false);
- SubMenu('E~x~it Alt-X',cmCloseApplication,0,altX,false,false);
- end;
-
- procedure TApplication.HandleEvent;
- begin
- TProgram.HandleEvent;
- case Event.Command of
- cmDate : SetDate;
- end; {case}
- end;
-
- procedure TApplication.SetDate;
- var Window:PDateWindow;
- begin
- Window:=new(PDateWindow, Init);
- InsertDesktop(Window);
- end;
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 160 -
-
-
-
-
-
-
-
- {Implementation TDateWindow}
-
- constructor TDateWindow.Init;
- var RR:TRect; z:string;
- Jahr,Monat,Tag,Wochentag:word;
- Stunde,Minute,Sekunde,Sek100:word;
- begin
- RR.Assign((GetMaxX div 2)-150,140,(GetMaxX div 2)+150,300);
- TDlgWindow.Init(RR,'Datum & Uhrzeit',winDouble+winPanel+winMenu);
-
- Das Editieren des Datums und der Uhrzeit erfolgt innerhalb einer Einga-
- bezeile. Zugelassene Zeichen sind nur Ziffern, wobei die Ziffernmenge
- modifiziert wird (bei der Uhrzeit werden als Begrenzer Doppelpunkte ver-
- wendet, beim Datum einfache Punkte).
-
- SetInputLine(95,70,10,'~D~atum ',10,Ziffern-['-']);
- SetInputLine(95,105,8,'~U~hrzeit',8,Ziffern+[':']-['.','-']);
- SetPushButton(200,40,80,22,'OK',cmOK);
- SetPushButton(200,70,80,22,'~A~bbrechen',cmCloseWindow);
- SetPushButton(200,115,80,22,'~H~ilfe',90);
-
- An dieser Stelle wird der Dialogrecord zusammengebastelt. Datum und
- Uhrzeit bekommen jeweils die aktuellen Werte und werden als Vorgabe in
- den Eingabezeilen aufgeblendet.
-
- with DT do
- begin
- Schalter:='LLTTT';
- Datum:=''; Zeit:='';
- GetDate(Jahr,Monat,Tag,Wochentag);
- str(Tag:2,z);
- Datum:=Datum+z+'.';
- str(Monat:2,z);
- Datum:=Datum+z+'.';
- str(Jahr:4,z);
- Datum:=Datum+z;
- GetTime(Stunde,Minute,Sekunde,Sek100);
- str(Stunde:2,z);
- Zeit:=Zeit+z+':';
-
-
-
- Programmierhandbuch WG-Vision - 161 -
-
-
-
-
-
-
-
- str(Minute:2,z);
- Zeit:=Zeit+z+':';
- str(Sekunde:2,z);
- Zeit:=Zeit+z;
- end;
- SetData(DT);
- end;
-
- procedure TDateWindow.HandleEvent;
- begin
- TDlgWindow.HandleEvent;
-
- Wenn die Hilfe-Taste gedrückt wird, muß das Childfenster aufgeblendet
- werden.
-
- if Event.Command=90 then SetHelp;
- if Event.Command=cmOK then
- begin
- with DT do
- begin
-
- {und hier kommen die Routinen zum Setzen des neuen
- Datums und der neuen Uhrzeit hinein. Dazu müssen Sie
- die Strings Datum und Uhrzeit zerpflücken und die
- in das word-Format umgewandelten Teilstrings den
- Routinen SetDate und SetTime übergeben. Vielleicht
- programmieren Sie diesen Teil einmal selbst ?}
-
- end;
- Event.Command:=cmCloseWindow;
- end;
- end;
-
- procedure TDateWindow.SetHelp;
- var HelpWindow:PHilfe;
- begin
- HelpWindow:=new(PHilfe, Init);
-
-
-
-
-
- Programmierhandbuch WG-Vision - 162 -
-
-
-
-
-
-
-
- Parent-Fenster deaktivierten
-
- FrameDeaktivated:=true;
- DrawNewFrame;
-
- Childwindow zeichnen und in die entsprechende Liste des Parent-Windows
- einfügen
-
- HelpWindow^.Draw;
- InsertChildWindow(HelpWindow);
- end;
-
- {Implementation THilfe}
-
- constructor THilfe.Init; {Childwindow}
- var RR:TRect;
- begin
- RR.Assign((GetMaxX div 2)-100,180,(GetMaxX div 2)+200,340);
- TDlgWindow.Init(RR,'Hilfe',winDouble+winPanel);
- SetStaticText(150,45,'Einstellen von',CenterText);
- SetStaticText(150,75,'Datum und Uhrzeit',CenterText);
- SetPushButton(110,130,80,22,'OK',cmCloseWindow);
- end;
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Demonstration Childfenster');
- MyApp.Run;
- MyApp.Done;
- end.
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 163 -
-
-
-
-
-
-
-
- 5.4. Programmierung einer Iconleiste
-
- Iconleisten oder Toolbars sind bei Windows-Programmierern
- sehr beliebt. Sie erlauben die schnelle Auswahl von Komman-
- dos ohne erst das Pull-Down-Menü bemühen zu müssen. Außerdem
- sehen sie gut aus und, das soll nicht verschwiegen werden,
- sie geben einem Programm ein professionelles Flair. In die-
- sem Abschnitt möchte ich zeigen, wie man unter Ausnutzung
- eines einfachen passiven Dialogfensters mit wenig Aufwand
- eine Iconleiste programmieren kann.
- Diese Iconleiste soll genau unterhalb der Menüzeile positio-
- niert werden. Natürlich ist auch jede andere Position im
- Clientbereich des Desktops denkbar, so z.B. senkrecht am
- linken Rand. Wo die Iconleiste konkret angeordnet wird,
- bleibt aber letztendlich dem Programmierer überlassen.
- Eine Iconleiste wird erst einmal genauso programmiert wie
- ein normales Dialogfenster. Natürlich wählt man kein ver-
- schiebbares Fenster (also eins mit Panel), sondern einfach
- einen schwarz umrandeten grauen Balken mit den gleichen Ab-
- messungen wie die Hauptmenüzeile:
-
- ...
-
- type PIconBar=^TIconBar;
- TIconBar=object(TDlgWindow)
- constructor Init;
- procedure InitBackground; virtual; {neuer Hintergrund}
- end;
-
- PIconBarBgrd=^TIconBarBgrd; {grauer Hintergrund}
- TIconBarBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
- ...
-
- constructor TIconBar.Init;
- var RR:TRect;
- begin
-
-
-
-
- Programmierhandbuch WG-Vision - 164 -
-
-
-
-
-
-
-
- Mit diesem Pointer-Schwanz bestimmen wir die Lage des Innenrahmens vom
- Desktop, in das wir die Iconleiste einpassen wollen. Damit die senkrech-
- ten Linien der Iconleiste mit den senkrechten Linien des Desktop-Innen-
- rahmens zusammenfallen, muß von A.x Eins abgezogen und zu B.x Eins
- dazuaddiert werden.
-
- with MyApp.Desktop^.Frame^.Area do RR(Assign(A.x-1,A.y+21,B.x+1,A.y+48);
-
- Implementation von Druckschaltern mit 16x16 Pixel-Icons. Die Kommandos,
- welche die Pushbuttons absetzen, werden im Eventhandler der Applikation
- abgefangen und ausgewertet.
-
- SetPushButton(3,3,0,0,'#ICON.I16/1',80);
- ChangePalColor(8,LightGray);
- SetPushButton(28,3,0,0,'#ICON.I16/2',81);
- ChangePalColor(8,LightGray);
- ...
-
- SetPushButton(400,3,0,0,'#ICON.I16/14',941);
- ChangePalColor(8,LightGray);
- WinModal:=true; {wir wollen das Menü ja auch noch bedienen}
- IconBarPresent:=true; {damit sagen wir WG-Vision, daß das erste}
- {Fenster eine Iconleiste ist}
- end;
-
- Jetzt benötigen wir nur noch ein Applikationsfenster, wel-
- ches die Iconleiste aufnimmt:
-
- procedure TApplication.IconBar;
- var IBar:PIconBar;
- begin
- IBar:=new(PIconBar, Init);
- InsertDesktop(IBar);
- end;
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 165 -
-
-
-
-
-
-
-
- Die Icons für die Druckschalter müssen natürlich zuvor mit
- dem Iconeditor erstellt und in der Datei ICON.I16 abgespei-
- chert sein. Das diese Datei zur Laufzeit verfügbar sein muß,
- ist selbstverständlich. Sonst haben Sie nur graue Tasten oh-
- ne Bildchen, also Grau auf Grau.
- Bleibt noch die Frage zu klären, an welcher Stelle des Pro-
- gramms die Iconleiste eingefügt werden soll. Sie darf ja nur
- einmal beim Programmstart geladen werden und muß dann wäh-
- rend des gesamten Programmlaufs aktiv bleiben. Am einfach-
- sten ist es, den Konstruktor der Applikation zu über-
- schreiben und darin die Methode IconBar aufzurufen:
-
- constructor TApplication.Init(Titel:string);
- begin
- TApp.Init(Titel);
- WorkArea.A.y:=WorkArea.A.y+26;
- IconBar;
- end;
-
- Außerdem wurde auch gleich das Workarea den neuen Gegeben-
- heiten angepaßt, damit die Fenster nicht über die Iconleiste
- geschoben werden können.
-
- Hinweis:
- Das wir die Iconleiste direkt von einem Dialogfenster abge-
- leitet haben, hat einige Konsequenzen. Immer dann, wenn ein
- nichtmodales Fenster (z.B. ein TWindow-Objekt) aufgeblendet
- wird, kann die Iconleiste nicht mehr bedient werden. Sie
- wird damit quasi tot gelegt. Das Pull-Down-Menü funktioniert
- natürlich weiter. Deshalb folgender Ratschlag: Rufen Sie
- über die Iconleiste nur modale Fenster, also in erster Linie
- Dialogfenster, auf.
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 166 -
-
-
-
-
-
-
-
- Beispiel:
-
- program MenuTest;
-
- uses WApp,
- WDecl,
- WViews,
- WDlg,
- WDriver,
- WUtils,
- WFileDlg,
- WEvent,
- crt;
-
- const cmNewWindow = 101;
- cmOpen = 102;
-
- type TApplication=object(TApp)
- constructor Init(Titel:string);
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- procedure IconBar;
- procedure NewWindow;
- procedure Eingabe;
- end;
-
- PIconBar=^TIconBar;
- TIconBar=object(TDlgWindow)
- constructor Init;
- procedure InitBackground; virtual;
- end;
-
- PIconBarBgrd=^TIconBarBgrd;
- TIconBarBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
-
- var MyApp:TApplication;
-
-
-
- Programmierhandbuch WG-Vision - 167 -
-
-
-
-
-
-
-
- {Implementation TApplication}
-
- constructor TApplication.Init(Titel:string);
- begin
- TApp.Init(Titel);
- WorkArea.A.y:=WorkArea.A.y+26;
- IconBar; {Iconleiste einfügen}
- end;
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~D~atei',0);
- SubMenu('~N~eues Fenster',cmNewWindow,0,0,false,false);
- SubMenu('~D~atei laden',cmOpen,0,0,false,false);
- NewLine;
- SubMenu('E~x~it Alt-X',cmCloseApplication,0,altX,false,false);
- MainMenu('~B~earbeiten',0);
- SubMenu('~A~dressen Erfassen',cmNothing,0,0,true,false); {nur Dummys}
- SubMenu('~B~lättern',cmNothing,0,0,true,false);
- SubMenu('B~r~owse',cmNothing,0,0,true,false);
- end;
-
- procedure TApplication.HandleEvent;
- var i:integer;
- z:string;
- LfdPtr:PGroup;
- begin
- TProgram.HandleEvent;
- case Event.Command of
- cmNewWindow : NewWindow;
- cmOpen : Eingabe;
- 80..91 : begin {unsere erste Messagebox !}
- str(Event.Command-79:2,z);
- MessageBox(1,'Iconleiste betätigt','Schalter-
- Nummer '+z);
- end;
- end; {case}
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 168 -
-
-
-
-
-
-
-
- procedure TApplication.IconBar;
- var Window:PIconBar;
- begin
- Window:=new(PIconBar, Init);
- InsertDesktop(Window);
- end;
-
- procedure TApplication.NewWindow;
- var R:TRect;
- Window:PWindow;
- begin
- R.Assign(60,80,440,280);
- Window:=new(PWindow,Init(R,'Beispiel',winDouble+winPanel+winMenu+winKey));
- InsertDesktop(Window);
- end;
-
- procedure TApplication.Eingabe;
- var Window:PInputDialog;
- begin
- Window:=new(PInputDialog, Init('Eingabe','*.*'));
- InsertDesktop(Window);
- end;
-
- {Implementation TIconBar}
-
- constructor TIconBar.Init;
- var RR:TRect;
- begin
- with MyApp.Desktop^.Frame^.Area do
- RR.Assign(A.x-1,A.y+21,B.x+1,A.y+48);
- TDlgWindow.Init(RR,'',winSingle);
- SetPushButton(3,3,0,0,'#ICON.I16/1',cmOpen);
- ChangePalColor(8,LightGray);
- SetPushButton(28,3,0,0,'#ICON.I16/2',cmNewWindow);
- ChangePalColor(8,LightGray);
- SetPushButton(65,3,0,0,'#ICON.I16/3',80);
- ChangePalColor(8,LightGray);
-
-
-
-
-
- Programmierhandbuch WG-Vision - 169 -
-
-
-
-
-
-
-
- SetPushButton(90,3,0,0,'#ICON.I16/4',81);
- ChangePalColor(8,LightGray);
- SetPushButton(115,3,0,0,'#ICON.I16/5',82);
- ChangePalColor(8,LightGray);
- SetPushButton(150,3,0,0,'#ICON.I16/6',83);
- ChangePalColor(8,LightGray);
- SetPushButton(175,3,0,0,'#ICON.I16/7',84);
- ChangePalColor(8,LightGray);
- SetPushButton(200,3,0,0,'#ICON.I16/8',85);
- ChangePalColor(8,LightGray);
- SetPushButton(225,3,0,0,'#ICON.I16/9',86);
- ChangePalColor(8,LightGray);
- SetPushButton(250,3,0,0,'#ICON.I16/10',87);
- ChangePalColor(8,LightGray);
- SetPushButton(325,3,0,0,'#ICON.I16/11',88);
- ChangePalColor(8,LightGray);
- SetPushButton(350,3,0,0,'#ICON.I16/12',89);
- ChangePalColor(8,LightGray);
- SetPushButton(375,3,0,0,'#ICON.I16/13',90);
- ChangePalColor(8,LightGray);
- SetPushButton(400,3,0,0,'#ICON.I16/14',91);
- ChangePalColor(8,LightGray);
- WinModal:=true; IconBarPresent:=true;
- end;
-
- procedure TIconBar.InitBackground;
- var RR:TRect;
- begin
- RR:=Frame^.Area;
- Bgrd:=new(PIconBarBgrd, Init(RR));
- List^.InsertItem(Bgrd);
- end;
-
- {Implementation TIconBarBgrd}
-
- procedure TIconBarBgrd.Draw;
- begin
- with Border do FBar(A.x,A.y,B.x,B.y,LightGray);
- end;
-
-
-
- Programmierhandbuch WG-Vision - 170 -
-
-
-
-
-
-
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Menü-Test');
- MyApp.Run;
- MyApp.Done;
- end.
-
-
- Komplexbeispiel Dateiauswahldialog
-
- Das Laden von Dateien gehört mit zu den Funktionen, auf die
- fast kein Programm verzichten kann. Deshalb wurde in die
- Unit WFileDlg von WG-Vision ein komplettes Dialogfenster im-
- plementiert, mit dessen Hilfe eine sehr komfortable Auswahl
- von Dateien möglich ist. Außerdem lassen sich Verzeichnisse
- und Laufwerke mit nur wenigen Mausklicks wechseln. Da das
- Objekt TInputDialog sehr gut zeigt, wie man komplexe Algo-
- rithmen in ein abgeschlossenes Objekt einpacken kann, soll
- es an dieser Stelle, sozusagen als Abschluß zum Thema Dia-
- logfenster, etwas ausführlicher behandelt und dokumentiert
- werden. Wer sich ernsthaft mit der Programmierung auf der
- Grundlage von WG-Vision auseinandersetzen möchte, sollte auf
- jeden Fall versuchen, die Funktionsweise dieses speziellen
- Dialogs zu verstehen. Die Anmerkungen zum Quelltext sollen
- Ihnen dabei helfen.
- Das Objekt TInputDialog zeigt auch am Beispiel Listbox und
- Eingabezeile, wie man objektintern Daten austauschen oder
- gemeinsam auf Daten zugreifen kann. Außerdem finden Sie in
- diesem Objekt eine mustergültige Fehlerbehandlung.
-
- Aufgabenstellung
- Aus einer Dialogbox sollen genau spezifizierte Dateinamen
- ausgewählt und mit vollständigem Pfad via Event.InfoString
- dem Hauptprogramm zur Verfügung gestellt werden. Es ist die
- Möglichkeit des Verzeichnis- und Laufwerkswechsel vorzuse-
- hen. Der Dateiname soll wahlweise auch über eine Eingabezei-
- le eingegeben werden können.
-
-
-
-
- Programmierhandbuch WG-Vision - 171 -
-
-
-
-
-
-
-
- Aus der hier wiedergegebenen Unit WFileDlg wurde das Objekt
- TOutPutDialog entfernt.
-
- UNIT WFileDlg;
-
- interface
-
- uses WDecl,
- WDlg,
- WViews,
- WEvent,
- WDriver,
- WUtils,
- dos,
- graph;
-
- const msgLoadFile = 10; {Message, das ein gültiger Dateiname}
- {zur Verfügung steht}
-
- type PInputDialog=^TInputDialog;
- TInputDialog=object(TDlgWindow)
- Pfad : PathStr; {Originalpfad}
- Klick : boolean;
- constructor Init(ATitle:str80;FMask:str12);
- destructor Done; virtual;
- procedure SetFileMask; virtual; {Dateiauswahlmaske setzen}
- procedure InitBackground; virtual;
- procedure SetPalette; virtual;
- procedure SetDateiListBox(X,Y,xl,yl:integer;Bez:str25;
- LScroller:word);
- procedure HandleEvent; virtual;
- end;
-
- PDateiListBox=^TDateiListBox;
- TDateiListBox=object(TListBox)
- procedure CreateDataList; {Datei- und Verzeichnisnamen auflisten}
- end;
-
-
-
-
-
- Programmierhandbuch WG-Vision - 172 -
-
-
-
-
-
-
-
- PIDlgBgrd=^TIDlgBgrd;
- TIDlgBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
- var FileMask : str12;
-
- implementation
-
- type tDialogData=record{Dialogrecord}
- Schalter : string[12];
- DateiName : string[32]; {für Eingabezeile}
- Datei : string[12]; {Listbox}
- end;
-
- var DlgData:tDialogData;
-
- {Implementation TInputDialog}
-
- constructor TInputDialog.Init(ATitle:str80;FMask:str12);
- var RR:TRect;
- z:array[1..4] of string[20];
- Drives:str10;
-
- Mit dieser Funktion können Sie erfahren, welche logischen Laufwerke
- verfügbar sind. Aus praktischen Gründen wird angenommen, daß maximal 6
- logische Laufwerke (A bis F) vorhanden sein können. Als Ergebnis wird
- ein String übergeben, der alle gültigen Laufwerksbuchstaben enthält.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 173 -
-
-
-
-
-
-
-
- function DriveMap:str10;
- var LW,LWerk:str10;
- i:integer;
- reg:Registers;
- begin
- LW:='ABCDEF';
- LWerk:='';
- for i:=1 to 6 do
- begin
- reg.ah:=$44;
- reg.al:=$0E;
- reg.bl:=i;
- MSDos(reg);
- if (reg.flags and FCarry)=0 then LWerk:=LWerk+LW[i];
- end;
- DriveMap:=LWerk;
- end;
-
- begin
-
- WG-Vision ist konsquent zweisprachig programmiert. Das muß natürlich
- auch bei der Programmierung von Spezialdialogen beachtet werden, wenn
- man einfach durch Setzen von Sprache=Englisch eine englischsprachige
- Version kompilieren möchte.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 174 -
-
-
-
-
-
-
-
- if Sprache=Englisch then
- begin
- z[1]:='File~n~ame :';
- z[2]:='~F~ile';
- z[3]:='Cancel';
- z[4]:='Directory';
- end
- else
- begin
- z[1]:='Datei~n~ame :';
- z[2]:='~D~ateien';
- z[3]:='Abbrechen';
- z[4]:='Verzeichnis';
- end;
- Drives:=DriveMap;
-
- Hier folgen die üblichen Fensterinitialisierungen
-
- RR.Assign(120,80,382,400);
- TDlgWindow.Init(RR,ATitle,winDouble+winPanel+winMenu);
-
- Vorbereitung des Dialogrecords, hier einmal etwas anders !
-
- FillChar(DlgData.DateiName,SizeOf(DlgData.DateiName),' ');
- FileMask:=FMask; Klick:=false;
- DlgData.DateiName:=FileMask; {erst das,}
- DlgData.DateiName[0]:=#32; {Längenbyte} {dann das !}
-
- aktuellen Pfad merken
-
- GetDir(0,Pfad);
-
- Dialogelemente implementieren
-
- SetInputLine(145,55,12,z[1],32,ASCII);
- ChangePalColor(2,LightGray);
- SetDateiListBox(15,150,127,144,z[2],VScrBar);
- ChangePalColor(2,LightGray);
-
-
-
-
- Programmierhandbuch WG-Vision - 175 -
-
-
-
-
-
-
-
- SetPushButton(156,155,90,22,'OK',cmOK);
- ChangePalColor(7,DarkGray);
- ChangePalColor(8,LightGray);
- SetPushButton(156,185,90,22,z[3],cmCancel);
- ChangePalColor(7,DarkGray);
- ChangePalColor(8,LightGray);
- SetStaticText(20,85,z[4],LeftText);
- SetStaticText(20,105,Pfad,LeftText);
- ChangePalColor(10,Red);
-
- "Laufwerkstasten", Es werden zwar alle 6 Laufwerkstasten implementiert,
- aber nur die aktiviert, die wirklich vorhanden sind.
-
- SetPushButton(162,230,22,22,'A',ord('A'));
- if Pos('A',Drives)=0 then SetDisabled;
- ChangePalColor(7,DarkGray);
- ChangePalColor(8,LightGray);
- SetPushButton(191,230,22,22,'B',ord('B'));
- if Pos('B',Drives)=0 then SetDisabled;
- ChangePalColor(7,DarkGray);
- ChangePalColor(8,LightGray);
- SetPushButton(220,230,22,22,'C',ord('C'));
- if Pos('C',Drives)=0 then SetDisabled;
- ChangePalColor(7,DarkGray);
- ChangePalColor(8,LightGray);
- SetPushButton(162,260,22,22,'D',ord('D'));
- if Pos('D',Drives)=0 then SetDisabled;
- ChangePalColor(7,DarkGray);
- ChangePalColor(8,LightGray);
- SetPushButton(191,260,22,22,'E',ord('E'));
- if Pos('E',Drives)=0 then SetDisabled;
- ChangePalColor(7,DarkGray);
- ChangePalColor(8,LightGray);
- SetPushButton(220,260,22,22,'F',ord('F'));
- if Pos('F',Drives)=0 then SetDisabled;
- ChangePalColor(7,DarkGray);
- ChangePalColor(8,LightGray);
-
-
-
-
-
- Programmierhandbuch WG-Vision - 176 -
-
-
-
-
-
-
-
- Dialogrecord Objekt-intern übergeben
-
- with DlgData do {Input-Dialog}
- begin
- Schalter:='LBTTSSTTTTTT';
- FillChar(DateiName,SizeOf(DateiName),' ');
- DateiName[0]:=#32;
- FillChar(Datei,SizeOf(Datei),' ');
- Datei[0]:=#12;
- end;
- SetData(DlgData);
- end;
-
- destructor TInputDialog.Done;
- begin
- ChDir(Pfad); {Ausgangspfad wieder einstellen}
- TDlgWindow.Done;
- end;
-
- procedure TInputDialog.SetFileMask;
- begin
- FileMask:='*.*'; {Standard-Dateimaske, kann überschrieben werden}
- end;
-
- procedure TInputDialog.InitBackground;
- var RR:TRect;
- begin
- RR:=Frame^.Area;
- Bgrd:=new(PIDlgBgrd, Init(RR));
- List^.InsertItem(Bgrd);
- end;
-
- procedure TInputDialog.SetPalette;
- begin
- Palette:=Palette1;
- Palette[2]:=#1;
- Palette[3]:=#15;
- end;
-
-
-
-
- Programmierhandbuch WG-Vision - 177 -
-
-
-
-
-
-
-
- procedure TInputDialog.SetDateiListBox(X,Y,xl,yl:INTEGER;Bez:str25;
- LScroller:WORD);
- VAR LBox:PDateiListBox;
- begin
- TDlgWindow.SetListBox(X,Y,xl,yl,Bez,LScroller);
- LBox:=New(PDateiListBox, Init(R,Bez,SBH,SBV));
- LBox^.CreateDataList;
- LBox^.P.X:=X; LBox^.P.Y:=Y;
- DlgList^.InsertItem(LBox);
- end;
-
- Und hier kommt der eigentlich interessante Teil !
-
- procedure TInputDialog.HandleEvent;
- var LfdPtr:PGroup;
- I:byte;
- ActPfad:PathStr;
- zz:string;
-
- begin
- TDlgWindow.HandleEvent; {wie gehabt}
- with Event do
- begin
- GetDir(0,ActPfad);
- if Event.Command in [65..70] then {Laufwerksauswahltasten gedrückt}
- begin
-
- Event.Command enthält raffinierterweise den ASCII-Code des
- Laufwerksbezeichners
-
- {$I-}
- ChDir(chr(Event.Command)+':\');
- {$I+}
-
- Fehlermessage provozieren, wenn DOSError<>0
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 178 -
-
-
-
-
-
-
-
- DOSError:=IOResult;
- ClearEvent;
- if DOSError<>0 then
- begin
- ChDir(ActPfad);
- case DOSError of
- 1..18 : Fehler.FTyp:=ds;
- 100..106 : Fehler.FTyp:=io;
- 150..162 : Fehler.FTyp:=mst;
- end; {case}
- Fehler.FNummer:=DOSError;
- Event.Message:=msgError;
- EXIT;
- end;
-
- Datei-Listbox mit Dateinamen etc. füllen
-
- LfdPtr:=DlgList^.GetItems(2);
- with PDateiListBox(LfdPtr)^ do
- begin
- CreateDataList;
- Draw;
- end;
-
- Aktuellen Pfad als statischen Text in das Dialogfenster eintragen. Bitte
- beachten Sie die Vorgehensweise! Hier können Sie lernen, wie man zur
- Laufzeit einen statischen Text ändern kann.
-
- LfdPtr:=DlgList^.GetItems(6); {statischer Text, 6.Eintrag}
- {in DlgList}
- with PStaticText(LfdPtr)^ do {Typecast}
- begin
- GetDir(0,ActPfad);
- if length(ActPfad)>26 then {wenn zu lang, dann}
- begin {zusammenkürzen}
- while length(ActPfad)>22 do
- repeat
- delete(ActPfad,3,1);
- until ActPfad[3]='\';
-
-
-
- Programmierhandbuch WG-Vision - 179 -
-
-
-
-
-
-
-
- insert('\...',ActPfad,3);
- end;
- Bezeichner.Zeile:=ActPfad;
- FBar(Origin.x,Origin.y,Origin.x+223,Origin.y+8,LightGray);
- Draw;
- end;
- end;
-
- OK-Taste gedrückt. Wenn die ausgewählte Datei wirklich auf dem
- Datenträger existiert, dann Dateinamen mit Pfad ergänzen, in
- Event.InfoString verpacken und mit der Mitteilung msgLoadFile auf die
- Reise schicken ...
-
- if Event.Command=cmOK then
- begin
- zz:=Trim(FExpand(DlgData.DateiName)); {Trim entfernt}
- {nachfolgend Leerzeichen}
- if Exists(zz) then {nachschauen, ob es die Datei}
- {überhaupt gibt}
- begin
- Message:=msgLoadFile; {Message abschicken}
- LfdPtr:=DlgList^.GetItems(1); {Dateiname mit Pfad aus der}
- {Eingabezeile lesen}
- with PInputLine(LfdPtr)^ do
- InfoString:=Trim(FExpand(DlgData.DateiName));
- Command:=cmCloseWindow;
- end
- else Message:=msgError;
- end;
-
- Abbrechen gedrückt. Fenster schließen und sonst nichts
-
- if Command=cmCancel then
- with DlgData do
- begin
- DateiName:='';
- Datei:='';
- Command:=cmCloseWindow;
- end;
-
-
-
- Programmierhandbuch WG-Vision - 180 -
-
-
-
-
-
-
-
- Wenn Sie in die Eingabezeile eine neue Dateiauswahlmaske geschrieben und
- mit <ENTER> quittiert haben, dann muß der Inhalt der Listbox neu
- erstellt werden.
-
- if (What=evKeyboard) AND (Keyb.KeyCode=kbEnter) then
- if Pos('*',DlgData.DateiName)<>0 then
- begin
- if Pos('\',DlgData.DateiName)<>0 then
- begin
- FileMask:=Trim(copy(DlgData.DateiName,Pos('\',
- DlgData.DateiName)+1,length(DlgData.DateiName)-
- Pos('\',DlgData.DateiName)));
- end
- else FileMask:=Trim(DlgData.DateiName);
- LfdPtr:=DlgList^.GetItems(2);
- with PDateiListBox(LfdPtr)^ do
- begin
- CreateDataList;
- Draw;
- end;
- end;
-
- Anklick-Bereich für den Doppelklick festlegen. Das ist notwendig, wenn
- ein Doppelklick auf den Rollbalken nicht die Übernahme der gerade
- gekennzeichneten Datei veranlassen soll.
-
- LfdPtr:=DlgList^.GetItems(2); {Klick-Bereich für Doppelklick}
- with PDateiListBox(LfdPtr)^ do
- begin
- if Border.Contains(Mouse.Position) then
- if Mouse.Double then Klick:=true;
- end;
-
- Dateiauswahl aus der Listbox
-
- if (Keyb.KeyCode=kbSpace) or Klick then
- begin
- Mouse.DoubleKlick:=FALSE;
- Klick:=false;
-
-
-
- Programmierhandbuch WG-Vision - 181 -
-
-
-
-
-
-
-
- if PDateiListBox(LfdPtr)^.Focus then
- begin
- LfdPtr:=DlgList^.GetItems(1);
- with PInputLine(LfdPtr)^ do
- begin
- Data:=DlgData.Datei;
- if (Trim(Data)='.') or (Trim(Data)='..') or
- (Pos('<D>',Data)<>0) then
- begin
- if Pos('<D>',Data)<>0 then
- delete(Data,Pos('<D>',Data),3);
- if Trim(Data)='.' then Data:='\';
- ChDir(Data);
- if Trim(Data)<>'\' then Data:=Trim(Data)+'\'+FileMask;
- LfdPtr:=DlgList^.GetItems(2);
- with PDateiListBox(LfdPtr)^ do
- begin
- CreateDataList;
- Draw;
- end;
-
- Statischen Text den neuen Gegebenheiten anpassen
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 182 -
-
-
-
-
-
-
-
- LfdPtr:=DlgList^.GetItems(6); {statischer Text}
- with PStaticText(LfdPtr)^ do
- begin
- GetDir(0,ActPfad);
- if length(ActPfad)>26 then {wenn zu lang, dann}
- begin {zusammenkürzen}
- while length(ActPfad)>22 do
- repeat
- delete(ActPfad,3,1);
- until ActPfad[3]='\';
- insert('\...',ActPfad,3);
- end;
- Bezeichner.Zeile:=ActPfad;
- FBar(Origin.x,Origin.y,Origin.x+223,Origin.y+8,
- LightGray);
- Draw;
- end;
- end;
- Draw;
- end;
- end;
- end;
- end;
- end;
-
- Datei- und Verzeichnisnamen in den Heap lesen zur Verwendung innerhalb
- der Listbox.
-
- {Implementation TDateiListBox}
-
- procedure TDateiListBox.CreateDataList;
- var SRec:SearchRec;
- LfdPtr:PLine;
- begin
- Liste^.DeleteItems;
- ChangeItem:=1; AktivItem:=1;
- Delta.X:=1; Delta.Y:=1;
- VertiScrollBar^.Value:=1;
- FindFirst('*.*',AnyFile,SRec);
-
-
-
- Programmierhandbuch WG-Vision - 183 -
-
-
-
-
-
-
-
- while DosError=0 do
- begin
- if SRec.Attr=$10 then
- begin
- LfdPtr:=New(PLine, Init);
- if (SRec.Name='.') or (SRec.Name='..') then
- LfdPtr^.Eintrag:=SRec.Name
- else
- begin
- while length(SRec.Name)<8 do SRec.Name:=SRec.Name+' ';
- LfdPtr^.Eintrag:=SRec.Name+' <D>'; {Unterverzeichnis}
- end;
- Liste^.InsertItem(LfdPtr);
- end;
- FindNext(SRec);
- end;
- FindFirst(FileMask,AnyFile,SRec);
- while DosError=0 do
- begin
- if SRec.Attr=$20 then
- begin
- LfdPtr:=New(PLine, Init);
- LfdPtr^.Eintrag:=SRec.Name;
- Liste^.InsertItem(LfdPtr);
- end;
- FindNext(SRec);
- end;
- DataLen:=12;
- SetLimit(12,Liste^.AnzElem,8,11);
- end;
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 184 -
-
-
-
-
-
-
-
- procedure TIDlgBgrd.Draw;
- begin
- with Border do
- begin
- FBar(A.x,A.y,B.x,B.y,LightGray);
- FBar(A.x+7,A.y+18,B.x-7,A.y+46,LightGray);
- D3Frame(A.x+7,A.y+18,B.x-7,A.y+46,Black,White);
- D3Frame(A.x+148,A.y+126,A.x+246,A.y+188,Black,White);
- end;
- end;
-
- END.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 185 -
-
-
-
-
-
-
-
- 5.5. Mitteilungsboxen
-
- Mitteilungsboxen sind spezielle Dialogfenster, die man zum
- Aufblenden von Informationen (Hinweise, Fragen etc.) ver-
- wenden kann.
- Das Objekt TProgram stellt eine solche Messagebox zur Verfü-
- gung. Sie kann z.B. sofort über die case-Auswahl des Event-
- handlers der Applikation aufgerufen werden. Eine
- Mitteilungsbox wird unabhängig vom eingestellten Grafikmodus
- immer zentriert auf dem Bildschirm dargestellt. Ihre Größe
- beträgt einheitlich 260x150 Pixel und sie wird in der roten
- Farbpalette angezeigt.
-
- Syntax
-
- MessageBox(Caption:word;PanelText,InfoText:string);
-
- Caption bestimmt das Schalterlayout der Box
-
- 0 keine Schalter
- 1 Schalter 'OK'
- 2 Schalter 'Abbrechen' (Cancel)
- 3 Schalter 'Ja' und 'Nein' (No und Yes)
-
- Paneltext Text im Panel der Messagebox
- InfoText Text im Clientbereich der Messagebox. InfoText
- kann maximal 2 Zeilen umfassen. Die Stelle, wo der
- Text umgebrochen werden soll, ist mit einem
- Doppelkreuz zu kennzeichnen
-
- Die Tasten einer Messagebox senden bei Betätigung folgende
- Kommandos:
-
- 'OK' cmCloseWindow
- 'Abbrechen' cmCancel
- 'Ja' cmYes
- 'Nein' cmNo
-
-
-
-
-
- Programmierhandbuch WG-Vision - 186 -
-
-
-
-
-
-
-
- Beispiel
- Ein Programmteil sendet im Event-Record folgende Mitteilung,
- die von einer Messagebox abgefangen und angezeigt werden
- soll:
-
- Event.Message:=msgInfo;
- Event.InfoString:='Ungültige Eingabe#Abbruch';
-
- Im Eventhandler der Applikation:
-
- ...
- if Event.Message=msgInfo then MessageBox(1,'Hinweis',Event.InfoString);
- ...
-
- 5.6. Anzeigen von Fehlermeldungen
-
- Zu einer sauberen Programmierung gehört, daß Fehler im Pro-
- gramm nicht zu einem unvorhersehbaren Verhalten oder sogar
- zu einem Systemabsturz führen. Auf jeden Fall sollte der
- Nutzer beim Auftreten eines Fehlers darüber informiert wer-
- den. Innerhalb einer grafischen Nutzeroberfläche gehört es
- sich, daß Fehlermeldungen innerhalb einer Messagebox anzu-
- zeigen sind.
- WG-Vision verwendet dazu folgendes Konzept:
-
- 1. Alle Fehlerarten werden in verschiedene Kategorien
- aufgeteilt, die in etwa die Fehlerquelle beschreiben:
-
- gr Grafik-Fehler
- ems EMS-Fehler
- joy Joystick-Fehler
- ds DOS-Fehler
- io Ein-/Ausgabefehler
- mst schwerwiegender Fehler
- pr Druckerfehler
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 187 -
-
-
-
-
-
-
-
- 2. Wird ein Fehler dedektiert (z.B. IOResult<>0), dann wird
- das Message-Feld des Event-Records auf msgError gesetzt.
- Außerdem wird in die Record-Variable Fehler der Fehlertyp
- (FTyp) und die Nummer des Fehlers (FNummer) eingetragen.
-
- 3. Der Eventhandler der Applikation veranlaßt als Reaktion
- auf die Message msgError, daß ein Mitteilungsfenster
- aufgeblendet wird, welches im Panel den Fehlertyp und im
- Fenster die Fehlermeldung entsprechend der Informationen,
- die im Record Fehler stehen) enthält. Die Texte zu den
- Fehlernummern stehen in der Unit WError.
-
- Exemplarisch soll als Beispiel eine Funktion vorgestellt
- werden, welche überprüft, ob der angeschlossene Drucker be-
- reit ist oder nicht und gegebenenfalls eine entsprechende
- Fehlermitteilung erzwingt. Sie wurde der Unit WPrint entnom-
- men.
-
- function TLinePrint.PrinterOK:boolean;
- var PrinterAdress:word;
- Status:byte;
- begin
- PrinterOK:=false;
- delay(10);
- PrinterAdress:=memw[$40:$08)]; {Basisadresse von LPT1}
- if PrinterAdress<>0 then
- begin
- Status:=port[PrinterAdress+1]; {Statusport einlesen}
- if (Status and $DF)=$DF then PrinterOK:=true
- else
- begin
- Fehler.FTyp:=pr;
- if (Status and $40)=$40 then {nicht On-Line}
- if (Status and $20)<>$20 then
- begin
- Fehler.FNummer:=303;
- Event.Message:=msgError;
- Exit;
- end
-
-
-
- Programmierhandbuch WG-Vision - 188 -
-
-
-
-
-
-
-
- else
- begin {kein Papier}
- Fehler.FNummer:=302;
- Event.Message:=msgError;
- Exit;
- end;
- if (Status and $87)=$87 then {Drucker nicht bereit}
- begin
- Fehler.FNummer:=301;
- Event.Message:=msgError;
- Exit;
- end;
- end;
- end
- else
- begin
- Fehler.FTyp:=pr;
- Fehler.FNummer:=304;
- Event.Message:=msgError;
- end;
- end;
-
- Wenn Sie in der Unit WError Fehlermeldungen vermissen oder
- eigene Fehlermeldungen verwenden möchten, können Sie die
- Unit entsprechend erweitern.
- Für das Abfangen eines Fehlers ist jedoch weiterhin der Pro-
- grammierer verantwortlich.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 189 -
-
-
-
-
-
-
-
- 5.7. Kontextsensitive Hilfe
-
- Der Aufbau einer kontextsensitiven Hilfe ist innerhalb von
- WG-Vision sehr einfach zu realisieren. Sie brauchen ledig-
- lich die Zeile
-
- SetOnLineHelp('hilf.dat')
-
- in den Quelltext ihres Programms einzufügen. Der beste Ort
- dafür ist die erste Zeile in InitMenubar bzw., vorausgesetzt
- Sie überschreiben ihn, der Konstruktor der Applikation. Der
- Parameter in SetOnlineHelp ist der Name der Hilfe-Datei. Sie
- muß sich im gleichen Verzeichnis wie das Programm befinden.
- Fehlt sie, kann das Hilfesystem nicht aktiviert werden (Ach-
- tung ! Es werden keine diesbezüglichen Hinweise ausgegeben).
- Die Hilfsdatei können Sie mit jedem ASCII-Editor erstellen.
- Sie hat folgenden Aufbau:
-
- Überschrift (ohne Bedeutung)
-
- ##1
-
- Hilfe-Text für Helpindex 1
-
-
- END
- ##2
-
- Hilfe-Text für HelpIndex 2
-
- END
-
- ...
-
- HELPEND
-
- Zwei Doppelkreuze gefolgt von einer Zahl definieren jeweils
- den Beginn des Hilfe-Textes. Beendet wird er durch das
- Kürzel END. Die Zahl hinter dem Doppelkreuz ist identisch
-
-
-
- Programmierhandbuch WG-Vision - 190 -
-
-
-
-
-
-
-
- mit den Hilfsindex, den Sie bei der Menüdefinition den
- einzelnen Me-nüpunkten zugeordnet haben. Ist der Hilfsindex
- 0, dann gibt WG-Vision eine Messagebox mit dem Hinweis aus,
- daß keine Hilfe verfügbar ist.
- Aktiviert wird das Hilfesystem mit der <F1>-Taste. Bedingung
- ist, daß sich der Auswahlbalken auf dem entsprechenden Menü-
- punkt befindet.
- Der dazugehörige Hilfstext wird in einem Rollfenster zur An-
- zeige gebracht.
-
- Beispiel für eine Hilfe-Datei:
-
- Helpfile für ....
-
-
- ##1
-
- BEISPIEL WG-Vision
-
-
- Menü : Datei
-
-
- Unter dem Menüpunkt "Datei" sind folgende Funktionen
- zusammengefaßt:
-
- Neues Bild F3 Der Bildschirm wird gelöscht und
- Sie können mit einem neuen Bild
- beginnen
-
- Bild Laden F2 Ein Dialogfenster wird aufgeblendet,
- aus dem Sie ein bereits vorhandenes
- Bild zur Weiterverarbeitung auswählen
- können
-
- Bild Speichern Das in Arbeit befindliche Bild wird
- gesichert. Wenn die Bilddatei noch
- keinen Namen hat, wird die Eingabe
- eines Dateinamens verlangt
-
-
-
- Programmierhandbuch WG-Vision - 191 -
-
-
-
-
-
-
-
- Drucken Druckt das Bild auf dem angeschlossenen
- Drucker aus
-
- Löschen Das gesamte Bild auf dem Bildschirm wird
- gelöscht
-
- Beenden Alt-X Malprogramm abbrechen und zurück zum
- Betriebssystem
- END
- ##2
-
- BEISPIEL WG-Vision
-
-
- Menü : Bearbeiten
-
-
- Unter dem Menüpunkt "Bearbeiten" sind folgende Funktionen
- zusammengefaßt:
-
- Rückgängig Die letzte Zeichenoperation wird rückgängig
- gemacht
-
- Schnitt Bildausschnitt festlegen
-
- Die folgenden Funktionen sind nur aktiv, wenn ein Bildausschnitt
- festgelegt worden ist
-
- Kopieren Bildausschnitt an eine andere Stelle des
- Bildschirms kopieren
-
- Verschieben Bildausschnitt verschieben
-
- Drehen Bildausschnitt Drehen
- END
- ##3
-
- BEISPIEL WG-Vision
-
-
-
-
- Programmierhandbuch WG-Vision - 192 -
-
-
-
-
-
-
-
- Menü : Werkzeuge
-
-
- Unter dem Menüpunkt "Werkzeuge" sind folgende Funktionen
- zusammengefaßt:
- END
- ##4
-
-
- BEISPIEL WG-Vision
-
- Menü : Schrift
-
-
- Unter dem Menüpunkt "Schrift" sind folgende Funktionen
- zusammengefaßt:
- END
-
-
- HELPEND;
-
- Verwenden Sie für Ihr Programm den VGA-Standardmodus
- M640x480 mit 16 Farben, dann können Sie mit SetFont einen
- der Zusatzzeichensätze für die Anzeige der Hilfstexte akti-
- vieren.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 193 -
-
-
-
-
-
-
-
- 5.8. Statuszeile
-
- Zur Programmierung einer Statuszeile stellt das Applikati-
- onsobjekt die virtuelle Methode StatusBar zur Verfügung. Mit
- ihrer Hilfe können Sie das Desktop mit einer Statuszeile
- ausstatten, in der Sie z.B. Ihr CopyRight oder andere Infor-
- mationen (z.B. Programminformationen) schreiben können.
- Statusbar besitzt selbst keinen Eventhandler. Deshalb muß
- sie vom Eventhandler der Applikation (bzw. der aufge-
- blendeten Fenster) mit bedient werden (Beispiel siehe
- Abschnitt "Objekte im Detail", "Tastatur").
-
- Beispiel
-
- procedure TApplication.StatusBar;
- var i:integer;
- begin
- FBar(4,GetMaxY-26,GetMaxX-4,GetMaxY-4,LightGray);
- D3Frame(6,GetMaxY-24,GetMaxX-6,GetMaxY-6,Black,White);
- OutTextXY(15,GetMaxY-19,'Copyright 1992/93 by Dipl.Phys.
- Mathias Scholz');
- SetColor(Black);
- OutTextXY(16,GetMaxY-18,'Copyright 1992/93 by Dipl.Phys.
- Mathias Scholz');
- end;
-
- In den meisten Fällen wird vom Programm direkt in die Sta-
- tuszeile geschrieben. Statusbar ist also gewissermaßen nur
- ein Rahmen, welches bei Bedarf Informationen aufnimmt. Die
- Methode Statusbar wird in der Regel nur einmal beim Aufblen-
- den des Desktops abgearbeitet.
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 194 -
-
-
-
-
-
-
-
- 5.9. Zweisprachige Programmierung
-
- Programme, die mit WG-Vision erstellt worden sind, können
- sofort in zwei Sprachvarianten (Deutsch und Englisch) er-
- stellt werden. Wird beim Programmstart die Variable Sprache
- mit "Englisch" initialisiert, dann erfolgen alle Ausschrif-
- ten auf den Bildschirm in Englisch (Sie müssen Ihr Programm
- natürlich auch zweisprachig gestalten. Schauen Sie sich dazu
- bitte noch einmal das Komplexbeispiel Dateiauswahldialog
- an). Außerdem müssen Sie eventuell noch die Menüressource
- durch eine englischsprachige Version ersetzen.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 195 -
-
-
-
-
-
-
-
- 6. Objekte im Detail
-
- 6.1. Unit WDRIVER.PAS
-
- 6.1.1. Ansteuerung der Grafikkarte - TVideoDevice
-
- Das Objekt Video ist eine Instanz des Objektes TVideoDevice.
- Dieses Objekt ist für die gesamte Grafikansteuerung verant-
- wortlich. Es stellt Methoden zur Initialisierung der einzel-
- nen Grafik-Modi und zum Umschalten in den Alphamodus zur
- Verfügung. Außerdem lassen sich zur Laufzeit die Auflösung,
- der gerade aktive Treiber und die Anzahl der unterstützten
- Farben erfragen.
-
- Felder
-
- Treiber
- Treiber:integer;
- Aktiver Grafiktreiber. Die Zahlen entsprechen folgenden
- Grafikkarten
-
- 3 EGA (16 Farben)
- 9 VGA (16 Farben)
- 6 IBM 8514 (256 Farben)
- 11 VESA (256 Farben)
-
- OrigMode
- OrigMode:integer;
- Enthält die Nummer des zuletzt aktiven Alphamodus (d.h.
- bevor in die Grafik umgeschalten wurde)
-
- 0 BW40 {siehe Turbo-Referenzhandbuch}
- 1 CO40
- 2 BW80
- 3 CO80
- 256 80 Zeichen mit 43 bzw. 50 Zeilen
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 196 -
-
-
-
-
-
-
-
- Modus
- Modus:integer;
- Z.Z. aktiver Grafikmodus. Folgende Grafikmodi sind möglich:
-
- 1 M640x350
- 2 M640x480
- 3 M800x600
- 4 M1024x768
-
- Modi
- Modi:tMinSet;
- Enthält als Menge alle für den konkreten Grafiktreiber
- verfügbaren Grafikmodi
-
- XMax,YMax
- Maximal mögliche x- bzw. y-Koordinate des Bildschirms
-
- Colors
- Anzahl der verfügbaren Farben
-
- Methoden
-
- Init
- constructor Init(Driver,Mode:integer);
- Initialisierung des Grafiksystems. Es erfolgt die Registrie-
- rung des gewünschten BGI-Treibers, der als Objekt-Datei vor-
- liegen muß. Folgende Treiber werden unterstützt: EGAVGA.BGI,
- IBM8514.BGI und VGAVESA.BGI. Anschließend schaltet der Rech-
- ner in den unter Mode angegebenen Grafikmodus. Alle VESA-
- Modi arbeiten mit 256 Farben. Tritt während der Initiali-
- sierung ein Fehler auf, wird auf dem Alphabildschirm eine
- entsprechende Fehlermeldung generiert.
-
- Done
- destructor Done; virtual;
- Grafik schließen und den beim Programmstart aktiven
- Textmodus setzen.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 197 -
-
-
-
-
-
-
-
- GetXMax
- function GetXMax:word;
- Maximale x-Koordinate des Bildschirms.
-
- GetYMax
- function GetYMax:word;
- Maximale y-Koordinate des Bildschirms.
-
- GetAnzColors
- function GetAnzColors:word;
- Anzahl der von der Grafikkarte im eingestellten Modus
- unterstützten Farben (16 oder 256).
-
- GetDriver
- function GetDriver:string;
- Übergibt den Namen des gerade aktiven Grafiktreibers.
-
- GetGrafikMode
- function GetGrafikMode:integer;
- Liefert die Nummer des gerade aktiven Grafikmodus.
-
- ChangeGraficMode
- ChangeGraficMode(Mode:integer);
- Diese Methode wird zum Wechseln des Grafikmodus benötigt.
- Übergeben wird die Nummer des Grafikmodus, in welchen
- gewechselt werden soll (bitte vordefinierte Konstanten
- verwenden). Innerhalb der Methode wird geprüft, ob der
- gerade aktive BGI-Treiber diesen Grafikmodus überhaupt
- unterstützt. Wenn nicht oder wenn es beim Umschaltvorgang zu
- Problemen kommt, wird eine Fehlermeldung an WG-Vision
- abgesetzt.
-
- SetTextMode
- procedure SetTextMode;
- Wechselt in den Textmodus, der vor der Grafikinitialisierung
- aktiv war.
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 198 -
-
-
-
-
-
-
-
- SetDirectVideo
- procedure SetDirectVideo(Direct:boolean);
- Mit dieser Methode können Sie festlegen, ob Schreibaktionen
- über das BIOS (Direct=false) oder direkt in den Bildspeicher
- erfolgen sollen. SetDirectVideo wirkt nur auf die Befehle
- write und writeln. Außerdem wird das CRT-Scrolling
- unterbunden.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 199 -
-
-
-
-
-
-
-
- 6.1.2. Ansteuerung eines Spielhebels - TJoyStickDevice
-
- Wenn Ihr Rechner über einen Spieleadapter verfügt, können
- Sie über eine Instanz des Objektes TJoyStickDevice einen
- Joystick ansteuern.
-
- Felder
-
- JoyPresent
- JoyPresent:boolean;
- Diese logische Variable wird vom Konstruktor des TJoyStick-
- Device-Objektes auf true gesetzt, wenn ein Spieleadapter
- verfügbar ist.
-
- JPos
- JPos:TPoint;
- Instanz eines TPoint-Objektes. Wird zur Speicherung der
- absoluten Position des Spielhebels verwendet.
-
- Phi
- Phi:real;
- Horizontale Auslenkung des Spielhebels.
-
- Elongation
- Elongation:real;
- Betrag der vertikalen Auslenkung des Spielhebels.
-
- FPush1,FPush2
- FPush1:boolean; FPush2:boolean;
- Status der Feuertasten. Wird eine Feuertaste gedrückt, dann
- wird die entsprechende Variable auf true gesetzt.
-
- Methoden
-
- Init
- constructor Init;
- Initialisierung des Joysticks. Dabei wird überprüft, ob ein
- Spieleadapter angeschlossen ist (Variable JoyPresent).
-
-
-
-
- Programmierhandbuch WG-Vision - 200 -
-
-
-
-
-
-
-
- JoyStickHandle
- procedure JoyStickHandle;
- Joystick-Handler. Ermittelt die Koordinaten, die Auslenkung,
- den Winkel der horizontalen Auslenkung und den Status der
- Feuerknöpfe. Diese Werte werden in den Feldern des TJoy-
- StickDevice-Objektes gespeichert.
-
- IfJoyPresent
- function IfJoyPresent:boolean;
- Gibt true zurück, wenn der Rechner über einen Spieleadapter
- verfügt.
-
- Degree
- function Degree:integer;
- Gibt den Winkel der horizontalen Auslenkung mit einer
- Genauigkeit von 5 Grad zurück. Wertebereich 0..360 Grad.
-
- Turn
- function Turn:word;
- Gibt den Betrag der Auslenkung des Joysticks zurück.
-
- GetXValue
- function GetXValue:integer;
- Liefert die momentane x-Koordinate der Auslenkung im Bereich
- von 0..300 zurück.
-
- GetYValue
- function GetXValue:integer;
- Liefert die momentane y-Koordinate der Auslenkung im Bereich
- von 0..300 zurück.
-
- PushOne
- function PushOne:boolean;
- Übergibt true, wenn die erste Feuertaste betätigt wurde.
-
- PushTwo
- function PushTwo:boolean;
- Übergibt true, wenn die zweite Feuertaste betätigt wurde.
-
-
-
-
- Programmierhandbuch WG-Vision - 201 -
-
-
-
-
-
-
-
- Beispiel
-
- program JoyTest;
-
- uses crt,
- WDriver;
-
- var Joy:TJoyStickDevice;
- begin
- ClrScr;
- Joy.Init;
- with Joy do
- repeat
- JoyStickHandle;
- GotoXY(10,10); writeln(Joy.x:5:0);
- GotoXY(10,11); writeln(Joy.y:5:0);
- GotoXY(10,13); writeln(Abstand:5:0);
- GotoXY(10,14); writeln(Degree:3);
- until FPush1;
- end.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 202 -
-
-
-
-
-
-
-
- 6.1.3. Tastatur - TKeyboardDevice
-
- Das Objekt TKeyboardDevice dient der Ansteuerung der Tasta-
- tur. Es enthält Methoden zum Auslesen von Key- und Scancodes
- und zur Bestimmung des Tastaturstatus (z.B. NumLock einge-
- schaltet ?). Außerdem kann bei AT-Tastaturen die Tastatur-
- Verzögerung und die Wiederholfrequenz bei gedrückter Taste
- eingestellt werden. Weitere Methoden dienen dem Sperren und
- der Freigabe der Tastatur.
-
- Felder
-
- ATFlag
- ATFlag:boolean;
- Wenn ATFlag true ist, dann ist eine AT-Tastatur ange-
- schlossen. Nur in diesem Fall können Sie mit der Methode
- SetTypmaticRate die Verzögerung und die Wiederholfrequenz
- bei einem Tastendruck einstellen.
-
- Delay
- Delay:integer;
- Diese Variable enthält die eingestellte Tastatur-Verzöge-
- rung. Darunter ist die Zeitdauer, die bis zum Einsetzen der
- automatischen Tastenwiederholung vergeht, zu verstehen.
- Standardmäßig ist sie Null, was einer Verzögerung von
- ungefähr 1/4 Sekunden entspricht. Nur wenn die Verzö-
- gerungsrate verändert wird, erhält sie einen Wert ungleich
- Null.
- Folgende Werte sind möglich :
-
- 0 1/4 Sekunde
- 1 1/2 Sekunde
- 2 3/4 Sekunde
- 3 1 Sekunde
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 203 -
-
-
-
-
-
-
-
- Speed
- Speed:integer;
- Wenn eine Taste längere Zeit niedergedrückt wird, dann sen-
- det der Tastatur-Controller das entsprechende Zeichen immer
- wieder an den Computer. Wie oft er das pro Sekunde macht,
- bestimmt die Wiederholrate. Sie kann zwischen zwei Wiederho-
- lungen pro Sekunde und dreisig Wiederholungen pro Sekunde
- liegen. Ihr Wert wird in der Variablen Speed hinterlegt, wo-
- bei folgende Zuordnung gilt:
-
- 0 30.0 Wiederholungen pro Sekunde
- 1 26.7 "
- 2 24.0 "
- 3 21.8 "
- .
- .
- .
- 30 2,1 "
- 31 2.0 "
-
- KeyCode
- KeyCode:char;
- Speichert den ASCII-Code der zuletzt gedrückten Taste.
-
- ScanCode
- ScanCode:byte;
- Speichert den Scancode der zuletzt gedrückten (Sonder-)
- Taste.
-
- Statusflag
- StatusFlag
- Speichert das Statusflag der Sondertasten.
-
- KeyPush
- KeyPush:boolean;
- Diese logische Variable ist solange true, wie eine Taste
- niedergedrückt ist.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 204 -
-
-
-
-
-
-
-
- Locking
- Locking:boolean;
- True, wenn die Tastatur nicht gesperrt ist.
-
- Methoden
-
- Init
- constructor Init;
- Initialisierung der Tastatur. Dabei wird untersucht, ob eine
- AT-Tastatur angeschlossen ist. Wenn ja, wird die private
- Variable ATFlag auf true gesetzt.
-
- LockKeyboard
- procedure LockKeyboard;
- Durch Aufruf dieser Methode können Sie die Tastatur sperren,
- d.h. alle Tastaturereignisse werden ignoriert.
-
- UnLockKeyboard
- procedure UnLockKeyboard;
- Aufheben der Tastatursperre.
-
- SetTypmaticRate
- procedure SetTypmaticRate(Verzoegerung,Wiederholfrequenz
- :integer):boolean;
- Typmatikrate einer AT-Tastatur einstellen. Folgende Werte
- sind sinnvoll:
- Verzoegerung 0 1/4 Sekunde
- 1 1/2 Sekunde
- 2 3/4 Sekunde
- 3 1 Sekunde
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 205 -
-
-
-
-
-
-
-
- Wiederholfrequenz 0 30.0 Wiederholungen pro Sekunde
- 1 26.7 "
- 2 24.0 "
- 3 21.8 "
- .
- .
- .
- 30 2,1 "
- 31 2.0 "
-
- ClearKeyboardBuffer
- procedure ClearKeyboardBuffer;
- Löschen des Tastatur-Puffers.
-
- KeyboardHandler
- function KeyboardHandler:boolean;
- Der Keyboardhandler übergibt nur dann true, wenn eine Tasta-
- tureingabe stattgefunden hat. In diesem Fall liest er die
- Tastatur aus und setzt die Felder KeyCode, ScanCode, KeyPush
- und StatusFlag. Um eine permanente Tastaturabfrage zu ge-
- währleisten, sollte der Keyboardhandler permanent in einer
- repeat-Schleife aufgerufen werden.
-
- GetKeyCode
- function GetKeyCode:char;
- Übergibt den Keycode der zuletzt gedrückten Taste.
-
- GetScanCode
- function GetScanCode:byte;
- Übergibt den Scancode der zuletzt gedrückten (Sonder-)
- Taste.
-
- IfKeyPush
- function IfKeyPush:boolean;
- Übergibt solange true, wie eine Taste gedrückt gehalten
- wird.
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 206 -
-
-
-
-
-
-
-
- IfKeybLock
- function IfKeybLock:boolean;
- Übergibt true, wenn die Tastatur nicht gesperrt ist.
-
- RShiftKey
- function RShiftKey:boolean;
- Übergibt true, wenn die rechte Shift-Taste betätigt wurde.
-
- LShiftKey
- function LShiftKey:boolean;
- Übergibt true, wenn die linke Shift-Taste betätigt wurde.
-
- CtrlKey
- function CtrlKey:boolean;
- Übergibt true, wenn die Kontroll-Taste betätigt wurde.
-
- AltKey
- function AltKey:boolean;
- Übergibt true, wenn die Alt-Taste betätigt wurde.
-
- ScrollLock
- function ScrollLock:boolean;
- Übergibt true, wenn die Scroll-Lock-Taste (Rollen) einge-
- schaltet ist.
-
- NumLock
- function NumLock:boolean;
- Übergibt true, wenn die Num-Lock-Taste eingeschaltet ist.
-
- CapsLock
- function CapsLock:boolean;
- Übergibt true, wenn die Caps-Lock-Taste eingeschaltet ist.
-
- Beispiel
-
- In der Statuszeile einer Applikation soll permanent der Sta-
- tus der Sondertasten Caps-Lock, Num-Lock und Scroll-Lock an-
- gezeigt werden. Außerdem soll noch angezeigt werden, ob die
- linke bzw. rechte Shifttaste betätigt ist.
-
-
-
- Programmierhandbuch WG-Vision - 207 -
-
-
-
-
-
-
-
- program StatusBar;
-
- uses WApp,
- WDecl,
- WDlg,
- WDriver,
- WUtils,
- WEvent,
- graph;
-
- const cmNewWindow = 103;
-
- type TApplication=object(TApp)
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- procedure StatusBar; virtual;
- procedure NewWindow;
- end;
-
- var MyApp:TApplication;
-
- {Implementation TApplication}
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~F~enster',0);
- SubMenu('~F~enster aufblenden',cmNewWindow,0,0,false,false);
- SubMenu('E~x~it Alt-X',cmCloseApplication,0,altX,false,false);
- end;
-
- procedure TApplication.HandleEvent;
- var i:integer;
-
- Da die Statuszeile keinen eigenen Eventhandler besitzt, müssen wir sie
- vom Eventhandler der Applikation aus bedienen. Um das Programm über-
- sichtlicher zu gestalten, wird zu diesem Zweck die Prozedur HandleSta-
- tusBar erstellt. In dieser Prozedur wird permanent der Status der
- Sondertasten überwacht und die gewünschte Anzeige in der Statuszeile
- realisiert. Da mit keypressed nicht festgestellt werden kann, ob eine
-
-
-
- Programmierhandbuch WG-Vision - 208 -
-
-
-
-
-
-
-
- Statustaste gedrückt wird, kann auch mit Event.What=evKeyboard nicht
- ausgetestet werden, ob eine Statustaste gedrückt wurde (der Keyboard-
- handler setzt sich nur dann auf true, wenn auch keypressed true ist).
- Deshalb der kleine Trick mit GetPixel, um zu sehen, wie der letzte Ta-
- stenstatus war.
-
- procedure HandleStatusBar;
- begin
- if Keyb.CapsLock and (GetPixel(254,GetMaxY-16)=LightGray) then
- begin
- Mouse.HideMouse;
- FBar(250,GetMaxY-18,258,GetMaxY-12,LightCyan);
- Mouse.ShowMouse;
- end;
- if not (Keyb.CapsLock) and (GetPixel(254,GetMaxY-16)=LightCyan) then
- begin
- Mouse.HideMouse;
- FBar(250,GetMaxY-18,258,GetMaxY-12,LightGray);
- Mouse.ShowMouse;
- end;
- if Keyb.NumLock and (GetPixel(350,GetMaxY-16)=LightGray) then
- begin
- Mouse.HideMouse;
- FBar(346,GetMaxY-18,354,GetMaxY-12,LightCyan);
- Mouse.ShowMouse;
- end;
- if not (Keyb.NumLock) and (GetPixel(350,GetMaxY-16)=LightCyan) then
- begin
- Mouse.HideMouse;
- FBar(346,GetMaxY-18,354,GetMaxY-12,LightGray);
- Mouse.ShowMouse;
- end;
- if Keyb.ScrollLock and (GetPixel(470,GetMaxY-16)=LightGray) then
- begin
- Mouse.HideMouse;
- FBar(466,GetMaxY-18,474,GetMaxY-12,LightCyan);
- Mouse.ShowMouse;
- end;
- if not (Keyb.ScrollLock) and (GetPixel(470,GetMaxY-16)=LightCyan)
-
-
-
- Programmierhandbuch WG-Vision - 209 -
-
-
-
-
-
-
-
- then
- begin
- Mouse.HideMouse;
- FBar(466,GetMaxY-18,474,GetMaxY-12,LightGray);
- Mouse.ShowMouse;
- end;
- if Keyb.LShiftKey and (GetPixel(547,GetMaxY-16)=LightGray) then
- begin
- Mouse.HideMouse;
- FBar(544,GetMaxY-18,551,GetMaxY-12,LightCyan);
- Mouse.ShowMouse;
- end;
- if not (Keyb.LShiftKey) and (GetPixel(547,GetMaxY-16)=LightCyan) then
- begin
- Mouse.HideMouse;
- FBar(544,GetMaxY-18,551,GetMaxY-12,LightGray);
- Mouse.ShowMouse;
- end;
- if Keyb.RShiftKey and (GetPixel(561,GetMaxY-16)=LightGray) then
- begin
- Mouse.HideMouse;
- FBar(559,GetMaxY-18,566,GetMaxY-12,LightCyan);
- Mouse.ShowMouse;
- end;
- if not (Keyb.RShiftKey) and (GetPixel(561,GetMaxY-16)=LightCyan) then
- begin
- Mouse.HideMouse;
- FBar(559,GetMaxY-18,566,GetMaxY-12,LightGray);
- Mouse.ShowMouse;
- end;
- end;
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 210 -
-
-
-
-
-
-
-
- {-------}
-
- begin
- TProgram.HandleEvent;
- HandleStatusBar; {Hier wird der Handler der Statuszeile aufgerufen}
- case Event.Command of
- cmNewWindow : NewWindow;
- end; {case}
- end;
-
- procedure TApplication.NewWindow;
- var R:TRect;
- Window:PWindow;
- begin
- R.Assign(60,80,440,280);
- Window:=new(PWindow, Init(R,'Beispiel',
- winDouble+winPanel+winMenu+winKey));
- InsertDesktop(Window);
- end;
-
- procedure TApplication.StatusBar;
- var i:integer;
- begin
- FBar(4,GetMaxY-26,GetMaxX-4,GetMaxY-4,LightGray);
- D3Frame(6,GetMaxY-24,GetMaxX-6,GetMaxY-6,Black,White);
- SetColor(Red);
- OutTextXY(15,GetMaxY-18,'Tataturstatus');
- SetColor(Black);
- OutTextXY(15,GetMaxY-18,' Caps Lock Num Lock
- Scroll Lock Shift');
- D3Frame(249,GetMaxY-19,259,GetMaxY-11,Black,White);
-
- {Damit es hübsch ausschaut ...}
-
- D3Frame(345,GetMaxY-19,355,GetMaxY-11,Black,White);
- D3Frame(465,GetMaxY-19,475,GetMaxY-11,Black,White);
- D3Frame(543,GetMaxY-19,552,GetMaxY-11,Black,White);
- D3Frame(558,GetMaxY-19,567,GetMaxY-11,Black,White);
- end;
-
-
-
- Programmierhandbuch WG-Vision - 211 -
-
-
-
-
-
-
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Statusbar mit Tastaturstatusanzeige');
- MyApp.Run;
- MyApp.Done;
- end.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 212 -
-
-
-
-
-
-
-
- 6.1.4. Maus - TMouseDevice
-
- Die Maus spielt eine wichtige Rolle innerhalb einer grafi-
- schen Nutzeroberfläche. Das Objekt TMouseDevice stellt eine
- große Anzahl von Methoden bereit, mit deren Hilfe fast alle
- Steuerungsaufgaben abgedeckt werden können. Eine der wich-
- tigsten Routinen ist der Maushandler. Er muß in eine Abfra-
- geschleife (repeat ... until) eingebettet sein und übergibt
- nur dann true, wenn sich der Zustand der Maus verändert hat.
- Aus der Zustandsänderung heraus wird der jeweils aktuelle
- Zustand bestimmt und in den Feldern des Objekts gespeichert.
- Das TMouseDevice-Objekt arbeitet nur im Grafikmodus.
-
- Felder
-
- MousePresent
- MousePresent:boolean;
- Diese logische Variable wird innerhalb der Initialisierungs-
- routine auf true gesetzt, wenn der Maustreiber aktiv und ei-
- ne Maus vorhanden ist.
-
- FName
- FName:string;
- Dateiname einer Mauszeiger-Ressource. Mauszeiger lassen sich
- in einer Ressourcendatei zusammenfassen und daraus über die
- Methode LoadCursorTyp laden.
-
- Position
- Position:TPoint;
- Aktuelle Lage des Mauszeigers auf dem Grafikbildschirm.
-
- LeftButton
- LeftButton:boolean;
- Ist true, wenn die linke Maustaste gedrückt wurde.
-
- RightButton
- RightButton:boolean;
- Wird auf true gesetzt, wenn die rechte Maustaste gedrückt
- wurde.
-
-
-
- Programmierhandbuch WG-Vision - 213 -
-
-
-
-
-
-
-
- LButtonChange
- LButtonChange:boolean;
- Ist true, wenn sich der Status der linken Maustaste verän-
- dert hat.
-
- RButtonChange
- RButtonChange:boolean;
- Ist true, wenn sich der Status der rechten Maustaste
- verändert hat.
-
- DoubleKlick
- DoubleKlick:boolean;
- Wird nach einem Doppelklick auf true gesetzt.
-
- KlickTime
- KlickTime:word;
- Zeitdifferenz zwischen zwei Klicks, die noch als Doppelklick
- interpretiert werden. Standardwert ist 25.
-
- Area
- Area:TRect;
- Bereichsgrenzen für die Mausbewegung. Nur Innerhalb von Area
- kann der Mauszeiger bewegt werden.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 214 -
-
-
-
-
-
-
-
- CursorTyp
- CursorTyp:byte;
- In dieser Variablen wird der Typ des gerade aktiven Mauskur-
- sors gespeichert. Standardmäßig sind folgende Werte möglich
- (gilt nicht für den Einsatz von Mauszeiger-Ressourcen):
-
- 1 Pfeil (Standard)
- 2 Schräges Kursorkreuz (Hair)
- 3 Sanduhr
- 4 Gerader Vierfach-Pfeil
- 5 Gerader Doppelpfeil mit Pfeilspitze oben und unten
- 6 Schräger Doppelpfeil von links unten nach schräg oben
- 7 Gerader Doppelpfeil mit Pfeilspitze rechts und links
- 8 Schräger Doppelpfeil von links oben nach rechts unten
- 9 Kursorstrich (Caret)
- 10 Handsymbol
- 11 Gerades Kursorkreuz
-
- Methoden
-
- Init
- procedure Init;
- Initialisierung der Maus. Es wird überprüft, ob überhaupt
- eine Maus vorhanden ist (Interrupt $33). Wenn ja, wird die
- logische Variable MousePresent auf true gesetzt. Der Bewe-
- gungsbereich der Maus ist der gesamte Bildschirm bis auf ei-
- nem Randbereich von 4 Pixeln (das entspricht in WG-Vision
- dem Doppelrahmen des Desktops). Außerdem erhalten die Felder
- ihre Anfangsbelegungen.
-
- ShowMouse
- procedure ShowMouse;
- Mauszeiger einschalten.
-
- HideMouse
- procedure HideMouse
- Mauszeiger ausschalten
-
-
-
-
-
- Programmierhandbuch WG-Vision - 215 -
-
-
-
-
-
-
-
- SetMouseArea
- procedure SetMouseArea(x1,y1,x2,y2:integer);
- Diese Methode legt den Bereich fest (Area), in dem sich die
- Maus bewegen darf.
-
- PutMouse
- procedure PutMouse(x,y:integer);
- Setzt den Mauszeiger an die Position x,y des Bildschirms.
-
- MouseSpeed
- procedure MouseSpeed(XSpeed,YSpeed:integer);
- Durch den Aufruf dieser Methode wird das Verhältnis Mausbe-
- wegung je Pixel verändert. Der Standardwert beträgt horizon-
- tal 8 Mickeys je 8 Pixel und vertikal 16 Mickeys je 8 Pixel,
- wobei ein Mickey 1/200 Zoll entspricht. Die Parameter XSpeed
- und YSpeed sind Werte in Mickeys. Je größer sie gewählt wer-
- den, desto langsamer bewegt sich der Mauszeiger auf dem
- Bildschirm.
-
- MouseHandler
- function MouseHandler:boolean;
- Der Mousehandler muß in eine Abfrageschleife eingebaut
- werden. Er übergibt immer dann true, wenn sich der Zustand
- der Maus verändert hat. Dazu aktualisiert er die Felder des
- Objekts mit den veränderten Werten.
-
- GetXPos
- function GetXPos:integer;
- Übergibt die momentane x-Position des Mauszeigers.
-
- GetYPos
- function GetYPos:integer;
- Übergibt die momentane y-Position des Mauszeigers.
-
- GetPos
- procedure GetPos(var MP:TPoint);
- Übergibt die momentane Position des Mauszeigers als Punkt.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 216 -
-
-
-
-
-
-
-
- LButtonKlick
- function LButtonKlick:boolean;
- Übergibt true, wenn die linke Maustaste angeklickt wurde.
-
- RButtonKlick
- function RButtonKlick:boolean;
- Übergibt true, wenn die rechte Maustaste angeklickt wurde.
-
- LButtonDrag
- function LButtonDrag:boolean;
- Übergibt true, wenn die linke Maustaste gedrückt bewegt
- wurde.
-
- RButtonDrag
- function RButtonDrag:boolean;
- Übergibt true, wenn die rechte Maustaste gedrückt bewegt
- wurde.
-
- LButtonRel
- function LButtonRel:boolean;
- Übergibt true, wenn die linke Maustaste losgelassen wird.
-
- RButtonRel
- function RButtonRel:boolean;
- Übergibt true, wenn die rechte Maustaste losgelassen wird.
-
- MDouble
- function MDouble:boolean;
- Übergibt bei einem Doppelklick true.
-
- SetKlickTime
- procedure SetKlickTime(t:byte);
- Mit dieser Methode können Sie die Zeitdifferenz setzen, in-
- nerhalb der zwei Klicks als Doppelklicks interpretiert wer-
- den. Der Standardwert beträgt 25.
-
- MMove
- function MMove:boolean;
- Übergibt true, wenn die Maus bewegt wird.
-
-
-
- Programmierhandbuch WG-Vision - 217 -
-
-
-
-
-
-
-
- SetCursorTyp
- procedure SetCursorTyp(CTyp:byte);
- Wechseln des Kursortyps. Standardmäßig sind folgende Kursor-
- typen verfügbar:
-
- 1 Pfeil (Standard)
- 2 Schräges Kursorkreuz (Hair)
- 3 Sanduhr
- 4 Gerader Vierfach-Pfeil
- 5 Gerader Doppelpfeil mit Pfeilspitze oben und unten
- 6 Schräger Doppelpfeil von links unten nach schräg oben
- 7 Gerader Doppelpfeil mit Pfeilspitze rechts und links
- 8 Schräger Doppelpfeil von links oben nach rechts unten
- 9 Kursorstrich (Caret)
- 10 Handsymbol
- 11 Gerades Kursorkreuz
-
- LoadCursorTyp
- procedure LoadCursorTyp(f:string);
- Mauskursor mit der Nummer n aus einer Ressourcendatei laden.
- Der String f enthält den Dateinamen mit vorangestellten Dop-
- pelkreuz und dahinter, durch den Schrägstrich getrennt, die
- Kursor-Nummer. Die Mauszeiger-Ressource muß die Extension
- .CUR besitzen.
-
- Beispiel:
-
- Mouse.LoadCursorTyp('#CURSOR/3');
-
- Lädt den Mauszeiger Nr. 3 aus der Ressorcendatei CURSOR.CUR.
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 218 -
-
-
-
-
-
-
-
- 6.1.4.1. Erstellung von Mauszeiger-Ressourcen
-
- Mauszeiger lassen sich am elegantesten mit einem speziellen
- Malprogramm entwerfen. Das soll aber nicht das Thema dieses
- Abschnitts sein. Ich möchte Ihnen lediglich den prinzipielle
- Weg aufzeigen, wie man eine WG-Vision-kompatible Mauszeiger-
- Ressourcendatei erzeugt. In dem Sie die hier vorgestellten
- Routinen in ein spezielles WG-Vision-Programm einbinden,
- können Sie selbst einen Mauszeiger-Editor zusammenbasteln.
- Mauszeiger werden durch folgenden Datentyp repräsentiert:
-
- type GraphCursorTyp=record
- Mask:array[0..1,0..15] of word;
- xspot,yspot:word;
- end;
-
- Das Array Mask beschreibt zwei Masken, die Screenmask und
- die Cursormask, die zusammen das Kursorbild ergeben. Beide
- sind 16x16 Bit-Arrays. Zusätzlich gibt es noch einen "Hot
- Spot", den Punkt des Cursors, der verwendet wird, um die Ko-
- ordinaten des Punktes zu bestimmen, an der sich der Cursor
- befindet. Die mit xspot und yspot angegebenen Werte beziehen
- sich auf die linke obere Ecke der Cursormaske.
- Am Beispiel des Pfeils soll nun gezeigt werden, wie Screen-
- und Cursormask aufgebaut sind:
-
- var Pfeil:GraphCursorTyp;
-
- with Pfeil do
- begin
-
- {Screenmask}
-
- Mask : (($3FFF,$1FFF,$0FFF,$07FF,$03FF,$01FF,$00FF,$007F,
- $003F,$001F,$000F,$00FF,$10FF,$F87F,$F87F,$F87F),
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 219 -
-
-
-
-
-
-
-
- {Cursormask}
-
- ($0000,$4000,$6000,$7000,$7800,$7C00,$7E00,$7F00,
- $7F80,$7FC0,$7C00,$6600,$0600,$0300,$0300,$0000));
-
- {Hot Spot}
-
- xspot : 0;
- yspot : 0);
- end;
-
-
- Screenmask
-
- 8421 8421 8421 8421
-
- 0 ..XX XXXX XXXX XXXX 3FFF
- 1 ...X XXXX XXXX XXXX 1FFF
- 2 .... XXXX XXXX XXXX 0FFF
- 3 .... .XXX XXXX XXXX 07FF
- 4 .... ..XX XXXX XXXX 03FF
- 5 .... ...X XXXX XXXX 01FF
- 6 .... .... XXXX XXXX 00FF
- 7 .... .... .XXX XXXX 007F
- 8 .... .... ..XX XXXX 003F
- 9 .... .... ...X XXXX 001F
- 10 .... .... .... XXXX 000F
- 11 .... .... XXXX XXXX 00FF
- 12 ...X .... XXXX XXXX 10FF
- 13 XXXX X... .XXX XXXX F87F
- 14 XXXX X... .XXX XXXX F87F
- 15 XXXX X... .XXX XXXX F87F
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 220 -
-
-
-
-
-
-
-
- Cursormask
-
- 8421 8421 8421 8421
-
- 0 .... .... .... .... 0000
- 1 .X.. .... .... .... 4000
- 2 .XX. .... .... .... 6000
- 3 .XXX .... .... .... 7000
- 4 .XXX X... .... .... 7800
- 5 .XXX XX.. .... .... 7C00
- 6 .XXX XXX. .... .... 7E00
- 7 .XXX XXXX .... .... 7F00
- 8 .XXX XXXX X... .... 7F80
- 9 .XXX XXXX XX.. .... 7FC0
- 10 .XXX XXX. .... .... 7C00
- 11 .XX. .XX. .... .... 6600
- 12 .... .XX. .... .... 0600
- 13 .... ..XX .... .... 0300
- 14 .... ..XX .... .... 0300
- 15 .... .... .... .... 0000
-
- Hot Spot : 0,0
-
- Auf diese Weise können Sie ihren eigenen Mauskursor entwer-
- fen. Mit folgenden Programm erstellen Sie daraus eine
- Ressourcendatei. Diese Ressourcendatei muß in WG-Vision die
- Extension .CUR erhalten:
-
- program Mouse_Ressource;
-
- type GraphCursorTyp=record
- Mask:array[0..1,0..15] of word;
- xspot,yspot:word;
- end;
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 221 -
-
-
-
-
-
-
-
- var f:file; {Ressourcendatei}
- Result,i:integer;
-
- Hier folgt die Definition von 10 verschiedenen Mauszeigern. Sie können
- die Anzahl der Mauszeiger natürlich beliebig erweitern, indem Sie das
- array neu dimensionieren.
-
- const MCursor : array[1..11] of GraphCursorTyp =
- ((Mask : {Pfeil}
- (($3FFF,$1FFF,$0FFF,$07FF,$03FF,$01FF,$00FF,$007F,
- $003F,$001F,$000F,$00FF,$10FF,$F87F,$F87F,$F87F),
- ($0000,$4000,$6000,$7000,$7800,$7C00,$7E00,$7F00,
- $7F80,$7FC0,$7C00,$6600,$0600,$0300,$0300,$000));
- xspot : 0;
- yspot : 0),
- ( Mask : {Hair}
- (($FFFF,$8FF1,$87E1,$C3C3,$E187,$F00F,$F81F,$FC3F,
- $F81F,$F00F,$E187,$C3C3,$87E1,$8FF1,$FFFF,$FFFF),
- ($0000,$0000,$300C,$1818,$0C30,$0660,$03C0,$0180,
- $03C0,$0660,$0C30,$1818,$300C,$0000,$00000,$0000));
- xspot : 8;
- yspot : 7),
- ( Mask : {Sanduhr}
- (($007F,$007F,$007F,$80FF,$80FF,$80FF,$80FF,$C1FF,
- $C1FF,$80FF,$80FF,$80FF,$80FF,$007F,$007F,$007F),
- ($0000,$0000,$3E00,$0000,$3E00,$2A00,$1400,$0800,
- $0000,$0800,$1400,$2A00,$0000,$3E00,$0000,$0000));
- xspot : 5;
- yspot : 8),
- ( Mask : {Vierfach-Pfeil}
- (($FEFF,$FC7F,$F83F,$F01F,$E00F,$C447,$8003,$0001,
- $8003,$C447,$E00F,$F01F,$F83F,$FC7F,$FEFF,$FFFF),
- ($0000,$0100,$0380,$07C0,$0100,$1110,$3118,$7FFC,
- $3118,$1110,$0100,$07C0,$0380,$0100,$0000,$0000));
- xspot : 8;
- yspot : 8),
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 222 -
-
-
-
-
-
-
-
- ( Mask : {Pfeil oben/unten gerade}
- (($FEFF,$FC7F,$F83F,$F01F,$E00F,$C007,$F83F,$F83F,
- $F83F,$F83F,$C007,$E00F,$F01F,$F83F,$FC7F,$FEFF),
- ($0000,$0100,$0380,$07C0,$0FE0,$0380,$0380,$0380,
- $0380,$0380,$0380,$0FE0,$07C0,$0380,$0100,$0000));
- xspot : 8;
- yspot : 8),
- ( Mask : {Pfeil links/rechts schräg}
- (($FFFF,$FE03,$FF01,$FF81,$F701,$F201,$F001,$F009,
- $F01D,$F03F,$F01F,$F80F,$FFFF,$FFFF,$FFFF,$FFFF),
- ($0000,$0000,$007C,$003C,$007C,$00FC,$05F4,$07E0,
- $07C0,$0780,$07C0,$0000,$0000,$0000,$00000,$0000));
- xspot : 10;
- yspot : 7),
- ( Mask : {Pfeil links/rechts gerade}
- (($FFFF,$FFFF,$FBDF,$F3CF,$E3C7,$C003,$8001,$0000,
- $8001,$C003,$E3C7,$F3CF,$FBDF,$FFFF,$FFFF,$FFFF),
- ($0000,$0000,$0000,$0000,$0810,$1818,$3FFC,$7FFE,
- $3FFC,$1818,$0810,$0000,$0000,$0000,$00000,$0000));
- xspot : 8;
- yspot : 8),
- ( Mask : {Pfeil rechts/links schräg}
- (($FFFF,$C07F,$80FF,$81FF,$80EF,$804F,$800F,$900F,
- $B80F,$FC0F,$F80F,$F01F,$FFFF,$FFFF,$FFFF,$FFFF),
- ($0000,$0000,$3E00,$3C00,$3E00,$3F00,$2FA0,$07E0,
- $03E0,$01E0,$03E0,$0000,$0000,$0000,$0000,$0000));
- xspot : 7;
- yspot : 7),
- ( Mask : {Kursorstrich}
- (($FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,
- $FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF,$FFFF),
- ($0000,$6C00,$1000,$1000,$1000,$1000,$1000,$1000,
- $1000,$1000,$1000,$1000,$1000,$1000,$6C00,$0000));
- xspot : 4;
- yspot : 7),
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 223 -
-
-
-
-
-
-
-
- ( Mask : {Hand}
- (($E1FF,$E1FF,$E1FF,$E1FF,$E1FF,$E000,$E000,$E000,
- $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000),
- ($1E00,$1200,$1200,$1200,$1200,$13FF,$1249,$1249,
- $F249,$9049,$9001,$8001,$8001,$8001,$8001,$FFFF));
- xspot : 4;
- yspot : 7),
- ( Mask : {Kursor-Kreuz gerade}
- (($FC7F,$FC7F,$FC7F,$FC7F,$FC7F,$FC7F,$0001,$0001,
- $0001,$FC7F,$FC7F,$FC7F,$FC7F,$FC7F,$FC7F,$FFFF),
- ($0100,$0100,$0100,$0100,$0100,$0100,$0100,$FFFE,
- $0100,$0100,$0100,$0100,$0100,$0100,$0100,$0000));
- xspot : 8;
- yspot : 8));
-
- Und das ist schon alles ...
-
- begin
- assign(f,'CURSOR.CUR'); {Name der Ressourcendatei}
- rewrite(f,SizeOf(GraphCursorTyp));
- for i:=1 to 11 do {11 Kursortypen schreiben}
- BlockWrite(f, MCursor[i],1,Result);
- close(f);
- end.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 224 -
-
-
-
-
-
-
-
- 6.1.4.2. Einige Hinweise zur Benutzung des Mausobjekts
-
- Wenn Sie mit irgendeinem Grafikbefehl auf den Bildschirm
- schreiben, schalten Sie zuvor den Mauszeiger aus und danach
- wieder ein. Sonst kann es zu Fehlern bei der Bildschirmaus-
- gabe kommen.
-
- ...
- Mouse.HideMouse;
- OutTextXY(12,56,'Test');
- Bar(0,80,150,120);
- Mouse.ShowMouse;
- ...
-
- Um zu überprüfen, ob sich der Mauszeiger innerhalb eines be-
- stimmten Areals auf dem Bildschirm befindet, reicht folgende
- if -Anweisung aus:
-
- ...
- Area.Assign(345,128,458,260);
- if Area.Contains(Mouse.Position) then ...
- ...
-
- Diese Abfrage können Sie natürlich auch noch mit der Abfrage
- der Maustaste koppeln:
-
- ...
- if Area.Contains(Mouse.Position) and Mouse.LButtonKlick then ...
- ...
-
- Da die Mouse quasi unabhängig vom Eventhandler arbeitet, ist
- eine Abfrage der Form
-
- ...
- if Event.What=evMouse then ...
- ...
-
- nur in Ausnahmefällen notwendig. Das gilt auch für eine
- Tastaturabfrage.
-
-
-
- Programmierhandbuch WG-Vision - 225 -
-
-
-
-
-
-
-
- Der Maushandler wird in WG-Vision nur innerhalb der Prozedur
- GetEvent aufgerufen. Wenn Sie sich in einem Programmteil aus
- dem Eventhandler ausklinken, indem Sie z.B. eine separate
- Schleife programmieren, dann müssen Sie, wenn Sie die Maus
- weiterhin benutzen möchten, innerhalb dieser Schleife den
- Maushandler aufrufen.
-
- procedure MeinFenster.HandleEvent;
- begin
- TDlgWindow.HandleEvent;
- ...
- if Kennzahl=1 then
- repeat
- if Mouse.MouseHandler then;
- ...
- until Area.Contains(Mouse.Position) and Mouse.LButtonKlick;
- ...
- end;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 226 -
-
-
-
-
-
-
-
- 6.1.5. SummaSketch-Digitizer - TSSDigiDevice
-
- Zur Ansteuerung eines SummaSketch-Digitizers der Typen MM II
- 1201 und MM II 1812 stellt WG-Vision das Objekt TSSDigiDevi-
- ce zur Verfügung. Die Summagraphic-Digitizer lassen sich in
- zwei verschiedenen Betriebsmodi betreiben. Während im MM-Mo-
- de einfache ASCII-Codes vom Host-Rechner zur Steuerung des
- Tabletts verwendet werden, ähnelt der UIOF ("Universal Input
- Output Format") Mode mehr der Ansteuerung eines Druckers. In
- diesem Modus wird zuerst das ESC-Zeichen und anschließend
- meistens zwei Befehls-Codes gesendet.
- Das Objekt TSSDigiDevice verwendet eine Auswahl der wichtig-
- sten Befehle des MM-Modus. Sie unterteilen sich im wesentli-
- chen in vier Gruppen:
-
- 1. Übertragungs-Mode einschalten
-
- POINT
- Punkt-Modus. Das Tablett sendet nur dann ein Koordinaten-
- paar, wenn der Stift oder eine Lupentaste gedrückt wird
-
- STREAM
- Stream-Modus. Das Tablett sendet kontinuierlich Daten.
-
- SWSTREAM
- Switch-Stream-Modus. Das Tablett überträgt immer dann konti-
- nuierlich Daten, wenn der Stift oder eine Lupentaste ge-
- drückt ist.
-
- 2. Report-Rate einstellen
-
- Die Reportrate gibt an, wieviele Koordinatenpaare pro Sekun-
- de vom Tablett gesendet werden.
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 227 -
-
-
-
-
-
-
-
- 3. Auflösung einstellen
-
- Ein Digitizer läßt sich in verschiedenen Auflösungen betrei-
- ben. In der Unit WDecl von WG-Vision finden Sie vordefinier-
- te Konstanten, die Sie mit dem Befehl SetCommand zum Tablett
- übertragen können. Die Maßeinheit ist Linien pro Zoll (lpi).
-
- 4. Allgemeine Steuerfunktionen
-
- Zu dieser Gruppe gehören Kommandos für den Selbsttest, zum
- Rücksetzen des Tabletts auf die Standardwerte, zur Überprü-
- fung der momentanen Konfiguration und zur Definition des Ko-
- ordinatensystems.
-
- Bedingung für die Arbeit mit TSSDigiDevice ist, daß das gra-
- fische Tablett an einer der beiden seriellen Schnittstellen
- des Rechners angeschlossen ist und in der Standardeinstel-
- lung betrieben wird (9600 Baud, ungerade Parität, 8 Daten-
- bits, 1 Stoppbit). Zur Übertragung wird das XON-XOFF-
- Protokoll verwendet.
- Bei der Initialisierung schaltet das Tablett in den ASCII-
- BCD-Report-Mode um. In diesem Moment sendet der Digitizer
- die Stift- bzw. Lupenkoordinaten als ASCII-Strings. Mit ein-
- fachen Stringoperationen lassen sich daraus die momentanen
- Koordinaten und der Stiftstatus bestimmen. Diese Arbeit wird
- von der privaten Methode SelectValue ausgeführt. Sie über-
- nimmt die vom Digitizer-Handler in einem Puffer bereitge-
- stellten Daten, sucht sie nach Terminatorzeichen ab (Kommas)
- und extrahiert daraus die x- und y-Koordinaten und die Num-
- mer der gedrückten Taste. Anschließend werden diese Werte in
- einem tDigiData-Record zwischengespeichert und können von
- dort mit den Methoden GetXValue, GetYValue und GetTaste aus-
- gelesen werden.
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 228 -
-
-
-
-
-
-
-
- Konstanten (Befehlscodes), implementiert in WDECL.PAS
-
- Übertragungsprotokoll
-
- XON = ^Q;
- XOFF = ^S;
-
- Konfigurationsbefehle
-
- DGRESET = #0; Rücksetzen
- SELFTEST = #116; Selbsttest
- SENDRES = #119; Senden der Selbsttest-Resultate
- SENDCONF = #97; Konfiguration senden
- SENDMODEL = #5; Modell-Identifikationsstring senden
-
- Modi
-
- BCD = #122#97; Ausgabe im ASCII-BCD-Format
-
- POINT = #66; Point-Mode einschalten
- STREAM = #64; Stream-Mode einschalten
- SWSTREAM = #65; Switch-Stream-Mode einschalten
-
- Report-Rate
-
- RR110 = #81; Report-Rate 110 rps (reports per
- second)
- RR50 = #82; Report-Rate 50 rps
- RR10 = #83; Report-Rate 10 rps
- RR2 = #84; Report-Rate 2 rps
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 229 -
-
-
-
-
-
-
- Auflösung
-
- Res1 = #108 Auflösung 1 lpi (lines per inch)
- Res2 = #110; Auflösung 2 lpi
- Res4 = #112; Auflösung 12 lpi
- Res100 = #100; Auflösung 100 lpi
- Res200 = #101; Auflösung 200 lpi
- Res400 = #103; Auflösung 400 lpi
- Res500 = #104; Auflösung 500 lpi
- Res1000 = #106; Auflösung 1000 lpi
-
- Koordinatensystem
-
- ABSOLUT = #70; absolutes Koordinatensystem
- RELATIV = #69; relatives Koordinatensystem
-
- Felder
-
- COMPort
- COMPort:byte;
- Nummer der seriellen Schnittstelle (1 = COM1, 2 = COM2).
-
- Buffer
- Buffer:string[20];
- Puffer zum Zwischenspeichern der Koordinaten
-
- DigiData
- DigiData:tDigiData;
- Enthält die Koordinaten und die Nummer der gedrückten Lupen-
- Taste.
-
- Methoden
-
- Init
- procedure Init(SPort:byte);
- Initialisierung des grafischen Tabletts. Übergabeparameter
- ist die Nummer der seriellen Schnittstelle.
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 230 -
-
-
-
-
-
-
-
- SetCommand
- procedure SetCommand(cc:string);
- Kommando oder Kommandofolge senden.
-
- SetStreamMode
- procedure SetStreamMode;
- Stream-Mode setzen. Auflösung 50 lpi.
-
- SetPointMode
- procedure SetPointMode;
- Point-Mode setzen. Koordinaten werden immer nur dann über-
- tragen, wenn eine der Lupentasten oder der Stift gedrückt
- wurde.
-
- SetSwitchStream;
- procedure SetSwitchStream;
- Switch-Sream-Mode setzen. Kontinuierliches Senden von Koor-
- dinaten, wenn eine Lupentaste oder der Stift gedrückt ist.
-
- SetResolution
- procedure SetResolution(cc:char);
- Auflösung des Tabletts festlegen. Bitte verwenden Sie nur
- die in der Unit WDecl vordefinierten Konstanten (Res1 ...).
-
- SetReportRate
- procedure SetReportRate(cc:char);
- Einstellen der Reportrate des Tabletts. Verwenden Sie als
- Übergabeparameter bitte die in der Unit WDecl vordefinierten
- Konstanten (RR110 ...).
-
- SetFrameWork
- procedure SetFrameWork(cc:char);
- Festlegen des Koordinatensystems. Für cc können die
- Konstanten ABSOLUT und RELATIV verwendet werden.
-
- GetModelIdentifier
- function GetModelIdentifier:string;
- Übertragung des Modell-Identifikationsstrings veranlassen.
-
-
-
-
- Programmierhandbuch WG-Vision - 231 -
-
-
-
-
-
-
-
- DigiHandle
- procedure DigiHandle;
- Digitizer-Handler. Diese Routine muß in eine Handler-Schlei-
- fe eingebunden werden. Der Handler übernimmt kontinuierlich
- Daten vom Digitizer in seinen Puffer und bestimmt daraus die
- Koordinaten und den Tastenstatus.
-
- GetXValue
- function GetXValue:word;
- Übergibt den x-Wert der Lupenposition.
-
- GetYValue
- function GetYValue:word;
- Übergibt den y-Wert der Lupenposition.
-
- GetTaste
- function GetTaste:byte;
- Übergibt die Nummer der gedrückten Taste.
-
- Beispiel
-
- program DigiTest;
- uses WDecl,
- WDriver;
- var Digi:TSSDigiDevice;
- begin
- with Digi do
- begin
- Init(2);
- SetStreamMode;
- repeat
- DigiHandle;
- write(GetXValue:10);
- writeln(GetYValue:10);
- until GetTaste=2;
- end;
- end.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 232 -
-
-
-
-
-
-
-
- 6.2. UNIT WTEXT.PAS
-
- Die Unit WText gehört mit zu den Kernroutinen von WG-Vision,
- obwohl sie nur ein Objekt (TText) und drei Routinen zur Aus-
- gabe der VGA-Sonderzeichensätze beinhaltet.
-
- 6.2.1. Standard-VGA: Sonderzeichensätze
-
- Die Sonderzeichensätze, die als Objekt-Dateien in die Unit
- eingebunden sind, können nur in den 16-farbigen VGA-Modi
- verwendet werden. Folgende Zeichensätze sind verfügbar:
-
- type GraficFont=(Thin8,Thin14,Thin16,Brdwy19,Wndw19,Sansf19,VGAF);
-
- VGAF ist der Standardzeichensatz der Unit Graph, die gewöhn-
- lich in Verbindung mit OutTextXY verwendet wird. Die Zei-
- chenbreite der Sonderfonts beträgt 8 Pixel, die Höhe ist der
- Zahl zu entnehmen, die Bestandteil des Fontnamens ist.
- Zur Arbeit mit den Sonderzeichensätzen stehen folgende Pro-
- zeduren zur Verfügung:
-
- SetFont
- procedure SetFont(NewFont:GraficFont);
- Aktivieren eines Sonderzeichensatzes vom Typ GraficFont.
-
- WriteText
- procedure WriteText(x,y:integer;st:string);
- Entspricht OutTextXY, verwendet aber den aktivierten Sonder-
- zeichensatz.
-
- SetFontColor
- procedure SetFontColor(bg,vg:byte);
- Legt die Hintergrund- und Vordergrundfarbe des Sonderzei-
- chensatzes fest.
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 233 -
-
-
-
-
-
-
-
- Um die Geschwindigkeit der Textausgabe zu erhöhen, wurde ein
- Teil der Routine WriteText in BASM formuliert.
- Die Horizontale Positionierung des mit WriteText ausgegebe-
- nen Strings ist nur an den Scan-Lines (d.h. alle 8 Pixel)
- möglich.
-
- Objekt TText
-
- Felder
-
- R
- R:TRect;
- Rechteckiger Bereich, der den Viewport bestimmt, in das der
- Text geschrieben wird. Die Bereichsgrenzen sind gleichzeitig
- die Clip-Grenzen.
-
- Font
- Font:word;
- Aktiver Vektorzeichensatz. Die Nummern entsprechen den in
- der Unit WDecl vorgegebenen Konstanten.
-
- Direction
- Direction:word;
- Ausrichtung des Textes. Folgende Werte sind möglich: Horiz-
- Dir, VertDir
-
- CharSize
- CharSize:byte;
- Buchstabengröße entsprechend der Konventionen der Unit
- Graph.
-
- TextHeight
- TextHeight:word;
- Texthöhe entsprechend der Konventionen der Unit Graph.
-
- TextWidth
- TextWidth:word;
- Textbreite entsprechend der Konventionen der Unit Graph.
-
-
-
-
- Programmierhandbuch WG-Vision - 234 -
-
-
-
-
-
-
-
- Zeile
- Zeile:string;
- Auszugebender Text.
-
- Methoden
-
- Init
- constructor Init;
- Setzt R auf den gesamten Bildschirm, aktiviuert den Stan-
- dardzeichensatz und setzt die Textkonstanten auf die Stan-
- dardwerte.
-
- Done
- destructor Done;
- Leere Methode. (Hier müßte eigentlich der zuletzt geladene
- Vektorzeichensatz aus dem Speicher geschmissen werden. Wer
- hat dazu eine Idee ?)
-
- SetFont
- procedure SetFont(FFont,FDirection:word);
- Vektorzeichensatz und Ausgaberichtung festlegen.
-
- SetCharSize
- procedure SetCharSize(FCharSize:byte);
- Buchstabengröße festlegen.
-
- SetClipFrame
- procedure SetClipFrame(T:TRect);
- Bereich festlegen, in welcher geschrieben werden darf. Die
- Bereichsgrenzen dienen als Clip-Grenzen.
-
- SetDefaultText;
- procedure SetDefaultText;
- Aktiviert den Standardzeichensatz.
-
- LText
- procedure LText(x,y:integer;z:string);
- Linksbündige Ausgabe des Textes z an der Position x,y rela-
- tiv zum Clipfenster.
-
-
-
- Programmierhandbuch WG-Vision - 235 -
-
-
-
-
-
-
-
- RText
- procedure RText(x,y:integer;z:string);
- Rechtsbündige Ausgabe des Textes z an der Position x,y rela-
- tiv zum Clipfenster.
-
- CText
- procedure CText(x,y:integer;z:string);
- Zentrierte Ausgabe des Textes z an der Position x,y relativ
- zum Clipfenster.
-
- Instanzen des Objekts TText werden besonders in der Unit
- WDlg verwendet (Paneltext, statischer Text in Dialogfen-
- stern). Weitere Zeichensätze stellt die WG-Vision Zusatz-
- Unit WFONT zur Verfügung.
-
- Beispiel: Auflisten aller in WText implementierten
- Sonderzeichensätze
-
- program Sonderzeichensaetze;
-
- uses WDecl,
- WDriver,
- WText,
- crt,
- graph;
-
- begin
- Video.Init(VGA,M640x480);
- SetFont(Brdwy19);
- SetFontColor(Black,Yellow);
- WriteText(10,50,'Sonderzeichensätze der Unit WText');
- SetFontColor(Black, White);
- SetFont(Thin8);
- WriteText(10,100,'Thin8 ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ
- abcdefghijklmnopqrstuvwxyzäöü0123456789');
-
-
- SetFont(Thin14);
-
-
-
-
- Programmierhandbuch WG-Vision - 236 -
-
-
-
-
-
-
-
- WriteText(10,125,'Thin14 ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ
- abcdefghijklmnopqrstuvwxyzäöü0123456789');
- SetFont(Thin16);
- WriteText(10,150,'Thin16 ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ
- abcdefghijklmnopqrstuvwxyzäöü0123456789');
- SetFont(Wndw19);
- WriteText(10,175,'Wndw19 ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ
- abcdefghijklmnopqrstuvwxyzäöü0123456789');
- SetFont(Sans19);
- WriteText(10,200,'Sans19 ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ
- abcdefghijklmnopqrstuvwxyzäöü0123456789');
- SetFont(Brdwy19);
- WriteText(10,225,'Brdwy19 ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ
- abcdefghijklmnopqrstuvwxyzäöü0123456789');
- SetFont(VGAF);
- WriteText(10,255,'VGAF ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÜ
- abcdefghijklmnopqrstuvwxyzäöü0123456789');
- repeat until keypressed;
- Video.Done;
- end.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 237 -
-
-
-
-
-
-
-
- 6.3. UNIT WFONT.PAS
-
- Die Verwendung von BGI-Vektorzeichensätzen und von VGA-ROM-
- Zeichensätzen, Erstellung von eigenen Zeichensatz-Ressourcen
- mit dem Shareware-Programm FontMania von REXXCOM-Systems
-
- 6.3.1. ROM- und Userzeichensätze in WG-Vision - TPixelFont
-
- Die Anzahl der Pixelzeichensätze, die ein geschickter Turbo-
- Pascal-Programmierer seiner VGA-Karte entlocken kann, ist
- nicht gerade überwältigend. Dabei bietet das BIOS der VGA-
- Karte alle Möglichkeiten, um in Verbindung mit einem VGA-
- Zeichensatzeditor die schönsten Fonts auf dem Bildschirm zu
- zaubern.
- Derartige Zeichensatzeditoren findet man in vielen Shareware-
- und Public Domain-Sammlungen. Das Programm FontMania der
- amerikanischen Firma REXXCOM-Systems ist für diesen Zweck
- besonders gut geeignet. Es besitzt die interessante Eigen-
- schaft, daß mit diesem Programm erzeugte Fonts in Form von
- Pascal-Includedateien abge-legt werden können. Aus diesen In-
- clude-Dateien lassen sich leicht allgemein nutzbare "Font-
- Ressourcen" erstellen, aus denen man zur Laufzeit eines Pro-
- gramms Zeichensätze laden und über den Interrupt $11 den
- Textausgaberoutinen von Turbo-Pascal zugänglich machen kann.
-
- 6.3.2. FONTMANIA
-
- FontMania besticht durch seine vielfältigen Editiermöglich-
- keiten. So können Fonts verschiedener Größe erstellt oder
- bereits vorhandene Schriften geladen und nachträglich verän-
- dert werden. Der eigenen Kreativität sind hier kaum Grenzen
- gesetzt. Wer sich jedoch diese Arbeit ersparen will, braucht
- nur die Vollversion bestellen. Neben dem Programm erhält man
- zusätzlich einen Satz von 25 ausgesuchten Schriften. Aber
- auch die Assembler- und C-Programmierer kommen nicht zu
- kurz. FontMania legt auf Wunsch die Fontdaten in Dateien ab,
- die Assembler- und C-Programme nutzen können. Das normale
- Ausgabeformat ist jedoch eine COM-Datei. Um im Alphamodus
- den Zeichensatz zu wechseln (wie wär's mal mit einem Kyril-
-
-
-
- Programmierhandbuch WG-Vision - 238 -
-
-
-
-
-
-
-
- lischen oder Hebräischen ?) brauchen Sie nur noch vom Sys-
- temprompt aus eine derartige COM-Datei zu starten. Bis auf
- Widerruf (mode co80) werden jetzt alle Textausgaben im neuen
- Zeichensatz ausgeführt. Sogar die meisten Programme zeigen
- sich nun mit den neuen Schriftzeichen. Starten Sie einfach
- innerhalb der Turbo-Pascal-IDE das Testprogramm zur
- Darstellung der Zeichensätze im Alphamodus. Da innerhalb
- dieses Programms der Destruktor nicht aufgerufen wird,
- erscheint nach Beendigung des Programms die Compiler-
- Oberfläche in einem neuen Zeichensatz.
-
- Aufbau
-
- Haben Sie einen neuen Font komplett erstellt (also alle 256
- Zeichen), dann können Sie über den Menüpunkt "Pascal" von
- FontMania eine Includedatei erzeugen. Diese Includedatei
- enthält als array of char die Pixeldaten der einzelnen
- Schriftzeichen und in der Variablen Points die Höhe der Zei-
- chen in Pixel. Im Deklarationsteil der Unit WFONT.PAS wird
- diese Struktur verallgemeinert:
-
- type FontType=record
- Name : string[10]; {Font-Name}
- Points : char; {Zeichenhöhe}
- Data : array[1..4096] of char; {Rasterdaten}
- end;
-
- Ist Points=$10, dann beschreibt FonType einen 8x16-Pixel-
- font. Data enthält die Rasterdaten für 256 Zeichen, so daß
- zur Kodierung eines Zeichens 16 Bytes benötigt werden. Der
- genauen Aufbau eines Zeichens wird im folgenden Abschnitt
- behandelt. Mit diesen Informationen können Sie dann selbst
- Zeichensätze auf kariertem Papier entwerfen und auf diese
- Weise ohne FontMania eigene VGA-Fontdateien erstellen (ich
- meine nur, wenn Sie nichts besseres zu tun haben ...).
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 239 -
-
-
-
-
-
-
-
- 6.3.3. Fonts-Ressourcen
-
- Fonts mit prinzipiell gleichem Aufbau sollten Sie in soge-
- nannten Fontressourcen speichern. Darunter versteht man un-
- typisierte Dateien, die aus Blöcken vom Typ FontType
- bestehen. Sie können beliebig viele Zeichensätze enthalten,
- die ein Anwendungsprogramm bei Bedarf nachladen kann.
- Der prinzipielle Aufbau eines Programms, welches aus FontMa-
- nia-Daten Fontressourcen erzeugen kann, zeigt Listing 1. Da-
- mit die Fontressource mit dem Objekt TPixelFont mitspielt,
- muß sie die Extension .FNT tragen.
- Die Rasterdaten kopieren Sie einfach innerhalb der IDE mit-
- tels der Blockbefehle aus den Include-Dateien in das Pro-
- gramm CreateFontFile. Anschließend löschen Sie alle unnützen
- Daten heraus und überprüfen die Klammerung. Nach fehlerfrei-
- er Kompilierung und Abarbeitung erhalten Sie die Fontdatei
- VGAFONT.FNT.
-
- 6.3.4. Objekt TPixelFont
-
- Die Methoden zum Zugriff auf VGA-ROM-Fonts und FontMania-Pixel-
- ressourcen sind in einem Objekt mit dem Namen TPixelFont verpackt:
-
- const Underline = 1; {Schriftattribute für ROM-Zeichensätze}
- Bold = 2;
- Small = 3;
-
- PPixelFont=^TPixelFont;
- TPixelFont=object(TObject)
- Font : FontType; {User-Zeichensatz}
- ROMFont : byte; {Funktionsnummer ROM-ZS}
- CharSize : byte; {Zeichenhöhe}
- constructor SetFont(f:string); {Zeichensatz installieren}
- destructor Done; virtual; {Rücksetzen auf 8x8}
- {Standardzeichensatz}
- function GetFontName:string; {Name des gerade aktiven}
- {Pixelfonts}
- procedure SetFontStyle(Style:byte);
- end;
-
-
-
- Programmierhandbuch WG-Vision - 240 -
-
-
-
-
-
-
-
- Mit dem Konstruktor SetFont können Sie eine Instanz von TPixel-
- font auf dem Heap anlegen. Für den String, den Sie dabei
- übergeben müssen, gelten folgende Konventionen:
-
- 1. ROM-Fonts
-
- Wenn Sie einen ROM-Font laden möchten, dann übergeben Sie
- einen der Bezeichner ROM8x8, ROM8x14 oder ROM8x16 als
- String. Die Rasterdaten für die Schriftsätze werden in die-
- sem Fall aus der entsprechenden Tabelle des VGA-BIOS ko-
- piert.
-
- 2. Font-Ressource
-
- Möchten Sie jedoch einen Zeichensatz aus einer Fontressource
- laden, dann übergeben Sie den Namen der Fontdatei mit
- vorangestellten Doppelkreuz und, mit einem Schrägstrich vom
- Dateinamen getrennt, die Nummer des Zeichensatzes (siehe
- Beispielprogramm).
-
- Der Destruktor Done schaltet wieder auf den 8x8 Standardzei-
- chensatz zurück. Mit der Funktion GetFontName erhalten Sie
- den Namen des gerade aktiven Zeichensatzes.
-
- Schriftattribute
-
- Durch Manipulation der ROM-Fonts im Speicher lassen sich
- leicht dünne, fette und unterstrichene Zeichensätze erzeu-
- gen. Sie brauchen dazu der Methode SetFontStyle nur die ent-
- sprechende typisierte Konstante (Underline, Bold, Small)
- übergeben. Auf diese Weise kommen Sie zu weiteren 9 Schrift-
- typen. In der in der Unit WFont implementierten Form lassen
- sich diese modifizierten Zeichensätze nur im Grafikmodus
- verwenden. Im Alphamode hat der Befehl SetFontStyle keine
- Auswirkungen.
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 241 -
-
-
-
-
-
-
-
- Grafikmodus
-
- Damit Sie die neuen Schriftarten auch im Grafikmodus nutzen
- können, sind ein paar Vorarbeiten notwendig. Neben der obli-
- gatorischen Unit Graph benötigen Sie die Unit CRT. Sie ist
- zwar in erster Linie für den Alphabildschirm konzipiert.
- Aber indem Sie die Variable DirectVideo auf false setzen,
- sind die wichtigsten Routinen von CRT wie z.B. write/wri-
- teln, gotoXY oder TextColor auch im Grafikmodus nutzbar.
- DirectVideo:=false erzwingt, daß sämtliche Textausgaben über
- das BIOS erfolgen.
- Daß das aber nicht völlig fehlerfrei vonstatten geht, merken
- Sie, wenn Sie im VGA-Standardmode ($12) mehr als 25 Zeilen
- schreiben möchten. Es kommt zu einem Scrolling mit der unan-
- genehmen Eigenschaft, daß jede neue Zeile mit der gerade ak-
- tiven Vordergrundfarbe gefüllt wird. Um Abhilfe zu schaffen
- gibt es einen einfachen, aber leider undokumentierten Trick.
- Sie setzen die in der Unit CRT vordefinierte Variable WindMax
- einfach auf $FFFF. und schon ist alles OK.
- Im Grafikmodus lassen sich Ausgaben mit verschiedenen Fonts
- mischen. Auf diese Weise ist echtes Wysiwyg ("what you see
- is what you get") möglich. Im Alphamodus bleibt Ihnen leider
- nichts anderes übrig, als mit immer nur einem Zeichensatz zu
- arbeiten. Ein Wechsel des Fonts hat Auswirkungen auf alle
- Ausgaben auf dem Bildschirm.
- In der Unit WFont wird mit einem kleinen Trick ausgetestet,
- ob sich der Rechner im Alpha- oder Grafikmodus befindet. Das
- ist notwendig, da in beiden Modi User-Zeichensätze unter-
- schiedlich aufgerufen werden. Die Prozedur GetMaxX ermittelt
- im Grafikmodus die maximal mögliche x-Koordinate des Bild-
- schirms. Ist jedoch ein Alphamode eingeschaltet, dann lie-
- fert diese Funktion Null.
-
- Beispiel-Listing 1
-
- Mit diesem Programm können Sie Fontressourcen erstellen. Die
- Rasterdaten für die einzelnen Schriften entnehmen Sie den
- Pascal-Include-Dateien, die Sie mit dem Zeichensatzeditor
- FontMania erzeugen (wenn Sie Lust haben, können Sie natür-
-
-
-
- Programmierhandbuch WG-Vision - 242 -
-
-
-
-
-
-
-
- lich auch Zeichensätze selbst kodieren. Oder, was noch bes-
- ser wäre, schreiben Sie mit WG-Vision selbst einen
- Fonteditor!).
-
- program CreateFontFile;
-
- type FontType=record
- Name : string[10]; {Font-Name}
- Points : char; {Zeichenhöhe}
- Data : array[1..4096] of char; {Rasterdaten}
- end;
-
- const VGAFont:array[1..4] of FontType= {4 Schriftarten}
- ((Name: 'JULIE';
- Points:#16;
- Data:( ---> hier stehen die aus der Include-Datei ent-
- nommenen Rasterdaten für 256 Zeichen der
- Schriftart JULIE ));
-
- (Name: 'POOTER';
- Points:#16;
- Data:( ---> hier stehen die aus der Include-Datei ent-
- nommenen Rasterdaten für 256 Zeichen der
- Schriftart POOTER ));
- ...
-
- var f:file;
- Font:FontType;
- i,Result:integer;
- begin
- assign(f,'VGAFONT.FNT');
- rewrite(f,SizeOf(Font));
- for i:=1 to 4 do BlockWrite(f, VGAFont[i],1,Result);
- close(f);
- end.
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 243 -
-
-
-
-
-
-
-
- Aufbau eines Eintrags in der Font-Ressource
-
- Codierung des Buchstabens "A"
-
- 8421 8421
-
- 0 .... .... 00
- 1 .... .... 00
- 2 .... .... 00
- 3 .... X... 08
- 4 .... X... 08
- 5 ...X .X.. 14
- 6 ...X .X.. 14
- 7 XXXX XXX. FE
- 8 ..X. ..X. 22
- 9 ..X. ..X. 22
- 10 .X.. ...X 41
- 11 -X.. ...X 41
- 12 .X.. ...X 41
- 13 .... .... 00
- 14 .... .... 00
- 15 .... .... 00
-
- Der neue Buchstabe "A" wird durch folgende Bytefolge
- codiert:
-
- $00,$00,$00,$08,$08,$14,$14,$FE,$22,$22,$41,$41,$41,$00,$00,$00
-
- 256 Zeichen ergeben demnach 4096 Byte (siehe Datenstruktur
- FontType). Die Zeichen müssen entsprechend der ASCII-Tabelle
- angeordnet sein.
- Wer bastelt mal einen ordentlichen Fonteditor (natürlich mit
- WG-Vision) zusammen ?
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 244 -
-
-
-
-
-
-
-
- Beispiel-Listing 2
-
- Ausschnitt aus der Unit WFONT.PAS von WG-Vision. Implementation der
- Objektklasse TPixelFont.
-
- UNIT WFont;
-
- INTERFACE
-
- uses dos,
- crt,
- graph;
-
- const Underline = 1; {Schriftattribute für ROM-Zeichensätze}
- Bold = 2;
- Small = 3;
-
- intern = 1; {Fehlerindex für Error}
-
- type FontType=record {Zeichensatzblock aus einer}
- Name : string[10]; {WG-Vision-Fontressource}
- Points : char;
- Data : array[1..4096] of char;
- end;
-
- tError =array[1..10] of integer; {Fehler-Code}
-
- PPixelFont=^TPixelFont;
- TPixelFont=object
- Font : FontType; {User-Zeichensatz}
- ROMFont : byte; {Funktionsnummer des ROM-ZS}
- CharSize : byte; {Zeichenhöhe}
- constructor SetFont(f:string); {Zeichensatz installieren}
- destructor Done; virtual; {Rücksetzen auf 8x8}
- {Standardzeichensatz}
- function GetFontName:string; {Name des gerade aktiven}
- {Pixelfonts}
- procedure SetFontStyle(Style:byte);
- end;
-
-
-
- Programmierhandbuch WG-Vision - 245 -
-
-
-
-
-
-
-
- var Error:tError;
-
- IMPLEMENTATION
-
- type CMatrix8 = array[0..7] of byte; {Zeichenmatrizen für ver-}
- CMatrix14= array[0..13] of byte; {schiedene Schriftgrößen}
- CMatrix16= array[0..15] of byte;
- FType8 = array[0..255] of CMatrix8;
- FType14 = array[0..255] of CMatrix14;
- FType16 = array[0..255] of CMatrix16;
-
- var reg:Registers;
-
- Font8 : array[1..3] of FType8; {Zeichensatztabellen für}
- Font14 : array[1..3] of FType14; {manipulierte ROM-Fonts}
- Font16 : array[1..3] of FType16;
-
- p : pointer;
- i,j : integer;
-
-
- {Implementation TPixelFont}
-
- Laden eines Pixelzeichensatzes aus einer Ressourcendatei (#Name/n) bzw
- aus dem VGA-ROM
-
- constructor TPixelFont.SetFont(f:string);
- var Nr:byte;
- s:string;
- err,Anzahl:integer;
- OK:word;
- dat:file;
- p:pointer;
- begin
- if f[1]='#' then
- begin
- delete(f,1,1);
- Nr:=Pos('/',f);
- s:=copy(f,Nr+1,length(f)-Nr);
-
-
-
- Programmierhandbuch WG-Vision - 246 -
-
-
-
-
-
-
-
- delete(f,Nr,(length(f)-Nr)+1);
- val(s,Nr,err);
- if err<>0 then Exit;
- f:=f+'.FNT'; {Extension anhängen}
- assign(dat,f);
- {$I-}
- reset(dat,SizeOf(Font));
- {$I+}
- if IOResult<>0 then
- begin
- Error[intern]:=IOResult;
- Exit;
- end;
- Anzahl:=FileSize(dat); {Anzahl Schriftarten in der Datei}
- if (Nr>0) and (Nr<=Anzahl) then
- begin
- seek(dat,Nr-1);
- BlockRead(dat,Font,1,OK);
- end;
- close(dat);
- if GetMaxX>0 then {im Grafikmodus ? --> Trick 0-8-15}
- with reg do {User-Zeichensatz Grafikmode aktivieren}
- begin
- ah:=$11;
- al:=$21;
- bl:=0;
- cx:=byte(Font.Points);
- dl:=43;
- es:=seg(Font.Data);
- bp:=ofs(Font.Data);
- intr($10,reg);
- end
- else
- with reg do
- begin {Alphamode}
- ah:=$11;
- al:=$10; {automatische Zeilenanpassung}
- bl:=0;
- bh:=byte(Font.Points);
-
-
-
- Programmierhandbuch WG-Vision - 247 -
-
-
-
-
-
-
-
- cx:=256;
- dx:=0;
- es:=seg(Font.Data);
- bp:=ofs(Font.Data);
- intr($10,reg);
- end;
- CharSize:=byte(Font.Points);
- ROMFont:=0;
- end
- else {ROM-Zeichensätze holen}
- begin
- ROMFont:=0;
- if f='ROM8x14' then
- begin
- ROMFont:=$22;
- CharSize:=14;
- end;
- if f='ROM8x8' then
- begin
- ROMFont:=$23;
- CharSize:=8;
- end;
- if f='ROM8x16' then
- begin
- ROMFont:=$24;
- CharSize:=16;
- end;
- with reg do {ROM-Zeichensätze aktivieren}
- begin
- ah:=$11;
- al:=ROMFont;
- bl:=0;
- dl:=43;
- intr($10,reg);
- end
- end;
- end;
-
-
-
-
-
- Programmierhandbuch WG-Vision - 248 -
-
-
-
-
-
-
-
- Lädt den 8x8 Standardzeichensatz
-
- destructor TPixelFont.Done;
- begin
- with reg do
- begin
- ah:=$11;
- al:=$23; {Unterfunktion zum Laden des 8x8 ROM-ZS}
- bl:=0;
- dl:=43;
- intr($10,reg);
- end;
- end;
-
- Ermittelt den Namen des gerade aktiven Fonts
-
- function TPixelFont.GetFontName:string;
- begin
- if ROMFont in [$22..$24] then
- begin
- case ROMFont of
- $22 : GetFontName:='ROM8x14';
- $23 : GetFontName:='ROM8x8';
- $24 : GetFontName:='ROM8x16';
- end;
- end
- else GetFontName:=Font.Name;
- end;
-
- Zusatzzeichensätze für unterstrichene, fette und schmale Zeichen. Die
- Ableitung erfolgt aus den ROM-Zeichensätzen.
-
- procedure TPixelFont.SetFontStyle(Style:byte);
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 249 -
-
-
-
-
-
-
-
- function FontAdr:pointer;
- begin
- if ROMFont in [$22..$24] then
- begin
- with reg do
- begin
- ah:=$11;
- al:=$30;
- case ROMFont of
- $22 : bh:=2;
- $23 : bh:=3;
- $24 : bh:=6;
- end; {case}
- intr($10,reg);
- FontAdr:=ptr(es,bp);
- end;
- end
- else FontAdr:=nil; {kein ROM-Font aktiv}
- end;
-
- procedure SetSpecialFont(var FTable);
- begin
- if GetMaxX>0 then
- with reg do {Spezial-Zeichensatz aktivieren}
- begin
- ah:=$11;
- al:=$21;
- bl:=0;
- cx:=CharSize;
- dl:=43;
- es:=seg(FTable);
- bp:=ofs(FTable);
- intr($10,reg);
- end;
- end;
-
- begin
- if ROMFont=0 then Exit;
- p:=FontAdr;
-
-
-
- Programmierhandbuch WG-Vision - 250 -
-
-
-
-
-
-
-
- case ROMFont of
- $22 : begin {8x14}
- for i:=1 to 3 do move(p^,Font14[i],CharSize*256);
- for i:=0 to 255 do
- begin
- Font14[1,i,CharSize-1]:=$FF;
- for j:=0 to CharSize-1 do
- begin
- Font14[2,i,j]:=Font14[2][i][j]
- or (Font14[2,i,j] shr 1);
- Font14[3,i,j]:=Font14[3,i,j] and (Font14[3,i,j] shr 1);
- end;
- end;
- SetSpecialFont(Font14[Style]);
- end;
- $23 : begin {8x8}
- for i:=1 to 3 do move(p^,Font8[i],CharSize*256);
- for i:=0 to 255 do
- begin
- Font8[1,i,CharSize-1]:=$FF; {Unterstreichen}
- for j:=0 to CharSize-1 do
- begin
- Font8[2,i,j]:=Font8[2,i,j] or (Font8[2,i,j] shr 1);
- Font8[3,i,j]:=Font8[3,i,j] and (Font8[3,i,j] shr 1);
- end;
- end;
- SetSpecialFont(Font8[Style]);
- end;
- $24 : begin {8x16}
- for i:=1 to 3 do move(p^,Font16[i],CharSize*256);
- for i:=0 to 255 do
- begin
- Font16[1,i,CharSize-1]:=$FF; {Unterstreichen}
- for j:=0 to CharSize-1 do
- begin
- Font16[2,i,j]:=Font16[2,i,j] or (Font16[2,i,j] shr 1);
- Font16[3,i,j]:=Font16[3,i,j] and (Font16[3,i,j] shr 1);
- end;
- end;
-
-
-
- Programmierhandbuch WG-Vision - 251 -
-
-
-
-
-
-
-
- SetSpecialFont(Font16[Style]);
- end;
- end; {case}
- end;
-
- END.
-
- Beispiel-Listing 3
-
- Dieses Programm demonstriert, wie Sie WFont im Grafikmodus
- einsetzen können
-
- Testprogramm zur Demonstration der Unit WFont im Grafikmodus
-
- program test;
-
- uses WFont,
- crt,
- graph;
-
- var FNT : PPixelFont;
- i,j,
- Driver,Modus : integer;
- ZSName,zz : string;
- kb : char;
- begin
- Driver:=VGA; Modus:=VGAHi;
- DirectVideo:=false; {Textausgabe über BIOS}
- WindMax:=$FFFF; {crt-Scrolling verhindern}
- InitGraph(Driver,Modus,'\bp\bgi'); {Grafik einschalten}
- TextColor(White);
- for j:=1 to 4 do
- begin
- gotoXY(1,4);
- str(j,zz);
- ZSName:='#VGAFONT/'+zz;
- new(FNT, SetFont(ZSName));
-
-
-
-
-
- Programmierhandbuch WG-Vision - 252 -
-
-
-
-
-
-
-
- for i:=31 to 255 do
- begin
- if (i-30) mod 80=0 then writeln;
- write(char(i));
- end;
- writeln; writeln;
- writeln('FontMania-Fonts im VGA-Grafikmodus');
- writeln(FNT^.GetFontName);
- writeln;
- kb:=ReadKey;
- ClearViewPort;
- end;
- new(FNT, SetFont('ROM8x8')); {ROM-Fonts modifizieren und}
- gotoXY(1,5); {darstellen}
- writeln('8x8 VGA-ROM-Font, normal');
- FNT^.SetFontStyle(Small);
- writeln('8x8 VGA-ROM-Font, schmal');
- FNT^.SetFontStyle(Bold);
- writeln('8x8 VGA-ROM-Font, fett');
- FNT^.SetFontStyle(UnderLine);
- writeln('8x8 VGA-ROM-Font, unterstrichen');
- kb:=ReadKey;
- new(FNT, SetFont('ROM8x14'));
- gotoXY(1,8); TextColor(LightRed);
- writeln('8x14 VGA-ROM-Font, normal');
- FNT^.SetFontStyle(Small);
- writeln('8x14 VGA-ROM-Font, schmal');
- FNT^.SetFontStyle(Bold);
- writeln('8x14 VGA-ROM-Font, fett');
- FNT^.SetFontStyle(UnderLine);
- writeln('8x14 VGA-ROM-Font, unterstrichen');
- kb:=ReadKey;
- new(FNT, SetFont('ROM8x16'));
- gotoXY(1,12); TextColor(LightCyan);
- writeln('8x16 VGA-ROM-Font, normal');
- FNT^.SetFontStyle(Small);
- writeln('8x16 VGA-ROM-Font, schmal');
- FNT^.SetFontStyle(Bold);
- writeln('8x16 VGA-ROM-Font, fett');
-
-
-
- Programmierhandbuch WG-Vision - 253 -
-
-
-
-
-
-
-
- FNT^.SetFontStyle(UnderLine);
- writeln('8x16 VGA-ROM-Font, unterstrichen');
- FNT^.Done;
- kb:=ReadKey;
- CloseGraph;
- end.
-
- Beispiel-Listing 4
-
- Userzeichensätze im Alphamodus
- Testprogramm zur Demonstration der Unit WFont im Alphamodus
-
- program AlphaTest;
- uses WFont,
- crt;
-
- var FNT : PPixelFont;
- i,j : integer;
- ZSName,zz : string;
- kb : char;
- begin
- TextColor(White);
- for j:=1 to 4 do
- begin
- gotoXY(1,4); str(j,zz);
- ZSName:='#VGAFONT/'+zz;
- new(FNT, SetFont(ZSName));
- for i:=31 to 255 do
- begin
- if (i-30) mod 80=0 then writeln;
- write(char(i));
- end;
- writeln; writeln;
- writeln('FontMania-Fonts im VGA-Alphamodus');
- writeln(FNT^.GetFontName);
- writeln;
- kb:=ReadKey;
- end;
- end.
-
-
-
- Programmierhandbuch WG-Vision - 254 -
-
-
-
-
-
-
-
- Objekt TPixelFont
-
- Felder
-
- Font
- Font:FontType;
- User-Zeichensatz. FontType ist folgendermaßen deklariert:
-
- type FontType=record
- Name : string[10]; {WG-Vision Fontressource}
- Points : char;
- Data : array[1..4096] of char;
- end;
-
- ROMFont
- ROMFont:byte;
- Funktions-Nummer des ROM-Zeichensatzes
-
- CharSize
- CharSize:byte;
- Zeichenhöhe in Pixel.
-
- Methoden
-
- SetFont
- constructor SetFont(f:string);
- Laden eines Pixelzeichensatzes.
-
- ROM-Zeichensätze : ROM8x8
- ROM8x14
- ROM8x16
-
- Ressource : #Name/n Name Dateiname der
- Fontressource ohne Extension,
- n Nr. des Zeichensatzes
-
- Fontressourcen müssen die Extension FNT besitzen !
-
-
-
-
-
- Programmierhandbuch WG-Vision - 255 -
-
-
-
-
-
-
-
- Done
- destructor Done; virtual;
- Lädt den 8x8 Standardzeichensatz
-
- GetFontName
- function GetFontName:string;
- Ermittelt den Namen des gerade aktiven Pixelfonts und
- übergibt ihn als String.
-
- SetFontStyle
- procedure SetFontStyle(Style:byte);
- Aktiviert die Zusatzzeichensätze für unterstrichene, fette
- und schmale Zeichen. Die Ableitung erfolgt aus den ROM-
- Zeichensätzen. User-Zeichensätze werden nicht unterstützt.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 256 -
-
-
-
-
-
-
-
- 6.3.5. Verwendung der Vektorzeichensätze - TVectorFont
-
- Das Objekt TVectorFont ist sehr einfach. Es besitzt aber die
- angenehme Eigenschaft, daß alle Vektorfonts normiert sind.
- Damit ist eine quasi stufenlose Skalierung der Font-Größe
- einheitlich für alle verfügbaren Fonts möglich.
-
- 6.3.5.1. Skalierung der BGI-Vektorzeichensätze
-
- Vielen Programmierern ist es schon unangenehm aufgefallen,
- daß trotz gleicher Parameterangabe in SetTextStyle die ein-
- zelnen Vektorfonts unterschiedlich groß auf dem Grafikbild-
- schirm dargestellt werden. Dieses Verhalten macht es
- schwierig, Texte eine bestimmte Größe (z.B. 25 Pixel hoch)
- zuzuweisen.
- Oftmals hilft dabei nur Probieren. Das in der Unit WFONT.PAS
- implementierte Objekt TVectorFont erlaubt es, alle Vektor-
- zeichensätzen mit Hilfe der Methode SetCharSize einheitlich
- zu skalieren. Ein Wert von z=1 und n=1 bewirkt, daß ein
- Textstring unabhängig vom aktivierten Vektorzeichensatz mit
- einer Höhe von 30 Pixeln ausgegeben wird. Die Variablen z
- und n sind als Zähler und Nenner eines Bruchs aufzufassen.
- Ist beispielsweise n=2, dann wird der Text nur halb so groß,
- also 15 Pixel hoch, dargestellt.
- Indem man den Skalierungsfaktor in einen gemeinen Bruch um-
- wandelt, kann die Zeichensatzhöhe auf jede gewünschte Größe
- gebracht werden.
-
- Felder
-
- Font
- Font:word;
- Nummer des aktiven Vektorfonts. Folgende Konstanten sind
- möglich (definiert in der Unit WDecl):
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 257 -
-
-
-
-
-
-
-
- DefaultFont = 0 Pixel-Zeichensatz, entspricht ROM8x8
- oder ROM8x16
- TriplexFont = 1
- SmallFont = 2
- SansSerifFont = 3
- GothicFont = 4
- ScriptFont = 5
- SimpleFont = 6
- TSCRFont = 7
- LCOMFont = 8
- EuroFont = 9
- BoldFont =10
-
- Direction
- Direction:word;
- Ausgaberichtung der Textzeile. Es sind die Werte HorizDir
- und VertDir möglich.
-
- CharSize
- CharSize:TPoint;
- Charsize enthält die Buchstabengröße, beschrieben durch n
- und z (CharSize.x:=n; CharSize.y:=z;)
-
- Methoden
-
- SetVectorFont
- constructor SetVectorFont(f:word);
- Vektorzeichensatz aktivieren. Bitte verwenden Sie für f die
- in der Unit WDecl vordefinierten Bezeichner.
-
- Done
- destructor Done; virtual;
- Rücksetzen auf den Defaultfont. Ausrichtung horizontal.
-
- SetCharSize
- procedure SetCharSize(z,n:word);
- Setzt die Größe eines Vektorfonts. Die Korrekturfaktoren
- innerhalb dieser Methode wurden so gewählt, daß ein Aufruf
- von n=1 und z=1 eine Texthöhe von 30 Pixeln ergibt.
-
-
-
- Programmierhandbuch WG-Vision - 258 -
-
-
-
-
-
-
-
- SetDirection
- procedure SetDirection(Dir:word);
- Legt die Ausgaberichtung einer Zeichenkette fest (HorizDir
- oder VertDir), die mit OutTextXY oder OutText ausgegeben
- wird.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 259 -
-
-
-
-
-
-
-
- 6.4. Unit WEMS - Die Verwaltung des Expanded Memory
-
- Die Unit WEMS ist nicht objektorientiert programmiert. Sie
- stellt lediglich Verwaltungs- und Zugriffsroutinen für den
- Expansionsspeicher zur Verfügung. Diese Routinen benutzt WG-
- Vision beispielsweise, um den Untergrund von Fensterobjekten
- in den EMS zu laden bzw. von dort wieder zu holen. Sie kön-
- nen diese Routinen in ihr eigenes Programm einbauen, um bei-
- spielsweise Daten im EMS unterzubringen. Wenn Sie mit
- Borland Pascal arbeiten, müssen Sie während der Entwick-
- lungsphase darauf achten, daß der DPMI-Server nicht den ge-
- samten verfügbaren Erweiterungs- und Expansionsspeicher
- belegt. Mit der Umgebungsvariablen DPMIMEM können Sie BP7
- anweisen, eine bestimmte Menge von Speicher freizuhalten.
- Sie müssen dazu lediglich die Zeilen
-
- SET DPMIMEM=MAXMEM nnnn
-
- in die AUTOEXEC.BAT einfügen. nnnn bezeichnet die maximale
- Größe des Speichers in KByte, die der DPMI-Server benutzen
- darf.
- Wenn Sie innerhalb eines WG-Vision-Programms mit Expanded
- Memory hantieren, sollten Sie in der Entwicklungsphase immer
- den EMS-Wächter aktivieren. Er zeigt permanent den noch ver-
- fügbaren Speicher und die Anzahl der noch verfügbaren Spei-
- cherseiten an. Auf diese Weise können Sie leicht erkennen,
- ob Sie den nicht mehr benötigten Expansionsspeicher auch
- ordentlich deallokiert haben. Ansonsten wird der Griff zum
- Reset-Schalter zu einem nicht sehr angenehmen Sport.
- In der Regel ist Expansionsspeicher nur in Maschinen mit ei-
- nem 386/486-Prozessor verfügbar. Wenn Sie solch eine Maschi-
- ne besitzen (und das sollten Sie, wenn Sie mit WG-Vision
- programmieren), dann installieren Sie vor der Verwendung der
- WEMS-Unit einen entsprechenden Gerätetreiber. Eine Anleitung
- dazu finden Sie in den Handbüchern Ihres Betriebssystems.
- WG-Vision testet in der Initialisierungsphase automatisch,
- ob ein EMS-Treiber installiert ist und setzt entsprechend
- die logische Variable EMS_Installed.
-
-
-
-
- Programmierhandbuch WG-Vision - 260 -
-
-
-
-
-
-
-
- WEMS unterstützt nur die Funktionen, die in der EMS-Spezifi-
- kation nach LIM 3.2 enthalten sind.
-
- 6.4.1. Ein paar Worte zur Funktionsweise
-
- In diesem Handbuch kann nicht detailliert auf die Funktions-
- weise des Expansionsspeichers eingegangen werden. Wenn Sie
- mehr darüber wissen möchten, dann empfehle ich Ihnen das
- Buch "Speicherverwaltung unter DOS" von Mario Bez, erschie-
- nen im te-wi Verlag. Darin finden Sie sehr detailliert alles
- Wissenswerte über Extended und Expanded Memory sowie eine
- ausführliche Referez aller EMS-Funktionen.
- Der gesamte als Expanded Memory zu nutzende Speicher wird in
- Stücke von 16 KByte Größe aufgeteilt. Diese Stücke werden
- als logische Seiten (logical pages) bezeichnet. Soll auf die
- darin enthaltenen Daten zugegriffen werden, dann werden sie
- vom EMS-Treiber in ein 64 KByte großes Fenster, welches ir-
- gendwo zwischen 640 KByte und 1024 KByte innerhalb des
- Adressbereiches von DOS im Hauptspeicher liegt, eingeblen-
- det. Diese "Page-Frame" besteht selbst aus 4 physikalischen
- Seiten (physical pages), auf die die CPU im Unterschied zu
- den logischen Seiten sofort zugreifen kann.
- Es wird also durch das Umschalten entschieden, welche Spei-
- cherbereiche (und ihre Inhalte) für die CPU zugänglich sind.
- Das Umschalten erfolgt durch ein "bank-switching", d.h. es
- wird zwischen den einzelnen Speicherbänken hin- und herge-
- schaltet.
-
- Globale Variablen
-
- EMS_Installed
- EMS_Installed:boolean;
- Wird auf true gesetzt, wenn bei der Initialisierung der Unit
- ein aktiver EMS-Treiber entdeckt wird.
-
- EMM_Version
- EMM_Version:string[3];
- Enthält nach der Initialisierung die EMS-Versionsnummer.
-
-
-
-
- Programmierhandbuch WG-Vision - 261 -
-
-
-
-
-
-
-
- Error
- Error:word;
- Enthält die Nummer des zuletzt aufgetretenen Fehlers.
-
- PageFrame
- PageFrame:word;
- Segmentadresse des Pageframe.
-
- Pages
- Pages:array[0..3] of word;
- Enthält die Segmentadressen der physikalischen Seiten.
-
- Prozeduren und Funktionen
-
- HexString
- function HexString(Number:word):string;
- Wandelt die Zahl Number in einen Hexstring um.
-
- GetUnallocatedPages
- function GetUnallocatedPages:word;
- Bestimmt die Gesamtzahl möglicher EMS-Seiten.
-
- GetFreePages
- function GetFreePages:word;
- Übergibt die Anzahl der noch freien EMS-Seiten.
-
- GetPageFrameAddress
- function GetPageFrameAddress:word;
- Diese Funktion liefert die Segmentadresse des Anfangs vom
- 64-KByte-Fenster des EMS-Bereichs (PageFrame).
-
- MapPages
- procedure MapPages(NumberPages,P1,P2,P3,P4:word;
- var Handle:word);
- Reserviert die in NumberPages angegebene Anzahl von EMS-Sei-
- ten und weist ihnen ein eindeutiges Handle zu. In P1 bis P4
- sind die Nummern der logischen Seiten einzutragen, welche
- auf die physikalischen Seiten abgebildet werden sollen. Lo-
- gische Seiten werden von Null an durchnumeriert. Die logi-
-
-
-
- Programmierhandbuch WG-Vision - 262 -
-
-
-
-
-
-
-
- sche Seite muß sich im Bereich von Null bis (NumberPages-1)
- befinden. Mit einem Aufruf von MapPages können maximal 64
- KByte allokiert werden.
-
- ReMapPages
- procedure ReMapPages(P1,P2,P3,P4:word;var Handle:word);
- Diese Prozedur bildet die logischen Seiten P1 .. P4, die zum
- Handle gehören, auf das Pageframe ab.
-
- AllocatePages
- function AllocatePages(NumberPages:word):word;
- Allokiert die Anzahl der in NumberPages angegebenen Seiten
- und übergibt ein eindeutiges Handle.
-
- DeAllocatePages
- procedure DeAllocatePages(Handle:word);
- Diese Prozedur gibt die aktuell an einen Handle gebundenen
- Seiten wieder frei.
-
- MapHandlePages
- procedure MapHandlePages(Handle:word;PhysicalPage,
- LogicalPage:byte);
- Bildet die zum Handle gehörende logische Seite LogicalPage
- auf die physikalische Seite PhysicalPage ab.
-
- GetHandleCount
- function GetHandleCount:word;
- Diese Funktion liefert die Anzahl der im System gerade akti-
- ven EMM-Handles zurück.
-
- GetHandlePages
- function GetHandlePages(var Handle:word):word;
- Diese Funktion liefert die Anzahl der Seiten, die für den
- angegebenen EMM-Handle reserviert wurden.
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 263 -
-
-
-
-
-
-
-
- Komplexbeispiel Text im EMS speichern
-
- Die Verwendung von Expansionsspeicher in eigenen Programmen
- ist nicht sonderlich schwierig, aber etwas gewöhnungsbedürf-
- tig. Im folgenden Beispiel möchte ich Ihnen zeigen, wie man
- unser Listprogramm veranlassen kann, die Quelltexte anstatt
- in den Heap in den Expansionsspeicher auszulagern. Zum Auf-
- listen verwenden wir ein Scrollfenster, dessen Scroller al-
- lein für die Verwaltung der Daten, die im Fenster
- aufgelistet werden sollen, verantwortlich ist. In allen un-
- seren Beispielen haben wir die Daten in eine doppelt verket-
- teten Liste eingelesen, die TLine-Objekte aufnehmen kann und
- bereits vom TScroller zur Verfügung gestellt wird (Liste).
- Die Kapazität dieser Liste hängt entscheidend von der Größe
- des zur Laufzeit noch vorhandenen Heaps ab. Das Listen gro-
- ßer Quelltexte ist ohne das Heraufbeschwören eines Heap-Feh-
- lers kaum möglich.
- Jetzt soll das TScroller-Objekt so umgestaltet werden, daß
- die Daten im Expanded Memory gespeichert und auch von dort
- wieder gelesen werden können.
- Zur Vereinfachung verwenden wir jetzt ein einfaches Array,
- welches 3072 Programmzeilen mit einer Maximallänge von
- jeweils 128 Byte aufnehmen kann. 3072 Strings deshalb, weil
- zu ihrer Speicherung genau 3072*128/16384=24 logische Seiten
- benötigt werden. Eine logische Seite faßt genau 16 KByte.
- Da eine Zeile Turbo-Pascal-Quelltext 128 Bytes enthalten
- kann, definieren wir folgenden neuen Datentyp und einen Zei-
- ger darauf:
-
- type str128=string[128]; {String mit einer Länge von 128 Zeichen}
- pStr=^str128; {String-Pointer}
-
- Die Pointerliste wird Bestandteil des neuen TScroller-
- Objekts genauso wie das Handle, welches wir für den Zugriff
- auf den Expanded Memory benötigen:
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 264 -
-
-
-
-
-
-
-
- type TNewScroller=object(TScroller)
- EMSHandle:word;
- Eintrag:array[1..3072] of pStr;
- destructor Done; virtual;
- procedure CreateData;
- procedure ScrollDraw; virtual;
- end;
-
- Den Destruktor müssen wir auf jeden Fall überschreiben,
- damit wir am Ende beim Schließen des Scrollfensters auch
- alle dem Handle zugeordneten Seiten wieder freigeben. Nicht
- wieder freigegebene Seiten sind quasi verloren ! Sie können
- nicht wieder neu belegt werden. Damit dieser Fehler niemals
- auftreten kann, sollten Sie die Anzeige des Heapwächters im
- Auge behalten.
-
- destructor TNewScroller.Done;
- begin
- DeAllocatePages(EMSHandle);
- TScroller.Done;
- end;
-
- In der Methode CreateData werden die Zeilen der Textdatei in
- das Array und damit in den EMS geschrieben:
-
- procedure TNewScroller.CreateData;
- var dat:text;
- i,k,S,AnzPages:word;
- zz:string[120];
- z:string[4];
- begin
- SetFont(Wndw19);
- k:=1; S:=0;
- assign(dat,Event.InfoString);
- reset(dat);
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 265 -
-
-
-
-
-
-
-
- Als Erstes schauen wir nach, ob überhaupt 24 logische Seiten verfügbar
- sind. Wenn nicht, dann sollte entweder der Heap genutzt oder eine
- Fehlerbehandlung realisiert werden.
-
- AnzPages:=GetFreePages;
- if AnzPages<=24 then
- begin
-
- An dieser Stelle sollte die Fehlerbehandlung stehen.
-
- end
- else
- begin
-
- Wir allokieren 24 logische Seiten unter dem Handle "EMSHandle"
-
- EMSHandle:=AllocatePages(24);
-
- In diesem Beispiel verwenden wir nur die physikalische Seite Null zum
- Übertragen der Daten in den Expansionsspeicher. Die ersten 128
- Textzeilen werden in die logische Seite Null geschrieben.
-
- MapHandlePages(EMSHandle,0,0);
-
- Index-Schleife für das Daten-Array
-
- for i:=1 to 3072 do
- begin
-
- Immer wenn 128 Strings geschrieben wurden, muß eine neue logische Seite
- in das Pageframe eingeblendet werden.
-
- if i mod 128=0 then
- begin
- k:=1;
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 266 -
-
-
-
-
-
-
-
- Hier ordnen wir der physikalischen Seite Null die neue logische Seite
- mit der Nummer (i div 128) zu,
-
- MapHandlePages(EMSHandle,0,i div 128);
- end
-
- sonst erhöhen wir nur den "Zeilenzähler" innerhalb der Seite.
-
- else inc(k);
-
- Hier wird ein Pointer absolut im Pageframe, physikalische Seite Null,
- positioniert
-
- Eintrag[i]:=ptr(PageFrame,(k-1)*128);
-
- und dann mit "Daten" beladen.
-
- if (i<=3071) and (not EOF(dat)) then
- begin
- readln(dat,zz); {Zeilennummern dranbasteln}
- str(i:4,z);
- Eintrag[i]^:=z+' '+zz
- end
- else
-
- Ist das Ende der Textdatei erreicht oder das Array voll, dann
- verabschieden wir uns mit einer kleinen Mitteilung an uns selbst
- (SetLimit...) aus dieser Methode.
-
- begin
- SetLimit(65,i-1,8,16);
- close(dat);
- Exit; {Adios Amigos !}
- end;
- end;
- end;
- end;
-
-
-
-
-
- Programmierhandbuch WG-Vision - 267 -
-
-
-
-
-
-
-
- Der Scroller muß jetzt in Abhängigkeit der Lage der Rollbal-
- ken die im EMS abgelegten Strings wieder auf den Bildschirm
- zaubern. Zu diesem Zweck muß die gerade benötigte logische
- Seite wieder in das Pageframe eingeblendet werden. Wie das
- konkret geschieht, zeigt die Methode ScrollDraw:
-
- procedure TNewScroller.ScrollDraw;
- var i:integer;
- Max:word;
- LfdPtr:PGroup;
-
- function clip(p,n:byte;z:string):string;
- begin
- clip:=copy(z,p,n);
- end;
-
- {------}
-
- begin
- SetFontColor(White,Red);
-
- Wieviele Seiten hat EMSHandle allokiert ?
-
- Max:=GetHandlePages(EMSHandle);
- Mouse.HideMouse;
- with Border do
- begin
- SetFillStyle(SolidFill,GetPalColor(1));
- SetColor(GetPalColor(2));
-
- Das einzige Problem an dieser Stelle ist auszurechnen, in welcher
- logischer Seite sich der Eintrag mit dem Index i befindet. Wenn diese
- logische Seite ins Pageframe eingeblendet wird (konkret wieder in die
- physikalische Seite 0), sind die darin enthaltenen Daten sofort
- zugänglich.
-
- for i:=Delta.y to WDelta.y do
- begin
-
-
-
-
- Programmierhandbuch WG-Vision - 268 -
-
-
-
-
-
-
-
- Einblenden der zum Index i gehörenden logischen Seite (i div 128)
-
- MapHandlePages(EMSHandle,0,i div 128);
- Bar(A.x,A.y+(i-Delta.y)*Py+10,B.x,A.y+(i-Delta.y)*Py+10+Py);
-
- und auf den Bildschirm malen.
-
- WriteText(A.x+20,A.y+(i-Delta.y)*Py+10,clip(Delta.x,
- Spalten*8 div 8-5,Eintrag[i]^));
- end;
- if VertiScrollBar<>nil then
- for i:=(WDelta.y-Delta.y)+1 to Zeilen do
- Bar(A.x,A.y+i*Py+10,B.x,A.y+i*Py+10+Py);
- end;
- Mouse.ShowMouse;
- end;
-
- Wie Sie sehen, ist bei der Arbeit mit Expanded Memory etwas
- Überlegung und ein klein wenig Rechnen nötig. Wenn das Prin-
- zip aber erst einmal verstanden ist, dann kann man sich auch
- mit der Ablage komplizierterer Datenstrukturen (z.B. Records
- oder Listen) befassen.
- Im folgenden Beispiel gilt es einen rechteckigen Ausschnitt
- des Grafikbildschirms in den EMS zu schaufeln. In WG-Vision
- ist dafür das Objekt TEMS zuständig. Sie finden es in der
- Unit WViews.
- Die Implementation sieht folgendermaßen aus:
-
- type TEMS=object(TMemory)
- Version : byte; {EMS-Version}
- FreeMemory : LongInt; {freier EMS-Speicher}
- ...
-
- Handle : word; {EMS-Handle für den Ausschnitt}
- Part : word; {Speichert Höhe eines 16 KByte-Teils}
- {des Ausschnitts}
- constructor Init(Bounds:TRect);
- destructor Done; virtual;
-
-
-
-
- Programmierhandbuch WG-Vision - 269 -
-
-
-
-
-
-
-
- procedure Save; virtual;
- procedure Restore(P:TPoint); virtual;
- ...
-
- end;
- ...
-
- constructor TEMS.Init(Bounds:TRect);
- begin
- SetBounds(Bounds); {Größe des zu speichernden Bildschirmbereichs}
- FreeMemory:=GetFreePages*LONGINT(16384); {verfügbarer EMS-Speicher}
- {in Byte}
- ...
-
- end;
-
- destructor TEMS.Done;
- begin
- DeAllocatePages(Handle); {Alle zum Handle gehörenden Speicherseiten}
- {freigeben}
- end;
-
- procedure TEMS.Save;
- var Seiten:word;
- i:integer;
- S,ss:single;
- Buffer:pointer; {Pointer auf den Zwischenpuffer}
- EMSBuffer:pointer; {Pointer auf die physikalische Seite 0}
- {im FramePage}
- begin
- EMSBuffer:=Ptr(Pages[0],0);
-
- Anzahl der Bytes, die zur Speicherung des Ausschnitts notwendig sind.
- Mit ImageSize können maximal 64 KByte erfaßt werden. Ist der Bereich
- größer, dann wird für BSize Null übergeben.
-
- BSize:=ImageSize(0,0,Size.X,Size.Y);
-
-
-
-
-
- Programmierhandbuch WG-Vision - 270 -
-
-
-
-
-
-
-
- Speicherbedarf des Ausschnitts größer 64 KByte. Deshalb Handarbeit.
-
- if BSize=0 then
-
- Da der Speicher bei Super-VGA's in den 256-Farb-Modi anders ausschaut
- als bei der normalen VGA-Auflösung 640x480x16 muß BSize natürlich auch
- anders berechnet werden, nähmlich viel einfacher ...
-
- if SVGA then BSize:=LongInt(Size.X)*LongInt(Size.Y)+6
- else BSize:=(LongInt(Size.X)*LongInt(Size.Y)+6) div 2;
- {normale VGA}
-
- Wieviele Speicherseiten benötigen wir, um den Ausschnitt zu speichern ?
- (man beachte den kleinen "Trick")
-
- S:=BSize/16384; {zu allokierende Seiten}
- Seiten:=BSize div 16384;
- while Seiten<=S do inc(Seiten,2);
- ss:=Size.Y/Seiten;
-
- Unter Umständen müssen wir den Ausschnitt in horizontale Streifen der
- Höhe Part mit einem Inhalt <= 16 KByte aufteilen.
-
- Part:=Size.Y DIV Seiten;
- while Part<=ss do inc(Part);
-
- Wieviele Bytes faßt solch ein Streifen ?
-
- BSize:=ImageSize(0,0,Size.X,Part);
-
- Pufferspeicher im Heap zum Zwischenspeichern allokieren.
-
- GetMem(Buffer,BSize);
-
- Speicherseiten im EMS allokieren
-
- Handle:=AllocatePages(Seiten);
-
-
-
-
-
- Programmierhandbuch WG-Vision - 271 -
-
-
-
-
-
-
-
- "Streifen" in den EMS schreiben.
-
- for I:=0 to Seiten-1 DO
- begin
- MapHandlePages(Handle,0,I); {immer in Page 0 abbilden}
- GetImage(Origin.X,Origin.Y+I*Part,Origin.X+Size.X,Origin.Y+(I+1)
- *Part, Buffer^);
- Move(Buffer^,EMSBuffer^,BSize); {in das Pageframe, Seite Null,}
- {schieben}
- end;
- FreeMem(Buffer,BSize); {Pufferspeicher im Heap wieder freigeben}
- end;
-
- Das Lesen aus dem EMS ist besonders einfach, da wir uns die
- Streifenbreite gemerkt haben. Mit PutImage wird der Bildschirmausschnitt
- rekonstruiert.
-
- procedure TEMS.Restore(P:TPoint);
- var Buffer:Pointer;
- EMSBuffer:Pointer;
- Max,I:word;
- begin
- EMSBuffer:=Ptr(Pages[0],0);
- Max:=GetHandlePages(Handle); {Anzahl vom Handle belegter Seiten}
- GetMem(Buffer,BSize);
- for I:=0 to Max-1 do
- begin
- MapHandlePages(Handle,0,I);
- Move(EMSBuffer^,Buffer^,BSize);
- PutImage(P.X,P.Y+(I*Part),Buffer^,NormalPut); {Restaurieren}
- end;
- FreeMem(Buffer,BSize);
- Done; {Auf keinem Fall vergessen, sonst ist beizeiten der EMS alle}
- end;
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 272 -
-
-
-
-
-
-
-
- 6.5. Schwelgen in Farben - Die Unit WPalette.pas
-
- Die Ausführungen in diesem Abschnitt beziehen sich aus-
- schließlich auf die VESA Super-VGA-Modi mit 256 Farben. Alle
- Routinen befinden sich in der Unit WPalette.pas.
-
- WG-Vision arbeitet in den VESA-Modi mit 256 Farben, die aus
- einer Palette von insgesamt 262144 möglichen Farben ausge-
- wählt werden können. Zur Beschreibung einer Farbe wird das
- RGB-Modell verwendet. Im RGB-Modell wird eine Farbe durch
- seine Rot (R) -, Grün (G) - und Blau (B) - Bestandteile be-
- schrieben. Jeder Farbbestanteil gibt gewissermaßen seine
- "Helligkeit" an, mit der er der Farbe beigemischt ist. Der
- Helligkeitswert kann nur innerhalb des Bereichs 0 bis 63 va-
- riiert werden.
- Um eine Farbpalette aus 256 Farben zu beschreiben, verwendet
- die Unit WPalette folgende Datenstruktur:
-
- type tRGB=record
- R,G,B:byte;
- end;
-
- tPalType=array[0..255] of tRGB;
-
- Zur Manipulation einzelner Farben bzw. der gesamten Farbpa-
- lette (bei vielen Methoden mit Ausschluß der ersten 16 Ein-
- tragungen, da sie für das Desktop verwendet werden) dient
- das Objekt TPalette:
-
- Felder
-
- F
- F:file;
- Palettendatei. In einer Palettendatei kann jeweils eine
- Farbpalette gespeichert werden.
-
- LUT
- LUT:tPalType;
- Look Up Table. Enthält die gerade aktive Farbpalette.
-
-
-
- Programmierhandbuch WG-Vision - 273 -
-
-
-
-
-
-
-
- CLUT
- CLUT:array[1..10] of tPalType;
- Dieses Array von LUT's kann maximal 10 verschiedene Farbpa-
- letten aufnehmen, die damit zur Laufzeit schnell zugänglich
- sind.
-
- Methoden
-
- SetPaletteColor
- procedure SetPaletteColor(Nr,Rot,Gruen,Blau:byte);
- Der Paletteneintrag mit der Nummer "Nr" wird mit den Farbbe-
- standteilen Rot, Gruen und Blau geladen (Wertebereich je-
- weils 0..63). Die Werte werden aus Geschwindigkeitsgründen
- sofort in die Ports der VGA-Karte geschrieben. Es kann in
- ungünstigen Fällen dabei zu "Schnee" auf dem Bildschirm kom-
- men, da die Retrace-Phase des Elektronenstrahls nicht abge-
- wartet wird (führt u.U. zu einem starken Geschwindigkeits-
- verlust beim Setzen vieler Farben).
-
- GetPaletteColor
- procedure GetPaletteColor(var Nr,Rot,Gruen,Blau:byte);
- Der Rot, Grün und Blau-Anteil des Paletteneintrags Nr wird
- ausgelesen und in den var -Variablen übergeben.
-
- GetPalette
- procedure GetPalette;
- Schreibt die gerade aktive Farbpalette in die Tabelle LUT.
-
- SetPalette
- procedure SetPalette;
- Übergibt die Werte in der Tabelle LUT an die VGA-Karte
- (schnelles Setzen einer Farbpalette).
-
- SetNewPalette
- procedure SetNewPalette(NLUT:tPalType);
- Setzen einer neuen, in NLUT gespeicherten Farbpalette.
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 274 -
-
-
-
-
-
-
-
- LoadPalette
- procedure LoadPalette(FName:PathStr);
- Eine in der Datei FName gespeicherte Farbpalette wird gela-
- den und aktiviert.
-
- SavePalette
- procedure SavePalette(FName:PathStr);
- Die in der Tabelle LUT enthaltenen Farbwerte werden in die
- Datei FName geschrieben.
-
- RotatePalette
- procedure RotatePalette(Typ,Direction:byte);
- Rotiert die gerade aktive Palette um jeweils einen Eintrag
- nach links (Direction=0) oder rechts (Direction=1). Die er-
- sten 16 Eintragungen bleiben unverändert. Der Typ legt fest,
- ob die Palette rotiert werden soll (im Sinne der letzte Ein-
- trag wird zum Ersten) oder ob der letzte bzw erste Eintrag
- ins "Nichts" verschoben wird.
-
- RotatePart
- procedure RotatePart(Direction,Von,Bis:byte);
- Der durch die Farbnummern "Von" und "Bis" begrenzte Palet-
- tenbereich wird in die Richtung Direction rotiert.
-
- SetVerlauf
- procedure SetVerlauf(Nr1,Rot1,Gruen1,Blau1,
- Nr2,Rot2,Gruen2,Blau2:byte);
- Erzeugt einen stufenlosen Farbverlauf zwischen den Farbnum-
- mern Nr1 und Nr2.
-
- TransFormRGBtoHSV
- procedure TransFormRGBtoHSV(R,G,B:byte;var H,S,V:real);
- Transformiert eine Farbe im RGB-Modell in die gleiche Farbe
- im HSV-Modell. H (Hue) stellt den Farbwinkel (0..360 Grad),
- S (Saturation) die Farbsättigung (0..1) und V (Value) den
- Helligkeitswert (0..1) dar.
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 275 -
-
-
-
-
-
-
-
- TransFormHSVtoRGB
- procedure TransformHSVtoRGB(H,S,V:real;var R,G,B:byte);
- Zerlegt eine Farbe im HSV-Modell in seine Farbbestandteile
- Rot, Grün und Blau.
-
- TransFormtoGrayScale
- procedure TransformtoGrayScale(Nr,Number:byte);
- Wandelt ab dem Registereintrag Nr eine bestimmte Anzahl von
- Farbregister (Number) in Graustufen um.
-
- StretchScale
- procedure StretchScale(Minimalwert,Maximalwert,
- Delta:byte;Positiv:boolean);
- Erzeugt eine lineare Graustufenpalette zwischen den Werten
- Minimalwert und Maximalwert. Ist Positiv=true, wird eine po-
- sitive, ansonsten eine negative Farbpalette (von Weiß nach
- Schwarz) erzeugt. Die ersten 16 Farbregister bleiben von der
- Manipulation ausgeschlossen.
-
- StretchPolynom
- procedure StretchPolynom(Minimalwert,Maximalwert:byte;
- Degree:real;Positiv:boolean);
- Funktionsweise wie StretchScale. Es wird jedoch eine Potenz-
- funktion vom Grad Degree als Display-Transferfunktion ver-
- wendet.
-
- StretchColor
- procedure StretchColor(Minimalwert,Maximalwert:integer);
- Berechnung eines linearen Farbübergangs (Spektrum) zwischen
- den Paletteneintragungen Minimalwert und Maximalwert.
-
- Isophote
- procedure Isophote(Delta,Brightness:byte;Positiv:boolean);
- Eine Isophote ist ein Bereich gleicher Helligkeit oder Far-
- be. Delta gibt die Breite dieses Bereiches und Brightness
- den Anfangswert der Helligkeit an (die Isophote erstreckt
- sich zwischen Brightness und Brightness+Delta). Im Positiv-
- Modus (Positiv=true) wird die Isophote Weiß auf schwarzem
- Untergrund dargestellt. Im Negativmodus genau umgekehrt.
-
-
-
- Programmierhandbuch WG-Vision - 276 -
-
-
-
-
-
-
-
- Aequidensiten
- procedure Aequidensiten(Delta,Abstand:byte;Positiv:boolean);
- Es wird eine Schar von Isophoten der Breite Delta und gege-
- benen Abstand berechnet.
-
- Komplexbeispiel: Völlig nutzloses Demonstrationsbeispiel für
- die Arbeit mit der Unit WPalette
-
- Das Programm PalTest.pas zeigt, wie man mit minimalen Auf-
- wand durch Manipulation der Farbregister der Super-VGA-Karte
- interessante Animationseffekte programmieren kann. Auf das
- Desktop, welches einen stufenlosen Übergang von Hell- zu
- Dunkelblau zeigt (wie die Oberfläche des Windows-Installati-
- onsprogramms) soll ein skalierbares Fenster mit einer aus
- 700 Rechtecken bestehenden Spirale aufgeblendet werden, die
- in den VGA-Standardfarben rotiert. Außerdem soll ein Palet-
- tenworkshop zur Änderung der Paletteneintragungen aufblend-
- bar sein (Objekt TPalWorkShop in der Unit WPalette).
-
- program PalTest;
-
- uses WDecl,
- WApp,
- WEvent,
- WViews,
- WDlg,
- WDriver,
- WUtils,
- WPalette,
- graph;
-
- const cmPalEdit=101;
- cmDemo=102;
- cmGrayBar=103;
-
- var Pal:TPalette;
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 277 -
-
-
-
-
-
-
-
- type TApplication=object(TApp)
- procedure InitVideoDevice; virtual;
- procedure SetDesktopBackground; virtual;
- procedure InitMenuBar; virtual;
- procedure HandleEvent; virtual;
- procedure PalettenEditor;
- procedure PalettenDemo;
- procedure Graukeil;
- end;
-
- PPalDemo=^TPalDemo;
- TPalDemo=object(TWindow)
- Richtung:byte; {gibt die Richtung an, in welcher "spiralt" wird}
- constructor Init;
- procedure InitBackGround; virtual;
- procedure SetPalette; virtual;
- procedure HandleEvent; virtual;
- end;
-
- PNewDTBgrd=^TNewDTBgrd;
- TNewDTBgrd=object(TDsktpBgrd)
- procedure Draw; virtual;
- end;
-
- PPalDemoBgrd=^TPalDemoBgrd;
- TPalDemoBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
- var MyApp:TApplication;
-
- {Implementation TApplication}
-
- Dieses Beispiel funktioniert nur in den 256-Farben VESA-Modi. Deshalb
- ist es unerläßlich, die Methode InitVideoDevice zu überschreiben.
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 278 -
-
-
-
-
-
-
-
- procedure TApplication.InitVideoDevice;
- begin
- Video.Init(VESA,M640x480);
- end;
-
- procedure TApplication.SetDesktopBackground;
- var R:TRect;
- begin
- with Desktop^ do
- begin
- R:=Frame^.Area;
- Bgrd:=new(PNewDTBgrd, Init(R));
- List^.InsertItem(Bgrd);
- end;
- end;
-
- procedure TApplication.InitMenuBar;
- begin
- MainMenu('~P~alette',1);
- SubMenu('~P~aletteneditor', cmPalEdit,0,0,false,false);
- SubMenu('~D~emonstration',cmDemo,0,0,false,false);
- SubMenu('~G~raukeil',cmGrayBar,0,0,false,false);
- NewLine;
- SubMenu('E~x~it <Alt><X>',cmCloseApplication,0,0,false,false);
- end;
-
- procedure TApplication.HandleEvent;
- begin
- TProgram.HandleEvent;
- case Event.Command of
- cmPalEdit:PalettenEditor;
- cmDemo:PalettenDemo;
- cmGrayBar:Graukeil;
- end; {case}
- end;
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 279 -
-
-
-
-
-
-
-
- Der Paletteneditor ist ein Bestandteil der Unit WPalette. Mit seiner
- Hilfe können sehr komfortabel Paletteneintragungen im RGB- und HSV-
- Farbmodell editiert werden. Außerdem lassen sich Paletten abspeichern
- und wieder laden.
-
- procedure TApplication.PalettenEditor;
- var Window:PPalWorkShop;
- begin
- Window:=new(PPalWorkShop, Init(180,100));
- InsertDesktop(Window);
- end;
-
- procedure TApplication.PalettenDemo;
- var Window:PPalDemo;
- begin
- Window:=new(PPalDemo, Init);
- InsertDesktop(Window);
- end;
-
- Der Graukeil dient der Anzeige der gerade aktiven Palette als "Graukeil"
- oder "Spektrum". Das Objekt TGrayBar ist auch Bestandteil der Unit
- WPalette.
-
- procedure TApplication.Graukeil;
- var Window:PGrayBar;
- begin
- Window:=new(PGrayBar, Init(300,350));
- InsertDesktop(Window);
- end;
-
- {Implementation TPalDemo}
-
- constructor TPalDemo.Init;
- var R:TRect;
- begin
- R.Assign(100,60,300,260);
- TWindow.Init(R,'Spirale',winDouble+winPanel+winKey+winMenu);
- Richtung:=0;
- end;
-
-
-
- Programmierhandbuch WG-Vision - 280 -
-
-
-
-
-
-
-
- procedure TPalDemo.InitBackground;
- var R:TRect;
- begin
- R:=Frame^.Area;
- Bgrd:=new(PPalDemoBgrd, Init(R));
- List^.InsertItem(Bgrd);
- end;
-
- Hier ändern wir die Panelfarbe in Gelb und die Textfarbe für die
- Titelleiste in Blau.
-
- procedure TPalDemo.SetPalette;
- begin
- Palette:=Palette1;
- Palette[4]:=#14; Palette[5]:=#14; Palette[6]:=#1;
- end;
-
- Der Eventhandler des Demonstrationsfensters gestaltet sich sehr einfach.
- In ihm wird bei jedem Durchgang die Methode RotatePart aufgerufen,
- welche den Palettenbereich zwischen den Eintragungen 166 und 182
- rotieren läßt. Durch Drücken der rechten Maustaste kann die Drehrichtung
- jeweils umgeschalten werden.
-
- procedure TPalDemo.HandleEvent;
- begin
- TWindow.HandleEvent;
- Pal.GetPalette;
- if Mouse.RButtonKlick then
- if Richtung=0 then Richtung:=1 else Richtung:=0;
- Pal.RotatePart(Richtung,166,182);
- end;
-
- {Implementation TNewDTBgrd}
-
- Erzeugen eines stufenlosen Übergangs von Hell- zu Dunkelblau. Für diesen
- Übergang wird der Palettenbereich zwischen 16 und 155 genutzt.
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 281 -
-
-
-
-
-
-
-
- procedure TNewDTBgrd.Draw;
- var dy,i:integer;
- begin
- Pal.GetPalette; {aktive (Standard-) Palette in Pal übernehmen}
- Pal.SetVerlauf(16,0,0,63,155,0,0,20); {von Hellblau zu Dunkelblau}
-
- Damit die "Spirale" in den Standard-VGA-Farben Blau bis Weiß erstrahlt,
- werden die Paletteneintragungen 166 bis 182 auf diese Werte gesetzt.
-
- for i:=1 to 15 do PAL.LUT[165+i]:=Pal.LUT[i];
-
- Achtung! Die Palettenänderungen werden nur innerhalb des Paletten-
- Objekts ausgeführt (konkret, die Tabelle LUT wird verändert). Das hat
- keine Auswirkungen auf dem Bildschirm. Erst wenn die manipulierte
- Palette in die VGA-Karte geladen wird, erscheinen die Änderungen auf dem
- Bildschirm. Deshalb muß unbedingt die Methode SetPalette aufgerufen
- werden.
-
- Pal.SetPalette;
-
- Neuen Desktop-Hintergrund malen.
-
- with Border do
- begin
- dy:=(B.y-A.y) div 139; {Streifenbreite}
- for i:=0 to 138 do
- FBar(A.x,A.y+i*dy+18,B.x,A.y+(i+1)*dy+18,15+i);
- end;
- end;
-
- {Implementation TPalDemoBgrd}
-
- Auf den Fensterhintergrund wird eine Spirale aus farbigen Rechtecken
- gezeichnet, wobei sich die Farbnummern der Rechtecke zyklisch zwischen
- 166 und 182 bewegen. Da das Fenster skalierbar ist, muß auch die Größe
- der Spirale (genauer ihr Radius nach dem Motto "kleines Fenster - kleine
- Spirale, großes Fenster - große Spirale) an die Fenstergröße angepaßt
- werden. Die Rechnungen dafür beanspruchen nur den wichtigsten
- mathematischen Lehrsatz des Computergrafikers, des Dreisatzes.
-
-
-
- Programmierhandbuch WG-Vision - 282 -
-
-
-
-
-
-
-
- procedure TPalDemoBgrd.Draw;
- var Color:byte;
- i,x,y:integer;
- Radius:real;
- xm,ym:integer;
- dx,dy:real;
-
- begin
- Color:=165;
- with Border do
- begin
- FBar(A.x,A.y,B.x,B.y,Black); {Schwarzer Untergrund}
- xm:=(B.x-A.x) div 2; {Mitte der Spirale}
- ym:=(B.y-A.y) div 2;
- dx:=B.x-A.x; dy:=B.y-A.y;
- for i:=0 to 700 do {Spirale malen}
- begin
- inc(Color);
- if Color=182 then Color:=166;
- if dx<dy then Radius:=i*dx/4480.0 {Radius an Fenstergröße}
- {anpassen}
- else Radius:=i*dy/4480.0;
- x:=trunc(Radius*cos(Radius)*3)+xm;
- y:=trunc(Radius*sin(Radius)*3)+ym;
- FBar(A.x+x,A.y+y,A.x+x+8,A.y+y+6,Color);
- {Farbrechteck malen}
- end;
- end;
- end;
-
- {Hauptprogramm}
-
- begin
- MyApp.Init('Paletten-Demo');
- MyApp.Run;
- MyApp.Done;
- end.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 283 -
-
-
-
-
-
-
-
- Das Objekt PAL als Instanz von TPalette wurde global im
- Programm vereinbart, damit alle Programmteile ohne Umwege
- darauf zugreifen können.
-
- 6.5.1. Farbmodelle
-
- WG-Vision unterstützt in den VESA-Modi zwei verschiedene
- Farbmodelle, das RGB-Modell und das HSV-Modell.
- Das RGB-Modell ist in der Computergrafik am weitesten ver-
- breitet, wenn es auch meistens nur intern und damit für den
- Benutzer nicht sichtbar wirkt. Die gesamte Funktionsweise
- der VGA-Karte liegt diesem Farbmodell zugrunde.
-
- 6.5.1.1. RGB-Modell
-
- Beim RGB-Modell handelt es sich um ein sogenanntes additives
- Farbmodell. Zur Darstellung verwendet man einen Einheitswür-
- fel. Jede Farbe innerhalb dieses Würfels wird durch ihre Ko-
- ordinaten, d.h. durch ihre Anteile an den Grundfarben Rot,
- Grün und Blau charakterisiert. Die Farbe Gelb ergibt sich
- z.B. als Summe von Rot und Grün in ihrer vollen Intensität,
- dargestellt durch das Zahlentripel (1,1,0). Um einen konti-
- nuierlichen Übergang zwischen zwei verschiedenen Farben zu
- erreichen, muß man lediglich die beiden den Farben entspre-
- chenden Punkte im Einheitswürfel durch eine Gerade verbinden
- und in n gleiche Teile teilen, wobei n die Anzahl der ge-
- wünschten Zwischenstufen ist. In der Prozedur SetVerlauf
- wird von dieser Methode gebrauch gemacht. Aus technischen
- Gründen wird die volle Intensität einer Farbe innerhalb der
- Unit WPalette nicht der Wert 1, sondern der Wert 63 zugeord-
- net. In WG-Vision würde die Farbe Gelb also durch das Tripel
- (63,63,0) und die Farbe Blau durch das Tripel (0,0,63) be-
- schrieben werden.
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 284 -
-
-
-
-
-
-
-
- 6.5.1.2. HSV-Modell
-
- Das RGB-Farbmodell ist für viele Anwendungsfälle nicht sehr
- gut geeignet. Besser ist es, eine Farbe, so wie es ein Maler
- macht, durch Farbton, Helligkeit und Schattierung zu be-
- schreiben. Diesen Ansatz verfolgt das HSV-Modell, das zwar
- letztendlich vom RGB-Modell abgeleitet wird, aber die Para-
- meter Hue (Farbe, ausgedrückt als Winkel), Saturation /Farb-
- sättigung) und Value (Helligkeit) verwendet. Der Parameter S
- (Saturation) liegt im Bereich von 0 bis 1 und repräsentiert
- das Verhältnis der Reinheit der Farbe zu ihrer maximalen
- Reinheit (S=1). Die Intensität der Farbe wird durch den Pa-
- rameter V (Value) bestimmt, der im Bereich zwischen Null
- (keine Helligkeit) und 1 (maximale Helligkeit) liegt.
- Die Farbe selbst wird durch einen Winkel repräsentiert, wo-
- bei 0° der Farbe Rot, 60° Gelb, 120° Grün, 180° Cyan, 240°
- Blau und 300° Magenta entspricht. Die reinsten Farben besit-
- zen die Werte V=S=1 und unterscheiden sich nur im Farbwin-
- kel.
- Das Objekt TPalette enthält Methoden, wie man Farbwerte aus
- dem RGB-Modell in das HSV-Modell umrechnen kann und umge-
- kehrt. Eine Anwendung dieser Methoden finden Sie im Palet-
- tenworkshop. Ich empfehle eine genaue Analyse dieses
- Werkzeugs, da es sehr schön zeigt, wie Palettenmanipulatio-
- nen innerhalb eines Dialogfensters in WG-Vision programmiert
- werden.
-
- Eine komplexe Anwendung, die von Palettenmanipulationen ex-
- tensiv gebrauch macht, finden Sie im Demonstrationsprogramm
- SBGDEMO.
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 285 -
-
-
-
-
-
-
-
- 7. Die Kern-Units von WG-Vision
-
- 7.1. Unit WAPP.PAS
-
- Die Unit WAPP stellt das Applikationsobjekt zur Verfügung.
- Jedes WG-Vision-Programm leitet sich von diesem Objekt ab.
-
- 7.1.1. Aufbau eines WG-Vision-Programms
-
- Das Minimalprogramm
-
- program Mini;
-
- uses WApp:
-
- type WApplication=object(WApp)
- end;
-
- var MyApp:TApplication;
-
- begin
- MyApp.Init;
- MyApp.Run;
- MyApp.Done;
- end.
-
- führt im Einzelnen folgende Schritte aus:
-
- constructor TApp.Init(Titel:string);
- begin
-
- Der Konstruktor des Vorgängerobjekts TProgram führt sämtliche Program-
- minitialisierungen aus. Dazu gehört die Initialisierung der Grafik, der
- Maus, der Tastatur und des Joysticks, für die jeweils Instanzen (Video,
- Mouse,Keyboard und Joy) bereitgestellt werden. Anschließend wird ein
- Desktop-Objekt auf dem Heap erzeugt. Dieses Objekt verwaltet in der dop-
- pelt verketteten Liste mit der Bezeichnung List alle Bestandteile des
- Desktops, die über die virtuellen Methoden SetDesktopFrame und SetDesk-
- topBackground in das Desktop eingefügt werden. Eine weitere Initialisie-
-
-
-
- Programmierhandbuch WG-Vision - 286 -
-
-
-
-
-
-
-
- rung betrifft Instanzen der Objekte TMemory und TEMS. Letztere Instanz
- wird nur dann angelegt, wenn während der Abarbeitung des Initialisie-
- rungsteils der Unit WEMS Expanded Memory entdeckt wurde. Zum Abschluß
- wird das Menü erzeugt und die Dialogrecords initialisiert. InitMenuBar
- und SetDialogData sind leere Methoden, die der Programmierer mit den
- richtigen Code selbständig belegen muß.
-
- TProgram.InitTitel);
-
- Die Draw-Methode von TProgram stellt alle Desktopelemente auf dem
- Bildschirm dar und blendet eventuell vorhandene Menüs und Statuszeilen
- auf.
-
- Draw;
- end;
-
- Die Methode Run ist die eigentliche Abarbeitungsschleife.
- Ihr Aufbau ist recht einfach:
-
- procedure TProgram.Run;
- begin
-
- Der anfänglich mit zufälligen Werten belegte Event-Record wird auf seine
- Standardwerte gesetzt.
-
- ClearEvent;
- ClearMessage;
-
- Jetzt folgt die große Abarbeitungsschleife, die solange ausgeführt wird,
- bis der Eventhandler das Kommando cmCloseApplication sendet. GetEvent
- arbeitet Tastatur und Maus ab und aktualisiert jeweils die Felder dieser
- Objekte. In HandleEvent sind alle Eventhandler der zum Zeitpunkt aktiven
- Fensterobjekte und der Eventhandler des Menüs enthalten. ClearEvent
- setzt u.a. das Feld What des Event-Records auf evNothing.
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 287 -
-
-
-
-
-
-
-
- repeat
- Heap^.HeapWatch;
- if EMS_Installed then EMS^.Watch;
- GetEvent;
- HandleEvent;
- ClearEvent;
- until Event.Command=cmCloseApplication;
- end;
-
- TApp.Done entfernt alle dynamischen Objekte vom Heap und
- beendet das Programm.
-
- Objekt TProgramm
-
- Felder (Auswahl)
-
- Desktop
- Desktop:PDesktop;
- Desktop ist ein Nachfahre von TGroup und enthält Zeiger, die
- auf den Desktop-Rahmen und den Hintergrund zeigen. Außerdem
- enthält dieses Objekt die doppelt verkettete Liste WinList,
- die alle Fensterobjekte aufnimmt.
-
- MMenu
- MMenu:PMainMenu;
- Zeiger auf die Hauptmenüeintragungen. Jeder Hauptmenüpunkt
- verwaltet separat sein Untermenü.
-
- Heap,EMS
- Instanzen der Objekte, die für die Verwaltung bzw. Überwa-
- chung des Heaps und des Expanded Memory verantwortlich sind.
-
- MAnzahl
- MAnzahl:byte;
- Enthält die Anzahl der Hauptmenüfelder.
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 288 -
-
-
-
-
-
-
-
- Aktiv
- Aktiv:boolean;
- Aktiv ist immer dann true, wenn ein Menü aufgeblendet bzw.
- die Menüzeile aktiviert ist.
-
- SAktiv
- SAktiv:boolean;
- Immer wenn ein Pull-Down-Menü aufgeblendet ist, wird SAktiv
- auf true gesetzt.
-
- WinAnz
- WinAnz:byte;
- In WinAnz wird die Anzahl der Eintragungen in der Window-
- Liste des Desktops gespeichert.
-
- Modal
- Modal:boolean;
- Dieser Wert ist immer dann true, wenn das aktive Fenster
- nicht-modal ist.
-
- ifHelp
- ifHelp:boolean;
- Wenn das Desktop mit einem Hilfesystem ausgestattet ist, ist
- diese Variable true.
-
- HelpFile
- HelpFile:string;
- Enthält den Namen der Help-Datei, wenn das Hilfesystem akti-
- viert ist.
-
- Methoden (Auswahl)
-
- InsertDesktop
- procedure InsertDesktop(Item:PGroup);
- Mit InsertDesktop wird ein Fenster in die Windowliste des
- Desktops eingefügt. Item muß ein Zeiger auf solch ein Fen-
- sterobjekt sein.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 289 -
-
-
-
-
-
-
-
- SetDesktopFrame
- procedure SetDesktopFrame(Titel:string); virtual;
- Einfügen des Rahmens mit Panel und Titelzeile in das Desk-
- top. Wenn Sie den Rahmen des Desktops verändern möchten,
- müssen Sie diese Methode überschreiben.
-
- SetDesktopBackground
- procedure SetDesktopBackground(Titel:string); virtual;
- Einfügen des Clientbereichs (Hintergrund)in das Desktop.
- Wenn Sie den Desktop-Hintergrund ändern möchten, müssen Sie
- diese Methode überschreiben.
-
- Statusbar
- procedure Statusbar; virtual;
- Leere Methode. Dient der Implementierung einer Statuszeile.
-
- MainMenu, SubMenu, NewLine
- Diese Methoden werden für die Implementierung eines
- Menübaums benötigt. Sie werden innerhalb von InitMenuBar
- implementiert.
-
- InitVideoDevice
- procedure InitVideoDevice; virtual;
- Initialisierung der Grafik. Diese Methode muß überschrieben
- werden, wenn ein neuer Grafikmodus eingestellt werden soll.
-
- InitMenuBar
- procedure InitMenuBar; virtual;
- Diese leere Methode muß überschrieben werden, wenn ein Menü
- benötigt wird.
-
- LoadMenu
- procedure LoadMenu(ResName:str80);
- Laden eines Menübaums aus einer Menüressource. Diese Methode
- wird innerhalb von InitMenuBar angewendet.
-
- ClearMenu
- procedure ClearMenu;
- Löschen des momentan aktiven Menübaums.
-
-
-
- Programmierhandbuch WG-Vision - 290 -
-
-
-
-
-
-
-
- DrawMainMenu
- procedure DrawMainMenu;
- Zeichnet die Hauptmenüzeile neu auf das Desktop.
-
- SetDialogData
- procedure SetDialogData; virtual;
- Diese leere Methode, die im Anwendungsfall überschrieben
- werden muß, dient der Initialisierung der Dialogrecords von
- Dialogfenstern.
-
- SetOnlineHelp
- procedure SetOnlineHelp(HelpDatei:string);
- Initialisiert die kontextsensitive Hilfe und lädt die
- Helpdatei.
-
- MessageBox
- procedure MessageBox(Caption:word;PanelText,
- InfoText:string);
- Installiert ein Mitteilungsfenster in die Window-Liste des
- Desktops.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 291 -
-
-
-
-
-
-
-
- 7.2. Unit WViews.pas
-
- In der Unit WViews befinden sich ein paar wichtige Objekte,
- die einmal für die innere Organisation (z.B. TView, TGroup)
- der Toolbox und zum anderen für das äußere Erscheinungsbild
- von WG-Vision (TFrame, TBackground, TMainMenu, TDeskTop)
- verantwortlich sind. Alle Objekte, die irgendwie auf dem
- Bildschirm sichtbar sind, leiten sich letztendlich von TView
- ab.
-
- 7.2.1. Objekt TView
-
- Felder
-
- Prev
- Prev:PGroup;
- Zeiger auf den Vorgänger (wichtig für die verkettete Liste
- TGroup)
-
- Next
- Next:PGroup;
- Zeiger auf den Nachfolger (wichtig für die verkettete Liste
- TGroup)
-
- Palette
- Palette:TPalette;
- Dem TView-Objekt zugeordnete Farbpalette
-
- Origin
- Origin:TPoint;
- Koordinaten der linken oberen Ecke des TView-Objekts
-
- Size
- Size:TPoint;
- Länge (Size.x) und Breite (Size.y) des TView-Objekts.
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 292 -
-
-
-
-
-
-
-
- RSize
- RSize:boolean;
- Diese logische Variable wird auf true gesetzt, wenn ein Fen-
- ster als Nachfolger von TView bis auf Minimalgröße verklei-
- nerbar ist.
-
- Methoden (Auswahl)
-
- Init
- constructor Init(var Bounds:TRect; SetSize:boolean);
- Setzt Prev und Next auf nil und belegt die Felder Origin und
- Size mit den Werten, die sich aus Bounds ergeben. SetSize
- setzt die logische Variable RSize.
-
- SetBounds
- procedure SetBounds(var Bounds:TRect);
- Belegt die Felder Origin und Size mit den Werten, die sich
- aus Bounds ergeben. Ist RSize=true und Size.x<100 bzw.
- Size.y<86, dann wird Size auf (100,86) gesetzt. (Minimale
- Größe von Fenster mit Panel).
-
- GetBounds
- procedure GetBounds(var Bounds:TRect);
- Übergibt die in Origin und Size gespeicherten Werte in
- Bounds als TRect-Objekt.
-
- ChangeBounds
- procedure ChangeBounds(var Bounds:TRect);
- Setzt die Werte von Origin und Size entsprechend Bounds neu.
-
- GrowTo
- procedure GrowTo(x,y:integer);
- Vergrößert Size um x und y.
-
- Locate
- procedure Locate(var Bounds:TRect);
- Stellt sicher, daß ein TView-Objekt mit RSize=true seine Mi-
- nimalgröße von 100x86 nicht unterschreitet.
-
-
-
-
- Programmierhandbuch WG-Vision - 293 -
-
-
-
-
-
-
-
- GetPalColor
- GetPalColor(Index:byte):byte;
- Übergibt die Nummer der Farbe an der Position Index der
- Farbpalette von TView.
-
- 7.2.2. Objekt TGroup
-
- TGroup ist eines der wichtigsten Objekte in WG-Vision. Es
- stellt eine doppelt verkettete Liste zur Verfügung, die alle
- möglichen TView-Objekte aufnehmen und verwalten kann.
-
- Felder
-
- First
- First:PGroup;
- Zeiger auf das erste Element der Liste.
-
- Last
- Last:PGroup;
- Zeiger auf das letzte Element der Liste
-
- Current
- Current:PGroup;
- Zeiger auf das gerade aktive Element der Liste.
-
- CurrNo
- CurrNo:word;
- Index des gerade aktiven Elements der Liste.
-
- AnzElem
- AnzElem:word;
- Anzahl der Elemente der Liste.
-
- Methoden {Auswahl}
-
- Init
- constructor Init;
- Setzt First, Last und Current auf nil sowie CurrNo und
- AnzElem auf Null.
-
-
-
- Programmierhandbuch WG-Vision - 294 -
-
-
-
-
-
-
-
- Done
- destructor Done;
- Löscht die Liste und entfernt sie vom Heap.
-
- InsertItem
- InsertItem(Item:PGroup);
- Fügt das Element Item in die Liste ein.
-
- DeleteItems
- procedure DeleteItems;
- Löscht die gesamte Liste.
-
- GetItems
- function GetItems(Nr:word):PGroup;
- Übergibt einen Zeiger auf das Listenelement mit dem Index
- Nr.
-
- UnChainItem
- procedure UnChainItem(N:PGroup);
- Kettet das Element N aus der Liste aus.
-
- DelItem
- procedure DelItem(N:PGroup);
- Löscht das Element N aus der Liste.
-
- DelLastItem
- procedure DelLastItem;
- Löscht das letzte Element aus der Liste.
-
- Draw
- procedure Draw; virtual;
- Veranlaßt, daß nacheinander die Draw-Methoden aller Listen-
- elemente abgearbeitet werden.
-
- Hide
- procedure Hide; virtual;
- Ruft die Hide-Methode aller Listenelemente auf. Die Objekte
- verschwinden vom Bildschirm.
-
-
-
-
- Programmierhandbuch WG-Vision - 295 -
-
-
-
-
-
-
-
- SwapItems
- procedure SwapItems(i:word);
- Tauscht das letzte Element der Liste gegen das Element mit
- dem Index i aus.
-
- 7.2.2.1. Aufbau einer doppelt verketteten Liste
-
- Doppelt verkettete Listen enthalten in jedem Element zwei
- Pointer, wobei der Eine auf den Vorgänger (Prev) und der
- andere auf den Nachfolger (Next) zeigt:
-
-
- Item A <┐ ┌──> Item B <┐ ┌──> Item C <┐ ┌──> Item D
- [Inhalt] │ │ [Inhalt] │ │ [Inhalt] │ │ [Inhalt]
- Next ───┼─┘ Next ───┼─┘ Next ───┼─┘ Next ─────> nil
- nil <─── Prev └───── Prev └───── Prev └───── Prev
-
-
- FIRST (CURRENT) LAST
-
- Index 1 2 3 (CurrNo) 4 = AnzElem
-
- Durch Umkettung können leicht Listenelemente aus der Liste
- entfernt, ausgetauscht oder neue eingebaut werden.
- Um die Arbeit mit Listen vom Typ TGroup zu demonstrieren,
- folgt jetzt ein kommentierter Ausschnitt aus dem Eventhand-
- ler des Applikationsobjekts (TProgram.HandleEvent), welches
- sehr schön die Arbeit mit der Fensterliste des Desktops
- zeigt:
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 296 -
-
-
-
-
-
-
-
- In der Toolbox verwenden wir die Variable LfdPtr zum
- Zwischenspeichern eines Listenelements:
-
- var LfdPtr:PGroup;
-
- ...
- with DeskTop^ do {Window zeichnen}
- begin
-
- In Desktop werden in der Liste WinList alle Fenster verwaltet. WinAnz
- und WinCount enthalten, gewissermaßen global, die Anzahl dieser Fenster,
- wobei WinAnz bereits dann inkrementiert wird, wenn ein Fenster in die
- Windowliste eingebaut wird. WinCount wird erst nach dem Aufblenden auf
- dem Bildschirm um eins erhöht. Auf diese Weise kann der Eventhandler
- entscheiden, ob er das in die Liste eingefügte Fenster aufblenden soll
- oder nicht.
-
- if (WinAnz<>WinCount) and (WinCount<255) then
- begin
-
- Mauskursor eventuell auf Standard setzen.
-
- if Mouse.CursorTyp<>1 then Mouse.SetCursorTyp(1);
-
- Wenn WinCount größer Null ist, bedeutet das, daß bereits mindestens ein
- Fenster auf der Arbeitsfläche angeordnet ist. Dieses Window kann entwe-
- der ein reguläres Fenster oder ein Childfenster sein. Das Rahmenobjekt
- dieses Fensters erhält die "Botschaft" FrameDeAktivated=true und wird
- gezwungen, seinen Rahmen neu zu zeichnen, wobei die Palette für "inak-
- tiv" verwendet wird. Anschließend wird die Draw-Methode des neuen Fen-
- sters abgearbeitet, die Variable Modal gesetzt und dementsprechend die
- Menüzeile neu gezeichnet. Bei modalen Fenstern wird die Schrift in der
- Menüzeile Grau dargestellt, um auch optisch zu zeigen, daß das Menü de-
- aktiviert ist. Zum Abschluß wird WinAnz und WinCount gleichgesetzt, um
- zu verhindern, daß dieser Schleifenteil beim nächsten Durchlauf des
- Eventhandlers nochmals abgearbeitet wird.
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 297 -
-
-
-
-
-
-
-
- if WinCount>1 then {vorheriges Fenster deaktivieren}
- begin
- LfdPtr:=WinList^.GetItems(WinCount-1); {Zeiger auf vorheriges}
- {Fenster}
- FrameDeAktivated:=true; {Info an "Frame.Draw"}
- if (TypeOf(LfdPtr^)=TypeOf(TDlgWindow)) and
- (PDlgWindow(LfdPtr)^.ChildPresent) then {Childfenster}
- {aktiv ?}
- begin
- with PDlgWindow(LfdPtr)^ do {Rahmen des Childfensters}
- {deaktivieren}
- begin
- LfdPtr:=Child^.First;
- PWindow(LfdPtr)^.DrawNewFrame;
- end;
- end
- else
- begin
- if PDlgWindow(LfdPtr)^.ChildPresent then
- with PDlgWindow(LfdPtr)^ do
- begin
- LfdPtr:=Child^.First;
- PWindow(LfdPtr)^.DrawNewFrame;
- end
- else
- PWindow(LfdPtr)^.DrawNewFrame; {reguläres Fenster}
- {deaktivieren}
- end;
- end;
-
- LfdPtr:=WinList^.GetItems(WinCount); {neues Fenster aufblenden}
- {und aktivieren}
- LfdPtr^.Draw;
- Modal:=PWindow(LfdPtr)^.WinModal; {Modalitätszustand auslesen}
- DrawMainMenu; {Menüzeile neu zeichnen}
- WinAnz:=WinCount;
- end
-
-
-
-
-
- Programmierhandbuch WG-Vision - 298 -
-
-
-
-
-
-
-
- WinAnz=WinCount. Eventhandler des letzten Fensters aufrufen und
- abarbeiten
-
- else
- if (WinAnz>0) then
- if not Modal then
- begin
- LfdPtr:=WinList^.Last; {Pointer auf das letzte Listenelement}
- LfdPtr^.HandleEvent; {Fenster-Handler aufrufen}
- end
- else
- if not SAktiv then {kein Untermenü aufgeblendet}
- begin
- LfdPtr:=WinList^.Last;
- LfdPtr^.HandleEvent;
- end;
-
- Wenn der Eventhandler des aktiven Fensters das Kommando cmCloseWindow
- sendet, muß das Fenster geschlossen und aus der Window-Liste entfernt
- werden.
-
- if Event.Command=cmCloseWindow then {Fenster aus der WinList}
- {entfernen}
- begin
- LfdPtr:=WinList^.Last;
- LfdPtr^.Hide; {aktives Fenster schließen}
- WinList^.DelLastItem; {und aus der Liste entfernen}
- Dec(WinCount); {WinCount dekrementieren}
-
- Wenn noch Fenster offen sind, muß das jetzt letzte Fenster (Index
- WinCount) aktiviert werden, indem es seinen Rahmen neu zeichnet
- (FrameDeaktivated=false) und seinen Eventhandler in die
- Abarbeitungsschleife einklingt. Auch hier muß die Präsenz eines
- Childfensters beachtet werden.
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 299 -
-
-
-
-
-
-
-
- if WinCount>0 then {noch Fenster offnen ?}
- begin
- LfdPtr:=WinList^.GetItems(WinCount); {vorheriges Fenster}
- {aufblenden}
- if (TypeOf(LfdPtr^)=TypeOf(TDlgWindow)) and
- (DlgWindow(LfdPtr)^.ChildPresent) then
- begin
- with PDlgWindow(LfdPtr)^ do
- begin
- LfdPtr:=Child^.First;
- PWindow(LfdPtr)^.DrawNewFrame;
- end;
- end
- else
- begin
- if PDlgWindow(LfdPtr)^.ChildPresent then
- with PDlgWindow(LfdPtr)^ do
- begin
- LfdPtr:=Child^.First;
- PWindow(LfdPtr)^.DrawNewFrame;
- end
- else
- PWindow(LfdPtr)^.DrawNewFrame;
- end;
- Modal:=PWindow(LfdPtr)^.WinModal;
- WinAnz:=WinCount;
- end
- else
- begin
- WinAnz:=0; {keine Fenster mehr da. Liste leer}
- Modal:=true;
- end;
- DrawMainMenu; {Je nach Modalitätszustand Hauptmenüzeile neu}
- {darstellen}
- Event.Command:=cmNothing; {Kommando rücksetzen}
- end;
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 300 -
-
-
-
-
-
-
-
- Wird mit der Maus die Größe eines Fensters oder seine Position
- verändert, dann sendet das Rahmenobjekt das Kommando cmWindowNewSize.
- Als Reaktion darauf wird das letzte Element der Fensterliste mit den
- neuen Maßen bzw. der neuen Rahmenposition neu aufgeblendet.
-
- if Event.Command=cmWindowNewSize then {Größe des aktives Fenster}
- {ändern}
- begin
- LfdPtr:=WinList^.Last;
- LfdPtr^.NewItemList;
- LfdPtr^.Draw;
- Event.Command:=cmNothing; {Kommando rücksetzen}
- end;
-
- Wenn sich mehrere modale Fenster auf dem Bildschirm befinden, kann man
- durch Anklicken eines deaktivierten Fensters dieses Fenster zum aktiven
- Fenster machen. Technisch wird das wie folgt realisiert: Über die Maus-
- position zum Zeitpunkt des Anklickens wird der Index Focus dieses Fen-
- sters in der Window-Liste bestimmt. Anschließend wird dieses Element
- ausgekettet und gegen das letzte Element der Liste ausgetauscht. Das zu-
- letzt aktive Fenster wird an die Position des selektierten Fensters ein-
- gebaut und das selektierte Fenster wird auf die letzte (also aktive)
- Position der Fensterliste gesetzt. Danach werden die Draw-Methoden aller
- Fenster von hinten nach vorn bis zur Position Focus abgearbeitet (wegen
- möglicher Überlappungen).
-
- if Modal and (Event.Command=cmSelectWindow) then {Fenster}
- {selektieren}
- begin
- Focus:=SelectWindow; {bestimmt Index des selektierten Fensters}
-
- Die Iconbar ist nichts anderes als ein Dialogfenster an der Position
- FIRST der Fensterliste !
-
- if IconBarPresent then ff:=1 else ff:=0;
-
- if Focus>ff then
- begin
-
-
-
-
- Programmierhandbuch WG-Vision - 301 -
-
-
-
-
-
-
-
- Alle Fenster von AnzElem bis zur Position Focus löschen.
-
- for i:=WinList^.AnzElem downto Focus do
- begin
- LfdPtr:=WinList^.GetItems(I);
- LfdPtr^.Hide;
- end;
-
- Fenster tauschen.
-
- WinList^.SwapItems(Focus);
-
- Alle Fenster von Focus bis AnzElem neu zeichnen.
-
- for i:=Focus to WinList^.AnzElem do
- begin
- LfdPtr:=WinList^.GetItems(I);
-
- Außer dem letzten Fenster müssen alle Fenster mit deaktivierten Rahmen
- gezeichnet werden
-
- if i<>WinList^.AnzElem then FrameDeaktivated:=true;
- LfdPtr^.Draw;
- Modal:=PWindow(LfdPtr)^.WinModal;
- DrawMainMenu;
- end;
- end;
- Focus:=0;
- end;
- end;
-
- Beim Anklicken des Systemmenüs Applikation schließen.
-
- if Modal then
- if SWButton.Contains(Mouse.Position) and Mouse.LButtonKlick then
- Event.Command:=cmCloseApplication;
-
- ... und hier noch das Aufblenden einer Messagebox bei der Präsenz eines
- modul-internen Fehlers.
-
-
-
- Programmierhandbuch WG-Vision - 302 -
-
-
-
-
-
-
-
- if Event.Message=msgError then
- begin
- ErrorMessage(Fehler,z1,z2,BoxTyp);
- MessageBox(BoxTyp,z1,z2);
- Event.Message:=msgNothing;
- end;
- ...
-
- An diesem wirklich nicht einfach zu verstehenden Programm-
- fragment erkennen Sie deutlich die Vorgehensweise, wenn man
- auf ein Listenelement zugreifen möchte:
-
- 1. LfdPtr ein Listenelement über den Index zuordnen :
-
- LfdPtr:=WinList^.GetItems(Index);
-
- 2. Methoden (eventuell über Typecast) aufrufen
-
- LfdPtr^.Draw;
-
- In der prinzipiell gleichen Weise wie die Fensterliste wer-
- den auch die Dialogelemente in einen Dialogfenster verwal-
- tet. Auch dort erfolgt der Zugriff in den meisten Fällen
- über einen LfdPtr vom Typ PGroup und den Positionsindex.
-
- 7.2.3. Speicherobjekte
-
- Speicherobjekte dienen modulintern der Speicherung von
- rechteckigen Bildschirmausschnitten (Fensteruntergrund) in
- Swapdateien bzw. in den Expanded Memory. Außerdem können Sie
- verwendet werden, um zur Laufzeit den Heap, die Festplatte
- und den EMS zu überwachen.
- WViews stellt folgende Speicherobjekte zur Verfügung:
-
- TMemory ─ THardDisk
- TEMS
- THeap
-
-
-
-
-
- Programmierhandbuch WG-Vision - 303 -
-
-
-
-
-
-
-
- Im Feld FreeMemory wird der jeweils verfügbare Speicher
- abgelegt. Ein kommentiertes Listing von TEMS finden Sie im
- Abschnitt "Expansionsspeicher".
-
- 7.2.4. Das Rahmenobjekt
-
- TFrame ist mit einer gehörigen Portion "Eigenintelligenz"
- ausgestattet worden. Sein Eventhandler kann z.B. auf Tasta-
- tur- und Mausereignisse reagieren. Bei einem skalierbaren
- Fenster ändert sich z.B. die Form des Mauszeigers bei Berüh-
- rung des Rahmens mit der Maus. Die Gestalt des Mauszeigers
- zeigt an, wie die Form des Fensters im Dragmode verändert
- werden kann. Auch beim Anklicken des Panels und Verschieben
- der Maus mit gedrückter linker Maustaste verändert sich die
- Gestalt des Mauskursors. Außerdem wird ein Drag-Rahmen auf-
- geblendet, welche die Neupositionierung oder Skalierung ei-
- nes Fensters vereinfacht.
- Auch das Systemmenü eines Fensters gehört eigentlich zu des-
- sen Rahmen. Es kann sowohl mit der Maus als auch über die
- Tastatur (<ESC>, Kursortasten) bedient werden.
- Die für den Programmierer wichtigsten Felder von TFrame
- sind:
-
- FTyp
- FTyp:byte;
- Rahmentyp. FTyp ergibt sich aus der Summe folgender Konstan-
- ten, die beliebig (d.h. soweit sinnvoll) kombiniert sein
- können: winDouble, winSingle, winPanel, winMenu und winKey.
- FTyp bestimmt das Aussehen und die Eigenschaften eines Rah-
- mens.
-
- Header
- Header:TText;
- Paneltext. Der Variablentyp TText stellt sicher, daß der
- Text auch bei skalierbaren Fenstern immer richtig positio-
- niert und gegebenenfalls abgeschnitten wird.
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 304 -
-
-
-
-
-
-
-
- Area
- Area:TRect;
- Koordinaten des Bereichs innerhalb des Rahmens (Clientbe-
- reich). Diesen Wert verwenden die Hintergrundobjekte, um
- sich in ihrer Größe dem Rahmen anzupassen.
-
- ZoomRect
- ZoomRect:TRect;
- In dieser Variablen wird die Originalgröße und die Original-
- position eines skalierbaren Fensters gespeichert.
-
- DragMode
- DragMode:byte;
- Bestimmt das Verhalten des Fensters bei Veränderungen.
- DragMode kann folgende Werte annehmen:
-
- dmNoMove = 0 Rahmen darf nicht bewegt weren
- dmMove = 1 Rahmen darf verschoben werden
- dmGrow = 2 Rahmen darf seine Größe und Position ändern
- dmNoGrow = 3 Rahmen darf seine Größe nicht ändern
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 305 -
-
-
-
-
-
-
-
- 7.3. Unit WDLG.PAS
-
- 7.3.1. Das Standard-Fenster - TWindow
-
- Alle Fensterobjekte leiten sich von TWindow ab. Dieses Ob-
- jekt stellt ein komplettes Fenster zur Verfügung, von dem
- der Anwendungsprogrammierer seine eigenen Fenster ableiten
- muß.
-
- Felder
-
- List
- List:PGroup;
- Liste der Fensterelemente. Ein WG-Vision-Fenster besteht in
- der Reihenfolge der Implementation aus folgenden Bestandtei-
- le: Untergrund, Rahmen und Hintergrund (eventuell Rollbalken
- und Scroller).
-
- Undergrd
- Undergrd:PMemory;
- Zeiger auf das Speicherobjekt, welches den Fensteruntergrund
- gespeichert hat (Swapdatei oder EMS).
-
- Frame
- Frame:PFrame;
- Zeiger auf das Rahmenobjekt.
-
- Bgrd
- Bgrd:PBackground;
- Zeiger auf das Hintergrundobjekt.
-
- SBH,SBV
- SBH,SBV:PScrollBar;
- Zeiger auf die Rollbalken.
-
- ZoomRect
- ZoomRect:TRect;
- Original-Fenstergröße und Position.
-
-
-
-
- Programmierhandbuch WG-Vision - 306 -
-
-
-
-
-
-
-
- Title
- Title:str80;
- Paneltext des Fensters.
-
- Typ
- Typ:byte;
- Rahmentyp des Fensters.
-
- WinModal
- WinModal:boolean;
- Fenster nicht-Modal ?
-
- Methoden (Auswahl)
-
- Init
- constructor Init(var Bounds:TRect;ATitle:str80;AType:byte);
- Initialisiert ein Fenster mit der Größe Bounds und den Rah-
- mentyp AType.
-
- Done
- destructor Done; virtual;
- Entfernt die Fenster-Elemente vom Heap.
-
- SetWindowAttrib
- SetWindowAttrib(Modal:boolean);
- Legt die modalen Eigenschaften eines Fensters fest.
-
- SetPalette
- procedure SetPalette; virtual;
- Fensterpalette einstellen. Diese Methode kann in einem
- konkreten Anwendungsfall überschrieben werden.
-
- InitUnderGround, InitFrame, InitBackground,
- InitWindowScroller
- Diese virtuellen Methoden fügen Fensterelemente in List ein.
- Sie können bei Bedarf überschrieben werden.
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 307 -
-
-
-
-
-
-
-
- Draw
- procedure Draw; virtual;
- Zeichnet das komplette Fenster auf den Bildschirm.
-
- DrawClientArea
- procedure DrawClientArea; virtual;
- Leere Methode. Muß im Anwendungsfall überschrieben werden.
- Mit dieser Methode kann der Fensteruntergrund zur Laufzeit
- ohne Manipulation und Neuzeichnen des Hintergrundobjekts
- verändert werden.
-
- Hide
- procedure Hide; virtual;
- Entfernt das Fenster vom Bildschirm.
-
- DrawNewFrame
- procedure DrawNewFrame; virtual;
- Zeichnet den Rahmen des Fensters neu.
-
- HandleEvent
- procedure HandleEvent; virtual;
- Eventhandler des Fensters
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 308 -
-
-
-
-
-
-
-
- 7.3.2. Dialogfenster - TDlgWindow
-
- Dialogfenster leiten sich direkt von TWindow ab und erben
- von ihm alle wichtigen Eigenschaften. Dialogfenster sind im-
- mer modal und nicht skalierbar (läßt sich aber eventuell
- durch Neusetzen von TFrame^.DragMode ändern).
- Sie können eine beliebige Anzahl von aktiven und passiven
- Dialogelementen enthalten, die sie in der Liste DlgList ver-
- walten. Außerdem lassen sich Dialogfenster mit beliebig vie-
- len Child-Fenster ausstatten, wobei jedoch immer nur eins
- aktiv sein darf.
-
- Felder
-
- R
- R:TRect;
- Enthält die Größe und Position des Dialogfensters.
-
- DlgElemente
- DlgElemente:string;
- Diese Zeichenkette enthält die Buchstabencodes aller instal-
- lierten Dialogelemente in der Reihenfolge ihrer Implementa-
- tion (entspricht der Variablen Schalter im Dialogrecord).
-
- DlgList
- DlgList:PGroup;
- Doppelt verkettete Liste aller im Fenster implementierten
- Dialogelemente.
-
- Child
- Child:PGroup;
- Enthält einen Zeiger auf das gerade aktive Childfenster. Im
- Normalfall ist Child^.First=nil.
-
- FocElem
- FocElem:byte;
- Index des gerade fokussierten Dialogelements in der Liste
- DlgList.
-
-
-
-
- Programmierhandbuch WG-Vision - 309 -
-
-
-
-
-
-
-
- ChildPresent
- ChildPresent:boolean;
- Wird auf true gesetzt, wenn ein Childfenster aufgeblendet
- ist.
-
- Methoden (Auswahl)
-
- DrawMask
- procedure DrawMask; virtual;
- Zeichnet eine Eingabemaske aus TInputLine-Objekten neu auf
- den Bildschirm.
-
- InsertChildWindow
- procedure InsertChildWindow(Item:PGroup);
- Fügt ein Child-Fenster in das Dialogfenster ein.
-
- SetPushButton
- procedure SetPushButton(x,y,xl,yl:integer;
- Bez:str25;Kommando:word);
- Drucktaste in die Dialogliste einfügen.
-
- SetRadioButton
- procedure SetRadioButton(x,y:integer;
- Bez:str25;FGruppe:byte);
- Fügt ein Radiobutton der Gruppe FGruppe in die Dialogliste
- des Dialogfensters ein.
-
- SetCheckButton
- procedure SetCheckButton(x,y:integer;Bez:str25);
- Fügt ein Checkbutton in die Dialogliste des Dialogfensters
- ein.
-
- SetInputLine
- procedure SetInputLine(x,y,xl:integer;
- Bez:str25;MaxLen:byte;Zeich:ZMenge);
- Mit dieser Methode stellen Sie dem Dialogfenster eine frei
- editierbare Eingabezeile für Strings zur Verfügung.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 310 -
-
-
-
-
-
-
-
- SetNumButton
- procedure SetNumButton(x,y,xl:integer;Bez:str25;
- MaxLen,TTyp:byte,Min.Max,Step,Format:real);
- Implementierung eines Zählschalters in das Dialogfenster.
-
- SetListBox
- procedure SetListBox(x,y,xl,yl:integer;Bez:str25;
- LScroller:word); virtual;
- Diese virtuelle Methode muß im Anwendungsfall überschrieben
- werden. Sie implementiert eine Listbox in ein Dialogfenster.
-
- SetGroupFrame
- procedure SetGroupFrame(x,y,xl,yl:integer;Bez:str25;
- FrameTyp:word);
- Gruppenfenster mit dem Rahmentyp FrameTyp in ein Dialogfen-
- ster einfügen.
-
- SetIcon
- procedure SetIcon(x,y:integer;Bez:str25);
- Icon aus der Ressourcendatei mit dem Dateinamen Bez an die
- Position x,y des Dialogfensters einfügen.
-
- SetStaticText
- procedure SetStaticText(x,y:integer;Bez:string;RelPos:byte);
- Statischen Text in ein Dialogfenster schreiben.
-
- SetTextPosition
- procedure SetTextPosition(x,y:integer);
- Position des Bezeichners des zuletzt implementierten Dialog-
- elementes verändern.
-
- ChangePalColor
- procedure ChangePalColor(Eintrag,Color:byte);
- Palettteneintrag des zuletzt implementierten Dialogelements
- verändern.
-
- SetTextParameters
- procedure SetTextParameters(Fnt,Direct:word;CharSz:byte);
- Textparameter eines statischen Textes ändern.
-
-
-
- Programmierhandbuch WG-Vision - 311 -
-
-
-
-
-
-
-
- SetDisabled
- procedure SetDisabled;
- Das zuletzt implementierte Dialogelement wird deaktiviert.
-
- GetFocElem
- function GetFocElem:word;
- Übergibt den Index des gerade fokussierten Elements in der
- Dialogelementeliste
-
- 7.3.2.1. Dialogelemente
-
- Hierarchie der Dialogelemente von WG-Vision
-
- TGroup ─ TButton ─ TPushButton
- TRadioButton ─ TCheckButton
- TInputLine ─ TNumButton
- TScroller ─ TListBox
- TGroupFrame
- TIcon
- TStaticText
-
- Alle Dialogelemente leiten sich von TButton ab. In diesem
- Objekt werden folgende Werte gespeichert (Auswahl):
-
- TextPos
- TextPos:TRect;
- Rechteckiger Bereich des Bildschirms, in dem der Bezeichner
- positioniert ist.
-
- dx,dy
- dx,dy:integer;
- Textposition relativ zum Button.
-
- ShortCut
- ShortCut:char;
- Buchstabe, über den das Dialogelement fokussiert werden
- kann.
-
-
-
-
-
- Programmierhandbuch WG-Vision - 312 -
-
-
-
-
-
-
-
- Focus
- Focus:boolean;
- Focus ist immer dann true, wenn das Dialogelement fokussiert
- ist.
-
- Enabled
- Enabled:boolean;
- Dialogelement aktiviert (true) oder deaktiviert (false).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 313 -
-
-
-
-
-
-
-
- 8. WG-Vision und der Coprozessor
-
- Alle Units von WG-Vision unterstützen prinzipiell einen
- arithmetischen Coprozessor. Ist kein Coprozessor vorhanden,
- muß mit {$E+} der Emulator eingebunden werden. Das ge-
- schieht, indem Sie diese Compilerdirektive oberhalb des
- Schlüsselworts program in Ihr Hauptprogramm einfügen.
- In WG-Vision wurde aus diesem Grund der Datentyp real durch-
- gängig durch den Datentyp single ersetzt.
-
- 8.1. Erweiterte Funktionen des Coprozessors
-
- Es ist ein offenes Geheimnis, daß Turbo-Pascal den Coprozes-
- sor mehr schlecht als recht auslastet. Besonders bedauerlich
- ist es, daß die Erweiterungen, welche ab dem 80387 verfügbar
- sind, vom Pascal-Compiler völlig ignoriert werden. Das be-
- trifft fast alle "fest verdrahteten" Funktionsaufrufe wie
- Sinus, Cosinus oder Arcustangens. Wenn diese Funktionen di-
- rekt angesprochen werden, erhält man durchschnittlich eine
- weitere Geschwindigkeitssteigerung um den Faktor 3. Damit
- Sie diese Kapazitäten in Ihren Programmen nutzen können,
- wurde die Unit WCProc entwickelt. Sie stellt Ihnen folgende
- Funktionen zur Verfügung:
-
- function wgSin(x:extended):extended; Sinus
- function wgCos(x:extended):extended; Cosinus
- function wgTan(x:extended):extended; Tangens
- function wgCot(x:extended):extended; Cotangens
- function wgAtn(x:extended):extended; Arcus Tangens
- function wgAsn(x:extended):extended; Arcus Sinus
- function wgAcs(x:extended):extended; Arcus Cosinus
- function wgExp(x:extended):extended; Exponentialfunktion
- function wgPow(x,n:extended):extended; Potenzfunktion
- function wgLn(x:extended):extended; Logarithmus naturalis
- function wgLog10(x:extended):extended; Dekad. Logarithmus
-
- Diese Funktionen werden direkt vom Coprozessor zur Verfügung
- gestellt (ab 80387).
-
-
-
-
- Programmierhandbuch WG-Vision - 314 -
-
-
-
-
-
-
-
- Wenn Sie diese Unit neu kompilieren möchten, muß das
- Objektmodul FMATH.OBJ für den Compiler ereichbar sein.
-
- Folgendes kleine Testprogramm wurde auf einem 33 MHz 386'er
- AT mit ITT-Coprozessor abgearbeitet. Die Abarbeitungszeiten
- wurden mit dem Turbo-Profiler ermittelt:
-
- ...
- for i:=1 to 3600 do x:=ln(Pi/4); {bzw x:=wgln(Pi/4)}
- for i:=1 to 3600 do x:=sin(Pi/4); {bzw x:=wgsin(Pi/4)}
- for i:=1 to 3600 do x:=cos(Pi/4); {bzw x:=wgcos(Pi/4)}
- for i:=1 to 3600 do x:=exp(Pi/4); {bzw x:=wgexp(Pi/4)}
- ...
-
- 3.9106 sec ohne Coprozessor
- 0.6778 sec mit Coprozessor
- 0.1290 sec mit der Unit WCProc und Coprozessor
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 315 -
-
-
-
-
-
-
-
- 9. Verwendung von Overlays
-
- Zur effektiven Nutzung des verfügbaren Speichers ist die
- Verwendung von Overlays angebracht. Da die Toolbox selbst
- einen nicht unbeträchtlichen Teil des Hauptspeichers belegt,
- sollte bei der Entwicklung eines Anwendungsprogramms
- Funktionseinheiten konsequent in Units abgelegt werden, die
- sich als Overlays deklarieren lassen. Auf diese Weise können
- Sie mit Pascal mit ein wenig Überlegung und Planung sehr
- große und komplexe Programme entwickeln. Folgendes
- Programmfragment zeigt, wie ein WG-Vision-Programm aussieht,
- wenn es von Overlays gebrauch macht:
-
- {$I OVERLAY.INC}
- program SBG;
-
- USES Overlay, {muß an der ersten Position stehen !}
- WDecl,
- SBGDecl,
- WEMS,
- WDriver,
- WApp,
- WEvent,
- WViews,
- WDlg,
- WUtils,
- W256PCX,
- WFileDlg,
- SBGDlg,
- SBGIm,
- WCalc,
- WPalette,
- SBGPrint,
- printer,
- crt,
- dos,
- graph;
-
-
-
-
-
- Programmierhandbuch WG-Vision - 316 -
-
-
-
-
-
-
-
- {$O SBGDlg} {Overlays}
- {$O SBGIm}
- {$O WUtils}
- {$O WCalc}
- {$O WPalette}
- {$O W256PCX}
-
- const cmLoad=101;
- cmSaveAs=102;
-
- ...
-
- ...
-
- {Hauptprogramm}
-
- begin
- Sprache:=Deutsch;
- Nummer:=0;
- OvrInit('SBG.OVR'); {Overlay-Verwaltung initialisieren}
- if Sprache=Deutsch then MyApp.Init('Astronomische Bildbearbeitung')
- else MyApp.Init('Astronomical Image Processing');
- MyApp.Run;
- MyApp.Done;
- end.
-
- Prinzipiell kann ein größerer Teil von WG-Vision als
- Overlays verwendet werden. Aufgrund ihrer Verzahnung ist das
- jedoch selten sinnvoll, da die Performance des Programms da-
- durch stark abnimmt. Eigene Objekte, wie im obigen Beispiel
- praktiziert, sollten dagegen in Overlay-Dateien verpackt
- werden, besonders, wenn sie eine funktionelle Einheit bil-
- den.
- Weitere Einzelheiten zur Overlayverwaltung unter Turbo-
- Pascal finden Sie in den Handbüchern der Programmiersprache.
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 317 -
-
-
-
-
-
-
-
- Folgende Units von WG-Vision können als Overlays verwendet
- werden:
-
- WPCX
- W256PCX
- WCALC
- WERROR
- WFONT
- WHELP
- WICNEDIT
- WPALETTE
- WUHR
- WUTILS
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 318 -
-
-
-
-
-
-
-
- 10. Tips und Tricks
-
- 10.1. Wir basteln uns einen Screensaver
-
- Wenn Sie den Norton-Commander eine zeitlang sich selbst
- überlassen haben, schaltet er seinen Screensaver ein. Wir
- wollen jetzt in der gleichen Weise unsere WG-Vision-Program-
- me mit einem solchen Screensaver ausstatten. Wie Sie gleich
- sehen werden, ist das ganz einfach. Als Pausenbild wollen
- wir die Grafik-Animation verwenden, die in Form des Bei-
- spielprogramms ARTY.PAS den älteren Turbo-Pascal-Versionen
- beigelegt worden sind (z.B. Turbo-Pascal 5.5). Aus diesem
- Programm entfernen wir alle unnötigen Routinen und wandeln
- es in eine Unit um, die als einzige Prozedur DoArt nach
- außen übergibt. Es ist empfehlenswert, diese Unit in einem
- konkreten Anwendungsfall als Overlay zu kompilieren. Sie
- können übrigens in der gleichen Art weitere Units erstellen
- oder weitere Prozeduren in der Art von DoArt in die Unit
- ARTY.PAS einbauen, die andere Pausenanimationen aufblenden.
- Vielleicht schauen Sie sich mal zwecks "Ideenfindung" die
- Screensaver von Windows 3.1 an. Wenn Sie jetzt noch ein
- passendes Dialogfenster zur Einstellung des Screensavers
- programmieren (Art der Animation, Wartezeit bis zur
- Aktivierung), dann haben Sie mit Ihrem Programm fast das
- Niveau von Windows erreicht.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 319 -
-
-
-
-
-
-
-
- Hier der Quelltext der Unit ARTY.PAS:
-
- UNIT ARTY;
-
- interface
-
- uses crt,
- graph;
-
- procedure DoArt;
-
- implementation
-
- type ColorList=array[1..4] of integer;
- var Line:array[1..100] of record
- LX1,LY1: integer;
- LX2,LY2: integer;
- LColor : ColorList;
- end;
- X1,X2,Y1,Y2,CurrentLine,
- ColorCount,IncrementCount,
- DeltaX1,DeltaY1,DeltaX2,DeltaY2,
- i,MaxDelta:integer;
- Colors:ColorList;
- ChangeColors:boolean;
-
- procedure DoArt;
-
- procedure AdjustX(var X,DeltaX:integer);
- var TestX:integer;
- begin
- TestX:=X+DeltaX;
- if (TestX<1) or (TestX>640) then
- begin
- TestX:=X;
- DeltaX:=-DeltaX;
- end;
- X:=TestX;
- end;
-
-
-
- Programmierhandbuch WG-Vision - 320 -
-
-
-
-
-
-
-
- procedure AdjustY(var Y,DeltaY:integer);
- var TestY:integer;
- begin
- TestY:=Y+DeltaY;
- if (TestY<1) or (TestY>480) then
- begin
- TestY:=Y;
- DeltaY:=-DeltaY;
- end;
- Y:=TestY;
- end;
-
- procedure SelectNewColors;
- begin
- if not ChangeColors then Exit;
- Colors[1]:=Random(16)+1;
- Colors[2]:=Random(16)+1;
- Colors[3]:=Random(16)+1;
- Colors[4]:=Random(16)+1;
- ColorCount:=3*(1+Random(5));
- end;
-
- procedure SelectNewDeltaValues;
- begin
- DeltaX1 := Random(MaxDelta)-(MaxDelta Div 2);
- DeltaX2 := Random(MaxDelta)-(MaxDelta Div 2);
- DeltaY1 := Random(MaxDelta)-(MaxDelta Div 2);
- DeltaY2 := Random(MaxDelta)-(MaxDelta Div 2);
- IncrementCount := 2*(1+Random(4));
- end;
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 321 -
-
-
-
-
-
-
-
- procedure SaveCurrentLine(CurrentColors:ColorList);
- begin
- with Line[CurrentLine] do
- begin
- LX1:=X1; LY1:=Y1;
- LX2:=X2; LY2:=Y2;
- LColor:=CurrentColors;
- end;
- end;
-
- procedure Draw(x1,y1,x2,y2,color:word);
- begin
- SetColor(color);
- graph.line(x1,y1,x2,y2);
- end;
-
- procedure Updateline;
- begin
- Inc(CurrentLine);
- if CurrentLine>100 then CurrentLine:=1;
- Dec(ColorCount);
- Dec(IncrementCount);
- end;
-
- procedure DrawCurrentLine;
- var c1,c2,c3,c4:integer;
- begin
- c1:=Colors[1];
- c2:=Colors[2];
- c3:=Colors[3];
- c4:=Colors[4];
- Draw(X1,Y1,X2,Y2,c1);
- Draw(640-X1,Y1,640-X2,Y2,c2);
- Draw(X1,480-Y1,X2,480-Y2,c3);
- Draw(640-X1,480-Y1,640-X2,480-Y2,c4);
- SaveCurrentLine(Colors);
- end;
-
-
-
-
-
- Programmierhandbuch WG-Vision - 322 -
-
-
-
-
-
-
-
- procedure EraseCurrentLine;
- begin
- with Line[CurrentLine] do
- begin
- Draw(LX1,LY1,LX2,LY2,0);
- Draw(640-LX1,LY1,640-LX2,LY2,0);
- Draw(LX1,480-LY1,LX2,480-LY2,0);
- Draw(640-LX1,480-LY1,640-LX2,480-LY2,0);
- end;
- end;
-
- begin
- CurrentLine:=1; ColorCount:=0; MaxDelta:=16;
- IncrementCount:=0; ChangeColors:=true;
- for i := 1 to 100 do
- with Line[i] do
- begin
- LX1:=320; LX2:=320;
- LY1:=240; LY2:=240;
- end;
- X1:=320; X2:=320; Y1:=240; Y2:=240;
- ClearViewport; SelectNewColors;
- repeat
- EraseCurrentLine;
- if ColorCount=0 then SelectNewColors;
- if IncrementCount=0 then SelectNewDeltaValues;
- AdjustX(X1,DeltaX1); AdjustX(X2,DeltaX2);
- AdjustY(Y1,DeltaY1); AdjustY(Y2,DeltaY2);
- if Random(5)=3 then
- begin
- x1:=(x1+x2) div 2;
- y2:=(y1+y2) div 2;
- end;
- DrawCurrentLine; Updateline;
- until keypressed;
- end;
-
- END.
-
-
-
-
- Programmierhandbuch WG-Vision - 323 -
-
-
-
-
-
-
-
- Der Screensaver wird in den Eventhandler der Applikation
- eingebaut. Er soll immer dann aktiviert werden, wenn inner-
- halb der Wartezeit Wait (in Sekunden) weder ein Tastatur-
- noch ein Mausereignis stattgefunden hat. Das bedeutet, wir
- müssen immer dann die Zeit stoppen, wenn Event.What<>evNot-
- hing ist und diesen Zeitpunkt als Nullpunkt verwenden (Zero-
- Time). Danach bestimmen wir die Differenz zwischen der
- aktuellen Zeit (wenn das Programm den Eventhandler durch-
- läuft) und ZeroTime und vergleichen Sie mit der Pausenzeit
- Wait. Überschreitet die Zeitdifferenz den Wert von Wait,
- dann wird der Screensaver aufgeblendet:
-
- procedure ScreenSaver;
- var Stunde,Minute,Sekunde,HSec:word;
- begin
- GetTime(Stunde,Minute,Sekunde,HSec);
- if Event.What<>evNothing then ZeroTime:=Stunde*3600+Minute*60+Sekunde
- else StopTime:=Stunde*3600+Minute*60+Sekunde;
- if (StopTime-ZeroTime)>Wait then
- begin
- Mouse.HideMouse;
- DoArt;
- Draw;
- Mouse.ShowMouse;
- end;
- end;
-
- Wait wird entweder fest im Programm festgelegt (z.B. 5 Minu-
- ten=300 Sekunden) oder über einen Dialog individuell einge-
- stellt. ZeroTime, StopTime und Wait werden am besten als
- Feld des Applikationsobjekts deklariert und im Konstruktor
- initialisiert.
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 324 -
-
-
-
-
-
-
-
- Der Eventhandler sieht mit dem Screensaver in etwa folgen-
- dermaßen aus:
-
- procedure TApplication.HandleEvent;
- begin
- TProgram.HandleEvent;
- ScreenSaver;
- case Event.Command of
- ...
-
- end; {case}
- end;
-
- Hinweis:
- Wenn Sie auf dem Bildschirm Objekte aufgeblendet haben, die
- nicht irgendwie in der Objektliste des Programms enthalten
- sind (z.B. Bildchen, die gerade auf dem Desktophintergrund
- bearbeitet werden und noch nicht abgespeichert sind), dann
- kann die Draw-Methode allein den ursprünglichen Bildschirm-
- Zustand nicht wieder rekonstruieren. In diesem Fall machen
- Sie einfach von folgender Möglichkeit gebrauch. Retten Sie
- bevor Sie DoArt aufrufen den gesamten Bildschirminhalt in
- den EMS oder auf die Festplatte (TEMS, THardDisk). Nach Be-
- endigung von DoArt wird dann der Untergrund einfach wieder-
- hergestellt. In diesem Fall brauchen Sie die Draw-Methode
- von TApplication überhaupt nicht mehr bemühen. Da eventuell
- vorhandene Fenster nicht neu dargestellt werden müssen, ist
- dieser Weg auch bedeutend schneller.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 325 -
-
-
-
-
-
-
-
- WG-VISION 1.0
-
- INTERFACEDOKUMENTATION DER UNITS
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Globale Deklarationen und grund- *
- * legende Objekte (TRect,TPoint) *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WDecl;
-
- interface
-
- const {Grafik-Treiber}
-
- EGA = 3; { 16 Farben}
- VGA = 9; { 16 Farben}
- IBM8514 = 6; {256 Farben}
- VESA = 11; {256 Farben}
-
- {Grafik-Modi}
-
- M640x350 = 1;
- M640x480 = 2;
- M800x600 = 3;
- M1024x768 = 4;
-
-
-
-
- Programmierhandbuch WG-Vision - 326 -
-
-
-
-
-
-
-
- {Summasketch-Digitizer}
-
- XON = ^Q; {Übertragungsprotokoll}
- XOFF = ^S;
-
- DGRESET = #0; {Rücksetzen}
- SELFTEST = #116; {Selbsttest}
- SENDRES = #119; {Senden der Selbsttest-Resultate}
- SENDCONF = #97; {Konfiguration senden}
- SENDMODEL = #5; {Model-Identifikationsstring senden}
-
- BCD = #122#97; {Ausgabe im ASCI-BCD-Format}
-
- POINT = #66; {Point-Mode einschalten}
- Stream = #64; {Stream-Mode einschalten}
- SWSTREAM = #65; {Switch-Stream-Mode einschalten}
-
- {Report-Rate}
-
- RR110 = #81; {Report-Rate 110 rps}
- RR50 = #82; {Report-Rate 50 rps}
- RR10 = #83; {Report-Rate 10 rps}
- RR2 = #84; {Report-Rate 2 rps}
-
- {Auflösung}
-
- Res1 = #108; {Auflösung 1 lpi}
- Res2 = #110; {Auflösung 2 lpi}
- Res4 = #112; {Auflösung 12 lpi}
- Res100 = #100; {Auflösung 100 lpi}
- Res200 = #101; {Auflösung 200 lpi}
- Res400 = #103; {Auflösung 400 lpi}
- Res500 = #104; {Auflösung 500 lpi}
- Res1000 = #106; {Auflösung 1000 lpi}
-
- {Koordinatensystem}
-
- ABSOLUT = #70; {absolutes Koordinatensystem}
- RELATIV = #69; {relatives Koordinatensystem}
-
-
-
- Programmierhandbuch WG-Vision - 327 -
-
-
-
-
-
-
-
- {Fehler}
-
- gr = 1; {Index für Grafik-Fehler (GraphResult)}
- ems = 2; {Index für EMS-Fehler}
- joy = 3; {Joystick-Fehler}
- DS = 4; {DOS-Fehler}
- io = 5; {Ein-/Ausgabefehler}
- mst = 6; {schwerwiegende Fehler}
- pr = 7; {Drucker-Fehler}
-
- {Joystick-Fehler}
-
- joyNoGamePortPresent = 1;
-
- {VGA/EGA Standardfarben}
-
- Black = 0;
- Blue = 1;
- Green = 2;
- Cyan = 3;
- Red = 4;
- Magenta = 5;
- Brown = 6;
- LightGray = 7;
- DarkGray = 8;
- LightBlue = 9;
- LightGreen = 10;
- LightCyan = 11;
- LightRed = 12;
- LightMagenta = 13;
- Yellow = 14;
- White = 15;
-
- LeftText = 0; {Text-Ausrichtung}
- CenterText = 1;
- RightText = 2;
-
- HorizDir = 0;
- VertDir = 1;
-
-
-
- Programmierhandbuch WG-Vision - 328 -
-
-
-
-
-
-
-
- NormWidth = 1; {Linien- und Rahmenstärke}
- ThickWidth = 3;
-
- DefaultFont = 0; {Vektorzeichensätze}
- TriplexFont = 1;
- SmallFont = 2;
- SansSerifFont = 3;
- GothicFont = 4;
- ScriptFont = 5;
- SimpleFont = 6;
- TSCRFont = 7;
- LCOMFont = 8;
- EuroFont = 9;
-
- Deutsch = 1;
- Englisch = 2;
-
- winSingle = 0;
- winDouble = 1;
- winPanel = 2;
- winMenu = 4;
- winKey = 8;
-
- palStandard = 1;
- palRed = 2;
- palGray = 3;
- palGreen = 4;
-
- VScrBar = 1;
- HScrBar = 2;
- DScrBar = 3;
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 329 -
-
-
-
-
-
-
-
- {Ereignisse}
-
- evNothing = 0; {kein Ereignis}
- evMouse = 1; {Mausereignis}
- evKeyboard = 2; {Keyboard-Ereignis}
- evMessage = 3; {Botschaft oder Befehlsereignis}
- evCommand = 4; {Befehlsereignis}
- evBroadcast = 5; {Rundruf-Ereignis}
-
- {Infos}
-
- infNothing = 0; {keine Info}
- infMenuAktiv = 1; {Info "Menü ist aktiv"}
- infDeaktivated = 2; {Fenster deaktiviert}
-
- {Kommandos}
-
- cmNothing = 0; {nichts}
- cmCloseApplication = 1; {Programm beenden}
- cmCloseWindow = 2; {Fenster schließen}
- cmWindowNewSize = 3; {Fenster hat sich verändert}
- cmSelectWindow = 4; {Fenster selektiert}
- cmScrollBarChanged = 5; {Rollbalken verändert}
- cmExit = 7;
- cmOK = 8;
- cmCancel = 9;
-
- cmYes =10;
- cmNo =11;
-
- cmUp =12;
- cmDown =13;
-
- {Mitteilungen}
-
- msgNothing = 0; {nichts}
- msgError = 1; {Fehler aufgetreten}
- msgNewMask = 2; {neue Eingabemaske}
-
-
-
-
- Programmierhandbuch WG-Vision - 330 -
-
-
-
-
-
-
-
- {Tasten-Codes}
-
- kbF1 = 59; kbF6 = 64; kbF11 = 133;
- kbF2 = 60; kbF7 = 65; kbF12 = 134;
- kbF3 = 61; kbF8 = 66;
- kbF4 = 62; kbF9 = 67;
- kbF5 = 63; kbF10 = 68;
-
- kbArrowLeft = 75; kbHome = 71; CtrlPgUp = 132;
- kbArrowRight = 77; kbPgDn = 81; CtrlPgDn = 118;
- kbArrowUp = 72; kbPgUp = 73;
- kbArrowDown = 80; kbEnd = 79;
- kbInsert = 82; kbDel = 83;
-
- altA = 30; altM = 50; altY = 21; altF1 = 104;
- altB = 48; altN = 49; altZ = 44; altF2 = 105;
- altC = 46; altO = 24; altF3 = 106;
- altD = 32; altP = 25; altF4 = 107;
- altE = 18; altQ = 16; altF5 = 108;
- altF = 33; altR = 19; altF6 = 109;
- altG = 34; altS = 31; altF7 = 110;
- altH = 35; altT = 20; altF8 = 111;
- altI = 23; altU = 22; altF9 = 112;
- altJ = 36; altV = 47; altF10 = 113;
- altK = 37; altW = 17; altF11 = 139;
- altL = 38; altX = 45; altF12 = 140;
-
- alt1 = 120; ShiftF1 = 84; ShiftF11 = 135;
- alt2 = 121; ShiftF2 = 85; ShiftF12 = 136;
- alt3 = 122; ShiftF3 = 86;
- alt4 = 123; ShiftF4 = 87;
- alt5 = 124; ShiftF5 = 88;
- alt6 = 125; ShiftF6 = 89;
- alt7 = 126; ShiftF7 = 90;
- alt8 = 127; ShiftF8 = 91;
- alt9 = 128; ShiftF9 = 92;
- alt0 = 129; ShiftF10 = 93;
-
-
-
-
-
- Programmierhandbuch WG-Vision - 331 -
-
-
-
-
-
-
-
- CtrlA = ^A; CtrlM = ^M; CtrlY = ^Y; CtrlF1 = 94;
- CtrlB = ^B; CtrlN = ^N; CtrlZ = ^Z; CtrlF2 = 95;
- CtrlC = ^C; CtrlO = ^O; CtrlF3 = 96;
- CtrlD = ^D; CtrlP = ^P; CtrlF4 = 97;
- CtrlE = ^E; CtrlQ = ^Q; CtrlF5 = 98;
- CtrlF = ^F; CtrlR = ^R; CtrlF6 = 99;
- CtrlG = ^G; CtrlS = ^S; CtrlF7 = 100;
- CtrlH = ^H; CtrlT = ^T; CtrlF8 = 101;
- CtrlI = ^I; CtrlU = ^U; CtrlF9 = 102;
- CtrlJ = ^J; CtrlV = ^V; CtrlF10 = 103;
- CtrlK = ^K; CtrlW = ^W; CtrlF11 = 137;
- CtrlL = ^L; CtrlX = ^X; CtrlF12 = 138;
-
- kbShiftTab = 15;
-
- kbEsc = #27;
- kbEnter = #13;
- kbTab = #9;
- kbSpace = #32;
-
- {Menge der Scancodes aller Tasten, die sich als Shortcuts eignen}
-
- SpecialKey = [16..25,30..38,44..50,59..68,84..113,120..129,135..140];
-
- {Zahlen, Komma,Vorzeichen}
-
- Ziffern = ['0'..'9','.','-'];
-
- {ASCII-Zeichen}
-
- ASCII = [' '..'■'];
-
- {Buchstaben}
-
- Character = ['A'..'Z','a'..'z','Ä','Ö','Ü','ä','ö','ü','ß'];
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 332 -
-
-
-
-
-
-
-
- type tMinSet=set of 0..15; {Kleine Zahlenmenge}
- tError =record
- FTyp:byte;
- FNummer:integer; {Fehler-Code}
- end;
-
- var SVGA : boolean; {Super-VGA mit 256 Farben ?}
- Fehler : tError; {Container für Fehler}
-
- FrameDeaktivated : boolean; {Rahmen deaktiviert ?}
- WListPresent : boolean; {Window-Liste in Abarbeitung ?}
- IconBarPresent : boolean; {Iconbar vorhanden ?}
-
- {Objekt-Deklarationen}
-
- type {String-Typen}
-
- str8 = string[8];
- str10 = string[10];
- str12 = string[12];
- str25 = string[25];
- str40 = string[40];
- str80 = string[80];
-
- {Punkt}
-
- TPoint=object
- X,Y:integer;
- end;
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 333 -
-
-
-
-
-
-
-
- {Rechteck-Objekt}
-
- TRect=object
- A,B:TPoint;
- procedure Assign(XA,YA,XB,YB:integer); {Koordinatenzuweisung}
- procedure Copy(R:TRect); {R in A,B kopieren}
- procedure Get(var R:TRect); {A,B in R kopieren}
- procedure Move(ADX,ADY:integer); {Verschieben}
- procedure Grow(ADX,ADY:integer); {Resize, Punkt A bleibt fest}
- function Contains(P:TPoint):boolean; {Punkt P innerhalb TRect ?}
- function Equals(R:TRect):boolean; {R=TRect ?}
- end;
-
- {Basis-Objekt}
-
- PObject = ^TObject;
- TObject = object
- constructor Init;
- destructor Done; virtual;
- end;
-
-
- var Path_To_SwapFile : str80;
- Sprache : byte;
- WorkArea: TRect; {Arbeitsbereich des Desktop}
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 334 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Applicationsobjekt *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WApp;
-
- interface
-
- uses WDecl,
- WDriver,
- WViews,
- WDlg,
- WEvent,
- WUtils,
- WEMS,
- WHelp,
- WError,
- Graph,
- Crt;
-
-
- type PDsktpBgrd=^TDsktpBgrd; {Standard-Hintergrund des Desktop}
- TDsktpBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 335 -
-
-
-
-
-
-
-
- PProgram=^TProgram;
- TProgram=object(TGroup)
- DeskTop : PDeskTop; {Desktop}
- MMenu : PMainMenu; {Liste der Hauptmenüeintragungen}
- Heap : PHeap; {Heapverwaltung}
- EMS : PEMS; {EMS-Verwaltung}
- MPos : integer;
- MAnzahl : byte; {Enthält die Anzahl der Hauptmenüfelder}
- Aktiv : boolean; {Menü aktiv ?}
- SAktiv : boolean; {PD-Menü aktiv ?}
- SIndex : byte;
- WinAnz : byte; {Anzahl der Eintragungen in der Windowliste}
- Modal : boolean; {aktives Fenster nicht-modal ?}
- ifHelp : boolean; {mit Hilfe-System ?}
- HelpFile: string; {Name der Hilfsdatei}
- constructor Init(Titel:string);
- destructor Done; virtual;
- procedure Draw; virtual;
- procedure Run;
- procedure HandleEvent; virtual;
- procedure InsertDesktop(Item:PGroup);
- procedure SetDesktopFrame(Titel:string); virtual;
- procedure SetDesktopBackground; virtual;
- procedure StatusBar; virtual;
- procedure MainMenu(Eintrag:str25;Help:byte);
- procedure SubMenu(Eintrag:str25;Kommando:word;Help,Key:byte;
- Akt,Kennz:boolean);
- procedure NewLine;
- procedure InitVideoDevice; virtual;
- procedure InitMenuBar; virtual;
- procedure LoadMenu(ResName:str80);
- procedure ClearMenu;
- procedure DrawMainMenu;
- procedure SetDialogData; virtual;
- procedure SetOnlineHelp(HelpDatei:string);
- procedure MessageBox(Caption:word;PanelText,InfoText:string);
- procedure HelpBox(FName:string;HelpCtx:word);
-
-
-
-
-
- Programmierhandbuch WG-Vision - 336 -
-
-
-
-
-
-
-
- Private
- Delta : ShortInt;
- ImgSize : word;
- P : Pointer;
- AktivNr : byte; {Nr des aktiven Hauptmenüpunktes}
- SAktivNr : byte; {Nr des aktiven Untermenüpunktes}
- FK : byte;
- LfdPtr : PGroup;
- SWButton : TRect;
- procedure DrawSubMenu(Nr:byte);
- procedure RestoreMenuBackground(Nr:byte);
- end;
-
- PApp=^TApp;
- TApp=object(TProgram)
- constructor Init(Titel:string);
- destructor Done; virtual;
- end;
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 337 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Objektverwaltung *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WViews;
-
- interface
-
- uses WDecl,
- WText,
- WUtils,
- WDriver,
- WEvent,
- WEMS,
- Dos,
- Graph;
-
- const MaxMainMenu = 10;
- MaxSubMenu = 20;
-
- {Speichertypen}
-
- memNothing = 0;
- memEMS = 1;
- memHardDisk = 2;
- memHeap = 3;
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 338 -
-
-
-
-
-
-
-
- {DragMode}
-
- dmNoMove = 0; {Objekt darf nicht bewegt werden}
- dmMove = 1; {Objekt darf verschoben werden}
- dmGrow = 2; {Objekt darf seine Größe ändern}
-
- {Farbpaletten}
-
- Palette1 : string = #0#7#0#1#9#15#15#15#15#8#0#15#7; {Rahmen}
- Palette2 : string = #15#0#15#8#15#0#0#0#7#7#15#8; {Standardpalette}
- {Menü}
- Palette3 : string = #15#0#7#7#15#0#8; {Rollbalken}
- Palette4 : string = #0#15#7#8#15#0#7#15; {Push-Button}
- Palette5 : string = #0#15#8#0#7#8#0#8#15#0#7; {Radio/Check-}
- {Button,InputLine,Listbox}
-
- palStandard = 1;
- palRed = 2;
- palGray = 3;
- palGreen = 4;
-
- Pal : array[1..4] of string =
- ((#0#7#0#1#9#15#15#15#15#8#0#15#7), {palStandard}
- (#0#12#0#4#12#14#15#15#15#8#0#15#7), {palRed}
- (#0#7#0#7#15#0#15#15#15#8#0#15#7), {palGray}
- (#0#2#0#2#10#1#15#15#15#8#0#15#7)); {palGreen}
-
- Gray50 : FillPatternType = ($AA,$55,$AA,$55,$AA,$55,$AA,$55);
-
- type TPalette=string;
-
- PObject=^TObject;
- TObject=object
- end;
-
- PGroup=^TGroup;
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 339 -
-
-
-
-
-
-
-
- PView=^TView;
- TView=object(TObject)
- Prev : PGroup;
- Next : PGroup;
- Palette : TPalette; {Farbpalette}
- Origin : TPoint; {Ursprung (linke obere Ecke)}
- Size : TPoint; {Länge und Breite}
- RSize : boolean; {Fenster bis auf Minimalmaße verkleinerbar}
- constructor Init(var Bounds:TRect;SetSize:boolean);
- destructor Done; virtual;
- procedure SetBounds(var Bounds:TRect); virtual;
- procedure GetBounds(var Bounds:TRect);
- procedure ChangeBounds(var Bounds:TRect);
- procedure GrowTo(X,Y:integer);
- procedure Locate(var Bounds:TRect);
- function GetPalColor(Index:byte):byte; virtual;
- end;
-
- TGroup=object(TView)
- First : PGroup;
- Last : PGroup;
- Current : PGroup;
- CurrNo,
- AnzElem : word;
- constructor Init;
- destructor Done; virtual;
- procedure SetArea(Bounds:TRect); virtual;
- procedure InsertItem(Item:PGroup);
- procedure DeleteItems;
- function GetItems(Nr:word):PGroup;
- procedure UnchainItem(N:PGroup);
- procedure DelItem(N:PGroup);
- procedure DelLastItem;
- procedure Draw; virtual;
- procedure Hide; virtual;
- procedure NewItemList; virtual;
- procedure SwapItems(I:word);
- procedure SetPos(R:TRect); virtual;
- procedure SetTextPos(X,Y:integer); virtual;
-
-
-
- Programmierhandbuch WG-Vision - 340 -
-
-
-
-
-
-
-
- procedure SetData(var Rec); virtual;
- procedure GetData(var Rec); virtual;
- procedure HandleEvent; virtual;
- Private
- Flag : boolean;
- procedure DisposeItem(N:PGroup);
- procedure AddElem(N,NextPos:PGroup);
- end;
-
- PLine=^TLine;
- TLine=object(TGroup)
- Eintrag:string;
- function GetDataString:string; virtual;
- end;
-
- PHardDisk = ^THardDisk; {Zeiger auf die Speicherobjekte}
- PEMS = ^TEMS;
- PHeap = ^THeap;
-
- PMemory=^TMemory;
- TMemory=object(TGroup)
- BSize : longint; {notwendige Puffergröße in Byte}
- Error : byte; {Fehler-Nr.}
- HardDisk : PHardDisk;
- EMS : PEMS;
- Heap : PHeap;
- MemoryTyp : byte;
- constructor Init(Bounds:TRect);
- destructor Done; virtual;
- procedure SetArea(Bounds:TRect); virtual;
- procedure Draw; virtual;
- procedure Hide; virtual;
- Private
- MaxSize : word; {65534 = 2*MaxInt}
- end;
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 341 -
-
-
-
-
-
-
-
- THardDisk=object(TMemory)
- Drive : byte;
- SwapFile : PathStr; {Name der Swapdatei}
- FreeMemory : longint; {freie Festplattenkapazität}
- Part : word;
- constructor Init(Bounds:TRect);
- destructor Done; virtual;
- procedure Save; virtual;
- procedure Restore(P:TPoint); virtual;
- end;
-
- TEMS=object(TMemory)
- Version : byte; {EMS-Version}
- FreeMemory : longint; {freier EMS-Speicher}
- Anzeige : TText;
- Handle : word;
- Part : word;
- constructor Init(Bounds:TRect);
- destructor Done; virtual;
- procedure Save; virtual;
- procedure Restore(P:TPoint); virtual;
- procedure Watch;
- procedure ShowEMSStatus(X,Y,Color:integer);
- Private
- Change : boolean;
- end;
-
- THeap=object(TMemory)
- FreeMemory : longint; {freier Heap}
- FreeMaxAvail : longint; {größter freier zusammenhängender}
- {Speicherblock}
- Anzeige : TText;
- Buffer : Pointer;
- constructor Init(Bounds:TRect);
- destructor Done; virtual;
- procedure Save; virtual;
- procedure Restore(P:TPoint); virtual;
- procedure HeapWatch;
- procedure ShowHeapStatus(X,Y,Color:integer);
-
-
-
- Programmierhandbuch WG-Vision - 342 -
-
-
-
-
-
-
-
- Private
- Change : boolean;
- end;
-
- PFrame=^TFrame;
- TFrame=object(TGroup)
- FTyp : byte; {Rahmentyp}
- Header : TText; {Headertext}
- Area : TRect; {Bereich innerhalb des Rahmens}
- ZoomRect : TRect; {Speichert die originale Fenstergröße}
- DragMode : byte; {Verhalten des Fensters bei Veränderungen}
- constructor Init(var Bounds,Z:TRect;KopfText:string;Typ:byte);
- destructor Done; virtual;
- procedure SetArea(Bounds:TRect); virtual;
- procedure SetActivAreas(var Bounds:TRect); virtual;
- procedure Draw; virtual;
- procedure Hide; virtual;
- procedure HandleEvent; virtual;
- Private
- ActFrame : array[1..17] of TRect;
- procedure DrawFrame(Typ:byte);
- end;
-
- PBackground=^TBackground;
- TBackground=object(TGroup)
- Border : TRect;
- constructor Init(R:TRect);
- destructor Done; virtual;
- procedure SetArea(Bounds:TRect); virtual;
- procedure Draw; virtual;
- procedure Hide; virtual;
- end;
-
- PSubMenu=array[1..MaxSubMenu] of ^TSubMenu;
-
- PMainMenu=array[1..MaxMainMenu] of ^TMainMenu;
- TMainMenu=object(TView)
- Area : TRect; {Bereich des PD-Menüs}
- Item : str25; {Eintrag}
-
-
-
- Programmierhandbuch WG-Vision - 343 -
-
-
-
-
-
-
-
- BS : byte; {Position des Kennbuchstabens}
- HelpCtx : word; {Nummer für Hilfesystem}
- AnzSMenu : byte; {Anzahl der PD-Menüeintragungen}
- SbMenu : PSubMenu;
- constructor Init(R:TRect;Bez:str25;Help:byte);
- destructor Done; virtual;
- end;
-
- TSubMenu=object(TMainMenu)
- MCommand : word; {Aufruf-Kommando}
- ShortKey : byte; {spezielle Aufruftaste}
- Grayed : boolean; {Menüfeld anwählbar}
- Haken : boolean; {zeigt bei Menüschaltern Schalterstellung an}
- constructor Init(R:TRect;Bez:str25;Kommand:word;Help,Key:byte;
- Act,Kennz:boolean);
- destructor Done; virtual;
- procedure Aktiviere;
- procedure DeAktiviere;
- procedure HookOn;
- procedure HookOff;
- end;
-
- PDeskTop=^TDeskTop;
- TDeskTop=object(TGroup)
- List : PGroup; {Desktop-Elemente}
- Frame : PFrame; {Zeiger auf den Rahmen}
- Bgrd : PBackground; {Zeiger auf den Untergrund}
- WinList : PGroup; {Liste der Windows}
- WinCount : byte; {Anzahl der geöffneten Fenster}
- constructor Init;
- destructor Done; virtual;
- procedure SetBackground;
- procedure Draw; virtual;
- end;
-
-
- implementation
-
-
-
-
-
- Programmierhandbuch WG-Vision - 344 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Treiber für Bildschirm, Maus *
- * Joystick und Summagraphics- *
- * Digitizer *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WDriver;
-
- interface
-
- uses WDecl,
- Dos,
- Crt,
- Graph;
-
- type tDigiData=record {Datenrecord Summagrafic-Digitizer}
- X,Y:word;
- Taste:byte;
- end;
-
- TVideoDevice=object(TObject)
- Treiber : integer; {Grafik-Treiber}
- OrigMode : integer; {letzter Textmodus}
- Modus : integer; {aktiver Grafik-Modus}
- Modi : tMinSet; {erlaubte Grafik-Modi}
- XMax : word; {maximal mögliche x-Koordinate des Bildschirms}
- YMax : word; {maximal mögliche y-Koordinate des Bildschirms}
- Colors : word; {Anzahl Farben}
-
-
-
-
-
- Programmierhandbuch WG-Vision - 345 -
-
-
-
-
-
-
-
- constructor Init(Driver,Mode:integer);
- destructor Done; virtual;
- function GetXMax:word;
- function GetYMax:word;
- function GetAnzColors:word;
- function GetDriver:string;
- function GetGrafikMode:integer;
- procedure ChangeGraficMode(Mode:integer);
- procedure SetTextMode;
- procedure SetDirectVideo(Direct:boolean);
- end;
-
- TJoyStickDevice=object(TObject)
- JoyPresent : boolean; {Spieleadapter vorhanden ?}
- JPos : TPoint; {absolute Position}
- Phi : Single; {horizontale Auslenkung}
- Elongation : Single; {Betrag der Auslenkung}
- FPush1 : boolean; {1. Feuertaste gedrückt ?}
- FPush2 : boolean; {2. Feuertaste gedrückt ?}
- procedure Init;
- procedure JoyStickHandle; {Joystick-Handler}
- function IfJoyPresent:boolean; {Spieleadapter vorhanden ?}
- function Degree:integer; {Winkel}
- function Turn:word; {Betrag der Auslenkung}
- function GetXValue:integer; {x-Position}
- function GetYValue:integer; {y-Position}
- function PushOne:boolean; {erste Feuertaste betätigt}
- function PushTwo:boolean; {zweite Feuertaste betätigt}
- end;
-
- TMouseDevice=object(TObject)
- MousePresent : boolean; {Maus installiert ?}
- FName : string; {Dateiname der Mauszeiger-Ressource}
- Position : TPoint; {Position des Mauskursors}
- DX,Dy : integer; {letzte Veränderung}
- LeftButton : boolean; {linke Taste gedrückt}
- RightButton : boolean; {rechte Taste gedrückt}
- LButtonChange : boolean; {linke Maustaste verändert ?}
- RButtonChange : boolean; {rechte Maustaste verändert ?}
-
-
-
- Programmierhandbuch WG-Vision - 346 -
-
-
-
-
-
-
-
- DoubleKlick : boolean; {Doppelklick ?}
- Time : word;
- KlickTime : word; {Zeitdifferenz für Doppelklick}
- Area : TRect; {Bereichsgrenzen für die Mausbewegung}
- CursorTyp : byte; {Kursortyp}
- procedure Init; {Initialisierung}
- procedure ShowMouse; {Mauskursor anzeigen}
- procedure HideMouse; {Mauskursor löschen}
- procedure SetMouseArea(X1,Y1,X2,Y2:integer);
- procedure PutMouse(X,Y:integer); {Maus auf dem Bildschirm}
- {positionieren}
- procedure MouseSpeed(XSpeed,YSpeed:integer); {Mausgeschwindigkeit}
- function MouseHandler:boolean; {Maushandler}
- function GetXPos:integer; {x-Koordinate des Mauszeigers}
- function GetYPos:integer; {y-Koordinate des Mauszeigers}
- procedure GetPos(var MP:TPoint); {Koordinaten des Mauszeigers}
- function LButtonKlick:boolean; {linke Maustaste geklickt ?}
- function RButtonKlick:boolean; {rechte Maustaste geklickt ?}
- function LButtonDrag:boolean; {linke Maustaste gedrückt bewegt?}
- function RButtonDrag:boolean; {rechte Maustaste gedrückt bewegt?}
- function LButtonRel:boolean; {linke Taste losgelassen ?}
- function RButtonRel:boolean; {rechte Taste losgelassen ?}
- function Double:boolean; {Doppelklick}
- procedure SetKlickTime(T:byte); {Zeitdifferenz für Doppelklick}
- function MMove:boolean; {Maus nur bewegt}
- procedure SetCursorTyp(CTyp:byte); {Mauskursor ändern}
- procedure LoadCursorTyp(F:string); {Mauszeiger aus Ressource laden}
- Private
- function GetTicks:word;
- end;
-
- TKeyboardDevice=object(TObject)
- ATFlag : boolean; {AT-Tastatur ?}
- Delay : integer; {Tastatur-Verzögerung}
- Speed : integer; {Wiederholfrequenz}
- KeyCode : Char; {ASCII-Zeichen der Taste}
- ScanCode : byte; {Scancode der Taste}
- StatusFlag : byte; {Statusflag der Sondertasten}
- KeyPush : boolean; {Taste gedrückt (true) oder losgelassen ?}
-
-
-
- Programmierhandbuch WG-Vision - 347 -
-
-
-
-
-
-
-
- Locking : boolean; {Tastatur gesperrt ? (false)}
- procedure Init;
- procedure LockKeyboard; {Tastatur sperren}
- procedure UnLockKeyboard; {Tastatur wieder freigeben}
- procedure ClearKeyboardBuffer; {Tastaturpuffer löschen}
- function SetTypmaticRate(Verzoegerung,
- Wiederholfrequenz:integer):boolean;
- function KeyboardHandler:boolean;
- function GetKeyCode:Char; {übergibt Keycode}
- function GetScanCode:byte; {übergibt Scancode}
- function IfKeyPush:boolean; {Taste heruntergedrückt ?}
- function IfKeybLock:boolean; {Tastatur gesperrt ?}
- function RShiftKey:boolean; {rechte Shift-Taste gedrückt ?}
- function LShiftKey:boolean; {linke Shifttaste gedrückt ?}
- function CtrlKey:boolean; {Ctrl-Taste gedrückt ?}
- function AltKey:boolean; {Alt-Taste gedrückt ?}
- function ScrollLock:boolean; {Scroll-Lock-Taste gedrückt ?}
- function NumLock:boolean; {Num-Lock-Taste gedrückt ?}
- function CapsLock:boolean; {Caps-Lock-Taste gedrückt ?}
- end;
-
- TSSDigiDevice=object(TObject)
- COMPort : byte; {serielle Schnittstelle}
- Buffer : string[20]; {Puffer zum Zwischenspeicher der}
- {Koordinaten}
- DigiData : tDigiData; {Digitizer-Daten}
- procedure Init(SPort:byte); {Initialisierung der seriellen}
- {Schnittstelle}
- procedure SetCommand(cc:string); {Kommando cc senden}
- procedure SetStreamMode; {Stream-Mode einschalten}
- procedure SetPointMode; {Point-Mode einschalten}
- procedure SetSwitchStreamMode; {Switch-Stream-Mode einschalten}
- procedure SetResolution(cc:Char); {Auflösung festlegen}
- procedure SetReportRate(cc:Char); {Übertragungsrate festlegen}
- procedure SetFrameWork(cc:Char); {Koordinatensystem festlegen}
- function GetModelIdentifier:string; {Identifikationsstring empfangen}
- procedure DigiHandle; {Digitizer-Handler}
- function GetXValue:word; {y-Wert}
- function GetYValue:word; {y-Wert}
-
-
-
- Programmierhandbuch WG-Vision - 348 -
-
-
-
-
-
-
-
- function GetTaste:byte; {Lupen-oder Stifttaste}
- Private
- procedure InitComPort(BaudRate:integer;par,stops,Char:byte);
- procedure SendChar(cc:Char);
- function ReceiveChar:Char;
- procedure SelectValue;
- end;
-
- var Mouse:TMouseDevice;
- Keyb :TKeyboardDevice;
- Video:TVideoDevice;
- Joy :TJoyStickDevice;
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 349 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Fenster- und Dialogobjekte *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WDLG;
-
- interface
-
- uses WDecl,
- WDriver,
- WEvent,
- WViews,
- WUtils,
- WText,
- Graph;
-
-
- type PScrollBar=^TScrollBar;
- PIcon=^TIcon;
-
- ZMenge=set of Char;
-
- PWindow=^TWindow;
- TWindow=object(TGroup)
- List : PGroup; {Fenster-Elemente}
- Undergrd : PMemory; {Speicher für Fenster-Untergrund}
- Frame : PFrame; {Zeiger auf den Rahmen des Fensters}
- Bgrd : PBackground; {Zeiger auf den Fenster-Hintergrund}
- SBH,SBV : PScrollBar; {vertikaler und horizontaler Scrollbalken}
- ZoomRect : TRect; {Original-Fenstergröße}
-
-
-
- Programmierhandbuch WG-Vision - 350 -
-
-
-
-
-
-
-
- Title : str80; {Fenster-Header}
- Typ : byte; {Rahmentyp}
- WinModal : boolean; {Fenster nicht-modal ?}
- ChildPresent : boolean; {Childfenster aktiv ?}
- constructor Init(var Bounds:TRect;ATitle:str80;AType:byte);
- destructor Done; virtual;
- procedure SetWindowAttrib(Modal:boolean);
- procedure SetPalette; virtual;
- procedure InitUnderGround; virtual;
- procedure InitFrame; virtual;
- procedure InitBackground; virtual;
- procedure InitWindowScroller; virtual;
- procedure Draw; virtual;
- procedure DrawClientArea; virtual;
- procedure Hide; virtual;
- procedure NewItemList; virtual;
- procedure DrawNewFrame; virtual;
- procedure HandleEvent; virtual;
- end;
-
- PDlgWindow=^TDlgWindow;
- TDlgWindow=object(TWindow)
- R : TRect;
- DlgElemente : string;
- DlgList : PGroup; {Liste der Dialogelemente}
- Child : PGroup; {Child-Fenster}
- FocElem : word; {Nr. des fokussierten Elements}
- DlgInput : boolean; {nur passive Dialogelemente ?}
- constructor Init(var Bounds:TRect;ATitle:str80;AType:byte);
- destructor Done; virtual;
- procedure Draw; virtual;
- procedure DrawMask; virtual;
- procedure Hide; virtual;
- procedure SetData(var Rec); virtual;
- procedure GetDataRec;
- procedure InsertChildWindow(Item:PGroup);
- procedure SetPushButton(X,Y,xl,yl:integer;Bez:str25;Kommando:word);
- procedure SetRadioButton(X,Y:integer;Bez:str25;FGruppe:byte);
- procedure SetCheckButton(X,Y:integer;Bez:str25);
-
-
-
- Programmierhandbuch WG-Vision - 351 -
-
-
-
-
-
-
-
- procedure SetInputLine(X,Y,xl:integer;Bez:str25;MaxLen:byte;Zeich:ZMenge);
- procedure SetNumButton(X,Y,xl:integer;Bez:str25;MaxLen:byte;
- TTyp:byte;Min,Max,Step,Format:Single);
- procedure SetListBox(X,Y,xl,yl:integer;Bez:str25;
- LScroller:word); virtual;
- procedure SetGroupFrame(X,Y,xl,yl:integer;Bez:str25;FrameTyp:word);
- procedure SetIcon(X,Y:integer;Bez:str25);
- procedure SetStaticText(X,Y:integer;Bez:string;RelPos:byte);
- procedure SetListData(LData:PGroup);
- procedure SetTextPosition(X,Y:integer);
- procedure ChangePalColor(Eintrag, Color:byte);
- procedure DrawLast;
- procedure SetTextParameters(Fnt,Direct:word;CharSz:byte);
- procedure SetDisabled;
- function GetFocElem:word;
- procedure HandleEvent; virtual;
- Private
- RecAdr : word;
- end;
-
- {Dialogelemente}
-
- PButton=^TButton;
- TButton=object(TGroup)
- P : TPoint;
- TextPos : TRect; {Position des Bezeichners}
- DX,Dy : integer; {TextPosition relativ zum Button}
- Bezeichner : TText;
- BS : byte; {Position Short-Cut}
- ShortCut : Char; {ShortCut}
- Focus : boolean; {Element fokussiert ?}
- Enabled : boolean; {Element aktiv ?}
- constructor Init(R:TRect;BText:string);
- destructor Done; virtual;
- procedure SetPos(R:TRect); virtual;
- procedure SetTextPos(X,Y:integer); virtual;
- procedure HandleEvent; virtual;
- procedure SetEnabled(On:boolean);
- end;
-
-
-
- Programmierhandbuch WG-Vision - 352 -
-
-
-
-
-
-
-
- PPushButton=^TPushButton;
- TPushButton=object(TButton)
- Kommando : word;
- PushDown : boolean; {Schalter heruntergedrückt}
- KeyIcon : PIcon;
- constructor Init(R:TRect;BText:str25;Komm:word);
- destructor Done; virtual;
- procedure SetPos(R:TRect); virtual;
- procedure SetTextPos(X,Y:integer); virtual;
- procedure Draw; virtual;
- procedure HandleEvent; virtual;
- end;
-
- PRadioButton=^TRadioButton;
- TRadioButton=object(TButton)
- Gruppe : byte; {Gruppen-Index}
- Gesetzt : boolean;
- constructor Init(R:TRect;BText:str25;FGruppe:word);
- destructor Done; virtual;
- procedure SetPos(R:TRect); virtual;
- procedure SetTextPos(X,Y:integer); virtual;
- procedure Draw; virtual;
- procedure SetData(var Rec); virtual;
- end;
-
- PCheckButton=^TCheckButton;
- TCheckButton=object(TRadioButton)
- constructor Init(R:TRect;BText:str25);
- destructor Done; virtual;
- procedure Draw; virtual;
- end;
-
- PInputLine=^TInputLine;
- TInputLine=object(TButton)
- Data : string;
- DataLen : byte;
- constructor Init(R:TRect;BText:str25);
- destructor Done; virtual;
- procedure SetPos(R:TRect); virtual;
-
-
-
- Programmierhandbuch WG-Vision - 353 -
-
-
-
-
-
-
-
- procedure SetTextPos(X,Y:integer); virtual;
- procedure Draw; virtual;
- procedure DrawData;
- procedure SetData(var Rec); virtual;
- procedure HandleEvent; virtual;
- Private
- zz : string;
- CPos : integer; {KursorPosition}
- MaskSize : integer; {Länge der Eingabemaske in Zeichen}
- k : byte;
- FieldAktiv : boolean;
- Zeichen : ZMenge; {erlaubte Zeichen}
- procedure CursorOn(pp:integer);
- procedure CursorOff(pp:integer);
- end;
-
- PNumButton=^TNumButton;
- TNumButton=object(TInputLine)
- UButton : PPushButton;
- DButton : PPushButton;
- Min : Single; {Maximalwert}
- Max : Single; {Minimalwert}
- Step : Single; {Schrittweite}
- Format : Single; {Formatierungsanweisung, n.m}
- constructor Init(R,W:TRect;BText:str25;TTyp:byte;AMin,AMax,
- aStep,aFormat:Single);
- destructor Done; virtual;
- procedure SetPos(R:TRect); virtual;
- procedure SetParameters(AMin,AMax,aStep,aFormat:Single);
- procedure Draw; virtual;
- procedure HandleEvent; virtual;
- end;
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 354 -
-
-
-
-
-
-
-
- TScrollBar=object(TView)
- SBereich : TRect; {vom Rollbalken umschlossener Bereich}
- Direction : byte; {Richtung des Rollbalkens}
- Value : integer; {Aktuelle Position des Indikators}
- PgStep : integer; {Schrittweiten}
- WinLength : longint; {Balkenlänge}
- Max : longint; {Maximalwerte von Value}
- constructor Init(Bounds:TRect;Richtung:byte);
- destructor Done; virtual;
- procedure DrawScrollBar;
- procedure SetStep(APgStep:integer);
- procedure SetValue(AValue:integer);
- procedure SetMaxValue(AMax:integer);
- procedure SetThumb;
- procedure HandleEvent; virtual;
- Private
- SNr : byte;
- ActAreaSB : array[1..8] of TRect; {aktive Bereiche}
- end;
-
- PScroller=^TScroller;
- TScroller=object(TButton)
- Border : TRect;
- HorizScrollBar : PScrollBar;
- VertiScrollBar : PScrollBar;
- Delta : TPoint; {relative Position}
- WDelta : TPoint;
- Limit : TPoint; {Ausmaße des Datenbereichs in Zeilen}
- {und Spalten}
- Px,Py : integer; {Pixelzahl pro Spalte/Zeile}
- Zeilen : word; {im Fenster}
- Spalten : word; {im Fenster}
- Liste : PLine; {enthält zeilenweise strings}
- constructor Init(R:TRect;HScroller,VScroller:PScrollBar);
- destructor Done; virtual;
- procedure SetArea(Bounds:TRect); virtual;
- procedure SetLimit(X,Y,Pxx,Pyy:integer);
- procedure ScrollDraw; virtual;
- procedure HandleEvent; virtual;
-
-
-
- Programmierhandbuch WG-Vision - 355 -
-
-
-
-
-
-
-
- procedure Draw; virtual; {zeichnet Rollbalken}
- procedure Hide; virtual;
- procedure SetPos(R:TRect); virtual;
- Private
- RR : TRect;
- end;
-
- PListBox=^TListBox;
- TListBox=object(TScroller)
- Data : string; {enthält ausgewähltes Listenelement}
- DataLen : byte;
- AktivItem : word; {Aktives Element der Liste}
- ChangeItem : word; {Auswahlelement Tastatur}
- constructor Init(R:TRect;BText:str25;HScroller,VScroller:PScrollBar);
- procedure CreateDataList;
- procedure ScrollDraw; virtual;
- procedure Draw; virtual;
- procedure SetPos(R:TRect); virtual;
- procedure SetTextPos(X,Y:integer); virtual;
- procedure HandleEvent; virtual;
- end;
-
- PGroupFrame=^TGroupFrame;
- TGroupFrame=object(TButton)
- FrameTyp : word;
- constructor Init(R:TRect;BText:str25;FTyp:word);
- destructor Done; virtual;
- procedure SetPos(R:TRect); virtual;
- procedure SetTextPos(X,Y:integer); virtual;
- procedure Draw; virtual;
- end;
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 356 -
-
-
-
-
-
-
-
- TIcon=object(TButton)
- F : file;
- Nr : word;
- FName : str80;
- IconSize : word;
- Anzahl : integer;
- constructor Init(R:TRect;IconName:str25);
- destructor Done; virtual;
- procedure SetPos(R:TRect); virtual;
- procedure Draw; virtual;
- end;
-
- PStaticText=^TStaticText;
- TStaticText=object(TButton)
- Pos : byte;
- Line : string;
- constructor Init(R:TRect;InfoString:string);
- destructor Done; virtual;
- procedure SetPos(R:TRect); virtual;
- procedure Draw; virtual;
- end;
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 357 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Event-Verwaltungsroutinen *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WEvent;
-
- interface
-
- uses WDecl,
- WDriver;
-
-
- type PEvent=^TEvent;
- TEvent=record
- What : byte;
- Command : word;
- Message : word;
- Info : word;
- case word of
- 0 : (InfoPtr:Pointer);
- 1 : (InfoLong:longint);
- 2 : (InfoWord:word);
- 3 : (InfoByte:byte);
- 4 : (InfoChar:Char);
- 5 : (InfoString:string);
- end;
-
-
- var Event:TEvent;
-
-
-
-
- Programmierhandbuch WG-Vision - 358 -
-
-
-
-
-
-
-
- procedure GetEvent;
- procedure ClearEvent;
- procedure ClearMessage;
- function CheckScanCode(SC:byte):Char;
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 359 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Fehlermeldungen Deutsch/Englisch *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WError;
-
- interface
-
- uses WDecl;
-
- procedure ErrorMessage(Nr:tError;var PText,EText:string;var MTyp:byte);
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 360 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Textausgabe und Texthandling *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WText;
-
- interface
-
- uses WDecl,
- WDriver,
- Crt,
- Graph;
-
-
- type GraficFont = (Thin8,Thin14,Thin16,Brdwy19,Wndw19,Sans19,VGAF);
-
- TText=object
- R : TRect;
- Font : word; {Zeichensatz}
- Direction : word; {Richtung}
- CharSize : byte; {Buchstabengröße}
- TxtHeight : word; {Texthöhe}
- TxtWidth : word; {Breite des Textes}
- Zeile : string; {auszugebender Text}
- constructor Init;
- destructor Done;
- procedure SetFont(FFont,FDirection:word);
- procedure SetCharSize(FCharSize:byte);
- procedure SetClipFrame(T:TRect);
- procedure SetDefaultText;
-
-
-
- Programmierhandbuch WG-Vision - 361 -
-
-
-
-
-
-
-
- procedure LText(X,Y:integer;z:string);
- procedure RText(X,Y:integer;z:string);
- procedure CText(X,Y:integer;z:string);
- end;
-
- var pitch : word;
- BColor : word;
- Color : word;
- CharHeight : word;
- CharLength : word;
- Font : GraficFont;
-
- procedure SetFont(NewFont:GraficFont);
- procedure WriteText(X,Y:integer;st:string);
- procedure SetFontColor(bg,vg:byte);
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 362 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Expanded Memory Verwaltung *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WEMS;
-
- interface
-
- uses Crt,
- Dos;
-
- var EMS_Installed:boolean; {EMS-Speicher verfügbar ?}
- EMM_Version:string[3]; {EMS Versionsnummer}
- Error:word; {Fehler-Nummer}
- PageFrame:word; {Segmentadresse des PageFrame}
- Pages:array[0..3] of word; {Segmentadressen der physikalischen Seiten}
-
- function HexString(Number:word):string;
- function GetUnallocatedPages:word;
- function GetFreePages:word;
- function GetPageFrameAddress:word;
- procedure MapPages(NumberPages,P1,P2,P3,P4:word;var Handle:word);
- procedure ReMapPages(P1,P2,P3,P4,Handle:word);
- function AllocatePages(NumberPages:word):word;
- procedure DeAllocatePages(Handle:word);
- procedure MapHandlePages(Handle:word;PhysicalPage,LogicalPage:byte);
- function GetHandleCount:word;
- function GetHandlePages(var Handle:word):word;
-
- implementation
-
-
-
- Programmierhandbuch WG-Vision - 363 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Allgemeine Hilfsfunktionen *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WUTILS;
-
- interface
-
- uses WDecl,
- WDriver,
- Crt,
- Dos,
- Graph;
-
-
- procedure FillBar(X1,Y1,X2,Y2:integer;Farbe1,Farbe2,Style:byte);
- procedure FBar(X1,Y1,X2,Y2:integer;Farbe:byte);
- procedure D3Frame(X1,Y1,X2,Y2:integer;C1,C2:byte);
- procedure Beep(Dauer:integer);
- function Exists(FName:string):boolean;
- procedure DrawImage(X,Y:integer;FName:string);
- function Trim(S:string):string;
-
- implementation
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 364 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Zusatzzeichensätze im Grafikmodus *
- * ROM-Zeichensätze *
- * BGI-Vektorzeichensätze
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WFont;
-
- interface
-
- uses WDecl,
- Dos,
- Crt,
- Graph;
-
-
- const DefaultFont = 0; {Pixel-Zeichensatz, entspricht ROM8x8 oder ROM8x16}
- TriplexFont = 1; {Vektor-Zeichensätze}
- SmallFont = 2;
- SansSerifFont = 3;
- GothicFont = 4;
- ScriptFont = 5;
- SimpleFont = 6;
- TSCRFont = 7;
- LCOMFont = 8;
- EuroFont = 9;
- BoldFont =10;
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 365 -
-
-
-
-
-
-
-
- Underline = 1; {Schriftattribute für ROM-Zeichensätze}
- Bold = 2;
- Small = 3;
-
- type FontType=record {Zeichensatzblock aus einer}
- Name : string[10]; {WG-Vision-Fontressource}
- Points : Char;
- Data : array[1..4096] of Char;
- end;
-
-
- PPixelFont=^TPixelFont;
- TPixelFont=object(TObject)
- Font : FontType; {User-Zeichensatz}
- ROMFont : byte; {Funktionsnummer des ROM-ZS}
- CharSize : byte; {Zeichenhöhe}
- constructor SetFont(F:string); {Zeichensatz installieren}
- destructor Done; virtual; {Rücksetzen auf 8x8}
- {Standardzeichensatz}
- function GetFontName:string; {Name des gerade aktiven Pixelfonts}
- procedure SetFontStyle(Style:byte);
- end;
-
- PVectorFont=^TVectorFont;
- TVectorFont=object(TObject)
- Font : word; {Nummer des aktiven Vektorfonts}
- Direction : word; {Ausrichtung}
- CharSize : TPoint; {Buchstabengröße, z,n}
- constructor SetVectorFont(F:word); {Zeichensatz setzen}
- destructor Done; virtual; {Default-Zeichensatz setzen}
- procedure SetCharSize(z,N:word); {Zeichengröße definieren}
- procedure SetDirection(Dir:word); {Ausgaberichtung festlegen}
- end;
-
-
- implementation
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 366 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Kontextsensitives Hilfesystem *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WHelp;
-
- interface
-
- uses WDecl,
- WDriver,
- WViews,
- WDlg,
- WText,
- Graph;
-
- type PHelpScroller=^THelpScroller;
- THelpScroller=object(TScroller)
- procedure CreateData(HelpDatei:string;HelpCtx:word);
- procedure ScrollDraw; virtual;
- end;
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 367 -
-
-
-
-
-
-
-
- PHelpWindow=^THelpWindow;
- THelpWindow=object(TWindow)
- HelpIndex:word;
- HelpDatei:string;
- Scroller:PHelpScroller;
- constructor Init(Datei:string;Hi:word;var Bounds:TRect;
- ATitle:str80;AType:byte);
- procedure InitWindowScroller; virtual;
- destructor Done; virtual;
- end;
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 368 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Lesen und Schreiben von 16- *
- * farbigen PCX-Bildern *
- * *
- * Nur für Standard-VGA 640x480x16 ! *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WPCX;
-
- interface
-
- uses WDecl,
- Dos;
-
- type TPCXImage=object
- T : TRect;
- DX,Dy : integer;
- FileName : PathStr;
- procedure Init(R:TRect;DName:PathStr);
- procedure LoadPCXImage(AddY:word);
- end;
-
- function SavePCXImage(MinX,MinY,MaxX,MaxY:integer;Name:PathStr):integer;
-
- implementation
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 369 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Speichern und Laden von 256- *
- * farbigen PCX-Bildern *
- * *
- ******************************************************
- * Verwendung nur in den VESA-Modi der Toolbox *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
-
- {$I COMPILER.INC}
-
- unit W256PCX;
-
- interface
-
- uses WPalette,
- Dos,
- Graph;
-
-
- type PCXheader = record
- Creator : byte; {10=Kennzeichen für PCX}
- Version : byte; {5=Version 3.0}
- Encoding : byte; {1=Runlength-Codierung}
- Bits : byte; {Bits pro Pixel}
- xmin : word; {Position Original-Bild}
- ymin : word;
- xmax : word;
- ymax : word;
- HRes : word; {horizontale Auflösung}
- VRes : word; {vertikale Auflösung}
- Palette16 : array[0..15, 0..2] of byte; {16 Farben-}
- {Palette}
-
-
-
- Programmierhandbuch WG-Vision - 370 -
-
-
-
-
-
-
-
- VMode : byte; {reserviert}
- Planes : byte; {Zahl der Ebenen}
- BytePerLine : word; {Bytes pro Zeile}
- PaletteInfo : word; {1=Farbe, 2=Schwarz/Weiß}
- Dummy : array[0..57] of byte; {reserviert}
- end;
-
- type PictLine = record
- Columns : word;
- Lines : word;
- Pixels : array[1..1280] of byte;
- end;
-
- procedure SavePCXImage(X1,Y1,X2,Y2:integer;Palette:tPalType;Name:string;
- var Error:integer);
- procedure LoadPCXImage(X1,Y1:integer;Name:string;var Error:integer);
- function GetPCXErrorMsg(Error:word) : string; { 530 <= Fehler <= 534 }
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 371 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Erweiterte Funktionen des *
- * Coprozessors 80387 *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WCProc;
-
- interface
-
- function wgSin(X:Extended):Extended;
- function wgCos(X:Extended):Extended;
- function wgTan(X:Extended):Extended;
- function wgCot(X:Extended):Extended;
- function wgAtn(X:Extended):Extended;
- function wgAsn(X:Extended):Extended;
- function wgAcs(X:Extended):Extended;
- function wgExp(X:Extended):Extended;
- function wgPow(X,N:Extended):Extended;
- function wgLog(X:Extended):Extended;
- function wgLog10(X:Extended):Extended;
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 372 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Datei Ein- und Ausgabedialog *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WFileDlg;
-
- interface
-
- uses WDecl,
- WDlg,
- WViews,
- WEvent,
- WDriver,
- WUtils,
- Dos,
- Graph;
-
- const msgLoadFile = 10;
- msgSaveFile = 11;
-
- type PInputDialog=^TInputDialog;
- TInputDialog=object(TDlgWindow)
- Pfad : PathStr; {Originalpfad}
- Klick : boolean;
- constructor Init(ATitle:str80;FMask:str12);
- destructor Done; virtual;
- procedure SetFileMask; virtual;
- procedure InitBackground; virtual;
- procedure SetPalette; virtual;
- procedure SetDateiListBox(X,Y,xl,yl:integer;Bez:str25;LScroller:word);
-
-
-
- Programmierhandbuch WG-Vision - 373 -
-
-
-
-
-
-
-
- procedure HandleEvent; virtual;
- end;
-
- POutputDialog=^TOutputDialog;
- TOutputDialog=object(TDlgWindow)
- constructor Init(ATitle:str80);
- procedure InitBackground; virtual;
- procedure SetPalette; virtual;
- procedure HandleEvent; virtual;
- end;
-
- PDateiListBox=^TDateiListBox;
- TDateiListBox=object(TListBox)
- procedure CreateDataList;
- end;
-
- PIDlgBgrd=^TIDlgBgrd;
- TIDlgBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
- PODlgBgrd=^TODlgBgrd;
- TODlgBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
- var FileMask : str12;
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 374 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Druck-Dialoge, TLinePrint-Objekt *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WPrint;
-
- interface
-
- uses WDecl,
- WDlg,
- WViews,
- WUtils,
- WEvent,
- Printer,
- Graph,
- Crt,
- Dos;
-
-
- type tDrOptData=record
- Schalter : string[12];
- Header : string[60];
- LRand : string[2];
- RRand : string[2];
- ORand : string[2];
- end;
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 375 -
-
-
-
-
-
-
-
- tOptionData=record
- Schalter : string[8];
- VonSeite : string[3];
- BisSeite : string[3];
- end;
-
- PLinePrint=^TLinePrint;
- TLinePrint=object
- AnzLines : byte; {Zeilen pro Seite}
- RLinks,RRechts : byte; {rechter und linker Rand}
- ORand : byte; {oberer Rand = Abstand zur Kopfzeile}
- Breite : byte;
- Zaehler : word; {Zeilenzähler}
- SZaehler : word; {Zeilenzähler in der Seite}
- Seite : word;
- FromPage : word;
- ToPage : word;
- WNumber : boolean; {Zeilen-Nummerierung ja/nein}
- SetLine : boolean;
- SetDate : boolean;
- Kopfzeile : string;
- Datum : string;
- constructor Init(KZeile:string);
- destructor Done; virtual;
- function PrinterOk:boolean;
- procedure Print(Line:string);
- procedure SetLineNumberPrint(Yes:boolean);
- procedure SetSatzSpiegel(RL,RR,RO,ALines:byte);
- procedure SetParameters; virtual;
- procedure DefineHeaderText(KZeile:string);
- procedure Eject;
- end;
-
- PDruckBgrd=^TDruckBgrd;
- TDruckBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
-
-
-
-
- Programmierhandbuch WG-Vision - 376 -
-
-
-
-
-
-
-
- POptionBgrd=^TOptionBgrd;
- TOptionBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
- PDruckOptionen=^TDruckOptionen;
- TDruckOptionen=object(TDlgWindow)
- Original:tDrOptData;
- constructor Init;
- procedure InitBackground; virtual;
- procedure HandleEvent; virtual;
- procedure CM_SetOptionen;
- end;
-
- PPrintOptionWindow=^TPrintOptionWindow;
- TPrintOptionWindow=object(TDlgWindow)
- Original:tOptionData;
- constructor Init(X,Y:integer);
- procedure InitBackground; virtual;
- procedure HandleEvent; virtual;
- end;
-
- var OptData:tDrOptData;
- Druckdata:tOptionData;
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 377 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 ICON-Editor (16x16 und 32x32) *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WICNEDIT;
-
- interface
-
- uses WDecl,
- WViews,
- WDlg,
- WUtils,
- WEvent,
- WDriver,
- WFileDlg,
- Dos,
- Graph;
-
-
- type PIconEdit=^TIconEdit;
- TIconEdit=object(TDlgWindow)
- IcnFName:PathStr; {Name der Icondatei}
- IcnDat:file;
- IcnSize:word;
- IcnAnz,IcnNr:byte;
- ITyp:byte;
- VG,HG:byte; {aktive Vorder- und Hintergrundfarbe}
- InWork:boolean; {Icon in Arbeit}
- constructor Init(X,Y:integer;IconFile:PathStr;IconTyp:byte);
- procedure InitBackground; virtual;
-
-
-
- Programmierhandbuch WG-Vision - 378 -
-
-
-
-
-
-
-
- procedure CM_SaveAs;
- procedure CM_Load;
- procedure HandleEvent; virtual;
- end;
-
- PIconEditBgrd=^TIconEditBgrd;
- TIconEditBgrd=object(TBackground)
- Great:boolean;
- constructor Init(R:TRect;ITyp:byte);
- procedure Draw; virtual;
- end;
-
- var Icn16Puffer:array[1..16,1..16] of byte;
- Icn32Puffer:array[1..32,1..32] of byte;
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 379 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Taschenrechner *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WCalc;
-
- interface
-
- uses WDecl,
- WEvent,
- WDriver,
- WViews,
- WDlg,
- Graph;
-
- type tCalcState=(calcOK,calcValid,calcError);
-
- PCalculator=^TCalculator;
- TCalculator=object(TDlgWindow)
- Status:tCalcState;
- Zahl:string[15];
- Sign:Char; {Vorzeichen}
- Operator:Char;
- Operand:Single;
- constructor Init;
- procedure SetPalette; virtual;
- procedure InitBackground; virtual;
- procedure Berechne(Key:Char);
- procedure ClearDisplay;
-
-
-
-
- Programmierhandbuch WG-Vision - 380 -
-
-
-
-
-
-
-
- procedure DrawDisplay;
- procedure Draw; virtual;
- procedure HandleEvent; virtual;
- end;
-
- PCalcBackground=^TCalcBackground;
- TCalcBackground=object(TBackground)
- procedure Draw; virtual;
- end;
-
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 381 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Digitaluhr *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WUhr;
-
- interface
-
- uses WDecl,
- WViews,
- WDlg,
- WDriver,
- Dos,
- Graph;
-
- type PDigitalUhr=^TDigitalUhr;
- TDigitalUhr=object(TWindow)
- constructor Init(X,Y:integer);
- procedure SetPalette; virtual;
- procedure InitBackground; virtual;
- procedure HandleEvent; virtual;
- end;
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 382 -
-
-
-
-
-
-
-
- PUhrBgrd=^TUhrBgrd;
- TUhrBgrd=object(TBackground)
- Stunde : word;
- Minute : word;
- Sekunde : word;
- procedure Draw; virtual;
- end;
-
- implementation
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 383 -
-
-
-
-
-
-
-
- (*****************************************************
- * *
- * WG-VISION 1.0 Palettenmanipulation und *
- * Paletteneditor für die 256- *
- * farbigen VESA-Modi *
- * *
- ******************************************************
- * *
- * *
- * (c) 1992/93 Dipl.Phys. Mathias Scholz *
- * *
- *****************************************************)
-
- {$I COMPILER.INC}
-
- unit WPalette;
-
- interface
-
- uses WDecl,
- WDriver,
- WViews,
- WDlg,
- WUtils,
- WEvent,
- WFileDlg,
- Crt,
- Dos,
- Graph;
-
-
- type tRGB=record
- R,G,B:byte;
- end;
-
- tPalType=array[0..255] of tRGB;
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 384 -
-
-
-
-
-
-
-
- PPalette=^TPalette;
- TPalette=object
- F : file; {Palettendatei}
- LUT : tPalType; {Look-Up Table}
- ALUT : tPalType; {angepaßte Palette für PCX-Bilder}
- CLUT : array[1..10] of tPalType;
- procedure SetPaletteColor(Nr,Rot,Gruen,Blau:byte);
- procedure GetPaletteColor(var Nr,Rot,Gruen,Blau:byte);
- procedure GetPalette;
- procedure SetPalette;
- procedure AdaptPalette;
- procedure SetNewPalette(NLUT:tPalType);
- procedure LoadPalette(FName:PathStr);
- procedure SavePalette(FName:PathStr);
- procedure RotatePalette(Typ,Direction:byte);
- procedure RotatePart(Direction,Von,Bis:byte);
- procedure SetVerlauf(Nr1,Rot1,Gruen1,Blau1,Nr2,Rot2,Gruen2,Blau2:byte);
- procedure TransformRGBtoHSV(R,G,B:byte;var H,S,V:Single);
- procedure TransformHSVtoRGB(H,S,V:Single;var R,G,B:byte);
- procedure TransformtoGrayScale(Nr,Number:byte);
- procedure StretchScale(Minimalwert,Maximalwert,Delta:byte;
- Positiv:boolean);
- procedure StretchPolynom(Minimalwert,Maximalwert:byte;
- Degree:Single;Positiv:boolean);
- procedure StretchColor(Minimalwert,Maximalwert:integer);
- procedure Isophote(Delta,Brightness:byte;Positiv:boolean);
- procedure Aequidensiten(Delta,Abstand:byte;Positiv:boolean);
- end;
-
- PGrayBar=^TGrayBar;
- TGrayBar=object(TWindow)
- Pal:TPalette;
- constructor Init(X,Y:integer);
- procedure InitBackground; virtual;
- end;
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 385 -
-
-
-
-
-
-
-
- PPalWorkShop=^TPalWorkShop;
- TPalWorkShop=object(TDlgWindow)
- Pal:TPalette;
- KlickArea:TRect;
- LastColor:byte;
- Hu,Sa,Va:Single; {aktueller HSV-Wert}
- rgbRed,rgbGreen,rgbBlue:byte; {aktueller RGB-Wert}
- constructor Init(X,Y:integer);
- procedure InitBackground; virtual;
- procedure CM_SaveAs;
- procedure CM_Load;
- procedure HandleEvent; virtual;
- end;
-
- PScale=^TScale;
- TScale=object(TDlgWindow)
- Pal:TPalette;
- StretchMode:byte;
- constructor Init(X,Y:integer;What:byte);
- procedure InitBackground; virtual;
- procedure HandleEvent; virtual;
- end;
-
- PColorBar=^TColorBar;
- TColorBar=object(TBackground)
- procedure Draw; virtual;
- end;
-
- PPWorkShopBgrd=^TPWorkShopBgrd;
- TPWorkShopBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
-
-
-
-
-
-
-
-
-
- Programmierhandbuch WG-Vision - 386 -
-
-
-
-
-
-
-
- PScaleBgrd=^TScaleBgrd;
- TScaleBgrd=object(TBackground)
- procedure Draw; virtual;
- end;
-
- var StretchL,StretchR:byte;
- PExponent:Single;
- PositivMode:boolean;
-
-
- implementation
-