profan ² 6.0
Transcription
profan ² 6.0
Roland G. Hülsmann Hinter der Mühle 6 69226 Nußloch email: rgh-soft@t-online.de homepage: http://www.profan.de Programmieren für Anwender P R O F A N ² 6.0 DIE einfache Programmiersprache für Windows 3.x und Windows 95 Einführung Programmierkurs Referenz RGH-PROFAN² INHALT Teil 1: Einführung 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Vorbemerkungen Installation und De-Installation 2.1 Installation 2.2 Was wird benötigt? 2.3 De-Installation Entwicklungsumgebung 3.1 Übersicht 3.2 Aufruf 3.3 Die Menüpunkte 3.4 Das externe Druckprogramm PROFAN-SCRIPT Direktiven für Interpreter und Compiler 5.1 $P+ - Verschlüsselung 5.2 $I - Include-Dateien 5.3 $O - Präprozessor für Operatoren Operatoren Variablen - Datentypen - Typumwandlung 7.1 Integer 7.2 LongInt 7.3 Float 7.4 String 7.5 Bereich 7.6 Typumwandlung 7.7 Zahlensysteme Arrays 8.1 Je Datentyp eine Liste 8.2 Mehrdimensionale Arrays Kontrollstrukturen 9.1 Case / CaseNot 9.2 If / IfNot - ElseIf - Else - EndIf 9.3 While / WhileNot - EndWhile 9.4 @If Prozeduren Funktionen 11.1 Grundlagen 11.2 Allgemeine Funktionen 11.3 Definierte Funktionen 11.4 externe Funktionen Resourcen 12.1 Allgemeines 12.2 Icons 12.3 Cursor 12.4 Bitmaps 12.5 Strings 12.6 Menüs 12.7 Dialoge Programm-Aufbau Befehle über mehrere Zeilen Fehlerbehandlung - TraceModus Seite 2 RGH-PROFAN² 16 17 18 19 20 21 22 23 24 25 26 27 28 Text- & Grafikmodus 16.1 Der "Textmodus" 16.2 Der Grafikmodus Bitmaps Sounds Multimediaschnittstelle 19.1 CD-Player 19.2 WAV-Dateien 19.3 MIDI-Dateien 19.4 Video für Windows Datenbanken 20.1 Grundlagen 20.2 Datenbankstrukturen und Tabellen 20.3 Tabellen bearbeiten 20.4 ODBC-Schnittstelle Dateien - Verzeichnisse - System - Zwischenablage 21.1 Dateien - Verzeichnisse - System 21.2 Textdateien 21.3 binäre Dateien 21.4 INI-Dateien 21.5 Registry (nur 32 Bit) 21.6 Zwischenablage 21.7 Lange Dateinamen unter Windows 95 Die Verbindung zur Außenwelt 22.1 Drucken mit PROFAN² 22.2 Die serielle Schnittstelle 22.3 I/O-Ports Vordefinierte Dialoge 23.1 MessageBox 23.2 InputBox und EditBox 23.3 ListBox 23.4 LOAD- und SAVE-Dialoge Selbstgestaltete Dialoge und Dialogfenster 24.1 Grundlagen 24.2 Buttons - Checkboxen - Radiobuttons 24.3 GroupBoxen - Texte - Icons 24.4 Editierfelder 24.5 ListBoxen 24.6 AuswahlBoxen 24.7 Scrollbalken 24.8 Beliebige Dialogelemente Kommunikation mit anderen Fenstern - Messages - DDE 25.1 Einfacher Zugriff über das Handle 25.2 Tastatureingaben simulieren 25.3 Messages versenden 25.4 Fernsteuerung per DDE Menüs und Mäuse 26.1 Fenster-Menüs 26.2 freie PopUp-Menüs 26.3 Warten auf Ereignisse Spezialitäten für Fortgeschrittene 27.1 Bildschirmschoner 27.2 Neuzeichen selbst übernehmen 27.3 Zeichen in Dialogfenstern 27.4 Messageverwaltung selbst übernehmen 27.5 Zur Verwendung von DLLs Kompatibilität zu früheren PROFAN-Versionen Seite 3 RGH-PROFAN² Teil 2: Programmierkurs 0 1 2 3 4 5 Vorbemerkungen PROFAN² als Batchsprache EVA: Eingabe > Verarbeitung > Ausgabe Grafik und Sound Multimediaprogrammierung Selbstdefinierte Dialoge Teil 3: Referenz 0 1 2 3 4 Übersicht Systemvariablen Funktionen Befehle Wichtige Messages ANHANG 1 2 3 Fehlermeldungen Messages im Überblick "Technische Daten" Seite 4 RGH-PROFAN² Programmieren für Anwender P R O F A N ² 6.0 DIE einfache Programmiersprache für Windows 3.x und Windows 95 Teil 1: Einführung Seite 5 RGH-PROFAN² 1 - VOBEMERKUNGN PROFAN² ist eine äußerst mächtige Programmiersprache und Batchsprache für Windows 3.1 bzw. Windows 95 in Einem! Außerdem ist PROFAN² auch noch ein SQL-fähiges Datenbank-Entwicklungssystem mit ODBC-Schnittstelle und direkter dBase-Unterstützung. Auch die Fähigkeiten als MultiMedia-Entwicklungstool können überzeugen. PROFAN² enthält beides: Interpreter und schnellen Compiler! PROFAN² gibt es sowohl als 16-Bit-Version für Windows 3.x als auch als 32-Bit-Version für Windows 95. Beide Versionen sind zueinander kompatibel, wenn sie sich auch in einigen "technischen Daten" (siehe Anhang) unterscheiden. Lediglich ein neues Linken mit der 32Bit-Version ist notwendig, um aus einem 16-Bit-Programm ein 32-Bit-Programm zu machen. Ziele der Entwicklung von PROFAN² waren: * Eine einfache - an BASIC angelehnte - Syntax auch für den Anfänger * Traditionelle prozedurale (nicht objektorientierte) Programmmierung * Alle Grafikmöglichlkeiten, die Windows bietet * umfangreiche Datei- und Verwaltungsfunktionen * das komplette Programm in einer nicht zu großen Datei * keine weiteren DLLs oder sonstige Dateien * Möglichkeit, Anwendungen ohne weitere Kosten weiterzugeben Herausgekommen ist bisher "PROFAN² 6.0". Eine komplette Programmiersprache. Der Anfänger wird viele BASIC-Befehle in gewohnter Form wiederfinden, u.a. PRINT, LOCATE, CLS, INPUT, IF, WHILE, WEND, SOUND, PRINT #n, INPUT #n, END, LET, ... Auch die Variablen und Konstanten werden weitestgehend wie in BASIC gehandhabt, wenn auch mit dem Bereichs-Typ ein Datentyp eingeführt wurde, der die Flexibilität von Zeigern bietet, ohne deren Gefährlichkeit in der Anwendung. Bei den Dateioperationen wurde allerdings das etwas vielseitigere Konzept von PASCAL übernommen: ASSIGN, RESET, REWRITE, APPEND, RENAME, ERASE, CLOSE, SETFATTR, ... Mit COPY können Dateien kopiert werden und mit CHDIR, MKDIR und RMDIR können Verzeichnisse verwaltet werden. Spezielle Funktionen geben Auskunft über das aktuelle Laufwerk, den aktuellen Pfad, Attribute, Änderungsdatum und vieles mehr. Unter Windows 95 werden auch in der 16-Bit-Version die langen Dateinamen unterstützt. Dazu kommen dann noch WINDOWS-spezifische Dinge, wie Menüs, Listboxen, Inputboxen, Load- und Save-Dialoge, ... um nur ein paar Möglichkeiten zu nennen. Zahlreiche vorgefertigte Dialogboxen nehmen dem Programmierer bei Standardaufgaben viel Arbeit ab. Wem das nicht ausreicht, wird mit den vielfältigen Möglichkeiten der Oberflächengestaltung gedient, die von zwei "Helfern" tatkräftig unterstützt wird. Dialoge können völlig frei gestaltet und variiert werden. Alle wesentlichen Dialogelemente stehen zur Verfügung. Sogar der Zugriff auf Resourcen ist möglich, sodaß es z.B. denkbar ist alle Menüs, Dialoge, Texte, Icons und Bitmaps eines Programmes mit einem Tool wie dem "Resource Workshop" von Borland in einer DLL oder dem Runtime-Modul unterzubringen Sehr wichtig sind natürlich die umfangreichen Grafikbefehle, die direkt auf den Grafik-Kern von Windows zugreifen: USEBRUSH, USEFONT, USEPEN, USEICON, COPYBMP, RECTANGLE, ROUNDRECT, ELLIPSE, ARC, PIE, DRAWTEXT, ... Mit LOADBMP und SAVEBMP können Bitmap-Grafiken geladen, verarbeitet und gespeichert werden. Das Drucken der Grafiken ist natürlich kein Problem! Seite 6 RGH-PROFAN² Für den Multimedia-Fan bietet PROFAN² auch einiges: Ansteuerung aller Multimediageräte und Abspielen von WAV-Sounddateien über die Soundkarte. Über die MIDI-Erweiterung der Befehle PLAY und MUSIC komponieren Sie mehrstimmige Songs mit den Sounds Ihrer Soundkarte. Das Abspielen von Musik-CDs ist ebensowenig ein Problem wie das Untermalen von Spielen mit Geräuschen oder das Abspielen von Microsofts Video für Windows: MCISEND, PLAYSOUND, ... PROFAN² hat zahlreiche Datenbankfunktionen zum Lesen und Bearbeiten von DBase IIIkompatiblen Datenbanken. Kleine und mittlere Datenbankanwendungen sind für PROFAN² kein Problem. Zusätzlich gibt es noch die ODBC-SQL-Schnittstelle hinzu, sodaß PROFAN² auch im Client-Server-Bereich eine immer größere Rolle spielt. SQL ist auch für PROFAN² keine Fremdsprache mehr. Die Kontrolle "fremder" Fenster ist ebenso möglich, wie das Senden von Messages und Tastaturcodes. Gerade die zahlreichen Windowsbotschaften eröffnen dem Programmierer umfangreiche Möglichkeiten, auch fremde Anwendungen durch ein PROFAN²-Programm anzusteuern und zu beeinflussen. Mittels DDE können z.B. Programmanagergruppen angelegt, umbenannt und auch wieder entfernt werden. Einige Spezialbefehle und eine Option des Linkers ermöglichen die einfache Programmierung von ScreenSavern, die über den Windows-Desktop angesteuert werden können. Der fortgeschrittene Anwender wird vermutlich zur Bildschirmausgabe die textorientierten Ausgabebefehle des BASIC weniger verwenden, als vielmehr die neuen und mächtigen Windows-Befehle, die volle Kontrolle über die Windows-Grafik bieten und auch TrueTypeSchriften voll unterstützen. Text in allen Größen, Farben und Ausrichtungen ist kein Problem. Wem all dies nicht ausreicht, der kann Funktionen aus Windows-API und DLLs einbinden und so den Funktionsumfang nahezu beliebig erweitern. Strukturierte und übersichtliche Programmierung wird ermöglicht, indem nur ein Befehl pro Zeile erlaubt ist und zahlreiche Kontrollstrukturen verfügbar sind: IF ... ELSEIF ... ELSE ... ENDIF, CASE, WHILE ... WEND. Mit PROC ... ENDPROC können - wie in Pascal - Prozeduren definiert werden und mit DEF können neue Funktionen definiert werden. In Prozeduren und Funktionen gibt es lokale Variablen. Außerdem ist beliebiges Einrücken ebenso statthaft, wie komplett leere Zeilen. PROFAN² hat einen Compiler, der einen sehr kompakten Zwischencode erzeugt, der mit einem Runtime-Modul gestartet werden kann. Das letzte Glied in der Kette zur kompletten Programmiersprache ist der Linker, der Runtimemodul und Zwischencode zu einer eigenständigen EXE- Datei oder zu einem ScreenSaver linkt. Und da das Runtime-Modul keine 250 kB groß ist, sind recht aufwendige Windowsapplikationen unter 300 kB möglich. Da die fertige PROFAN-Applikation immer noch als Runtime-Modul für weitere Zwischencode- Dateien dienen kann und sogar eine Übergabe von Parametern (über die Zwischenablage) möglich ist, steht der modularisierten Programmierung nichts im Wege. Die Sahnehaube aber ist PROFED, die komplette Entwicklungsumgebung, die in der vorliegenden Version komplett neu programmiert wurde und nun das Editieren nahezu beliebig großer Dateien zuläßt. Ach ja: Das berühmte "Hallo Welt"-Programm in Profan: Print "Hallo Welt" WaitKey End Seite 7 RGH-PROFAN² So einfach ist das. Das "WaitKey" steht nur deshalb da, damit der Anwender Gelegenheit hat, das Ergebnis zu betrachten: Ein Programm in einem Windows- Fenster mit allem was dazugehört. Sozusagen eine vollständige Windows- Applikation. Mit einem Tastendruck oder über die entsprechende Fensterfunktion wird das Programm beendet. Die Kombination von Interpreter und Compiler bietet interessante Vorteile. Im Interpretermodus entwickeln Sie das Programm und testen es aus. Ein zuschaltbarer TRACE-Modus unterstützt Sie dabei. Und wenn es dann fertig getestet ist, verleihen Sie ihm mit dem Compiler den nötigen Drive! ... und eine Batchsprache für Windows benötigen Sie auch nicht mehr, wenn Sie PROFAN² haben! Seite 8 RGH-PROFAN² 2 - Installation und De-Installation 16-Bit-Version für Windows 3.x: Ab Version 2.0 ist PROFAN nicht mehr unter Windows 3.0 lauffähig. Mindestens 3.1 muß es schon sein. Die 16-Bit-Version wurde auch erfolgreich unter Windows 95, Windows NT 3.1 und OS/2 WARP 3.0 getestet. Unter Windows 95 werden ab Version 4.1 auch die langen Dateinamen unterstützt. 32-Bit-Version für Windows 95: Diese Version läuft nur unter Windows 95 und - unter Verwendung eines angepaßten Interpreters und eines angepaßten Runtime-Moduls mit einigen Einschränkungen bei hardwarenahen Befehlen/Funktionen - Windows NT ab 4.0. Die Einschränkungen sind jeweils in der Referenz aufgeführt. Unter Windows 3.x mit 32-Bit-Erweiterung Win32s läuft diese Version nicht. Die 16-Bit-Version von PROFAN² benötigt mindestens einen 386er mit 4 MB RAM und VGAGrafik. Besser sind - wie für Windows 3.1 allgemein - 8 MB RAM auf einem 386er mit mind. 25 MHz. Windows 3.11 sollte auf einem 486er mit 33 MHz und mind. 8 MB installiert sein und für Windows 95 sollte es schon ein 486er ab 66 MHz mit 8 oder besser 16 MB RAM sein. Unterstützt werden SVGA ebenso wie alle nur denkbaren Multimediageräte, die über die MCI-Schnittstelle angesprochen werden. Die 32-Bit-Version unterstützt wie Windows 95 nicht mehr die Soundausgabe über den PC-Lautsprecher, sodaß eine Soundkarte empfohlen wird. 2.1 INSTALLATION PROFAN² ist vom Installationsprogramm auf dem von Ihnen gewählten gewählten Verzeichnis installiert worden. Datenträger im Windows 3.x: Damit PROFAN²-Programme, auch wenn sie nicht zur EXE-Datei gelinkt sind, durch Doppelklick im Dateimanager (oder was immer Sie an dessen Stelle benutzen) gestartet werden können, sind folgende Zeilen in die Datei WIN.INI unter dem Abschnitt "Extensions" einzufügen: prf=c:\profan\profan.exe ^.prf prc=c:\profan\profrun.exe ^.prc (Besitzer der Shareware-Version geben statt "profan.exe" bitte "shprofan.exe" an. Sollten Sie PROFAN² nicht auf Laufwerk C: in Verzeichnis PROFAN installiert haben, ändern Sie die Zeilen entsprechend ab.) Seite 9 RGH-PROFAN² In Windows 95 werden die entsprechenden Verknüpfungen gemäß der Anleitung von Windows 95 erstellt. Das 32-Bit-Runtime-Modul heißt PRFRUN32.EXE bzw. für Windows NT ist es PRFRUNNT.EXE. Nur die wenigsten Dateien, die das Installationsprogramm auf Ihre Festplatte kopiert hat, werden wirklich gebraucht. Die meisten Dateien gehören zum Demonstrationsprogramm und dienen Ihrer Information. DEMOPROGRAMM - PROGRAMMIERKURS - BEISPIELE - DOKUMENTATION: Das DEMO-Programm befindet sich im Unterverzeichnis DEMO, das das Installationsprogramm unterhalb des PROFAN-Verzeichnisses angelegt hat. Das DEMOProgramm ist komplett in PROFAN² geschrieben. Die Listings sind in der registrierten Vollversion mit dabei und werden ins Unterverzeichnis BEISPIEL kopiert. DEMO.EXE - Hauptprogramm *.PRC - kompilierte Programmodule. Beachten Sie die Kompaktheit selbst so komplexer Programme, wie RGH-DRAW. *.PLT - Beispiel-Farbpaletten für Malprogramm und Farbkasten. *.BMP - Bilder für die Beispielprogramme *.BLD - Bilder für das Malprogramm *.WAV - Sounddateien für das Spiel *.TXT - Texte für den Schnelleinstieg Im Verzeichnis BEISPIEL: *.PRF - Listings des DEMO-Programmes *.INC - Listing der Includedatei zum Malprogramm Die Dateien zum Programmierkus erkennen Sie an der Endung ".KRS". Sie befinden sich im PROFAN-Verzeichnis. Die Listungs dazu finden Sie im Unterverzeichnis BEISPIEL. Im Unterverzeichnis BEISPIEL finden sich außerdem noch weitere Beispielprogramme: CDPlayer, Adressverwaltung, Bidschirmschoner, ... Die Datei BEISPIEL.WRI listet die Beispiele samt kurzer Erklärung auf. Im Unterverzeichnis DOKU befindet sich die wichtige Datei LIESMICH.TXT mit den neuesten Informationen, sowie Handbücher und weitere informative Dateien im WRITE-Format. 2.2 WAS WIRD BENÖTIGT? PROFAN² (Entwicklung): Diese Dateien sind unbedingt notwendig: (In Klammern steht bei abweichendem Dateinamen der Name der Datei in der Shareware-Version.) PROFAN.EXE (SHPROFAN.EXE) - Der Interpreter PROFED.EXE (SHPROFED.EXE) - Die Entwicklungsumgebung HELFER.EXE - Runtime für die "Helfer" *.HLP - Hilfedateien *.HLF - Die "Helfer"-Programme (Assistenten) ANSI.EXE - (nur Vollversion) ANSI-Tabelle PROFCOMP.EXE (SHPRCOMP.EXE) - Der Compiler PROFLINK.EXE - Der Linker PROFRUN.EXE - Das Runtime-Modul (16 Bit) PRFRUN32.EXE - Das Runtime-Modul (Windows 95) PRFRUNNT.EXE - Das Runtime-Modul (Windows 95 + NT) PROF16.EXE * (nur 32-Bit-Version) Seite 10 RGH-PROFAN² * Wenn Sie aus einem 32-Bit-Programm 16-Bit-DLLs oder Funktionen der 16-Bit-API aufrufen wollen, benötigen Sie auch PROF16.EXE, welches in Ihrem Windowsverzeichnis installiert wurde. Der Hilfegenerator (nicht in der Sharewareversion) benötigt noch folgende Dateien: HCP.EXE HCP.ERR PROFAN² (Anwendung als Batchsprache für Windows): PROFAN.EXE (SHPROFAN.EXE) - Der Interpreter *.PRF - Das Batchprogramm (+ Module) in Profan PROF16.EXE * (nur 32-Bit-Version) PROFAN² (compilierte Anwendung): PROFRUN.EXE - Das Runtime-Modul oder ein zur EXE-Datei gelinktes Profanprogramm *.PRC - Programm, bzw. Programmmodule PROF16.EXE * (nur 32-Bit-Version) Ein zur EXE-Datei gelinktes Profanprogramm ist ohne weitere Dateien eigenständig lauffähig. Wenn aus 32-Bit-Programmen Zugriffe auf die 16-Bit-API oder 16-Bit-DLLs erfolgen, wird noch PROF16.EXE im Windowsverzeichnis benötigt. 2.3 DE-INSTALLATION Wollen Sie PROFAN² von Ihrer Festplatte tilgen - was ich mir kaum vorstellen kann -, so löschen Sie das einfach das komplette Verzeichnis, in das Sie PROFAN² installiert haben. Außerdem sind im Windowsverzeichnis noch folgende Dateien installiert worden, die auch zu löschen sind: TABELLEN.HLP, DIALOGE.HLP, STRUKTUR.HL, FENSTER.HLP und PROFED16.INI (für die 16-Bit-Version) und PROFED32.INI (32-Bit-Version). Die 32-BitVersion sollte über den entsprechenden Punkt in der Systemsteuerung (Software) deinstalliert werden. Seite 11 RGH-PROFAN² 3 - RGH-PROFAN-EDITOR Der Editor ist eine komplette Entwicklungsumgebung für RGH-PROFAN². 3.1 EDITOR - Übersicht Multi-File-Editor Der Editor ist ein "Multi-File"-Editor, das heißt: Es können mehrere Dateien gleichzeitig editiert werden. Das ermöglicht einfaches Kopieren und Verschieben auch zwischen verschiedenen Programmen über die Zwischenablage. Um ein anderes Programm oder einen anderen Text einzusehen, muß das aktuelle Programm nicht verlassen werden. Jedes Programmfenster kann bis zu 16 MB Text enthalten. Optionen Im Optionsmenü findet sich eine Möglichkeit, die Toolbar abzuschalten, man kann endlich die Tabulatorweite einstellen und es sind alle nichtproportionalen Schriften auswählbar, die auf Ihrem System installiert sind. Im Suchen-Menü ist die Möglichkeit hinzugekommen, eine Zeile direkt anzuspringen, außerdem können die zehn Textmarken angesprungen werden. Arbeitserleichterung Im Bearbeiten-Menü gibt es die meisten Erweiterungen: Es können nun nahezu beliebig viele (8 kB- Puffer) Aktionen rückgängig gemacht werden und dieses Rückgängigmachen kann auch wieder korrigiert werden. Es können nun komplette Dateien eingefügt werden bzw. kann auch der markierte Text als Datei gesichert werden. Das Datum und die Zeit können eingefügt werden und das Wichtigste in dem Menü: Es können bis zu zehn Textmarken gesetzt werden, die direkt angesprungen werden können. Hierfür gibt es natürlich auch schnelle Tastencodes, die in der Hilfe nachzuschlagen sind. Gerade bei längeren Programmtexten entfällt so viel lästiges Blättern. Rechte Maustaste Mittels der rechten Maustaste kann im Editoerfenster jederzeit auch ein Kontextmenü geöffnet werden, das die wichtigsten Bearbeitungsmöglichkeiten bietet. PROFED16.INI / PROFED32.INI Außerdem gibt es eine INI-Datei (je nach Version PROFED16.INI bzw. PROFED32.INI), in der die aktuellen Einstellungen (Schrift, Projektdatei) festgehalten werden. WICHTIG: Um die aktuellen Einstellungen für den nächten Programmstart zu speichern, muß das Programm über den Menüpunkt DATEI-ENDE verlassen werden. Toolbar - Statuszeile Eine (nun abschaltbare) Toolbar mit den wichtigsten Funktionen vereinfacht die Bedienung und eine Statuszeile informiert Sie über die aktuelle Kursorposition und ob der Text des Editors seit dem Laden bzw. letzten Speichern geändert wurde. Seite 12 RGH-PROFAN² Helfer und Hilfe Was in anderen Programmen Wizard oder Assistent genannt wird, ist bei PROFAN² der Helfer. So gibt es einen Helfer um Datenbanktabellen (Bestandsdateien) zu definieren und erzeugen, einen Helfer, um Datenbanktabellen zu bearbeiten, einen Helfer um Oberflächen zu entwerfen und einen Helfer, um Dialogboxen zu gestalten. Zusätzlich gibt es ein anwenderdefiniertes Menü, in das Sie Ihre meistgebrauchten Werkzeuge und Hilfsprogramme - etwa den ICON-Editor - aufnehmen können. Selbstverständlich gibt es eine kontextsensitive Hilfe, die mit <Strg-F1> oder über das Kontextmenü die Hilfe zum Schlüsselwort anzeigt, auf dem sich der Kursor befindet. (Ein Markieren des Wortes ist nicht mehr notwendig.) Projektverwaltung Eine Projektverwaltung vereinfacht die Arbeit an verschiedenen Projekten. Da man in verschiedenen Projekten oftmals verschiedene PROFRUN.EXE mit unterschiedlichen Icons bzw. Resourcen benutzt, kann zu jedem Projekt auch eine eigene PROFRUN.EXE definiert werden. Voreingestellt ist in der 16-Bit-Version die PROFRUN.EXE und in der 32-Bit-Version die PRFRUN32.EXE im PROFAN-Verzeichnis, die möglichst nicht verändert werden sollte. Es ist empfehlenswert, jedem Projekt einen eigenen Pfad zu geben. Ich habe mir angewöhnt, diesen unterhalb des PROFAN-Verzeichnisses anzulegen. Die Projektdateien speichere ich im PROFAN-Verzeichnis. Wenn ich nun ein neues Projekt beginne, lege ich mit dem Dateimanager ein neues Verzeichnis an. Anschließend starte ich PROFAN und erzeuge über den Menüpunkt "DATEI - NEUES PROJEKT" eine Projektdatei. Im anschließenden Optionen-Dialog gebe ich Runtime-Modul und Projektverzeichnis an. Anschließend erzeuge ich mit "DATEI - NEU" eine leere PROFAN-Datei und speichere sie im Projektverzeichnis ab. Dann speichere ich das Projekt noch einmal ab und nun wird beim Öffnen des Projektes, immer diese Datei geladen und die anderen Einstellkungen stimmen dann auch. Drucken Die Entwicklungsumgebung hat jetzt eine eigene Druckfunktion. Da unter Umständen jedoch die vielfältigeren Möglichkeiten des externen Druckprogrammes RGH-DRUCK sinnvoll sind, wird es weiterhin mitinstalliert und kann z.B. in das Benutzermenü der Entwicklungsumgebung eingebunden werden. 3.2 EDITOR - Aufruf Sie haben mehrere Möglichkeiten, um mit dem Editor zu arbeiten: Aufruf mit Kommandozeilenparameter Sie können beim Aufruf des Editors eine oder mehrere Dateien als Kommandozeilenparameter angeben. Die Dateien werden beim Start automatisch geladen. (Der Desktop der letzten Arbeitssitzung mit dem Editor bleibt dabei unberücksichtigt.) Wenn Sie dem Dateinamen ein @ voranstellen wird dieser als Projektdatei interpretiert. Beispiele: PROFED beispiel.prf hilfe.txt PROFED @cdplay.prj PROFED @cdplay.prj beispiel.prf Bei der 32-Bit-Version ist statt PROFED das Programm PROFED32 aufzurufen. Seite 13 RGH-PROFAN² Aufruf ohne Parameter Wenn Sie den Editor ohne Parameter (zum Beispiel über das Symbol des ProgrammManagers aufrufen, wird automatisch das Projekt der letzen Arbeitssitzung wiederhergestellt, das heißt: alle Dateien die damals bearbeitet wurden, werden wieder geladen und in das entsprechende Verzeichnis gewechselt. 3.3 Die Menüpunkte im Einzelnen: DATEI - Neues Projekt Es wird eine neue noch leere Projektdatei unter einem frei zu wählenden Namen gespeichert (vorgeschlagene Endung .PRJ). Als Projektpfad wird zunächst der Pfad genommen, indem man sich zur Zeit des Speicherns befindet. Im anschließenden Einstellungsdialog können jedoch Projekt- und Runtimepfad beliebig eingestellt werden. Alle Dateien, die beim Beenden oder Speichern des Projektes geöffnet sind, werden dem Projekt hinzugefügt. Wenn man dann weiterarbeiten will, kann man das Projekt mit allen Dateien laden. DATEI - Projekt - speichern als Das aktuelle Projekt (Dateinamen, Runtime-Modul, Projektpfad) wird unter einem frei zu wählenden Namen gespeichert (vorgeschlagene Endung .PRJ). DATEI - Projekt laden Ein gespeichertes Projekt wird mit allen seinen Dateien geöffnet. Bereits vorher geöffnete Dateien bleiben geöffnet, sodaß man ein Projekt zu einem anderen hinzuladen kann. DATEI - Projekt schließen Das aktuelle Projekt wird gespeichert und dann geschlossen: Alle Dateien werden geschlossen und anschließend das Projekt selbst. DATEI - Neue Datei Ein neues RGH-PROFAN-Programm schreiben. Es bekommt zunächst den Namen "OHNENAME.PRF". Existiert bereits ein Programm "OHNENAME.PRF", so wird es geladen. Es empfiehlt sich, das Programm sogleich mit "Speichern als" abzuspeichern und ihm einen neuen Namen zu geben. DATEI - Datei Öffnen Eine bereits bestehende Datei wird zum Bearbeiten geöffnet. Die wichtigsten Dateitypen werden zur Auswahl angeboten. DATEI - Datei Speichern Die aktuell aktive PROFAN-Datei wird unter ihrem Namen gespeichert. Seite 14 RGH-PROFAN² DATEI - Datei Speichern als Die aktuell aktive PROFAN-Datei kann unter einem neuen Namen/Pfad abgespeichert werden. DATEI - Datei schließen Die aktuell aktive Datei wird geschlossen. Es wird ggf. nachgefragt, ob Änderungen gespeichert werden sollen. DATEI - Drucker einrichten Der Drucker kann ausgewählt und eingerichtet werden. DATEI - Drucken Die aktuelle Datei wird gedruckt. Ist ein Text markiert, kann ausgewählt werden, ob der gesamte Text oder nur der ausgewählte Teil gedruckt werden soll. Der Programmtext wird mit Zeilennummern gedruckt. DATEI - Programm aufrufen Ein beliebiges EXE-Programm kann über diesen Menüpunkt aufgerufen werden. DATEI - Ende Der Editor wird beendet. Sollten Programme nach der Veränderung noch nicht abgespeichert sein, wird jeweils nachgefragt, ob man dies nun möchte. BEARBEITEN - Rückgängig Die letzten Editiervorgänge können noch rückgängig gemacht werden. Der RückgängigPuffer ist so bemessen, daß im Normalfall mehrere hundert bis tausend Editiervorgänge rückgängig gemacht werden können. BEARBEITEN - Widerrufen Die letzten Rückgängig-Aktionen können widerrufen werden. BEARBEITEN - Ausschneiden Der markierte Text wird in die Zwischenablage kopiert und aus dem Programm entfernt. BEARBEITEN - Kopie Der markierte Text wird in die Zwischenablage kopiert, bleibt aber im Programm. BEARBEITEN - Einfügen Der Text der Zwischenablage wird an der Kursorposition eingefügt. Seite 15 RGH-PROFAN² BEARBEITEN - Löschen Der markierte Text wird gelöscht. BEARBEITEN - Alles auswählen Der gesamte Text im aktuellen Fenster wird ausgewählt (markiert). BEARBEITEN - Alles löschen Der gesamte Text wird gelöscht. BEARBEITEN - Einfügen aus Datei Es kann eine Text-Datei ausgewählt werden, deren Inhalt an der Kursorposition eingefügt wird. BEARBEITEN - Kopieren als Datei Der ausgewählte (markierte) Text wird als Datei gespeichert. Es ist der Name der Datei einzugeben. Existiert die Datei schon, wird sie überschrieben. BEARBEITEN - Ablage Die Windows-Zwischenablage wird aufgerufen. So kann man nachsehen, was da gerade drin ist. BEARBEITEN - Datum + Zeit Datum und Zeit werden an der aktuellen Kursorposition eingefügt. BEARBEITEN - SetzeMerker An der aktuellen Kursorposition wird eine (sichtbare aber nicht druck- oder speicherbare) Markierung gesetzt. Es sind die Markierungen 0 bis 9 möglich. Diese Markierungen sind quasi Lesezeichen, zu denen jederzeit direkt mit <Strg-0> bis <Strg-9> gesprungen werden kann. Die Markierung kann auch mit <Umsch-Strg-0> bis <Umsch-Strg-9> bzw. über das Kontextmenü mittels der rechten Maustaste gesetzt werden. SUCHEN - Finden Sucht im aktuellen Programmfenster nach einem Text. Es kann angegeben werden, ob zwischen Groß- und Kleinschreibung zu unterscheiden ist. Mit <Strg-L> kann die Suche wiederholt werden. Seite 16 RGH-PROFAN² SUCHEN - Ersetzen Sucht im aktuellen Programmfenster nach einem Text und ersetzt ihn durch einen anderen. Es kann angegeben werden, ob Groß- und Kleinschreibung zu unterscheiden ist, ob im ganzen Text gesucht werden soll und ob vor jedem Ersetzen nachgefragt werden soll. SUCHEN - Weitersuchen Wiederholt die Suche bzw. das Suchen und Ersetzen. SUCHEN - GeheZuZeile Es kann direkt eine bestrimmte Zeile angesprungen werden. SUCHEN - GeheZuMerker Es wird direkt zur gewählten Markierung gesprungen. Schneller und effektiver läßt sich dies auch mit Strg-0 bis Strg-9 erreichen. Existiert die Markierung nicht, passiert garnichts. PROFAN - Ausführen (Interpreter) Führt ein PROFAN-Programm mit dem Interpreter aus. Das Programm wird von der Festplatte gelesen. Ist ein noch nicht in der aktuellen Version abgespeichertes Programm im Editor, wird nachgefragt, ob man es zuvor abspeichern will. PROFAN - als Script-Datei Ausführen Führt ein PROFAN-Programm mit PROFAN-SCRIPT aus. Hiermit kann ein Programm auf seine Tauglichkeit für den Einsatz mit PROFAN-SCRIPT getestet werden. Das Programm wird von der Festplatte gelesen. Ist ein noch nicht in der aktuellen Version abgespeichertes Programm im Editor, wird nachgefragt, ob man es zuvor abspeichern will . PROFAN - Compilieren Es wird ein PROFAN-Programm (.PRF) compiliert. Der Compiler PROFCOMP.EXE muß sich im gleichen Verzeichnis wie der Editor befinden. Das Ergebnis ist eine Datei mit der Endung .PRC, die vom Runtime-Modul PROFRUN oder jeder PROFAN-EXE-Datei ausgeführt werden kann. Die PRC-Datei ist in der Regel nur halb so groß, wie die PRF-Datei, dafür aber deutlich (!) schneller. Die entstehende PRC-Datei wird in dem Verzeichnis abgelegt, in dem sich die PRF-Datei befindet! PROFAN - Starten Ein compiliertes PROFAN-Programm wird vom Runtime-Modul gestartet und ausgeführt. PROFRUN.EXE muß sich im gleichen Verzeichnis wie der Editor oder im Windowsverzeichnis befinden. Seite 17 RGH-PROFAN² PROFAN - EXE-Datei erstellen Eine PRC-Datei wird mit dem Runtime-Modul zu einer EXE-Datei gelinkt. Der Linker PROFLINK.EXE muß sich im gleichen Verzeichnis wie der Editor befinden. Die EXE-Datei kann unter Windows selbstständig ausgeführt werden. Da sie das komplette RUNTIMEModul enthält, kann sie für PRC-Dateien auch als Runtime-Modul dienen. PROFAN - ScreenSaver erstellen Eine PRC-Datei wird mit dem Runtime-Modul zu einer SCR-Datei gelinkt. Der Linker PROFLINK.EXE muß sich im gleichen Verzeichnis wie der Editor befinden. Die SCR-Datei kann in der Systemsteuerung von Windows als Bildschirmschoner eingebunden werden. Der Name des Screensavers ist in der 32-Bit-Version der Dateiname; in der 16-Bit-Version wird er abgefragt. HELFER - Datenbankstruktur Mit diesem Modul können Sie Datenbankstrukturen definieren, diese als Templatedateien für den DBCREATE-Befehl ablegen oder auch die Tabelle gleich erzeugen. Näheres finden Sie in der Hilfe des Moduls. HELFER - Tabellen bearbeiten Mit diesem Modul können Sie beliebige dBase-III kompatiblen Tabellen (*.DBF) bearbeiten. Mit dem [*] können Sie auf jedes Feld einen Index legen. Der Index wird beim Suchen nach einem Eintrag mit [Suchen] benutzt. Ohne Index kann in jedem Feld mit [?] gesucht werden. Hat eine Tabelle mehr als zehn Felder, so können Sie mit [«] und [»] durch die Felder blättern. HELFER - Fenster gestalten Dieser Helfer ermöglicht Ihnen die einfache Gestaltung des Hauptfensters mit den zur Verfügung stehenden Dialogelementen. Nach dem Aufruf werden Sie gebeten, mit der Maus die Größe des Fensters zu markieren. Weitere Hilfe entnehmen Sie der Hilfe des Helfers, indem Sie den Button mit dem Fragezeichen anklicken. HELFER - Dialoge gestalten Dieser Helfer ermöglicht die bequeme Gestaltung von Dialogboxen. Zu Beginn können Sie wählen, ob Sie einen schon erstellten Dialog laden oder mit einem neuen beginnen. In letzterem Fall müssen Sie zunächst die Größe des Dialogfensters mit der Maus markieren. Auch dieses Modul hat eine eigene Hilfe. HELFER - Hilfe erzeugen Dieser Helfer ermöglicht die einfache Erzeugung einer Windows-Hilfedatei. Damit die Hildedatei erstellt werden kann, muß der Microsoft-Hilfecompiler HCP.EXE mit HCP.ERR im PROFAN-Verzeichnis sein. Auch der Hilfegenerator hat eine eigene Hilfe. Seite 18 RGH-PROFAN² HELFER - Menü-Designer Dieser Helfer ermöglicht die rasche und bequeme Gestaltung von Menüs für Ihre PROFAN²Programme. Der Menü-Designer erzeugt den entsprechenden Quellcode als ablauffähiges Programmgerüst. Nähere Hinweise entnehmen Sie bitte der Hilfe des Menü-Designers. HELFER - Benutzermenü Dem Benutzermenü kann ein Eintrag hinzugefügt werden. Es werden zwei Angaben erwartet: Bezeichnung des Eintrages im Menü und die dazugehörige Befehlszeile. (Um Menüpunkte zu löschen, muß die Datei PROFED.INI im Windowsverzeichnis bearbeitet werden. Die Anzahl der Menüpunkte muß angepaßt und die entsprechenden Zeilen gelöscht werden.) OPTIONEN - Toolbar Die Toolbar (Icon-Leiste) kann wahlweise ein- oder ausgeschaltet werden. OPTIONEN - Zeilenumbruch Der automatische Zeilenumbruch kann wahlweise ein- oder ausgeschaltet werden. Bei eingeschaltetem Zeilenumbruch werden Wörter, die nicht mehr in die aktuelle Bildschirmzeile passen, automatisch in die nächste Zeile gesetzt. Diese Einstellung sollte für die meisten Texte Verwendung finden. Ohne Zeilenumbruch kann eine Zeile bis zu 32000 Zeichen enthalten. Diese Einstellung ist zum Bearbeiten von Programmtexten zu empfehlen. OPTIONEN - Tabulator Der Tabulator kann eingestellt werden. Defaultmäßig sind 8 Zeichen eingestellt, d.h. [TAB] bewegt den Kursor auf die 8., 16., 24. etc. Position. OPTIONEN - Schrift ... Eine der installierten nichtproportionalen Schriften kann ausgewählt werden. OPTIONEN - Includepfad Der Pfad zu den Include-Dateien ist anzugeben. Er kann auch (wie der z.B. DOS-Pfad in der AUTOEXEC.BAT) mehrere Verzeichnisse durch Semikolon getrennt enthalten. Beispiel: "C:\PROFAN;C:\PROFAN\INCLUDE". Gesucht wird nach Include-Dateien in folgender Reihenfolge: 1. Im aktuellen Verzeichnis - 2. Im Includepfad. OPTIONEN - Projekt-Einstellungen Hier können Projektpad und Runtime-Modul des Projektes eingestellt werden. Jedem Projekt kann eine eigene Runtime-Datei (in der Regel PROFRUN.EXE bzw. PRFRUN32.EXE) zugeordnet werden, die beim Starten und Linken des compilierten Programmes genutzt wird. Das ist dann besonders sinnvoll, wenn man für ein Projekt eine geänderte PROFRUN.EXE mit einem eigenen Icon- bzw. Resourcen-Satz verwendet. Seite 19 RGH-PROFAN² FENSTER - Nebeneinander / Untereinander Die verschiedenen Programmfenster im Editor werden nebeneinander, bzw. übereinander angeordnet, sodaß sie sich nicht überschneiden. FENSTER - Überlappend Die Programmfenster werden versetzt hintereinander angeordnet, sodaß von allen die Titelseite zu sehen ist. FENSTER - Symbole anordnen Die Icons der verkleinerten Programmfenster werden in Reih' und Glied gebracht. FENSTER - Alle schließen Alle Programmfenster werden geschlossen. FENSTER - Rechner Der Windows-Taschenrechner wird für Berechnungen zwischendurch aufgerufen. FENSTER - Ansi-Tabelle Eine Ansi-Tabelle wird aufgerufen. Zeichen können aus der Ansi-Tabelle übernommen werden. (Siehe Hilfetext der ANSI-Tabelle) FENSTER - Kalender Der Windows-Kalender wird aufgerufen. FENSTER - 1 ... Hier sind alle geöffneten Programme aufgelistet. Wenn man die Editorfenster auf optimale Größe vergrößert hat, kann durch diese Menüpunkte einfach zwischen den Fenstern umgeschaltet werden. ? - PROFAN-Hilfe Die komplette Hilfe zu PROFAN wird aufgerufen. Diese Hilfedatei enthält sowohl die komplette Einführung als Hypertext, als auch die Referenz mit allen Systemvariablen, Funktionen und Befehlen ? - Referenz In der Referenz ist die komplette Programmiersprache RGH-PROFAN² in der aktuellen Version beschrieben. Im Zweifelsfalle ist diese Referenz aktueller als das entsprechende Handbuch. Für jede Systemvariable, jede Funktion und jeden Befehl findet sich eine Syntaxbeschreibung und häufig auch Beispiele. Seite 20 RGH-PROFAN² ? - kontextabhängige Hilfe Die Hilfe zum Wort (Befehl/Funktion/Systemvariable), auf dem der Kursor steht, wird angezeigt. Die kontextabhängige Hilfe kann auch mit <Strg-F1> oder über das Kontextmenü (rechte Maustaste) aufgerufen werden. ? - Editor Hilfe zur Entwicklungsumgebung. Alle Menüpunkte werden erläutert. ? - Suche in der Hilfe Der Such-Dialog der Hilfe wird geöffnet, um nach einem Begriff in der Hilfe zu suchen. ? - Hilfe verwenden Eine Einführung in die Benutzung der Hilfe-Funktion wird gegeben.. ? - Über Copyright-Vermerk: 1992-1997 - Roland G. Hülsmann, Nußloch. Seite 21 RGH-PROFAN² 3.4 - RGH-DRUCK RGH-DRUCK ist ein eigenständiges Programm zum Drucken beliebiger Texte. Es enthält weitreichende Formatierungsmöglichkeiten. Die Menüpunkte: Datei - Öffnen Datei - Drucken Datei - Drucker einrichten Datei - Seitenformat Datei - Ende Text - Schrift Alle diese Funktionen können auch über die entsprechenden Buttons direkt angewählt werden. Die Bilder sind selbsterklärend. Im System-Menü von RGH-DRUCK finden sich noch ein weiterer Menüpunkt: Über ... Datei - Öffen Öffnet die zu druckende Datei. Diese wird in den Speicher gelesen und kann auch betrachtet werden. Änderungen sind jedoch nicht möglich. Lange Texte werden auch nur teilweise angezeigt, jedoch vollständig gedruckt. Datei - Drucken Der Text wird im eingetellten Format mit der eingestellten Schrift gedruckt. Datei - Drucker einrichten Sie können den Drucker einrichten: Papierformat wählen, Einzugsschacht festlegen, Drucker wechseln, etc. Datei - Seitenformat Zahlreiche Formatierungen können eingestellt werden: Ränder, Zeilenlineal, Zeilennummern (bei PROFAN-Listings sinnvoll), ANSI-CC-Byte (in der Regel nicht anzukreuzen), Datum, Zeit, Tabulatorgröße. Die Tabulatorgröße sollte der PROFAN-Editors entsprechen; voreingestellt ist 8. Zusätzlich können Sie noch Kopf- und Fußzeile eingeben. Datei - Ende Beendet das Druckprogramm. Text - Schrift Es kann eine Schriftart und Schriftgröße gewählt werden. Es ist ratsam eine schmale Schrift zu verwenden, da Zeilen, die nicht ganz in eine Druckzeile passen, einfach abgeschnitten werden. Seite 22 RGH-PROFAN² Systemsteuerung Da kann der Drucker (und anderes) eingestellt werden. Über ... Copyright-Hinweis. Hinweis auf das amerikanische Programm, dessen Quellcode Grundlage von RGH-Druck ist: PLXpress 1.3 von Doug Overmyer. Erweitert und ins Deutsche übertragen von Roland G. Hülsmann. Seite 23 RGH-PROFAN² 4 - PROFAN-SCRIPT PROFAN-SCRIPT ist die Internet-Scriptsprache mit einer Untermenge des Befehlsumfanges der Programmiersprache PROFAN²! Sie binden es in Ihren Web-Browser ein, indem Sie die Dateiendung 'PSC' mit PROFSCR.EXE verknüpfen. In der Online-Hilfe von PROFAN² bzw. PROFAN-SCRIPT finden Sie Hinweise zur Verknüpfung mit MS Internet-Explorer, Mosaic und Netscape. Ausprobiert werden kann die richtige Einbindung über die PROFAN-SCRIPT-Testseite von Andreas Schulten u.A. mit einem kleinen Spielchen (5 k, in ca. 2-5 sec geladen): http://members.aol.com/ASchulten/psc.htm PROFAN-SCRIPT ist FREEWARE und darf unverändert beliebig weiterverbreitet werden. Ausdrücklich ist auch die Verbreitung auf CD-ROM und zusammen mit anderen Produkten erlaubt. Folgende Dateien gehören zu PROFAN-SCRIPT: PROFSCR.EXE (Der Interpreter in 16- oder 32-Bit-Version), PROFSCR.HLP (Hilfedatei) und PSED.EXE (eine minimalistische Entwicklungsumgebung). Wenn Sie PROFAN-SCRIPT mit dem PROFAN²-PAKET erhalten haben, wurden die Dateien für die Weitergabe von PROFAN-SCRIPT (mit Ausnahme des Interpreters) in das Verzeichnis PRPFSCR unterhalb Ihres PROFAN-Verzeichnisses kopiert. Die entsprechende PROFSCR.EXE befindet sich im PROFAN²-Verzeichnis. Mit PROFAN-SCRIPT sind keine Änderungen von Dateien und System des Anwenders möglich. Es können keine Infos ausgespäht und in das Internet weitergegeben werden! Seite 24 RGH-PROFAN² 5 - Direktiven für Interpreter und Compiler Eine Direktive für Interpreter und Compiler beeinflußt die Art, wie der Quelltext interpretiert bzw. umgesetzt wird. Eine Direktive wird mit einem $ eingeleitet und von einem Buchstaben gefolgt. Zur Zeit kennt PROFAN² folgende drei Direktiven für Interpreter und Compiler: 5.1 $P+ : Verschlüsselung des Zwischencodes Wenn diese Direktive im Programm vorkommt, wird der Zwischencode, den der Compiler erzeugt, verschlüsselt abgespeichert. Texte, die im Programm vorkommen, können dann nicht mehr mit einem Hex- Editor gelesen werden. So kann keiner Ihre Copyright-Meldungen oder andere Texte verändern. Dem Runtime-Modul und dem Linker ist es egal, ob der Zwischencode (die PRC-Datei) verschlüsselt ist oder nicht. Die Ablaufgeschwindigkeit des Programmes wird nicht beeinflußt, lediglich die Zeit die das Programm vom Aufruf bis zum Start braucht, wird ein wenig (aber unmerklich) erhöht, da das Programm vor der Ausführung im Speicher entschlüsselt werden muß. $P+ Hinweis: Das "P" muß groß geschrieben sein! 5.2 $I : Include-Dateien Seit PROFAN² 2.0 gibt es auch die Möglichkeiten, Programmodule während des Compilierens bzw. Interpretierens dazuzuladen. Das geschieht mit der Direktive: $I <Dateiname> (Hinter dem großen Buchstaben I muß ein Leerfeld sein.) Für den Interpreter oder Compiler ist es dann so, als stünde der Inhalt der Datei <Dateiname> an der entsprechenden Stelle im Programm. Wenn der Dateiname keine Pfadangabe enthält wird die Includedatei zunächst im aktuellen Verzeichnis und dann im Includepfad gesucht. Der Includepfad wird im EditorMenü "OPTIONEN/Include-Pfad" eingestellt. Beispiel: Declare Test%, Frage$, Antwort$ $I ZUSATZ.INC ... Auf diese Weise können häufig gebrauchte Module beliebig oft verwandt werden, ohne daß sie jedesmal neu eingetippt oder über die Zwischenablage kopiert werden müßten. Besonders sinnvoll ist diese Methode, wenn man zum Beispiel besonders häufig gebrauchte Prozeduren oder selbstdefinierte Funktionen in Include-Dateien abspeichert. Ich habe mir angewöhnt, Includedateien mit der Endung .INC zu versehen. Seite 25 RGH-PROFAN² 5.3 - $O : Präprozessor für Operatoren An sich kennt PROFAN² ja keine Operatoren, sondern alles wird in Funktionen ausgedrückt. Ab Version 4.1 gibt es aber einen integrierten Präprozessor, der in gewissem Maße Operatoren erlaubt. Dieser Präprozessor übersetzt im Quelltext vorkommende Operatoren in die übliche PROFAN²-Syntax. Standardmäßig ist dieser Präprozessor ausgeschaltet. Mit $O+ wird er eingeschaltet und ist so lange aktiv, bis er wieder mit $O- ausgeschaltet wird. Da der Interpreter bei eingeschaltetem Präprozessor bis zu 50% langsamer wird, sollte man ihn nur einschalten wenn er benötigt wird. Bei eingeschaltetem Präprozessor benötigt auch der Compiler etwas länger. Auf die Laufzeit des compilierten Programmes hat der Schalter keinen Einfluß. Näheres zu Operatoren siehe im folgenden Kapitel. Hinweis: Das "O" muß groß geschrieben sein!` Seite 26 RGH-PROFAN² 6 - Operatoren Operatoren, wie man sie von anderen Sprachen her kennt, gibt es in PROFAN normalerweise nicht. Alles wird mittels Funktionen erledigt. Es gibt für alle gewohnten Operatoren entsprechende Funktionen. Statt LET A% = A% + 3 muß z.B. geschrieben werden: LET A% = @ADD(A%,3) WICHTIG: Das LET darf nicht weggelassen werden. Diese Philosophie wird auch konsequent bei Vergleichen und Bedingungen eingesetzt: IF A% = B% IF A% AND B% wird zu wird zu IF @EQU(A%,B%) IF @AND(A%,B%) Ab Version 4.1 besitzt PROFAN² aber einen integrierten Präprozessor, der ansatzweise die Nutzung von Operatoren ermöglicht. Folgende Operatoren sind zugelassen, wenn der Präprozessor mit $O+ aktiviert ist: (A% (A% (A% (A% (A% (A% (A% (A% (A% + * / \ ^ < > = B%) B%) B%) B%) B%) B%) B%) B%) B%) entspricht entspricht entspricht entspricht entspricht entspricht entspricht entspricht entspricht @ADD(A%,B%) @SUB(A%,B%) @MUL(A%,B%) @DIV(A%,B%) @DIV&(A%,B%) @POW(A%,B%) @LT(A%,B%) @GT(A%,B%) @EQU(A%,B%) Die zwei (!) mit Operatoren verknüpften Werte müssen in Klammern stehen. (Das ist besonders bei -, = und > notwendig, da diese Zeichen auch Trennzeichen zwischen Parametern sein können und vom Präprozessor als solche interpretiert würden.) Ebenso wie Funktionen können Ausdrücke mit Operatoren verschachtelt werden. Beispiele: $O+ IF (A% > LOCATE ENDIF LET A% = SETPIXEL B%) (A%+5),(B%-3) (3 * (B% + C%)) X%,(5*@SIN(Y%)),0 Eine Verknüpfung von mehr als zwei Werten ist ohne zusätzliche Klammerung nicht möglich! LET A% = (B% + C% + D%) ist nicht erlaubt. Statt dessen ist zu schreiben: LET A% = ((B% + C%) + D%) ACHTUNG: Standardmäßig ist der Präprozessor ausgeschaltet. Vor der Nutzung muß er mit $O+ aktiviert werden! Damit der Präprozessor korrekt funktioniert, dürfen die Variablennamen weder einen der Operatoren, noch ein Zeichen enthalten, mit denen Parameter getrennt werden (das sind , ; - > = : und das Leerzeichen). Auch sonst können diese Zeichen in Variablennamen zu Problemen führen. Derzeit wird das von PROFAN² aber noch nicht angemeckert. Da der Präprozessor die entsprerchenden Zeilen vor der Ausführung bzw. vor dem Compilieren übersetzt, können sich Texte in Fehlermeldungen auf die übersetzte Syntax beziehen. Seite 27 RGH-PROFAN² Für schnelle Berechnungen mit Integer-Werten (z.B. in Schleifen, etc.) gibt es in PROFAN² einige neue Befehle, die schneller und übersichtlicher sind: INC DEC ADD SUB V% V% V%,n V%,n erhöht V% um 1 erniedrigt V% um 1 erhöht V% um n erniedrigt V% um n (Hierbei steht V% für eine beliebige Integer-Variable und n für einen beliebigen Ausdruck.) Für das Zusammenfügen von Strings (Zeichenketten) kann die Funktion @ADD$ verwandt werden. Es ist aber auch möglich, in einem LET-Befehl verschiedene Strings zusammenzufügen, indem die Stringausdrücke (wie beim PRINT-Befehl) durch Semikolon oder Komma getrennt, hintereinandergeschrieben werden. Beispiel: LET TEXT$ = "Du bist",Alter%,"Jahre alt." Dabei fügt ein Semikolon die Strings direkt zusammen, während ein Komma ein Leerzeichen einfügt. HINWEIS: Die automatische Typumwandlung funktioniert bei einfachen Variablen. Bei Funktionen, die einen numerischen Wert zurückgeben, wird nicht immer automatisch umgewandelt, daher ist hier immer die Funktion @Str$ zu verwenden! Seite 28 RGH-PROFAN² 7 - Variablen, Datentypen und Typen-Umwandlung Variablen sind Platzhalter, um im Programm gebrauchte Werte zwischenzuspeichern. Je nach Art des Wertes wird ein bestimmter Datentyp verwandt. PROFAN² kennt fünf Datentypen: Integer, LongInt, Float, String und Bereich. Wie in PASCAL müssen Variablen vor ihrer Verwendung deklariert werden. Nur deklarierte Variablen sind bekannt und können vom folgenden Programm genutzt werden. Das Deklarieren geschieht in PROFAN² mit dem Befehl "Declare". Wenn der Befehl auch überall im Programm stehen darf, so empfiehlt es sich doch, alle Declare-Anweisungen am Anfang des Programmes oder der Prozedur zu stellen. Mehrere Variablen können durch Kommata getrennt mit einem Declare-Befehl deklariert werden: Declare Zahl1%, Zahl2!, Text$ Declare Ergebnis& Der Typ der Variablen wird durch das Postfix (letztes Zeichen des Variablennamens festgelegt. Der Variablenname darf (inclusive Postfix) 32 Zeichen lang sein und außer dem Leerzeichen so ziemlich alle Zeichen enthalten. Trotzdem ist dringend zu empfehlen, nur Buchstaben, Ziffern, Unterstriche und Punkte zu verwenden. Sonst wirds unleserlich. Damit der Präprozessor für Operatoren korrekt funktioniert, dürfen die Variablennamen weder einen der Operatoren, noch ein Zeichen enthalten, mit denen Parameter getrennt werden (das sind , ; - > = : und das Leerzeichen). Auch sonst können diese Zeichen in Variablennamen zu Problemen führen. Derzeit wird das von PROFAN² aber noch nicht angemeckert. In einer Prozedur oder einem Unterprogramm definierte Variablen sind nur in der Prozedur bekannt. Hingegen sind in einer Prozedur oder einem Unterprogramm auch alle außerhalb declarierten Variablen bekannt. Hier verhält sich PROFAN eher wie PASCAL. (Das aus BASIC bekannte SHARED wird nicht benötigt.) ACHTUNG: Eine Ausnahme bilden die Bereichs- und Arrayvariablen: Diese sind immer global und überall bekannt! 7.1 Integer Integervariablen werden, wie in BASIC üblich, durch ein % als Postfix gekennzeichnet. Integervariablen können Werte von -32768 bis + 32767 annehmen. Wird dieser Wert überoder unterschritten, erfolgt zwar keine Fehlermeldung, aber die Ergebnisse werden ungewöhnlich sein. Nur mit Integervariablen können auch die vier Rechenbefehle INC, DEC, ADD und SUB durchgeführt werden. HINWEIS: Aus Kompatibilitätsgründen ist auch im 32-Bit-PROFAN² der "offizielle" Wertebereich eines Integers unverändert von -32768 bis 32767! Seite 29 RGH-PROFAN² 7.2 LongInt LongInt-Variablen haben das & als Postfix. Im übrigen gilt für den Variablennamen das gleiche, wie für Integer. Der Wertebereich geht von -2 Milliarden bis etwas über +2 Milliarden. 7.3 Float Float heißen jene Variablen, die reelle Zahlen (Fließkomma-Zahlen) aufnehmen können. Die Rechengenauigkeit ist mindestens 15 Stellen. Ach ja: Das Postfix ist, wie in BASIC, das Ausrufezeichen. Im Gegensatz zu BASIC darf das Postfix aber niemals weggelassen werden. Den Versuch, eine Variable ohne Postfix (%, &, !, $) zu declarieren, würde PROFAN² bemängeln! Soll eine ganze Zahl als Float gekennzeichnet werden (z.B., damit beim Ausdruck die Nachkommastellen gedruckt werden), ist sie trotzdem als Dezimalbruch zu schreiben: PRINT 5.0! Wenn PROFAN² auch ein deutsches Produkt ist, so wird trotzdem der Dezimalpunkt verwandt. 7.4 String Strings werden durch ein $ am Ende des Dateinamens gekennzeichnet und können maximal 255 Zeichen lang sein. Stringkonstanten werden durch Anführungszeichen eingeschlossen: LET Text$="Teststring" Für einige nicht direkt über die Tastatur eingebbare Zeichen gibt es nun (ähnlich wie in C) Ersatzzeichen. Dabei steht "\a" für @Chr$(8), "\t" für @Chr$(9) und "\n" für @Chr$(13). Das erleichtert z.B. die Formatierung von Messageboxen und Menüs erheblich. Um z.B. die Anzeige von Funktionstasten in Menüs auszurichten, reicht es jetzt zum Beispiel, folgende Zeile einzugeben: APPENDMENU 124,"Hilfe\tF1" Mit "\a" kann ein Menüpunkt in der Menüzeile ganz nach rechts positioniert werden, wie es häufig unter Windows 3.x bei der Hilfe der Fall ist: APPENDMENUBAR "\aHilfe" (Dies funktioniert nur in der 16-Bit-Version von PROFAN² und ist auch sonst unter Windows 95 nicht mehr üblich.) Mit "\n" erzielen Sie in Messageboxen einen Zeilenumbruch genau dort, wo Sie ihn haben wollen. Will man aber nun wirklich z.B. die Zeichenfolge "\a" im String verwenden, muß man den Backslash verdoppeln: "\\a". Es ist empfehlenswert, in Literalen (Strings zwischen zwei ") grundsätzlich für einen Backslash den doppelten Backslash einzugeben! (Aus Kompatibelität zu älteren PROFAN²-Versionen gilt: Auch "\." wird als "\" wiedergegeben.) HINWEIS: Bei Funktionen oder Befehlen, die einen Dateinamen (evt. mit Pfad) oder Pfad erwarten, werden die Ersatzzeichen nicht berücksichtigt, wenn der Datei- bzw. Pfadname ein Literal ist (in Anführungszeichen steht). Seite 30 RGH-PROFAN² 7.5 Bereich Bereichsvariablen werden durch ein # am Ende des Dateinamens gekennzeichnet: DECLARE Bereich# Diese Variable ist ein Zeiger auf einen Datenbereich. Man könnte auch sagen, sie ist ein Handle für einen Datenbereich. Der Wert der Variablen selbst kann zwar mit PRINT ausgegeben oder mit LET einer LongInt-Variable zugewiesen werden, ist aber für den Programmierer ohne Bedeutung. Die Variable kommt unter Anderem dort zum Einsatz, wo z.B. Messages Zeiger auf Datenstrukturen (meist Zeichenketten) verlangen. Außerdem kann sie in vielen Fällen auch als Ersatz für die aus anderen Sprachen gewohnten Arrays dienen. ACHTUNG: Da Bereichsvariablen grundsätzlich global sind, muß die Deklaration im Hauptprogramm erfolgen. Eine Deklaration in einer Prozedur würde beim zweiten Aufruf eine Fehlermeldung erzeugen. Bevor der Speicherbereich, auf den die Variable zeigt, benutzt werden kann, muß er mit DIM Name#,Groesse& bereitgestellt werden. Groesse& muß in der 16-Bit-Version von PROFAN² einen Wert zwischen 1 und 64500 haben. Beispiel: DIM Bereich#,32000 Mit BYTE Name#,A&=Wert& wird dem Byte an der Adresse A& im Speicherbereich Name# ein Wert zugewiesen. Die Adressbereich geht von 0 bis Groesse-1, anderenfalls erfolgt eine Fehlermeldung. Der Wert liegt hier zwischen 0 und 255. Weitere Befehle, um den Speicher zu belegen sind WORD, LONG, CHAR und STRING. Mit der Funktion @BYTE(Name#,A&) kann die Bereichsvariable ausgelesen werden. Weitere Funktionen zum Auslesen des Speicherbereiches Name# sind @WORD, @LONG, @CHAR und @STRING. BYTE Bereich#,0 = 56 BYTE Bereich#,1 = 251 BYTE Bereich#,31999 = 216 PRINT @BYTE(Bereich#,0) PRINT @BYTE(Bereich#,1) PRINT @BYTE(Bereich#,31999) Mit @BLOCKREAD lesen Sie den Inhalt von Dateien in Bereichsvariablen ein und mit BLOCKWRITE können Sie den Inhalt einer Bereichsvariablen in eine Datei schreiben. Keine Angst: Im Gegensatz zu allen anderen Sprachen bei der Verwendung von Zeigern (bzw. Pointern) achtet PROFAN darauf, daß Sie den mit DIM eingestellten Datenbereich nicht überschreiten oder gar eine Bereichsvariable nutzen, der noch kein Bereich zugewiesen wurde. Jeder mit DIM angeforderte Speicherbereich muß mit DISPOSE Name# nach Gebrauch wieder freigegeben werden: DISPOSE Bereich# DIM und DISPOSE dürfen auch in einer Prozedur vorkommen. Wenn allerdings ein DIM in einer Prozedur vorkommt muß diese Bereichsvariable auch mit DISPOSE wieder innerhalb der Prozedur freigegeben werden. freigegeben werden. Ansonsten ist beim erneuten Aufruf der Prozedur kein DIM mehr möglich! Beispiel: Seite 31 RGH-PROFAN² DECLARE Bereich# PROC Test Parameters Groesse% DIM Bereich#,Groesse% <... weiterer Programmcode ...> DISPOSE Bereich# ENDPROC ' Hauptprogramm Test 250 Test 30 Test 500 END Es gibt auch noch den Befehl READTEXT, der eine komplette (kleinere) Textdatei in eine Bereichsvariable einlesen kann. ACHTUNG: Wenn Sie allerdings bei einer Message, die als Parameter einen Zeiger auf Daten/Strings verlangt, anstelle einer Bereichsvariablen eine LongInt-Variable verwenden, können Sie Ihren Computer zum Absturz bringen und dadurch Datenverluste verursachen! Das ist auch möglich, wenn eine Bereichsvariable zu klein dimensioniert wurde. Hingegen kann eine nicht dimensionierte Bereichsvariable (Null-Zeiger) nicht verwandt werden. Es erfolgt in diesem Fall eine Fehlermeldung. Seite 32 RGH-PROFAN² 7.6 Typen-Umwandlung Die Umwandlung der verschiedenen Variablentypen in andere erfolgt zumeist automatisch, wenn ein Literal oder eine Variable einer Variablen zugewiesen werden. Bei einer Rechnung oder Zuweisung wird dann das Ergebnis automatisch in den Typ der Variable, der das Ergebnis zugewiesen wird, umgewandelt. Wenn Zahl1! den Wert 5.678 hätte, würde bei LET Zahl2% = Zahl1! der Variablen Zahl2% der Wert 5 zugewiesen. PRINT Zahl2% würde auf jeden Fall den Wert als Dezimalwert ausgeben, ebenso LET Text$=@STR$(Zahl2%) oder auch LET Text$=Zahl2% (Ja, das geht auch!). Mit der Funktion @INT können Sie jedoch bewußt die Nachkommastellen abschneiden: PRINT @INT(Zahl2%) Die Funktion @INT schneidet bei einer Zahl die Nachkommastellen ab. Das Ergebnis kann jedoch - wie immer - jedem Variablentyp zugewiesen werden, bevorzugt natürlich einer Integer- oder LongInt-Variablen. Die Funktion @STR$ verwandelt einen numerischen Wert in einen String, wobei bezüglich der Formatierung die Einstellungen mittels DECIMALS und NUMWIDTH berücksichtigt werden. Die Funktion wird also häufig bei formatierter Zahlenausgabe Verwendung finden. Wird keine Formatierung gewünscht, kann das @STR$ auch weggelassen werden. Besonders viele Möglichkeiten der Umwandlung eines Zahlenwertes in einen String bietet die Funktion @FORMAT$, bei der für eine Zahl bis zu drei verschiedene Formatierungen angegeben werden können, jenachdem ob der Wert kleiner als 0, größer als 0 oder exakt 0 ist. Auch die wissenschaftliche Darstellung und die Währungsdarstellung wird beherrscht. Der Funktionsumfang geht über den der BASIC-Anweisung USING weit hinaus. Die Funktion @VAL ermittelt den numerischen Wert eines Strings. Kann der String nicht komplett umgewandelt werden, wird der Wert 0 angenommen. Eine Fehlermeldung oder Warnung erfolgt nicht. Das @VAL kann oft auch weggelassen werden: LET Zahl% = Text$ Selbst eine Zeile LET Zahl% = Maier würde funktionieren. Die Zahl erhielte dann den Wert 0. Wenn die Warnungen mit "SETERRORLEVEL 1" eingeschaltet sind, würde in diesem Fall jedoch eine Warnung darauf hinweisen, daß "Maier" nicht als Zahl zu interpretieren ist. Diese Warnung erscheint immer dann, wenn Interpreter oder Runtime einen Ausdruck nicht interpretieren können, also auch dann, wenn ein String erwartet wird, aber etwas da steht, was weder String noch numerischer Wert ist. (Warum? Nun: Wenn kein String - erkennbar durch Anführungszeichen - gefunden wird, versucht PROFAN² eine Zahl zu lesen, um diese dann intern in einen String umzuwandeln.) Seite 33 RGH-PROFAN² Ich ziehe es vor, die Umwandlungen zwischen Strings und numerischen Werten immer mit @VAL und @STR$ zu programmieren. Das macht die Programme lesbarer. Außerdem gibt es häufig dann keine automatische Typumwandlung, wenn in der Zuweisung Ergebnisse aus Funktionen vorkommen. Von der Typumwandlung ausgeschlossen bleiben natürlich die Bereichsvariablen. Zwar kann eine Bereichsvariable einer LongInt-Variablen zugewiesen werden, aber dieser Wert stellt nur den Zeiger auf den Datenbereich dar und ist daher für den Programmierer nicht nutzbar. (Ausnahme: Man benutzt diesen Zeiger dann in einer @SENDMESSAGE-Funktion. Aber da hätte man auch die Bereichsvariable benutzen können.) 7.7 Zahlensysteme Bisher konnte PROFAN lediglich hexadezimale Zahlen (mit vorangestelltem "$") verarbeiten. Auch @VAL konnte damit schon umgehen. Ab Version 6.0 sind die Möglichkeiten der Zahlendarstellung und -umrechnung gewaltig erweitert worden: Mit "%" werden binäre Zahlen eingeleitet und mit "&" Zahlen im oktalen System: LET Zahl1& = $F0AE LET Zahl2& = &01734 LET Zahl3& = %01001011001 Auch die @VAL-Funktion kann mit den neuen Typen umgehen: LET A$ = "%0101" LET A% = @VAL(A$) Der Wertebeeich für Zahlen in hexadezimaler, oktaler oder binärer Darstellung beträgt den einer Longint-Variablen. Neu hinzugekommen sind Funktionen, um Werte auch entsprechend darstellen zu können. Diese Funktionen wandeln einen Wert in einen entsprechenden String um: @HEX$, @OCT$ und @BIN$: PRINT @HEX$(255), \ @OCT$(255), \ @BIN$(255) ACHTUNG: Der Ergebnisstring enthält nur die "Ziffern" des anderen Zahlensystems, nicht aber das Kennzeichen "$", "&" oder "%". Dieses muß bei Bedarf noch vorangestellt werden. Um mit binären Zahlen noch besser umgehen zu können, wurden zwei Bit-Funktionen hinzugefügt. Mit @TESTBIT kann man in Erfahrung bringen, ob das gewünschte Bit gesetzt ist oder nicht. Mit @SETBIT kann man ein spezielles Bit setzen: LET A% = %0020 PRINT @TESTBIT(A%,3) LET A% = @SETBIT(A%,3,1) PRINT A% WICHTIG: Die Zählung der Bitposition beginnt 0. Seite 34 RGH-PROFAN² 8 - Arrays Arrays in der von BASIC oder PASCAL gewohnten Form gibt es in PROFAN² erst seit Version 6.0. Vorher gab es (und gibt es aus Kompatibilitätsgründen immer noch) lediglich eine Liste mit max. 16383 Elementen (0 .. 16382) je Datentyp in der 16-Bit-Version bzw. max. 32768 Elemente (0 .. 32767) in der 32-Bit-Version von PROFAN². Um diese Listen von den wirklichen Arrays zu unterscheiden, verwende ich im Folgenden den Begriff "Liste". 8.1 Je Datentyp eine Liste Dimensioniert werden diese Listen mit den Befehlen DIM%, DIM!, DIM& und DIM$. Mit dem Befehl DIM% 499 wird eine Integerliste mit 500 Elementen definiert. Jeder dieser vier DIM-Befehle darf nur einmal während des Programmlaufes vorkommen und zwar zeitlich vor dem ersten Zugriff auf ein Element der entsprechenden Liste. Es ist sinnvoll, die DIM-Befehle an den Anfang des Programmes zu stellen. Nachträgliche Vergrößerung der Liste ist ebensowenig möglich, wie ein Löschen und Neudefinieren. Zum Füllen der Listen werden die Befehle LIST%, LIST!, LIST& und LIST$ verwandt. Mit der Zeile LIST& 99 = 120000 würde ich dem 99. Element der LongInt-Liste den Wert 120000 zuweisen. Ist die Liste nicht definiert oder ist 99 außerhalb der definierten Größe, erfolgt eine Fehlermeldung. Um den Inhalt eines Listen-Elementes zu lesen, wird je nach Typ einer der Funktionen @LIST%. @LIST!, @LIST& oder @LIST$ verwandt. Wenn ich den Inhalt des 34. Elementes der Stringliste der Variable Test% zuweisen möchte, verwende ich die Zeile: LET Test$ = @LIST$(34) Der DIM-Befehl ohne Datentypkennung gehört nicht hierher, da mit ihm eine Bereichsvariable dimensioniert wird. Andererseits läßt sich sicher in vielen Fällen, in denen in anderen Programmmiersprachen ein Array eingesetzt wird, eine Bereichsvariable verwenden. Ein Bereich kannn durchaus als ein Array (mit nahezu beliebiger Größe bzw. max. 64 kByte in der 16-Bit-Version) betrachtet werden. So können mit Bereichsvariablen problemlos Byte- und IntegerArrays simuliert werden. 8.2 Mehrdimensionale Arrays Hier handelt es sich um Arrays, wie sie z.B. von BASIC oder PASCAL her bekannt sind. Die meisten Probleme ließen sich auch mittels der einen Liste pro Datentyp erledigen, aber die Arrays sind sicher komfortabler. Eine Einschränkung soll nicht unerwähnt bleiben: Die neuen Arrays sind, ebenso wie die Bereichsvariablen, global. Der Speicherplatz eines einmal deklarierten Arrays wird erst bei Programmende wieder freigegeben. Wird ein Array ein weiteres Mal mit gleichem Namen und Typ deklariert, kann immer nur auf das zuletzt deklarierte Array zugegriffen werden. Es empfiehlt sich daher, alle im Programm genutzten Arrays am Anfang des Programmes zusammen mit den übrigen globalen Variablen zu deklarieren. Es können Arrays der Datentypen Float, Longint, Integer und String deklariert werden. Ein Array kann maximal drei Dimensionen aufweisen. Die Elemente aller Arrays eines Datentyps dürfen 32000 (32 Bit) bzw. 16000 (16 Bit) nicht überschreiten. Seite 35 RGH-PROFAN² Erzeugt werden Arrays mit dem DECLARE-Befehl, indem die Anzahl der Elemente und Dimensionen in eckigen Klammern mit angegeben wird: DECLARE Spielfeld%[8,8] Hier wird ein zweidimensionales Integer-Array aus 8 * 8 Elementen - etwa für ein Schachspiel - erzeugt. Im nächsten Beispiel erzeugen wir ein Array, um einen dreidiensionalen Würfel mit der Kantenlänge 25 zu beschreiben: DECLARE Wuerfel&[25,25,25] Zuweisungen und Zugriffe erfolgen wie bei anderen Variablen auch, nur daß bei Arrays in eckigen Klammern angegeben wird, auf welches Element ich zugreifen möchte: LET Spielfeld%[5,4] = Koenig% LET Wuerfel&[x%,y%,z%] = 0 LET Wert% = Spielfeld%[x%,y%] PRINT Wuerfel&[10,5,9] HINWEIS: Die bisherigen eindimensionalen Listen je Datentyp existieren zusätzlich (!) weiterhin! Seite 36 RGH-PROFAN² 9 - Kontrollstrukturen PROFAN² bietet im wesentlichen die aus anderen Sprachen bekannten Kontrollstrukturen: Case / CaseNot If / IfNot While / WhileNot @If Aus Gründen der Kompatibilität zu frühesten PROFAN²-Versionen gibt es auch noch die Befehle GOSUB und GOTO, die aber in künftigen PROFAN²-Versionen ebensowenig unterstützt werden, wie heute schon vom Support. 9.1 CASE / CASENOT Der CASE-Befehl stellt letztlich ein einzeiliges IF dar: CASE @Equ(A%,3) : PRINT "A hat den Wert 3" Der hinter dem CASE stehende Befehl bzw. Prozeduraufruf wird nur ausgeführt, wenn der Ausdruck vor dem Doppelpunkt einen von Null verschiedenen Wert hat, d.h. wenn die Bedingung erfüllt wird. Ist die Bedingung nicht erfüllt, geht es direkt mit der nächsten Zeile weiter. Eine Sonderform des CASE ist die Form CASENOT: CASENOT @Equ(A%,3) : PRINT "A ist ungleich drei" Dies ist lediglich eine bequemere (und in der Ausführung schnellere) Schreibweise der Zeile CASE @Not(@Equ(A%,3)) : PRINT "A ist ungleich drei" 9.2 IF / IFNOT ... Mit Ausnahme der Sonderform IFNOT, die für IF @Not steht, gilt hier das aus BASIC Bekannte: Die nach IF bzw. IFNOT stehenden Zeilen werden ausgeführt, wenn der Bedingungsausdruck hinter dem IF bzw. IFNOT ungleich 0 ist. Lediglich das THEN gibt es in PROFAN² nicht und wird weggelassen: IF @Equ(A%,1) PRINT "A ist gleich 1" ENDIF WICHTIG: Hinter der Bedingung darf (außer einer Anmerkung mit ') kein Befehl stehen. Das in BASIC und PASCAL bekannte einzeilige IF wird in PROFAN² durch CASE ersetzt. Zu jedem IF muß es ein entsprechendes ENDIF geben! Natürlich gibt es in PROFAN² auch den ELSE-Zweig, der ausgeführt wird, wenn die Bedingung nicht erfüllt wird: IF @Equ(A%,1) PRINT "A ist gleich 1" PRINT "--------------" ELSE COLOR 5,15 PRINT "A ist ungleich 1" ENDIF Seite 37 RGH-PROFAN² Auch eine Abfrage auf mehrere Bedingungen (z.B. bei der Auswertung eines Menüs) ist mit ELSEIF möglich. Sobald eine Bedingung erfüllt ist, wird der zugehörige Programmteil abgearbeitet und anschließend mit der Zeile nach dem ENDIF fortgefahren. Die SELECTund CASE-Strukturen anderer Sprachen lassen sich somit abbilden: IF @Lt(A%,1) COLOR 1,15 PRINT "A ist ELSEIF @Equ(A%,1) COLOR 2,15 PRINT "A ist ELSEIF @Equ(A%,2) COLOR 3,15 PRINT "A ist ELSE PRINT "A ist ENDIF kleiner als 1" gleich 1" gleich 2" größer als 2" Dieser Programmteil wäre identisch mit folgender Struktur: IF @Lt(A%,1) COLOR 1,15 PRINT "A ist kleiner als 1" ELSE IF @Equ(A%,1) COLOR 2,15 PRINT "A ist gleich 1" ELSE IF @Equ(A%,2) COLOR 3,15 PRINT "A ist gleich 2" ELSE PRINT "A ist größer als 2" ENDIF ENDIF ENDIF 9.3 WHILE / WHILENOT Selbstverständlich gibt es auch Schleifen in PROFAN². Der zwischen WHILE und WEND stehende Programmteil wird solange ausgeführt, solange die Bedingung erfüllt ist. Auch bei WHILE ist die Zusammenziehung mit @Not zu WHILENOT erlaubt. Ebenso wie bei Unterprogrammen/Prozeduren ist eine Schachtelungstiefe von 10 erlaubt. In der Praxis dürfte dieser Wert kaum erreicht werden. Ein Beispiel für eine WHILE-Schleife: LET A%=0 WHILENOT @Equ(A%,10) INC A% PRINT A%;" zum Quadrat ist ";@Squ(A%) ENDWHILE Anstelle von ENDWHILE ist auch die von BASIC her gewohnte Schreibweise WEND erlaubt. Aber analog zu den Befehlspaaren IF - ENDIF und PROC - ENDPROC ist die Verwendung der Schreibweise ENDWHILE logischer und für den nicht von BASIC her kommenden PROFAN²-Programmierer leichter zu merken. Seite 38 RGH-PROFAN² 9.4 @IF In Anlehnung an C gibt es das IF auch als Funktion. Die Funktion @IF hat drei Argumente: Das erste Argument ist die Bedingung; das zweite Argument ist der Wert, der zurückgegeben wird, wenn die Bedingung erfüllt ist und das dritte Argument ist schließlich der Wert, der bei unerfüllter Bedingung zurückgegeben wird. Beispiele: LET Text$ = @IF(@Equ(A%,1), "A ist gleich 1", \ "A ist ungleich 1") PRINT Text$ LET A% = @IF(@Gt(A%,1000), @Add(A%,200), @Add(A%,50) ) PRINT A% Im zweiten Beispiel wird zu A% 200 addiert wenn es größer als 1000 ist; im anderen Fall kommen nur 50 dazu. Seite 39 RGH-PROFAN² 10 - Prozeduren Prozeduren sind Unterprogramme, die wie neue Befehle behandelt werden können. Unterprogramme mit GOSUB werden daher in Zukunft weder notwendig noch erlaubt sein, da Prozeduren deutlich leistungsfähiger sind: Eine Prozedur wird einmal - vor ihrer ersten Verwendung - definiert und kann dann jederzeit wie ein neuer Befehl im Programm verwandt werden. Es ist sinnvoll, alle Prozedurdefinitionen vor dem Beginn des Programmes (nach den DECLARE-, DIM-, und DEF-Befehlen) durchzuführen. Häufig verwandte Funktionen (s.u.) und Prozeduren kann man in einer Include-Datei (s.o.) zusammenfassen und sich so beliebige Spracherweiterungen selbst programmieren. Eine Prozedur-Definition beginnt mit dem Befehl PROC, gefolgt vom Namen der Prozedur. Die Definition endet mit der Zeile ENDPROC. Eine Prozedur wird natürlich während Ihrer Definition nicht ausgeführt, sondern erst, wenn Sie aufgerufen wird. Hier ein komplettes MiniProgramm als Beispiel für eine sehr einfache Prozedur: 'Testprogramm '-----------PROC Titelzeile PRINT "Das ist der Titel" ENDPROC CLS PRINT "Das ist noch vor der Prozedur." TITELZEILE PRINT "Das ist nach der Prozedur." WAITKEY END Einer Prozedur können auch Parameter übergeben werden. Diese werden mit dem Befehl PARAMETERS in die Prozedur übernommen: Dem Befehl folgen die Variablen, denen die Parameter zugewiesen werden. Diese Variablen - wie alle in der Prozedur declarierten Variablen - sind "LOKAL", d.h. sie sind nur in der Prozedur dem System bekannt. Alle außerhalb der Prozedur bekannten Variablen sind in der Prozedur auch bekannt (es sei denn, es gibt lokale Variablen mit gleichem Namen). ACHTUNG: Bereichsvariablen und Arrays können NICHT als Prozedurparameter verwandt werden, da diese immer global sind. Ein Beispiel, bei dem eine Prozedur definiert wird, die eine Text wiederholt ausgibt: Testprogramm 2 '-------------PROC Wiederhole PARAMETERS Anzahl%, Text$ DECLARE I% LET I% = 0 WHILE @Lt(I%,Anzahl%) PRINT Text$ ENDWHILE ENDPROC CLS PRINT "Das ist noch vor der Prozedur." WIEDERHOLE 5, "Testtext" PRINT "Das ist nach der Prozedur." WAITKEY END Seite 40 RGH-PROFAN² Die Parameter, die der Prozedur übergeben werden, werden durch Kommata voneinander getrennt. Die Typen und die Anzahl der Parameter werden von PROFAN² nicht überprüft, obwohl sich die Anzahl über die Systemvariable %PCOUNT ermitteln läßt. Es sind maximal 12 Parameter erlaubt. Selbstverständlich können in Prozeduren wieder neue Prozeduren definiert werden. Diese sind dann natürlich auch nur lokal bekannt. Hier gilt sinngemäß das Gleiche, wie für Variablen. Eine Prozedur kann in PROFAN² auch einen Wert zurückgeben: Innerhalb der Prozedur darf der RETURN-Befehl vorkommen, wenn die Prozedur vor dem ENDPROC verlassen werden soll. Dem RETURN kann ein Parameter zurückgegeben werden, der je nach Typ mit der Funktion @$(0), @%(0), @&(0) oder @$(0) gelesen werden kann. (Diese Funktionen sind der "Parameterstack" von PROFAN². Für jeden Datentyp gibt es die Parameter 0 bis 12, wobei der 0. Parameter den Rückgabewert und die übrigen die übergebenen Parameter enthalten. Im obigen Beispiel könnte also auch über @$(2) auf den übergebenen Text zugegriffen werden.) Ein Beispiel für die Rückgabe eines Wertes aus einer Prozedur: 'Testprogramm 3 '-------------PROC Titelzeile PRINT "Das ist der Titel" RETURN "Ok" ENDPROC CLS PRINT "Das ist noch vor der Prozedur." TITELZEILE PRINT "Das ist nach der Prozedur: ";@$(0) WAITKEY END Auch wenn eine Prozedur mit RETURN verlassen wird, darf das ENDPROC nicht fehlen! Seite 41 RGH-PROFAN² 11 - Funktionen In PROFAN² gibt es zahlreiche "eingebaute" Funktionen. Zusätzlich gibt es die Möglichkeit eigene Funktionen zu definieren. Auch der Zugriff auf die Funktionen des Windows-API oder anderer DLLs ist möglich. 11.1 Funktionen - Grundlagen Eine Funktion gibt einen Wert zurück, der in der Regel von den Parametern der Funktion abhängig ist. Überall da, wo in PROFAN² Variablen oder konstante Werte (Literale) eingesetzt werden können, dürfen auch Funktionen stehen. Der Rückgabewert der Funktion sollte der gleiche Typ sein, wie der erwartete Wert. Alle Funktionsnamen in PROFAN² beginnen normalerweise mit einem @. Während viele Anwender mit mir der Meinung sind, daß das @ den Quellccode übersichtlicher macht, indem die Funktionen sofort erkennbar sind, gibt es auch einige, denen die Eingabe des @ (über <AltGr><Q>) zu umständlich ist. Ab der PROFAN²-Version 4.0 ist es möglich das @ überall (auch beim Parameterstack) wegzulassen. Im Interpretermodus kann dies zu Geschwindigkeitseinbußen führen. Die Performance der compilierten Programme ist davon unbeeinflußt. Im Handbuch wird durchgängig das @ als Funktionskennzeichen verwandt. Funktionen, deren Funktionsnamen mit dem $ endet, geben in vielen Fällen einen String zurück, die übrigen Funktionen einen numerischen Wert. In einigen Fällen enden auch Vergleichsfunktionen, die entweder 1 oder 0 zurückgeben mit einem $, um deutlich zu machen, das hiermit Strings verglichen werden. Wenn der Rückgabewert einer Funktion uninteressant ist, kann die Zuweisung auch weggelassen werden. Bis auf die immer noch notwendigen Klammern, wird die Funktion dann wie ein Befehl verwandt. Beispiel: @LISTBOX$("Das ist die Liste",0) In diesem Fall wird die Listbox nur zum Anschauen angezeigt oder aber das Ergebnis der Auswahl über die Systemvariable $GETTEXT gelesen. Seite 42 RGH-PROFAN² 11.2 Allgemeine Funktionen Neben den in PROFAN² zahlreich vertretenen Spezialfunktionen, die in den jeweiligen Kapiteln Erwähnung finden, gibt es auch eine ganze Reihe allgemeiner Funktionen zur Bearbeitung von Zeichenketten (Strings) und zur Verarbeitung mathematischer Formeln: Mathematische Funktionen: @Abs @Add @And @ArcTan @Cos @Cot @Div& @Div @Equ @Exp @GT @Int @Lg @Ln @LT @Mod @Mul @Neq @Not @Or @Pi @Pow @Rnd @Round @Sin @Sqr @Sqrt @Sub @Tan - Absolutwert - Addition (+) - logisches Und - ArcusTangens - Cosinus - Cotangens - ganzzahlige Division (\) - Division (/) - Vergleich: Gleichheit - Exponentialfunktion - Vergleich: Größer - Integer (Ganzzahl) - Dekadischer Logarithmus - Natürlicher Logarithmus - Vergleich: Kleiner - Modulo-Funktion - Multiplikation (*) - Vergleich: Ungleichheit - logisches Nicht - logisches Oder - Kreiszahl - Potenz-Funktion (^) - Zufallszahl - Rundungsfunktion - Sinus - Quadrat - Quadratwurzel - Subtraktion (-) - Tangens Seite 43 RGH-PROFAN² Zeichenketten-Funktionen: @Add$ @AnsiToOem$ @Bin$ @Chr$ @CToD$ @Del$ @DToC$ @Equ$ @GT$ @Hex$ @Ins$ @InStr @Len @Left$ @Lower$ @LT$ @Mid$ @MkStr$ @NEq$ @Oct$ @OemToAnsi$ @Ord @Space$ @Str$ @SubStr$ @Right$ @Translate$ @Trim$ @Upper$ @Val - Zusammenfügen - Ansi -> ASCII - Binär -> String - Zeichen - Datumsformat umwandeln - Teilstring löschen - Datumsformat umwandeln - Vergleich: Gleichheit - Vergleich: Größer - Hexadezimal -> String - Teilstring einfügen - Teilstringposition finden - Länge eines Strings - linker Teilstring - in Kleinbuchstaben wandeln - Vergleich: Kleiner - Teilstring ermitteln - Wiederholstring - Vergleich: Ungleichheit - Octal -> String - ASCII -> Ansi - Zeichencode (ASC) - String aus Leerrzeichen - Wert in String umwandeln - String in Teilstrings zerlegen - rechter Teilstring - Stringteile ersetzen - Leerzeichen entfernen - in Großbuchstaben wandeln - String in numerischen Wert umwandeln Nähere Hinweise zur Syntax entnehmen Sie bitte der Referenz. Seite 44 RGH-PROFAN² 11.3 Definierte Funktionen PROFAN² bietet auch die Möglichkeiten, selbst Funktionen zu definieren, die im Programm wie die eingebauten Funktionen verwandt werden können. Eine Funktionsdefinition beginnt mit dem Befehlswort DEF. Diesem folgt der Name der Funktion, der natürlich wie alle PROFAN²-Funktionen mit einem @ beginnen kann. (Das @ erreicht man im Übrigen mit der Tastenkombination <AltGr><Q>.) Nach dem Namen folgt in Klammern die Anzahl der Parameter. Dann kommt der Ausdruck, der die Funktion beschreibt. Die Funktionsparameter werden über den "Parameterstack" (s.o. unter Prozeduren) übergeben. Mit @$(n), @%(n), @&(n) bzw. @!(n) werden die Parameter gelesen, wobei n für die Nummer des Parameters (von 1 - 12) steht. Ein Beispiel für eine Funktion zur Errechnung der dritten Potenz einer Zahl: DEF @Pot3(1) @Mul(@Squ(@!(1)),@!(1)) Das Quadrat des ersten Parameters wird mit dem Parameter multipliziert. Aufgerufen wird die Funktion, wie jede andere auch: LET I% = 0 WHILE @Lt(I%,10) INC I% PRINT I%;"³ = ";@Pot3(I%) WEND Als zweites Beispiel dient eine Funktion, die die ersten n Zeichen eines Strings zurückgibt. Nennen wir sie LINKS$ und definieren wir sie uns: DEF @Links$(2) @Mid$(@$(1),1,@%(2)) Wenden wir Sie an: DECLARE A$ LET A$ = "Testbild" PRINT @Links$(A$,4) (Gewiß, ab PROFAN² 6.0 gibt es die Funktion LEFT$, die das Gleiche macht, aber das Beispiel ist eben schon etwas älter ...) Auch hier findet bewußt keine Typüberprüfung statt, da alle Typen automatisch ineinander umgewandelt werden. Sehr wohl überprüft wird aber die Anzahl der Parameter! Wie bei allen anderen Funktionen erfolgt eine Fehlermeldung, wenn zuwenig oder zuviel Parameter angegeben werden. Unter Verwendung der @IF-Funktion und/oder der Dialogbox-Funktionen sind sehr komplexe Funktionsdefinitionen möglich. Funktionsdefinitionen über mehrer Programm-Zeilen werden von PROFAN² nicht unterstützt. Seite 45 RGH-PROFAN² 11.4 Externe Funktionen Ab PROFAN² 4.2 ist es nun auch möglich, externe Funktionen (beliebige DLLs und Windows-API) zu definieren. HINWEIS: Auch in der 32-Bit-Version können externe Funktionen aus 16-Bit-DLLs bzw. der 16-BIT-API verwandt werden. Dafür ist für die Kommunikation zwischen 16- und 32-Bit-Welt das Programm PROF16.EXE verantwortlich, das bei der Installation in Ihr Windows-Verzeichnis kopiert wurde. Diese Möglichkeit ist jedoch als Notbehelf zu betrachten, da der Aufruf sehr langsam ist und auch bei einigen wenigen Funktionen nicht korrekt funktioniert. 32-Bit-Funktionen können ausschließlich mit der 32-Bit-Version von PROFAN² aufgerufen werden. Auch hier wird der für Funktionsdefinitionen zuständige Befehl DEF verwandt: Hinter dem DEF folgt wie gewohnt der freigewählte Name (der natürlich keinem Namen einer PROFAN²Funktion entsprechen darf) und in Klammern die Anzahl der Parameter (max. 12) der neuen Funktion. Dann folgt gekennzeichnet durch ein vorangestelltes "*" (16-Bit-Funktion) oder "!" (32-BitFunktion) ein String mit dem Namen der DLL und der Name der Funktion in der DLL (Groß/Kleinschreibung beachten). Beim Aufruf einer 16-Bit-Funktion folgen nun die Beschreibung der Parametertypen und die Beschreibung des Ergebnistyps. Bei den Parametertypen bedeuten: % = Integer (auch Handles, Words, Bytes und Boolsche Werte sind so zu kennzeichnen) & = LongInt (auch unsigned Long und alle anderen 4-Byte-Werte) # = Bereich (hierunter fallen alle Zeiger auf Strings, Datenstrukturen, etc.) Beim Ergebnistyp bedeutet: % = Integer (Handles, Words, Bytes, boolsche Werte) & = LongInt (4-Byte-Werte) Leerstring (kein Ergebniswert) Bereichsvariablen dienen dazu, Strings oder Datenstrukturen an die externe Funktion zu übergeben und/oder von ihr zu bekommen. Natürlich sind sie ausreichend zu dimensionieren. Bei 32-Bit-Funktionen erübrigt sich die Beschreibung der Parametertypen und des Ergebnistyps, da alle von PROFAN unterstützten Parameter exakt 4 Byte groß sind. Beispiele für Aufrufe in der 16-Bit-API: DEF DEF DEF DEF DEF DEF DEF @MoveWindow(6) *"USER","MoveWindow","%%%%%%","" @waveOutGetNumDevs(0) *"MMSYSTEM","waveOutGetNumDevs","","%" @GetWText(3) *"USER","GetWindowText","%#%","&" @GetApiPixel(3) *"GDI","GetPixel","%%%","&" @GetSysResources(1) *"USER","GetFreeSystemResources","%","%" @MsgBox(4) *"USER","MessageBox","%##%","%" @GetClientRect(2) *"USER","GetClientRect","%#","" Beispiele für Aufrufe in der 32-Bit-API: DEF DEF DEF DEF DEF DEF @MoveWindow(6) !"USER32","MoveWindow" @waveOutGetNumDevs(0) !"WINMM","waveOutGetNumDevs" @GetWText(3) !"USER32","GetWindowTextA" @GetApiPixel(3) !"GDI32","GetPixel" @MsgBox(4) !"USER32","MessageBoxA" @GetClientRect(2) !"USER32","GetClientRect" Seite 46 RGH-PROFAN² Drei ausführlich dokumentierte Beispielprogramme finden sich im Verzeichnis BEISPIEL: DLL16.PRF, DLL32.PRF (nur 32-Bit-Version) und RES.PRF. Letzteres ermittelt die freien Systemresourcen und zeigt sie in einer Messagebox an. Seite 47 RGH-PROFAN² 12 - Resourcen Seit Version 5.0 kann PROFAN² auch auf Resourcen in DLLs und EXE-Dateien zugreifen. 12.1 Allgemeines zu Resourcen Was sind Resourcen? Resourcen sind "Vorräte", zur Verfügung stehende Dinge, die man gegebenenfalls nutzen kann. Unter Windows (auch unter OS/2) ist es möglich, Teile des Programmes nicht im Code direkt zu erzeugen, sondern quasi auf "Fertigprodukte" zuzugreifen, vorgefertigte Elemente, die beim Erstellen des Programmes zum Programmcode dazugebunden (gelinkt) werden oder gar in einer zum Programm gehörenden DLL aufgehoben werden. Eine DLL (= Dynamische Bibliothek) kann also neben Funktionen und Prozeduren auch Resourcen beherbergen. Die Resourcen, auf die PROFAN² zugreifen kann, sind Icons, Cursor, Bitmaps, Strings (bis 255 Zeichen Länge), Menüs und Dialoge. So könnte man sich nun also vorstellen, daß ein international zu vertreibendes Programm alle Strings, Dialoge und Menüs in einer DLL enthält. Der englische Kunde erhält zu dem Programm die DLL mit den englischen Resourcen und seine italienische Kollegin die DLL mit den italienischen Resourcen. Die EXE-Datei des Programmes existiert nur in einer Version! Wie kommen nun die Resourcen in die DLL oder EXE-Datei? Hierzu benötigt man Hilfsmittel. Sehr empfehlenswert ist her der "Resource Workshop" von BORLAND, der nicht nur bei diversen Compilern dieses Herstellers mit dabei ist, sondern auch über BORLAND einzeln zu beziehen ist. Die zur Zeit aktuelle Version 4.5 unterstützt Resourcen für 16 und 32 Bit. Mit diesem Programm können Resourcen optimal erzeugt und verwaltet werden. Sollte man auf die - sicherlich nicht dumme - Idee kommen, PROFRUN.EXE um Resourcen zu erweitern, so ist darauf zu achten, daß dies VOR dem Linken einer PRC-Datei zur EXE-Datei geschehen muß! Wer nur 16-Bit Programme schreibt, findet einen älteren "Resource Workshop" auch auf mancher CD, die eine ältere Version einer BORLAND Programmiersprache enthält. (ACHTUNG: Turbo Pascal für Windows 1.0 enthielt noch ein anderes Tool, das nicht sonderlich kompatibel ist. Da war erst ab Version 1.5 der Resource-Workshop dabei.) Die Bedienung und Anwendung des "Resource Workshop" ist in dem dazugehörigen Handuch bzw. der Online-Hilfe ausführlich erläutert, so daß ich darauf nicht eingehe. Wer Resourcen unter PROFAN² verwenden will sollte, sich ein solches Tool aber zulegen, damit die Möglichkeiten voll genutzt werden können. PROFAN² enthält im Beispielverzeichnis eine DLL, die keinen Code, sondern nur Resourcen enthält. In der 16-Bit-Version ist es die LEER16.DLL und in der Version für Windows 95 die LEER32.DLL. Diese kann genutzt werden, um eigene Resourcen-DLLs zu erzeugen. Wie greift man auf die Resourcen zu? Um auf eine Resource zuzugreifen, benötigt man das Instanz- Handle der EXE-Datei bzw. der DLL, die die Resource enthält. Im Falle einer EXE-Datei ist dies das Ergebnis der Funktion @WinExec, bei einer DLL das Ergebnis der Funktion @UseDLL. Auf die Resourcen einer EXE-Datei kann nur solange zugegriffen werden, solange sie läuft. Auf Resourcen im laufenden PROFAN²-Programm kann über dessen Instanz-handle zugegriffen werden, das sich in der Systemvariablen %HInstance findet. WICHTIG: Aus einem 32-Bit Programm kann man normalerweise nur auf 32-Bit-DLLs zugreifen und umgekehrt aus einem 16-Bit-Programm nur auf 16-Bit-DLLs! PROFAN² ermöglicht jedoch auch die Nutzung von Resourcen in 16-Bit-DLLs in einem 32-Bit-Programm. @UseDLL wurde entsprechend erweitert: Ist der normale Aufruf (32-Bit) ungültig, wird automatisch versucht diese DLL als 16-Bit-DLL zu öffnen. Da hierzu undokumentierte Funktionen von Windows 95 genutzt werden, funktioniert dies aber nicht mit der auch zu Windows NT kompatoblen Version von PROFAN². Seite 48 RGH-PROFAN² 12.2 Icons aus Resourcen Der Befehl DrawExtIcon ist schon seit PROFAN² 3.3 bekannt. Mit ihm können Icons aus anderen EXE-Dateien und DLLs auf den Bildschirm gebracht werden. Allerdings bietet Windows eine Möglichkeit, Icons aus anderen Dateien auch anzuzeigen, wenn diese nicht mit @UseDLL oder @WinExec aktiviert sind: DrawLibIcon. Dieser Befehl ist in jedem Fall vorzuziehen. 12.3 Cursor aus Resourcen Mit UseExtCursor kann nun auch ein Cursor (Mauszeiger), der in den Resourcen vorhanden ist, genutzt werden. Ein Cursor besteht aus drei "Farben": schwarz, weiß und durchsichtig. An den durchsichtigen Stellen scheint der Hintergrund durch. Außerdem dürfen Sie nicht vergessen, beim Erzeugen des neuen Cursors den "HotSpot" festzulegen, den Punkt zu bestimmen, der beim Mausklick als Koordinaten weitergegeben wird. Beim Pfeil ist das die Spitze, bei einer Hand sollte das der Zeigefinger sein. 12.4 - Bitmaps aus Resourcen Besonders für Spiele und Multimediaanwendungen interessant ist die Möglichkeit, auch Bitmaps in der EXE-Datei bzw. einer DLL "verstecken" zu können. Da die EXE-Datei bzw. DLL sich beim Zugriff im Speicher befindet, sind die entsprechenden Befehle natürlich deutlich schneller, als das Laden eines Bildes von der Festplatte. Die Befehle sind aber nahezu die Gleichen: DrawExtBmp und DrawSizedExtBmp. Es können problemlos mehrere Bitmaps in einer EXE-Datei bzw. DLL vorhanden sein. Was in PROFAN² (noch) nicht möglich ist, ist das Kopieren eines Ausschnittes einer Resourcen-Bitmap auf den Bildschirm. Es wird immer die ganze Bitmap gezeichnet. (Wenn man derartiges braucht, bleibt immer noch der Weg über eine Bitmap als Datei, die mit MLoadBmp in den Speicher geladen und mit MCopyBmp / MCopySizedBmp stückchenweise oder komplett auf den Bildschirm kopiert werden kann). Seite 49 RGH-PROFAN² 12.5 - Strings aus Resourcen Während alle anderen Resorcen über Namen gekennzeichnet werden, bekommen die Strings in den Resourcen eindeutige Nummern (Integer). Beim Anlegen der Resourcen ist zu berücksichtigen, daß PROFAN² - auch in der 32-Bit-Version - nur mit Strings bis zu einer Länge von 255 Zeichen umgehen kann. Normalerweise sollten in Programmen selbst keine Literale (Strings in Anführungszeichen) vorkommen, wenn man daran denkt auf den internationalen Markt zu gehen. Bei einer Anpassung sind dann nämlich nur die Resourcen zu ändern, bzw. die Resourcen DLLs auszutauschen. (Auf diese Weise kann man sich mittels des "Resource Workshop" auch manches internationale Programm, z.B. aus der Shareware, für den privaten Einsatz eindeutschen. Gelesen werden Strings in den Resourcen mittels der Funktion @ExtString$. ACHTUNG: Eine Weitergabe derartig manipulierter Programme widerspricht in der Regel den Copyright-Bestimmungen, nach denen Sharewareprogramme nur unverändert weiterverbreitet werden dürfen.) 12.6 - Menüs aus Resourcen Auch komplette Menüs können mit dem "Resource Workshop" (oder einem anderen Resourcen-Editor) erzeugt werden. Mit UseExtMenu wird auf eine Menü aus den Resourcen zugegriffen. Ein bereits vorhandenes Menü wird durch das neue Menü ersetzt. Es ist somit durchaus möglich, während des Programmlaufes das Menü gegen ein anderes auszuwechseln. So ist es denkbar, daß der Benutzer eines Programmes eine Sprache wählen kann und dann das entrsprechende Menü geladen wird. Ebenso ist es möglich, durch Auswechseln der Resourcen DLL die Sprache zu wechseln. Beim Erstellen mit dem Resourcen-Editor bekommt das Menü einen Namen. Dieser wird bei UseExtMenu mit angegeben. Jeder Menüpunkt erhält eine Befehlsnummer (ID-Wert). Diese entspricht der Befehlsnummer bei im Programm erstellten Menüs und wird nach dem WaitInput genauso mit @MenuItem bzw. %MenuItem abgefragt.. Hier sind Werte von 1 bis 32766 erlaubt, wobei 255 nicht verwandt werden sollte, da diese in PROFAN² eine eigene Bedeutung haben... 12.7 - Dialoge aus Resourcen Zu den interessantesten Möglichkeiten bei der Verwendung von Resourcen zählen sicherlich die Dialoge. Hier sind dann auch die Dialogstile möglich, die unter PROFAN² normalerweise nicht unterstützt werden. Die Eigenschaft "Untergeordnet" (bzw. "Childwindow") sorgt zum Beispiel dafür, daß ein Dialog das Hauptfenster nicht verlassen kann. Außerdem ist es möglich, die Dialogelemenbte vor dem Überzeichnen zu schützen ("Schutz ..." im "Resource Workshop" bei den Dialogeigenschaften ankreuzen.). Hier lohnt es sich gewiß, etwas zu experimentieren und auszuprobieren. Bei den Dialogelementen, wie Listboxen, Scrollbars, etc. geben Sie jeweils einen "ID-Wert" and. Diese Identifikationsnummer eines Dialogelementes müssen Sie im Programm kennen, um auf das Element zuzugreifen. Auf den Dialog greifen Sie mit @CreateExtDialog über den Namen des Dialogs zu. Der Rückgabewert ist wie auch bei @CreateDialog das Handle des Dialogs. Um jetzt wie gewohnt in einer WaitInput-Schleife auf die Ereignisse des Dialoges reagieren zu können, benötigen Sie noch die Handle der einzelnen Dialogelemente. Da diese Handle erste bei der Darstellung des Dialoges vergeben werden, benötigen Sie die Funktion @GetHandle die zur jeweiligen Identifikationsnummer eines Dialogelementes das entsprechende Handle zurückggibt. Der Rückgabewert ist vergleichbar mit dem Handle, daß Sie bei im Programm erzeugten Dialogen von den @Create...-Funktionen zurückbekommen. Die übrige Behandlung des Dialoges unterscheidet sich nicht von der eines mit @CreateDialog erzeugten Dialoges: Anstelle des @CreateDialog steht @CreateExtDialog und anstelle der weiteren @Create...-Funktionen zur Erzeugung der Dialogelemente steht nun jeweils das entsprechende @GetHandle. Seite 50 RGH-PROFAN² Ein kleines Beispiel, das auf einen Dialog in einer "DIALOGE.DLL" zugreift, der "MELDUNG" heißt und die Buttons "OK" mit dem ID-Wert 1 und "Abbruch" mit dem ID-Wert 2 verwendet: Declare iDLL%, Ok%, Dlg%, Abbruch%, Ende% CLS Let iDLL% = @UseDLL("DIALOGE.DLL") Let Dlg% = @CreateExtDialog(iDLL%,%HWnd,"MELDUNG") Let Ok% = @GetHandle(Dlg%,1) Let Abbruch% = @GetHandle(Dlg%,2) Let Ende% = 0 WHILENOT Ende% WaitInput IF @GetFocus(Ok%) Print "OK" Let Ende% = 1 ELSEIF @GetFocus(Abbruch%) Print "ABBRUCH" Let Ende% = 1 ENDIF ENDWHILE END Seite 51 RGH-PROFAN² 13 - Programm-Aufbau Alle Variablen in PROFAN müssen vorher (wie etwa in PASCAL) deklariert werden. Die DECLARE- und DIM-Befehle sollten am Anfang des Programmes stehen. Lokale Variablen sollten am Anfang einer Prozedur definiert werden. Vor der ersten Bildschirmausgabe sollte immer ein WINDOW (oder CLS) stehen, um das Bildschirmfenster zu öffnen. Hierbei ist der Befehl WINDOW vorzuziehen. Der eigentliche Sinn von CLS liegt darin, ein bestehendes Fenster zu bereinigen, wobei dazu auch eine Farbe angegeben werden kann. BEISPIEL: 'DEKLARATIONSTEIL '---------------DECLARE ... DIM% ... DIM$ ... 'INCLUDE-DATEIEN MIT FUNKTIONEN UND PROZEDUREN '--------------------------------------------$I TOOLBOX.INC 'DEFINITION VON FUNKTIONEN '------------------------DEF @... 'PROZEDUREN '---------PROC ... PARAMETERS ... DECLARE ... ... ENDPROC 'DAS HAUPTPROGRAMM '----------------WINDOWTITLE ... WINDOWTYPE ... WINDOW ... ... ... ... END Sicher sind auch Programme ohne Fenster (d.h. ohne Bildschirmausgabe) möglich oder Programme, die nur ein (oder mehrere) Dialogfenster haben. Seite 52 RGH-PROFAN² 14 - Befehle über mehrere Zeilen Der Übersichtlichkeit wegen können Befehle (Programmzeilen) auch über mehrere Bildschirmzeilen geschrieben werden. Ist das letzte Zeichen einer Zeile ein \ , so wird die nächste Zeile ab dem ersten Zeichen, das kein Leerzeichen ist, angehängt. Beispiele: MESSAGEBOX "Überschrift",\ "Das ist ein Testtext, der \ etwas länger ist!",16 PRINT "Das ist ein ziemlich lang\ er Text!" COPYSIZEDBMP 34,34-16-16 > \ 12,12-32,32 ; 0 Beachten Sie: Auch eine Programmzeile über mehrere Bildschirmzeilen darf nicht länger als 254 Buchstaben sein. Führende und folgende Leerzeichen werden nicht gezählt. Seite 53 RGH-PROFAN² 15 - Fehlerbehandlung - Trace-Modus Fehlermeldungen und Warnungen werden in deutsch in einer Messagebox auf den Bildschirm gebracht. Nach einer Fehlermeldung bricht das Programm ab, nach einer Warnung läuft es weiter, wenn Sie "OK" anklicken oder bricht ab, wenn Sie "Abbrechen" wählen. Neben der Fehlerbeschreibung wird beim Interpreter auch die fehlerhafte Zeile angegeben, sodaß der Fehler genau lokalisiert werden kann. Die Systemvariable %ErrNumber enthält die Fehlernummer. Beim Auslesen wird sie auf Null zurückgesetzt. Eine Liste aller Fehlermeldungen befindet sich im Anhang. Zusätzlich wird (auch wenn der Fehler im compilierten Programm auftritt) die Zeilennummer angegeben. Da aber Includedateien mitgezählt werden und andererseits mit dem Backslash "\" verbundene Zeilen als eine gezählt werden, kann diese Zahl nur als Anhaltspunkt dienen. Auf alle Fälle ist es sehr dringend anzuraten, jegliches Programm im Interpretermodus auf Herz und Nieren zu testen, bevor man es compilert startet. Das Fehlerverhalten kann über den Befehl SETERRORLEVEL gesteuert werden. Der Befehl hat folgende mögliche Parameter: 210-1 - Für ganz Vorsichtige: Warnungen werden wie Fehler behandelt und führen zu einer Fehlermeldung mit Programmabbruch. Für die Programmentwicklung: Auch Warnungen werden ausgeben, aber das Programm läuft auf Wunsch weiter. Der Normalzustand: Warnungen werden nicht angezeigt. Diesen Errorlevel sollte man bei einem fertigen Programm verwenden. Fast schon kriminell: Auch Fehlermeldungen werden übergangen.Das kann unter Umständen zu einem Windowsfehler oder Absturz des Systemes mit Datenverlust führen. Warnungen treten auf, wenn ein Ausdruck nicht als numerischer Wert zu interpretieren ist oder z.B. eine Bilddatei nicht gefunden wird oder BITMAP-Befehle wegen Speicherplatzmangels nicht ausgeführt werden ... also immer dann, wenn keine ernstzunehmenden Folgen für das restliche Programm zu erwarten sind. Unabhängig vom gesetzten Errorlevel wird die Systemvariable %ERROR bei einer Warnung bzw. einem Fehler gesetzt. Auf diese Weise kann also der Programmierer die komplette Verantwortung zu Behandlung von Fehlern übernehmen. Wie auch %IORESULT wird %ERROR beim ersten Auslesen wieder auf 0 gesetzt. Die möglichen Error-Werte: 012- seit dem letzten Lesen von %ERROR ist kein Fehler aufgetreten eine Warnung wird gemeldet ein Fehler wird gemeldet ACHTUNG: Bei Dateioperationen wird nicht %ERROR verwandt, sondern die Systemvariable %IORESULT gesetzt, das Programm aber in keinem Fall abgebrochen. Das Programm muß also diese Variable auswerten, da ansonsten Abstürze möglich sind. Seite 54 RGH-PROFAN² Nach einer Dateioperation oder einer Directory-Suche enthält diese Variable den entsprechenden Wert: 023512 15 16 17 18 100 101 102 103 104 105 106 - kein Fehler aufgetreten Datei nicht gefunden Pfad nicht gefunden Zugriff verweigert (ReadOnly?) Ungültiger Dateimodus Laufwerksnummer unzuzulässig Verzeichnis kann nicht gelöscht werden (noch Dateien drin?) RENAME nicht über Laufwerksgrenzen möglich (siehe Rename) Kein weiterer Eintrag (bei @FindFirst/@FindNext) Lesefehler von Diskette/Platte Schreibfehler auf Diskette/Platte Dateinummer ist keiner Datei mit ASSIGN zugeordnet (siehe Assign) Datei nicht offen (Reset, Rewrite oder Append fehlt) Datei nicht zum Lesen geöffnet (Reset fehlt) Datei nicht zum Schreiben geöffnet (Rewrite oder Append fehlt) Falsches Format (bei Input #N,..) Eine dritte Art Fehler kann bei der Ansteuerung von Multimediageräten über die MCISchnittstelle erfolgen. Der zuletzt gemeldete Fehler beim Senden eines MCI- Strings zur Ansteuerung eines Multi-Media-Treibers (etwa CD, Soundkarte, MIDI- Gerät, etc.) wird in der Systemvariable %MCIERROR festgehalten. Wie auch %ERROR und %IORESULT wird sie beim ersten Auslesen auf 0 zurückgesetzt. Die Bedeutung der Fehlernummern hängt vom MCI-Gerätetreiber ab und ist für sich daher wenig aussagekräftig. Für den Programmierer bedeutet ein Wert ungleich Null lediglich, daß ein Fehler aufgetreten ist und die Funktion @MCISEND$ nicht einen Ergebnisstring zurückliefert, sondern eine Fehlermeldung (in der Landessprache). Um ein Programm im Interpreter zu testen, kann der Trace-Modus mit TraceOn eingeschaltet werden. Während das Programm im Tracemodus läuft, wird jede Programmzeile vor Ihrer Ausführung in einer Messagebox angezeigt. Der Befel TraceOff schaltet den Trace-Modus wieder aus. Das compilierte Programm ignoriert die Befehle TraceOn und TraceOff. Seite 55 RGH-PROFAN² 16 - Text- und Grafikmodus PROFAN kennt (für Windows unüblich) einen Text- und einen Grafikmodus. Da Windows natürlich nur einen Grafikbildschirm hat, wird der Textmodus auf diesem simuliert. Der Grafikmodus ist der windowseigene Modus, der nahezu all die Möglichkeiten bietet, die das Windows-Grafik-Interface beeinhaltet. Der Textmodus simuliert im Hauptfenster einen DOS-Bildschirm, der zeichenorientiert ist. Es gibt keinen SCREEN-Befehl, um zwischen den Modi umzuschalten, da immer beide gleichzeitig verfügbar sind. 16.1 Der "Textmodus" Im Textmodus funktionieren die von BASIC her bekannten Befehle, wie z.B. PRINT, LOCATE, INPUT, COLOR und CLS in gewohnter Weise. Zusätzlich sind in diesem Modus Befehle wie TBOX, FONT und @TMOUSE verfügbar. Ein wesentlicher Unterschied ist, daß CLS ohne Parameter den Bildschirm nicht in der aktuellen Farbe löscht, sondern grundsätzlich in weiß. Bei INPUT ist kein Prompt-Text erlaubt, sondern nur die Angabe einer Variable. Ein kleines Beispiel: Declare Zahl%, Text$ WindowTitle "Testprogramm" Cls Locate 2,2 Print "Das ist die Überschrift" Font 2 Locate 4,2 Print "Bitte gebe einen Text ein: "; Input Text$ Print "Bitte gebe eine Zahl ein: "; Input Zahl% Font 0 Print Color 1,15 Print "Du hast eingeben:",Zahl%,Text$ WaitKey End Das Semikolon nach einem Ausdruck beim Print-Befehl sorgt dafür, daß die nächste Ausgabe in die gleiche Zeile geht und direkt an die vorherige anschließt. Bei einem Komma wird hingegen ein Leerzeichen gelassen. (Die von BASIC her bekannte Tabulatorfunktion gibt es nicht.) Der Befehl WAITKEY wartet auf einen Tastendruck. Möchte man wissen, welche Taste gedrückt wurde, kann man die Systemvariable %KEY abfragen. Ebenso hätte man den Befehl WAITINPUT nutzen können, dann werden zusätzlich die Maustasten abgefragt. Das Ergebnis findet sich in der Systemvariablen %MOUSEKEY, wobei 1 für die linke und 2 für die rechte Maustaste steht. (In diesem Zusammenhang sei auch auf die Befehle WAITSCAN und WAITMOUSE, sowie die Funktionen @KEYIN, @INKEY$ und @GETKEY$ hingewiesen.) Mit dem Befehl FONT kann der Bildschirmfont im Textmodus eingestellt werden (0 = System, 1 = OEM (ASCII), 2 = ANSI). COLOR stellt die Textfarbe ein, wobei wie in BASIC Farbwerte von 0 bis 15 erlaubt sind. Oftmals möchte man Zahlen und Texte formatiert ausdrucken. Dies ist in PROFAN² mittels der Befehle NUMWIDTH, STRWIDTH und DECIMALS möglich. Mit DECIMALS wird festgelegt, wieviele Dezimalstellen bei der Ausgabe mit PRINT (und auch bei der Umformung mit @STR$) berücksichtigt werden: Seite 56 RGH-PROFAN² Declare Kreiszahl! Let Kreiszahl! = @PI() Decimals 0 Print Kreiszahl! Decimals 5 Print Kreiszahl! Decimals 10 Print Kreiszahl! WaitKey End Voreingestellt ist ein Wert von 6, d.h. wenn nichts anderes angegeben wird, werden 6 Ziffern hinter dem Komma ausgegeben. Mit NUMWIDTH kann ich festlegen, wieviele Zeichen mindestens gedruckt werden. Ist die Zahl kürzer, wird sie mit führenden Leerzeichen ausgegeben. Das ermöglicht die Ausgabe von Tabellen: Decimals 3 Numwidth 2 Print @PI() Numwidth 6 Print @PI() Numwidth 8 Print @PI() WaitKey End Gleiches ist mit STRWIDTH für die Ausgabe von Strings möglich. Beide Werte sind mit 0 vorbelegt, sodaß normalerweise alle Zahlen und Texte ohne führende Leerzeichen ausgegeben werden. Auch im Textmodus kann mit (wenn auch simulierten) "Buttons" gearbeitet werden, wobei abgefragt werden kann, ob ein Maus-Klick in diesem Button erfolgte. Ein kleines Beispielprogramm: Seite 57 RGH-PROFAN² Declare Ende% Cls ' Der Button Color 15,2 TBox 10,10 Locate 13,13 Print "A" ' Der Button Color 15,3 TBox 10,20 Locate 13,23 Print "B" Color 15,0 "A" wird gezeichnet 15,15; 3 "B" wird gezeichnet 15,25; 0 Let Ende% = 0 WhileNot Ende% 'Solange Ende den Wert 0 hat ... WaitInput 'Auf Tastendruck oder Mausklick warten If @TMouse(10,10 - 15,15) 'Mausklick im Button A? Locate 20,0 Print "Du hast 'A' gedrückt!" Let Ende% = 1 ElseIf @TMouse(10,20 - 15,25) 'Mausklick in B? Locate 20,0 Print "Du hast 'B'' gedrückt!" Let Ende% = 1 ElseIf @KeyIn("Aa") 'Taste "A"? Locate 20,0 Print "Du hast 'A' gedrückt!" Let Ende% = 1 ElseIf @KeyIn("Bb") 'Taste "B"? Locate 20,0 Print "Du hast 'B'' gedrückt!" Let Ende% = 1 Else 'Nichts von alledem ... Locate 20,0 Print "Daneben ..." EndIf Wend WaitKey End Der Befehl TBOX zeichnet in der mit COLOR eingestellten Farbe ein Rechteck zwischen den angegebenen Koordinatenpaaren. Wie auch bei LOCATE ist die jeweils erste Koordinate die Zeile und die zweite die Spalte. Der fünfte Parameter gibt die Art des Rahmens an: 0 einfacher Rahmen; 1 - doppelter Rahmen; 2 - teils einfach, teils doppelt; 3 - kein Rahmen. Der Rahmen wird mit ASCII- Grafikzeichen gemalt. Die Funktion @TMOUSE hat dann den Wert 1, wenn der letzte Mausklick in dem durch die zwei Koordinatenpaare angegebenen Rechteck erfolgte. Die Funktion @KEYIN hat den Wert 1, wenn die zuletzt gedrückte Taste im Funktionsargument (ein String) enthalten ist. Das Beispielprogramm demonstriert, wie man Programme schreibt, die sowohl auf die Maus als auch auf die Tastatur reagieren. Seite 58 RGH-PROFAN² 16.2 Der "Grafikmodus" Hier kommen die windowseigenen Text- und Grafikbefehle zur Geltung. Der fortgeschrittene Programmierer wird diesen Befehlen den Vorzug vor den textorientierten Befehlen geben. Alle Koordinatenangaben erfolgen hier in Pixel, also im Bereich 0,0 (links oben) bis z.B. bei Standard-VGA und Vollbildmodus 639,479 (rechts unten). Die maximal mögliche Größe des Bildschirmes erfahren wir über die Systemvariablen %MaxX und %MaxY. Übrigens: Die mögliche Farbtiefe liefert uns die Systemvariable %BitsPixel. Wenn man mit WINDOW eine andere Größe eingestellt hat, ist der Bereich natürlich entsprechend kleiner bzw. größer. Die augenblickliche Fensterposition und -größe läßt sich mit den Systemvariablen %WINTOP, %WINBOTTOM, %WINLEFT und %WINRIGHT ermitteln, wobei diese die Koordinaten in Bezug zur linken oberen Bildschirmecke angeben. Um z.B. die tatsächliche Breite des Fensters zu ermitten, ist ein wenig Rechnen angesagt: Let WinWidth% = %WinRight - %WinLeft Während diese Systemvariablen die Außenmaße des Hauptfensters betreffen, kann man mit @Height und @Width die Innenmaße eines beliebigen Fensers, also auch von Dialogfenstern und Dialogboxen, ermitteln. WICHTIG: Vor jedem der Ausgabe-Befehle (dazu gehören auch alle USE-Befehle) muß entweder Programmfenster geöfnet sein, oder die Grafikausgabe mit StartPaint auf ein anderes Fenster umgeleitet sein. Zum Öffnen des Programmfensters (Hauptfenster eines Programmes) verwenden wir den Befehl CLS oder WINDOW. Mit den Befehlen WINDOWSTYLE und WINDOWTITLE können wir zuvor die Attribute unseres Fensters festlegen! Zunächst einmal wollen wir Schrift auf den Bildschirm bringen. Dazu legen wir die Textfarbe mit dem Befehl TEXTCOLOR fest. Der erste Parameter ist die Vordergrundfarbe und der zweite die Hintergrundfarbe. Beide Werte sind Farbwerte im Bereich von 0 bis 32767 bzw. 16 Millionen, je nach eingestelltem Farbmodus. Der Modus wird mit SetTrueColor eingestellt. Im Modus 0, der standardmäßig voreingestellt ist, gibt es 32768 Farben, in Modus 1 sind es 16 Millionen mögliche Farbwerte. (Wenn der in Windows eingestellte Grafikmodus weniger Farben erlaubt, wird die nächstliegende Farbe angezeigt.) Da man sich unmöglich merken kann, welche Farbe welchen Wert hat, gibt es die Funktion @RGB. Diese hat drei Parameter, die für den ROT-, GRÜN- und BLAU-Anteil der Farbe stehen. Sind alle drei Parameter auf 0, ist die Farbe schwarz, sind alle auf 31 (in Farbmodus 0) bzw. 255 (in Farbmodus 1) gibt es ein reines Weiß. Eine Besonderheit gilt noch für die Hintergrundfarbe: Ist diese -1, so bedeutet das einen transparenten Hintergrund; d.h. der Hintergrund wird zwischen den Buchstaben sichtbar. Als nächstes müssen wir die Schriftart, den Font festlegen. Unter PROFAN² können wir alle Windows-Fonts einschließlich der True-Type-Fonts anwenden. Zur Einstellung eines Fonts dient der USEFONT- Befehl, der eine Reihe von Parametern hat: Der erste Parameter ist der Name des Fonts, z.B. "ARIAL" oder "COURIER NEW", wie er auch in der Font-Auswahl anderer Programme erscheint. Der zweite und der dritte Parameter geben Zeichenhöhe und -breite in Punkt an. Wird 0 angegeben, wird ein Defaultwert benutzt. der 4. bis 6. Parameter sind Schalter, die angeben, ob der Font unterstrichen, kursiv und/oder fett ausgegeben werden soll. Die Parameter im Überblick: 1. S : String - Fontname 2. N1 : Integer - Zeichenhöhe 3. N2 : Integer - Zeichenbreite 4. N3 : Integer - Fett? (0 .. 1) 5. N4 : Integer - Kursiv? (0 .. 1) 6. N5 : Integer - Unterstrichen? (0 .. 1) Seite 59 RGH-PROFAN² Für TrueType-Fonts ist noch der Befehl ORIENTATION interessant. Hier kann in 10tel Grad eingestellt werden, in welche Richtung der Text ausgegeben wird. Der ORIENTATION-Befehl muß vor (!) dem USEFONT-Befehl kommen, damit er wirkungsvoll wird. Außerdem gibt es noch den CHARSET-Befehl, der dem USEFONT-Befehl mitteilt, welcher Zeichensatz zu wählen ist, wenn der verlangte Font nicht vorhanden ist. In diesem Fall sucht Windows nämlich einen möglichst ähnlichen Font aus ... und der sollte den gleichen Zeichensatz haben. Angezeigt wird der Text schließlich mit dem DRAWTEXT-Befehl, dessen erste beiden Parameter die Koordinaten sind. Ein kleines Beispiel: Cls TextColor @RGB(31,0,0),-1 CharSet 0 Orientation 300 ' 30°-Winkel UseFont "ARIAL",30,40,1,0,1 DrawText 30,300,"Dies ist ein Text" WaitKey Ab Version 2.5 von PROFAN² kann auch eine numerische Variable bzw. Systemvarible mit DRAWTEXT ausgegeben werden, wobei zur Formatierung die Einstellungen mit NUMWIDTH und DECIMALS herangezogen werden. Selbstverständlich können wir mit PROFAN² auch Punkte und Linien zeichnen. Einen Punkt setzen wir mit dem SETPIXEL-Befehl. Als Parameter übergeben wir die Koordinaten und die Farbe: SetPixel 123,200,@RGB(13,20,3) Wenn Ihr Gafiktreiber nicht alle in PROFAN² möglchen 32768 bzw. 16 Millionen Farben unterstützt, wird der Punkt in der nächstmöglichen Farbe gesetzt. Ausgelesen werden kann ein Bildpunkt mit der Funktion @GETPIXEL, die den tatsächlichen Farbwert eines Punktes ermittelt: LET A% = @GetPixel(123,200) Mit den Funktionen @GETRVALUE, @GETGVALUE bzw. @GETBVALUE lassen sich die einzelnen Farbkomponenten ermitteln. Vor dem Linienziehen müssen wir festlegen, welchen Stift wir verwenden. Das erledigt der Befehl USEPEN. Der erste Parameter ist die Linienart, der zweite die Linienstärke und der dritte die Farbe. Die Linienarten 1 bis 5 (gestrichelt und gepunktet) sind nur bei Linienstärke 1 sinnvoll, d.h. dickere Linien werden immer durchgezogen dargestellt. Der eingestellte Stift gilt für alle (!) folgenden Grafikbefehle, mit Ausnahme von SETPIXEL. Eine Linie ziehen wir mit dem Befehl LINE, gefolgt von zwei Koordinatenpaaren. Zusätzlich gibt es noch den Befehl MOVETO, mit dem der Grafik-Kursor versetzt wird, ohne eine Linie zu zeichnen und den Befehl LINETO, der eine Linie vom Grafik-Kursor zum angegebenen Punkt zeichnet. Probieren Sie folgendes Beispiel aus: Cls UsePen 2,1,@RGB(0,31,0) Line 20,20 - 100,100 LineTo 100,20 MoveTo 120,20 LineTo 120,60 WaitInput Seite 60 RGH-PROFAN² Zusätzlich gibt es noch Befehle, um Flächen-Objekte (Rechtecke, Kreise, etc.) zu zeichnen. All diesen ist gemeinsam, daß die ersten beiden Koordinatenpaare das Rechteck angebeben, in dem das Objekt Platz findet. Außerdem muß der Pinsel definiert werden, mit dem das Objekt ausgemalt wird. Diese geschieht mit dem Befehl USEBRUSH. Dabei ist der erste Parameter die Art des Pinsels und der zweite die Farbe. Als Art des Pinsels kommen 0 (transparent = nicht ausgefüllt), 1 (voll ausgefüllt) und 2 - 8 (verschiedene Schraffuren) in Betracht. Die Umrandung des Objektes wird durch den Stift mit USEPEN bestimmt. Soll kein Rand gezeichnet werden, muß ein Stift mit Linienstärke 0 definiert werden. Folgende Befehle für Grafikobjekte gibt es: RECTANGLE (Rechteck), ROUNDRECT (mit abgerundeten Ecken), ELLIPSE (auch für Kreise), CHORD (Kreisabschnitt), ARC (Kreisbogen) und PIE (Kreisausschnitt: "Tortenstück"). Ein kleines Beispiel, um ein rotes Rechteck mit blauem Rand zu zeichnen, dazu ein ebensolcher Kreis: Cls UsePen 1,4,@RGB(0,0,31) UseBrush 1,@RGB(31,0,0) Rectangle 30,30 - 200,200 Ellipse 100,100 - 300,300 WaitInput Der Befehl ROUNDRECT erwartet noch ein Parameterpaar zu Definition der Abrundung und die Befehle ARC, CHORD und PIE erwarten jeweils noch ein Koordinatenpaar für den Beginn und eines für das Ende des betreffenden Ab- bzw. Ausschnittes. Näheres dazu finden Sie in der Referenz. Machen Sie ruhig ein paar Experimente und Sie finden sich schnell in der Windowsgrafik zurecht! Es sei an dieser Stelle auch noch auf den Befehl FILL hingewiesen, mit dem beliebige umrandete Flächen ausgefüllt werden können. Ab Version 6.0 ist auch ein "virtuelles" Koordinatensystem möglich. Das Koordinatensystem des Hauptfensters bzw. des mit STARTPAINT aktivierten Fensters wird mit dem SCRRENBefehl auf beliebige Breite und beliebige Höhe festgelegt. Alle weiteren Koordinatenangaben beziehen sich auf das mit SCREEN eingestellte Koordinatensystem. Auch die Anzeige von Bitmaps bezieht sich nun auf dieses neue Koordinatensystem. Auf diese Weise sind Bildschirmausgaben möglich, die sich immer an die aktuelle Fenstergröße anpassen. Beispiel: Cls ShowMax ' Fenster auf Maximalgröße vergrößern Screen 3000,2000 Rectangle 100,100 - 2900,1900 WaitInput Unabhängig vom eingestellten Bildschirmmodus bedeckt das Rechteck nahezu den ganzen Bildschirm. Seite 61 RGH-PROFAN² 17 - Bitmaps Wichtig unter Windows sind natürlich die Bilddateien. PROFAN² unterstützt hier das windowseigene Bitmap-Format, gekennzeichnet durch die Endung BMP! Die WindowsHintergrundbilder sind in diesem Format abgelegt und nahezu jedes Grafikprogramm unter Windows versteht dieses Format, so auch das mit Windows mitgelieferte Programm Paintbrush. Außerdem wird auch das sehr verwandte komprimierte RLE-Format unterstützt. Viele auf dem Markt befindliche Grafik-Konverter für Windows, wie z.B. das sehr empfehlenswerte PAINTSHOP PRO, daß es sowohl für Windows 3.x als auch Windows 95 gibt, können Bilder in dieses platzsparende Format umwandeln. Mit dem Befehl LOADBMP wird eine Grafik geladen und in Originalgröße angezeigt. Wir müssen also den Namen des Bildes wissen und wohin auf dem Bildschirm es ausgegeben werden soll. Beispiel: LoadBmp "PAPER.BMP", 10, 10; 0 Der letzte Parameter ist der Abbildungsmodus. Die 0 steht für unveränderte Abbildung. Andere Werte bedeuten Verknüpfungen mit dem Hintergrund oder negative Darstellung (z.B. OR, AND oder XOR-Verknüpfung): -1 01234- Transparenz normales Kopieren Quelle und Ziel mit UND verknüpft Quelle und Ziel mit ODER verknüpft Quelle und Ziel mit XOR verknüpft Zielbereich invertieren (Quellbereich wird nicht berücksichtigt) Bitmaps können auch eine transparente Farbe enthalten. Dazu gibt es den Abbildungsmodus -1. Dieser kann ausschließlich bei den Befehlen LOADBMP, COPYBMP, MCOPYBMP, CLIPLOADBMP und DRAWEXTBMP verwandt werden: MCOPYBMP 10,10-100,100 > 50,50;-1 Welche Farbe als transparent angesehen wird, bestimmt das linkeste unterste Pixel einer Bitmap. Auf diese Weise lassen sich endlich auch unter PROFAN Sprites aus Bitmaps verwenden. Zusammen mit der Möglichkeit, Bitmaps im Speicher zu halten, sollten sich recht ansprechende Animationen erzeugen lassen. Da jedes Bild eine eigene Palette haben kann, wird die Palette auf das aktuelle Bild eingestellt. Vorher geladene Bilder können dadurch falsche Farben erhalten. Soll das Bild nicht in der Origionalgröße angezeigt werden, sondern in einer genau festgelegten Größe, so verwenden wir den Befehl LOADSIZEDBMP, der zusätzlich noch Parameter über Breite und Höhe des Bildes benötigt: LoadSizedBmp "C:\WIN31\CHESS.BMP", 10,10 - 100, 80; 0 Mit dem Befehl MLOADBMP kann eine Bildatei auch in den Speicher geladen werden, ohne daß Sie angezeigt wird. Der einzige Parameter ist dann der Dateiname. Mit MCOPYBMP oder MCOPYSIZEDBMP kann dann ein Teil oder das ganze Bild aus dem Speicher auf den Bildschirm kopiert werden: MLoadBmp "SATURN.BMP" MCopyBmp 20,20 - 200,200 > 10,10;0 Wichtige Daten über die geladene Bildatei enthalten die Systemvariablen %BmpX, %BmpY und &BmpCol: Breite, Höhe und Anzahl der verwandten Farben. Seite 62 RGH-PROFAN² Neu ab Version 6.0 ist die Möglichkeit eine Bitmap im Speicher gezielt anzulegen. Hierzu dient der Befehl MCLS, mit dem eine Speicherbitmap in der angegebenen Größe erzeugt wird: MCLS 1024,768 Eine zuvor mit MLOADBMP geladene Bitmap würde dadurch allerdings überschrieben werden. Ebenso überschreibt ein MLOADBMP eine zuvor im Speicher befindliche Bitmap. Der neue Befehl COPYBMPTOMEM kopiert einen Teil des Bildschirmes in einem beliebigen Bereich der Speicherbitmap: COPYBMPTOMEM 30,30-100,100 > 500,500 Um die Speicherbitmap zu beschreiben, bemalen oder mit Bildern zu füllen kann die Graphikausgabe mit STARTPAINT umgeleitet werden, indem als Parameter statt eines Fensterhandles die -1 angegeben wird: MCLS 500,500 STARTPAINT -1 LOADBMP "WINLOGO.BMP",0,0;0 LINE 10,10 - 50,50 ENDPAINT Auf diese Weise ließen sich also auch mehrere kleine Bitmaps (z.B. Sprites) in eine größere Speicherbitmap laden. Anschließend könnten beliebige Teile wie gewohnt etwa mit MCOPYBMP auf den sichtbaren Bildschirm gebracht werden. Während der Umleitung auf die Speicherbitmap machen die Befehle COPYBMP, COPYBMPTOMEM und MCOPYBMP allerdings wenig Sinn, da sie dann nur ein Kopieren innerhalb der Speicherbitmap zur Folge hätten, da die Umleitung sowohl Quell- als auch Zielbitmap betrifft. WICHTIG: Aus Performancegründen findet beim Beschreiben der Speicherbitmap keine Überprüfung statt, ob diese auch groß genug ist. Wenn Sie mehr reinkopieren als reinpaßt oder in nicht existierene Bereiche malen, kann es zum Absturz von Windows mit Datenverlust kommen! Ein weiterer "Speicherplatz" für Bitmaps ist die Zwischenablage. Zwei neue Befehle geben nun auch PROFAN die Möglichkeit diese zu nutzen: Mit SAVEBMPTOCLIP wird ein Bereich des Bildschirmes in die Zwischenablage kopiert und mit CLIPLOADBMP wird der Inhalt der Zwischenablage - so er eine Bitmap ist - mit dem angegebenen Abbildungsmodus auf den Bildschirm gebracht: CLEARCLIP SAVEBMPTOCLIP 0,0-180,180 CLIPLOADBMP 100,100;0 Dem Austausch von Bitmaps mit anderen Grafikprogrammen steht also nun nichts mehr im Wege. Auch Bitmaps aus den Resourcen von DLLs und Programmen können auf den Bildschirm gebracht werden. Hierzu dienen die Befehle DRAWEXTBMP und DRAWSIZEDEXTBMP. Es können auch beliebige Bildschirmbereiche von einem Ort zum anderen kopiert werden. Auch hier gibt es die Möglichkeit in der Originalgröße zu kopieren oder aber die Größe zu verändern (Lupenfunktion): Seite 63 RGH-PROFAN² CopyBmp 10,10 - 100,80 > 200,200; 0 CopySizedBmp 10,10 - 100,80 > 200,200 - 200,160; 0 Eine weitere Möglichkeit ist das Abspeichern eines beliebigen Bildschirmausschnittes als Bitmap-Datei: SaveBmp "D:\GRAFIK\TEST.BMP", 10,10 - 100,80 Desweiteren gibt es natürlich auch in PROFAN² die kleinen Symbolbilder, die Icons. Zum einen stehen die Windows-System-Icons zur Verfügung. Diese werden über eine Nummer angesprochen und an beliebiger Stelle angezeigt: 01234- leeres Rechteck STOP-Zeichen Fragezeichen Ausrufezeichen Info-Zeichen Beispiel: DrawSysIcon 3, 10,50 Einige weitere Icons sind in PROFAN² eingebaut, um diese auszugeben, muß man deren Namen wissen: PROFAN KNOPF1 EIS BAUM KNOPF2 COMPUTER WEG TEXT GESICHT EIMER MUELL MUENZE STEIN WINDOWS WASSER DOS EDITOR SAND Beispiel: DrawIcon "GESICHT", 30,80 Hier sei noch der Hinweis angebracht, daß ein Icon eine feste Größe von 32 * 32 Pixel hat. Die in PROFAN² vorhandenen Icons können mit einem Resourcen-Editor und manchem Icon-Malprogramm verändert und teilweise sogar umbenannt werden. Sie können mit diesen Werkzeugen sogar Icons hinzufügen. WICHTIG: Bei als EXE-Datei gelinkten PROFAN²Programmen dürfen weder Icons entfernt noch hinzugefügt werden. Das Programm würde dann nicht mehr funktionieren. Den PROFAN²-Interpreter oder das Runtime-Modul können Sie beliebig um Icons erweitern. Eine EXE-Datei bekommt immer die Icons die das RuntimeModul zur Zeit des Linkens hat. Es können auch Icons aus anderen Dateien (.EXE, .DLL oder .ICO) benutzt werden. Ein direkter Zugriff auf Icons in anderen Dateien ist über DrawLibIcon gegeben. Es können Icons in beliebigen Dateien (EXE-Dateien, DLLs und Icon-Dateien) genutzt werden. Es ist der Name der Datei, die das Icon enthält, und die Nummer des Icons anzugeben. Die Zählung beginnt mit Null. Beispiele: DrawLibIcon "MOREICON.DLL",23,70,100 DrawLibIcon "TEST.ICO",0,110,100 Mit der Funktion @IconCount kann die Anzahl der Icons in einer Datei ermittelt werden. Seite 64 RGH-PROFAN² Ein letzter Hinweis zu den Icons: Auch das Icon, das ein PROFAN²-Programm bei Verkleinerung zum Symbol erhält kann eingestellt werden. Hierfür dient der Befehl USEICON: UseIcon "GESICHT" Seite 65 RGH-PROFAN² 18 - Sounds Wenn auch die meisten Windowsprogrammiersprachen aus unerfindlichen Gründen keine Befehle zur Tonerzeugung vorsehen (so. z.B. WinBasic, Visual Basic, TurboPascal für Windows, ...), bietet PROFAN² hier einiges an: Zunächst einmal ist das der aus BASIC bekannte BEEP-Befehl, der einen kurzen Ton erzeugt. Mehr Möglichkeiten bietet da schon der SOUND-Befehl, dem als Parameter die Frequenz (in Hz) und die Dauer (in 360tel Sekunden) übergeben wird: SOUND 440,360 Diese Zeile erzeugt eine Sekunde lang den Kammerton A! Übrigens kann dieser Befehl auch zum Erzeugen einer Pause benutzt werden, indem man als Tonhöhe 32767 angibt. Aber aufgepaßt: In dieser Zeit wird Windows 3.1 komplett angehalten! In der 32-Bit-Version von PROFAN² unter Windows 95 wird der Befehl wirkungslos sein, daher sollte man ihn möglichst nicht verwenden. Musikalisch wird es mit dem PLAY-Befehl, der als Parameter den Notenwert (in Halbtonschritten), die Notenlänge und die Punktierung erwartet. Der Notenwert beginnt beim tiefsten Ton mit 1. Eine Oktave höher ist dann der Ton 13. Ton 0 steht für die Pause. Die Notendauer wird reziprok angegeben, d.h. eine Viertelnote hat die Notendauer 4, eine Achtelnote die Notendauer 8, etc. Schließlich folgt die Anzahl der Punkte. Eine Punktierte Achtelnote würde z.B. mit folgender Zeile gespielt: PLAY 16,8,1 PLAY wurde für die MIDI-Wiedergabe über die Soundkarte erweitert: Werden statt eines Notenwertes mehrere durch Semikolon getrennt angegeben, werden diese gleichzeitig über die verschiedenen Kanäle wiedergegeben. Die Kanäle 1 bis 16 entsprechen den MIDIKanälen mit dem Unterschied, das der 4. und 10. Kanal vertauscht wurden. Das Schlagzeug befindet sich also bei General-MIDI jetzt auf Kanal 4, was das Erzeugen dreistimmiger Songs mit Schlagzeugbegleitung vereinfacht. Ein Dreiklang: PLAY 16;18;20,8,1 Wenn Dauer größer als 0 ist, werden die Töne entsprechend lang gespielt und das Programm verharrt. Ist die Dauer 0, wird der Ton angestoßen und der Ton klingt im Hintergrund solange bis er ausgeschaltet wird. Ausgeschaltet wird ein Ton, indem mit vorangestelltem Minus-Zeichen ausgegeben wird. Ist die Dauer -1, wird kein Ton erzeugt, sondern die Werte N1 bis N16 als Instrumente interpretiert, die den 16 Kanälen zugewiesen werden. Das Beispiel spielt einen C-Akkord (25;27;29) auf der Kirchenorgel (Instrument 20) solange, bis eine Taste gedrückt wird: PLAY 20;20;20,-1,0 PLAY 25;27;29,0,0 WAITKEY PLAY -25;-27;-29,0,0 Noch musikalischer ist der MUSIC-Befehl. Als Parameter hat er einen String in einer eigenen Makrosprache. Diese Makrosprache ist kompatibel zur Music-Makro-Sprache, wie sie von BASIC her (für den PLAY-Befehl) bekannt ist: Seite 66 RGH-PROFAN² A..G On > < Ln Pn Tn MN ML MS In Kn Vn entsprechende Note: # - Erhöhung + - Erhöhung - Erniedrigung . - Punktiert n - kennzeichnet die Notenlänge. 4 steht für Viertel, 2 für Halbe, etc. Wird n weggelassen, wird die Standardlänge verwandt. Oktave n (0..6) wird gewählt Eine Oktave höher Eine Oktave niedriger Setzt die Standardlänge Pause in der Länge n. Tempo: Anzahl der Viertelnoten pro Minute. Defaultwert ist 120. normale Musik. Jede Note wird 7/8 der Zeit gespielt Legato. Die Töne gehen in einander über. Staccato. Jede Note wird nur 3/4 der Zeit gespielt. Instrument n (0 ... 127) wird auf den aktuellen MIDI-Kanal gelegt. * MIDI-Kanal n (0..15) wird wiedergegeben. * Der aktuelle Kanal wird auf Lautstärke n (0...127) eingestellt. * * Diese Befehle wirken nur bei einer Soundkarte. Um eine Tonleiter in Viertel-Noten in der 4. Oktave zu spielen, reicht folgender Befehl: MUSIC "O4 C4 D4 E4 F4 G4 A4 B4 > C4" Erhöhungs- und Erniedrigungszeichen sind genauso möglich, wie auch Punktierungen: MUSIC "C#2 F-8 G4." Pausen haben den Notenwert "P". Der Befehl MUSIC gibt bei vorhandenem MIDI-Gerät (Soundkarte oder MIDI-Schnittstelle) die Musik über das MIDI-Gerät aus. Die Musik-Makrosprache von PROFAN² wurde dazu um folgende Befehle erweitert: I (Instrument), V (Volume/Lautstärke) und K (Kanal). Die Tonleiter gespielt mit der Kirchenorgel in voller Lautstärke: MUSIC "I019 V127 O4 C4 D4 E4 F4 G4 A4 B4 > C4" Beachten Sie, daß beim MUSIC-Befehl die Zählung der Instrumente bei 0 beginnt. HINWEIS: In der 32-Bit-Version von PROFAN² für Windows 95 bzw. Windows NT wird die Soundwiedergabe mit PLAY und MUSIC ohne Soundkarte nicht mehr unterstützt, da Windows dort diese nicht mehr vorsieht. In der 16-Bit-Version wird in diesen Fällen (auch wenn die Programme unter Windows 95 oder NT gestartet werden) der PC-Lautsprecher bemüht. Wer eine Soundblasterkompatible Karte hat oder auf andere Weise die WindowsSounddateien mit der Endung WAV hat, wird sich über den PLAYSOUND-Befehl freuen. Jede WAV-Datei kann damit abgespielt werden: PLAYSOUND "SIRENE.WAV", 1 Der letzte Paramater bestimmt den Abspiel-Modus. Sinnvolle Parameter sind: 019- Die Datei wird im Vordergrund gespielt. Das Programm wird solange angehalten. Die Datei wird im Hintergrund gespielt. Das Programm läuft weiter. Die Datei wird im Hintergrund gespielt und solange wiederholt, bis ein neuer PLAYSOUND-Befehl kommt. Seite 67 RGH-PROFAN² 19 - Multimediaschnittstelle Eine der interessantesten Neuerungen von Windows 3.1 war die Erweiterung um Multimediafähigkeiten. Es wurde eine Multimedia-Schnittstelle geschaffen, mit der alle möglichen (und zukünftigen) Multimediageräte angesprochen werden können. Diese Schnittstelle ist das MCI, das "Media-Control-Interface. Über die Funktion @MCISEND$ kann PROFAN² mit dieser Schnittstelle kommunizieren. Alle angeschlossenen Geräte können über diese Funktion mit einfachen, fast umgangssprachlichen (englischen) Kommandos steuern. Ist das Kommando erfolgreich ausgeführt worden, hat %MCIERROR den Wert 0 und der zurückgemeldete String enthält die angeforderte Information oder einfach "OK". Ist ein Fehler aufgetreten, ist der Rückgabestring die Fehlermeldung. Was sind Multimediageräte? Multimediageräte sind die Programme zum Abspielen von WAV-Dateien, MIDI-Dateien und neuerdings auch VIDEO-Dateien ebenso, wie z.B. der CDSpieler (das CD-ROM-Laufwerk als Audiogerät). Um ein solches "Gerät" zu nutzen, muß es erst einmal geöffnet werden. Dazu dient der Befehl OPEN, gefolgt vom Geräte- bzw. Dateinamen. Zur Vereinfachung der weiteren Befehle kann diesem Gerät mittels ALIAS ein Name zugewiesen werden, der bis zum CLOSE-Befehl gilt. Da es an dieser Stelle nicht möglich ist, alle MCI-Befehle aufzuführen, möchte ich wenigstens die wichtigsten Befehle in Programmzeilen bzw. Bespielprogrammen darstellen: 19.1 CD-Player Dieses Programmzeilen spielen die Titel 3 bis 5 der eingelegten CD. @MCISend$(open cdaudio alias cd") Print "Länge: ";@MCISend$("status cd length") Print "Titelzahl: ";\ @MCISend$("status cd number of tracks") @MCISend$("set cd time format tmsf") @MCISend$("play cd from 3 to 5") Das Zeitformat "tmsf" bedeutet, daß Start und Ende im PLAY-Befehl im Format "Track:Minute:Sekunde:Frame" angegeben werden, wobei eine Sekunde 75 "Frames" (kleinste Einheit) hat. Es können also beliebige Bruchstücke eines Titels gespielt werden. Die folgenden Zeilen halten die CD an und schließen das Gerät. @MCISend$("stop cd") @MCISend$("close cd") Weitere interessante MCI-Befehle im Zusammenhang mit Audio-CDs: SET CD DOOR OPEN SET CD DOOR CLOSED STATUS CD CURRENT TRACK STATUS CD LENGTH STATUS CD LENGTH TRACK Nr STATUS CD MODE STATUS CD POSITION öffnet das CD-Fach schließt CD-Fach Nummer des aktuellen Titels Länge der CD Länge des Titels Nr augenblicklicher Modus aktuelle Position im Zeitformat Wird ein anderer Alias-Name gewählt, ist das Wort "CD" entsprechend abzuändern. Seite 68 RGH-PROFAN² 19.2 WAV-Dateien Ausgabe einer "WAV"-Datei: Mit folgenden Zeilen wird eine WAV-Datei gespielt: @MCISend$("open gong.wav type waveaudio alias gong") @MCISend$("play gong") 'Datei spielen ... @MCISend$("close gong") '... schließen Zwischen PLAY und CLOSE muß natürlich genug Zeit gelassen werden, die Datei zu spielen oder es muß ein "wait" eingefügt werden, um solange zu warten, bis der Befehl ausgeführt ist: @MCISend$("play gong wait") Der Zusatz "wait" ist mit Vorsicht einzusetzen, da Windows solange keine anderen Ereignisse zuläßt! Mit folgendem Programm können beliebige WAV-Dateien abgespielt werden. Ein Mausklick bricht die aktuelle WAV-Datei ab und zeigt erneut die Datei-Auswahlbox an. (Gewiß, es ginge auch mit dem PROFAN²-Befehl PLAYSOUND, aber der ist nicht Thema dieses Kapitels!) CLS Declare A$,B$ WindowTitle "WAV-Player" Let A$=@LoadFile$("KLANG-DATEI","*.WAV") While @NEQ$(A$,"") Let A$=@ADD$(@ADD$("OPEN ",A$),\ " TYPE WAVEAUDIO ALIAS SOUND") Let B$=@MCISend$(A$) Case %MCIError : Print "Fehler: ";B$ Let B$=@MCISend$("PLAY SOUND") WaitMouse Let B$=@MCISend$("CLOSE SOUND") Let A$=@LoadFile$("KLANG-DATEI","*.WAV") Wend End WAV-Datei per Mikro aufnehmen: Folgende Zeilen nehmen eine WAV-Datei über das Mikrofon auf: @MCISend$("open new type waveaudio alias test") @MCISend$("set test time format milliseconds") @MCISend$("record test from 0 to 5000 wait") Nach der Aufnahme spielen wir sie ab und können sie auch abspeichern. @MCISend$("Play test from 0 wait") @MCISend$("save test test.wav") Seite 69 RGH-PROFAN² Weitere Interessante Befehle für WAV-Dateien: PLAY DT FROM x TO y spielt von x bis y SEEK DT x positioniert bei x im Zeiformat DELETE DT FROM x TO y löscht einen Teil der Datei INFO DT FILE Dateinamen der Datei STATUS DT LENGTH Länge der Datei im Zeitformat STATUS DT POSITION Aktuelle Position in der Datei STATUS DT TIME FORMAT Aktuelles Zeitformat SET DT TIME FORMAT BYTES stellt Zeitformat "Bytes" ein SET DT TIME FORMAT MILLISECONDS Zeitformat in Millisekunden "DT" steht hier für den Aliasnamen der entsprechenden Datei. Diese Befehle und Funktionen gelten im übrigen auch für MIDI- und VIDEO-Dateien. 19.3 MIDI-Dateien Da MIDI-Dateien den WAV-Dateien recht ähnlich sind, was die Ansteuerung durch MCI betrifft, hier nur ein kurzes Beispielprogramm: Cls Declare A$,B$ WindowTitle "MIDI-PLAYER" Let A$=@LOADFILE$("MIDI-DATEI","*.MID") While @NEQ$(A$,"") Let A$=@ADD$(@ADD$("OPEN ",A$),\ " TYPE SEQUENCER ALIAS MIDI") Let B$=@MCISend$(A$) Case %MCIError: Print "Fehler: ";B$ Let B$=@MCISend$("PLAY MIDI")? WaitMouse Let B$=@MCISend$("CLOSE MIDI") Let A$=@LOADFILE$("MIDI-DATEI","*.MID") Wend End Seite 70 RGH-PROFAN² 19.4 Video für Windows Ein Beispiel für das Abspielen von Filmen ist Microsofts "Video für Windows". Mit folgendem Programm können dieses Videodateien abgespiel werden, sofern zumindest die RuntimeVersion von Video für Windows installiert ist: Cls Declare A$,B$ WindowTitle "Testprogramm AVI-Video" Let A$=@LOADFILE$("FILM-DATEI","*.AVI") While @NEQ$(A$,"") Let A$=@ADD$(@ADD$("OPEN ",A$),\ " TYPE AVIVIDEO ALIAS FILM") Let B$=@MCISend$(A$) Case %MCIError: Print "Fehler: ";B$ Let B$=@MCISend$("PLAY FILM") WaitMouse Let B$=@MCISend$("CLOSE FILM") Let A$=@LOADFILE$("FILM-DATEI","*.AVI") Wend End Das Abspielen anderer Animationen, etwa von *.FLI- oder *.FLC-Dateien des AutdeskAnimators sieht sehr ähnlich aus, nur daß dann eben hinter TYPE ein anderer Begriff steht. Selbstverständlich müssen dazu die entsprechenden Autodesk-Treiber installiert sein. Genauso ist es auch mit Treibern für Apples Quicktime-Videos oder für MPEG-Filme. Weitere interessante Informationen zum Thema MCI finden sich in der einschlägigen Fachliteratur bzw. den Handbüchern zu den entsprechenden Treibern und Produkten. Seite 71 RGH-PROFAN² 20 - Datenbanken PROFAN² ist auch eine komplette Datenbanksprache. Einfache bis mittlere DatenbankAnwendungen können mit PROFAN problemlos realisiert werden. Das Gebiet reicht von einer einfachen Adreßverwaltung bis hin zu einer Kundenverwaltung mit Artikeln, Rechnungen etc. Die wesentlichen Leistungsmerkmale im Überblick: Datentabellen und Indizes im DBase-III-Format. Das heißt: Volle Kompatibilität zu allen DBase-kompatiblen Datenbanken. Beim Zugriff auf DOS-Datenbanken sollten Sie mit @ANSITOOEM$ bzw. @OEMTOANSI$ die unterschiedlichen Zeichensätze berücksichtigen oder mit FONT den OEM-Zeichsdatz einstellen. Seit Version 4.5a können Sie mit dem Befehl FONT festlegen, welchen Zeichensatz PROFAN² in den dBase-III-Tabellen benutzt! Bei 1 wird der OEM-Zeichensatz gewählt. Dieser ist dann zu verwenden, wenn etwa von anderen Programmen auf die Daten zugegriffen werden soll. Diese erwarten bei einer dBase-III-Datei in der Regel den ASCIIbzw. OEM-Zeichensatz; das gilt auch für die ODBC-Treiber. Was Größe und Struktur betrifft, wurde das dBase-Format etwas aufgebohrt: max. 1024 Felder pro Datensatz, max. 16000 Bytes pro Datensatz, max. ca. 2 Milliarden Sätze pro Tabelle. Es können gleichzeitig bis zu 15 Datenbanktabellen geöffnet sein. Ab Version 3.2 besitzt PROFAN² nun auch eine einfache ODBC-Schnittstelle, um auf andere Datenbanken zugreifen zu können. So empfiehlt sich PROFAN² auch als Frontend bzw. Client in einer Client-Server-Umgebung. 20.1 Datenbank-Grundlagen Einige Hinweise zur Nomenklatur: Da in der Literatur von Datenbanksystem zu Datenbanksystem unterschiedliche Begriffe für gleiche Sachverhalte (schlimmer noch: auch gleiche Begriffe für verschiedene Sachverhalte) verwandt werden, will ich hier die in dieser Anleitung gebrauchten kurz klären: Wenn ich z.B. eine Adresse abspeichern will, so besteht diese aus verschiedenen Teilen: Da gibt es z.B. den Vornamen, den Nachnamen, die Straße, den Ort, ... Dieses sind die einzelnen "Felder" der Adresse. Wenn ich mehrere Adressen speichere, so haben alle Adressen die gleichen Felder: Jede Adresse besteht aus Vorname, Nachname, ... Jede einzelne Adresse ist ein "Datensatz". Mehrere Datensätze mit der gleichen Struktur (d.h. den gleichern Feldern) bilden eine "Tabelle" (bzw. Datenbanktabelle). Wenn ich von der "Struktur" einer Tabelle rede, dann rede ich darüber, aus welchen Feldern jeder Datensatz der Tabelle aufgebaut ist. Größere Anwendungen kommen nicht mit einer Tabelle aus. Eine Kundenverwaltung benötigt vielleicht eine Tabelle mit Kundenadressen, eine weitere mit Rechnungen, eine dritte mit Artikeln, etc. All diese Tabellen bilden die "Datenbank". (Im DBase-Bereich wird manchmal auch von einer Tabelle als "Datenbank" gesprochen, das ist aber nicht korrekt.) Häufig nennt man die Tabellen auch "Entityset" und den Datensatz ein "Entity". Seite 72 RGH-PROFAN² 20.2 Datenbankstrukturen und Tabellen Bevor in eine Datenbanktabelle der erste Datensatz (englisch: Record) geschrieben werden kann, muß diese Tabelle erzeugt werden. Zum Erzeugen der Tabelle gibt es den Befehl dbCREATE. Dieser benlötigt eine Strukturdatei, die die Struktur der Tabelle beschreibt. Die Strukturdatei ist eine reine ASCII-Datei, die für jedes Feld der Datenbanktabelle eine Zeile enthält. Diese Zeile enthält durch Semikolons getrennt nacheinander den Namen des Feldes, dessen Typ, dessen Länge und die Anzahl der Dezimalstellen. Es müssen immer alle vier Eigenschaften angegeben werden. PROFAN² kann die Feldtypen C=Text, D=Datum, N=Zahlen, M=Memofeld und L=Ja/Nein bearbeiten. Beispiel einer Strukturdatei: NAME; VORNAME; STRASSE; PLZ_ORT; TELEFON; GEBURT; GEHALT; NOTIZ; C; C; C; C; C; D; N; M; 30; 30; 30; 30; 20; 8; 10; 10; 0 0 0 0 0 0 2 0 Der Name eines Feldes darf nur aus Großbuchstaben (Kleinbuchstaben werden automatisch umgewandelt), Ziffern und dem Unterstrich bestehen. Ein Feldname darf maximal zehn Zeichen lang sein und darf nicht mit einer Ziffer beginnen.Wenn Sie eine Datenbanktabelle mit obiger Struktur erzeugen wollen, geben Sie die Struktur wie gezeigt im Windows-Editor (oder auch mit PROFED) ein und speichern Sie unter einem Namen, z.B. "ADRESS.STR" ab. Mit der Befehlszeile dbCreate "ADRESS.STR" > "ADRESS.DBF" erzeugen Sie nun die noch leere Datenbanktabelle. Wesentlich komfortabler können Sie Datenbanktabellen mit dem "Helfer" für Datenbankstrukturen erzeugen, mit dem "StrukturEditor", den Sie im Menü "Helfer" der Entwicklungsumgebung finden. Natürlich können Sie mit PROFAN² auch die Struktur einer fremden oder unbekannten Datenbanktabelle (".DBF"-Datei) in Erfahrung bringen. Sie muß lediglich im DBase-Format vorliegen. Im Beispiel wird die Struktur der Tabelle "ADRESS.DBF" ausgelesen: Seite 73 RGH-PROFAN² Declare Anzahl%,I% Cls @dbOpen(#1,"ADRESS.DBF") @dbUse(#1) Print "db-Struktur von ADRESS.DBF" Print Print "Datensätze: ";&dbRecCount Print "Felder: ";%dbFCount Print "Satzgröße: ";%dbRecSize;" Byte" Print "Headergröße: ";%dbHeader;" Byte" Print "Letzte Änderung: ";$dbLUpdate Print Let Anzahl% = %dbFCount Let I% = 1 WhileNot @Gt(I%,Anzahl%) @dbGetField$(I%) Print $dbFName,$dbFType,%dbFLen,%dbFDecs Inc I% Wend @dbClose(#1) WaitKey End Zunächst wird die Tabelle mit @dbOPEN geöffnet. Da bis zu 15 Tabellen gleichzeitig geöffnet sein können, wird im Beispiel der Tabelle die Nummer 1 zugewiesen. Mit @dbUSE machen wir deutlich, daß sich die folgenden Zugriffe auf die Datenbank auf diese Tabelle mit der Nummer 1 beziehen. Jetzt können wir über die entsprechenden Systemvariablen die Merkmale der Datenbanktabelle in Erfahrung bringen. Dabei gibt die Systemvariable %dbFCOUNT die Anzahl der Felder an. In der nun folgenden WHILE-Schleife lesen wir mit @dbGETFIELD$ nacheinander alle Felder des aktuellen Datensatzes und ermitteln über die entsprechenden Systemvariablen die Eigenschaften der Felder. Da in unserem Beispiel @dbGETFIELDS nur dazu dient, um das entsprechende Feld zum aktuellen Feld zu machen, interessiert uns das Ergebnis der Funktion nicht. 20.3 Datenbanktabellen bearbeiten Bevor eine Datenbanktabelle bearbeitet werden kann, muß sie geöffnet werden. Das erreichen wir mit der Funktion @dbOpen. Als Ergebnis liefert die Funktion die Anzahl der Datensätze der geöffneten Tabelle zurück. Als Parameter wird zunächst die Tabellenkennung (eine Nummer von 1 - 15) erwartet und dann der Dateiname der Tabelle. Da wir insgesamt bis 15 Tabellen gleichzeitig geöffnet haben können, müssen wir als nächstes mit der Funktion @dbUse angeben, welche Tabelle wir bearbeiten wollen: Cls Declare Anzahl% Let Anzahl% = @dbOpen(#1,"ADRESS.DBF") @dbUse(#1) Print "ADRESS.DBF hat",Anzahl%,"Datensätze!" Jetzt können wir zum Beispiel einen Datensatz hinzufügen: Seite 74 RGH-PROFAN² @dbAppendBlank() @dbPut("NAME","Mustermann") @dbPut("VORNAME","Max") @dbPut("STRASSE","Sackgasse 13") @dbPut("PLZ_ORT","98765 Nirgendwo") @dbPut("TELEFON","09876/54321") @dbPut("GEBURT",@CToD$("23.09.1955")) @dbPut("GEHALT","4500.50") @dbPutRec(0) Mit @dbAPPENDBLANK wird ein neuer leerer Datensatz im Arbeitsspeicher erzeugt. Er wird hinter dem letzten bestehenden Datensatz positioniert. Mit @dbPut wird den einzelnen Feldern dieses Datensatzen ein Wert zugewiesen. Der erste Paramerer ist der Name des Feldes und der zweiter der Wert, bzw. der Text, den das Feld bekommen soll. Im Falle des Datumsfeldes wird das Datum zunächst mit @CTOD$ in das Datenbankformat umgewandelt. Die Funktion @dbPUTREC schreibt den Datensatz aus dem Arbeitsspeicher in die Tabelle. Der Parameter ist die Nummer des Datensatzes. Wird hier - wie in unserem Beispiel - eine Null angegeben, wird der Datensatz an die aktuelle Position zurückgeschrieben. Vor dem Ende des Programmes sollte die Tabelle in jedem Fall mit @dbCLOSE geschlossen werden: @dbClose(#1) Mit folgendem Programm könnten wir den Datensatz wieder auslesen und auf den Bildschirm bringen: Cls Declare Anzahl% Let Anzahl% = @dbOpen(#1,"ADRESS.DBF") @dbUse(#1) Print "ADRESS.DBF hat",Anzahl%,"Datensätze!" @dbGo("|<") Print "Name: ",@dbGet$("NAME") Print "Vorname: ",@dbGet$("VORNAME") Print "Straße: ",@dbGet$("STRASSE") Print "PLZ Ort: ",@dbGet$("PLZ_ORT") Print "Telefon: ",@dbGet$("TELEFON") Print "Geburtstag:",@DToC$(@dbGet$("GEBURT")) Print "Gehalt: ",@dbGet$("GEHALT") @dbClose(#1) Nach dem Öffnen der Tabelle wird mit @dbGO auf den ersten Satz der Datenbank positioniert. Mit dieser Funktion können wir auf den ersten Satz positionieren ("|<"), zurückblättern ("<"), vorwärtsblättern (">") und auf den letzten Satz positionieren (">|"). Ebenso könnten wir als Parameter eine bestimmte Satznummer angeben.Mit @dbGET$ wird der Inhalt des aktuellen Datensatzes gelesen, wobei der Parameter der Name des entsprechenden Feldes ist. Mit @dbDELETE könnten wir den aktuellen Datensatz auch als gelöscht markieren. Wohlgemerkt: er wird lediglich als gelöscht gekennzeichnet. Ob ein Datensatz als gelöscht gekennzeichnet ist, bringen wir durch die Systemvariable %dbDELETED in Erfahrung. Um alle als gelöscht gekennzeichneten Datensätze der Tabelle wirklich (und endgültig) zu löschen, muß die Funktion @dbPACK aufgerufen werden. Natürlich können wir den aktuellen Datensatz mit @dbPUT verändern und dann mit @dbPUTREC in die Datenbank zurückschreiben. Ab Version 4.2 kann mit @DBGETMEMO der Text eines Memo-Feldes aus der Memo-Datei Seite 75 RGH-PROFAN² in die Listboxliste eingelesen und mit @DBPUTMEMO der Inhalt der Listboxliste in ein Memo-Feld geschrieben werden. Zum Editieren des Inhaltes der Listboxliste bietet sich die Funktion @EDITBOX an. Im Zuge dieser Erweiterung wurde nun auch dafür Sorge getragen, daß mit @DBPUT bzw. @DBPUTFIELD der Inhalt eines Memofeldes nicht geändert werden kann. Ein versehentliches Ändern der Verweise auf die Memo-Datei würde im harmlosensten Fall dazu führen, daß der Text nicht mehr gefunden wird. Beide Funktionen geben nun 0 zurück, wenn ein Fehler auftrat. Ob eine Tabelle Memo-Felder enthält, können wir mittels der Systemvariablen %DBMEMO überprüfen. Folgende Prozedur ermöglicht also das Lesen, Editieren und Schreiben eines Memo-Feldes (entsprechend MEMOEDIT in dBase): PROC MEMOEDIT Parameters FeldName$ @DBGETMEMO(FeldName$) IF @EDITBOX("Memo editieren",1) @DBPUTMEMO(FeldName$) ENDIF ENDPROC Aufgerufen wird die Prozedur mit dem Feldnamen des Memofeldes als Parameter, z.B. MEMOEDIT "NOTIZ" Wenn wir viele Datensätze eingegeben haben, wollen wir sie auch sortiert anzeigen können. Hierzu benötigen wir einen Index, d.h. eine extra Datei, die die Sortierreihenfolge enthätt. Auch bei den Indizes unterstützt PROFAN² den dBase-III-Standard. Bevor solch eine IndexDatei genutzt werden kann, müssen wir sie zunächst erzeugen. Das geschieht mit dem Befehl dbCREATEINDEX. Um zum Beispiel unsere Adreß-Tabelle nach Namen zu sortieren erzeugen wir den entsprechenden Index: dbCreateIndex "NAME" > "INAME" Der erste Parameter ist der Name des betroffenen Feldes und der zweite der Name der erzeugten Indexdatei. Die Dateiendung ".NDX" wird automatisch angehängt und darf nicht mit angegeben werden. Wollen wir aber nach Namen UND Vornamen sortieren, so können wir auch beide Feldnamen mit "+" verbunden angeben: dbCreateIndex "NAME+VORNAME" > "INAME" Um diese Sortierreihenfolge zu nutzen, müssen wir dem Programm nun noch mitteilen, daß die entsprechende Index-Datei zu öffnen ist. Das geschieht mit der Funktion @dbINDEX. Beispiel: @dbIndex("INAME") Die Funktion gibt Null zurück, wenn der Index nicht geöffnet werden konnte, etwa weil die Indexdatei nicht existiert oder keine Datenbanktabelle geöffnet ist. Wurde der Index geöffnet, beziehen sich die folgenden @dbGO-Anweisungen auf diese Sortierreihenfolge. Oftmals will man in einer Datenbank nach einem bestimmten Eintrag suchen. Liegt auf dem Feld, das diesen Eintrag enthält, ein Index, geht die Suche besonders schnell mit der Funktion @dbFIND: @dbIndex("INAME") Let SatzNr& = @dbFind("Mustermann",1) Es wird der erste Datensatz gefunden, der mit dem Suchbegriff (in unserem Beispiel "Mustermann") identisch ist. Der zweite Parameter bei @dbFIND gibt an, wie exakt gesucht werden soll. Hat er den Wert 0, so genügt es für eine erfolgreiche Suche, wenn der das entsprechende Feld des Datensatz mit dem Suchbegriff beginnt. War die Suche nicht erfolgreich, gibt die Funktion @dbFIND den Wert Null zurück. Seite 76 RGH-PROFAN² Die Funktion @dbSEEK sucht ohne Index in jedem beliebigen Feld nach dem Suchbegriff. Beispiel: Let SatzNr& = @dbSeek("STRASSE","gasse") Der erste Parameter ist der Name des Feldes, in dem gesucht werden soll, und der zweite Parameter ist der Suchbegriff. Ausgehend vom aktuellen Datensatz wird der nächste Datensatz gefunden, der den Suchbegriff im gewünschten Feld enthält. Auf diesen Datensatz wird positioniert. Über einen optionalen dritten Parameter kann auch hier die Suchgenauigkeit festgelegt werden. Wenn man sich z.B. mit @dbGO(">") durch eine Tabelle bewegt, kommt man irgendwann zum letzten Datensatz. In diesem Fall wird die Systemvariable %dbEOF auf den Wert eins gesetzt, will heißen: Das Datei-Ende ist erreicht. Die augenblickliche Satznummer findet sich in der Systemvariablen &dbRecNo. Die FeldTypen: Feldtyp "C" - Text Der Feldtyp "C" (Character) kann einen String (max. Länge: 254 Zeichen) aufnehmen. Bei der Definition der Struktur muß die Länge des Feldes (1 - 254) mit angegeben werden. Der String darf beliebige Zeichen enthalten. Feldtyp "D" - Datum Der Feldtyp "D" (Date) enthält ein Datum. Das Datum wird immer im Format JJJJMMTT gespeichert. Aus dem 23.09.1955 würde somit der Feldinhalt "19550923". Der Vorteil dieser Schreibweise ist der, daß einerseits Daten miteinander korrekt verglichen werden können (ein späteres Datum ist immer größer als ein früheres) und andererseits mit dem Inhalt sogar gerechnet werden kann. Um ein Datum in vernünftiges europäisches Format umzuwandeln, gibt es die Funktion @DToC$. Soll ein Datum, das im europäischen Format ("TT.MM.JJJJ") vorliegt in ein Datenbankfeld geschrieben werden, muß es mit der Funktion @CToD$ zuvor in das Datenbankformat umgewandelt werden. Feldtyp "N" - Zahlen Der Feldtyp "N" (Numeric) enthält Zahlen, numerische Werte. Ein solches Feld kann eine Länge zwischen 1 und 19 Zeichen haben, wobei in diesen max. 19 Zeichen auch der Dezimalpunkt und das Vorzeichen enthalten ist. Zusätzlich zur Längenangabe benötigen wir bei numerischen Feldern noch die Angabe der Dezimalstellen. Um z.B. Werte zwischen "999999.99" und "999999.99" darstellen zu können, benötigen wir ein numerisches Feld mit der Länge 10 und 2 Dezimalstellen. Feldtyp "L" - Ja/Nein Der Feldtyp "L" (Logical) enthält einen logischen Wert, also entweder "WAHR" oder "FALSCH". "WAHR" wird in der Datenbank durch "T" (True) oder "Y" (Yes) dargestellt und "FALSCH" durch "F" (False) oder "N" (No). Ein logisches Feld hat also immer die Länge 1 und darf nur einen der vier genannten Buchstaben enthalten. Unter Windows wird man ein logisches Feld in der Eingabemaske in der Regel durch eine Checkbox darstellen. Seite 77 RGH-PROFAN² Feldtyp "M" - Memo-Feld Memo-Felder haben in der Datenbank-Datei (der DBF-Datei) eine konstante Länge von 10. Der Inhalt dieser Datei ist ein Verweis auf den Anfang des zugehörigen Textes in der MemoDatei. Diese hat den gleichen Dateinamen wie die DBF-Datei mit der Endung DBT. Ob eine DBF-Datei überhaupt Memo-Felder hat, kann nach dem Öffnen der Tabelle mit der Systemvariablen %DBMEMO festgestellt werden. Seite 78 RGH-PROFAN² 20.4 ODBC-Schnittstelle PROFAN² unterstützt nun auch die Programmierung der ODBC-Schnittstelle, wenn sie auf dem Rechner installiert ist. ODBC ist ein Datenbankstandard, der inzwischen von allen wichtigen Datenbankherstellern unterstützt wird. Datenbanken, die diese Schnittstelle unterstützen, haben einen entsprechenden Treiber, der über die Windows-Systemsteuerung konfiguriert werden kann. In der Systemsteuerung findet sich eigens ein Icon für die ODBC-Treiber. Über diesen Treiber kann auf den Datenbankserver (z.B. ORACLE, DB2, SQLServer, ...) zugegriffen werden. Es gibt aber auch Treiber, um die ACCESS-, dBASE- oder PARADOX-Tabellen als Datenbankserver anzusprechen. Solche ODBC-Treiber werden z.B. mit WORD FÜR WINDOWS 6.0 installiert. Auf der einen Seite haben wir also als Server (Lieferanten von Daten) die Datenbank. Auf der anderen Seite der Schnittstelle steht der Client (Kunde, Empfänger der Daten), der über diese ODBC-Schnittstelle auf die Datenbank zugreift, d.h. Tabellen ändert und/oder erweitert und vor allen Dingen auswertet. Die Sprache mit der dies geschieht heißt SQL, was soviel wie "Strukturierte Abfrage-Sprache" bedeutet. SQL ist genormt, sodaß es egal ist, welche Datenbank nun auf der anderen Seite als Server fungiert. Über die ODBC-Schnittstelle kann nun ein PROFAN²-Programm als Client fungieren und auf die Daten des Servers zugreifen. Damit dies möglich ist, muß zuerst die Verbindung zum Server hergestellt werden. Das geschieht mit der Funktion @SQLINIT. Als Parameter wird der Initialisierungs- bzw. Anmeldestring übergeben. Wenn als Parameter ein Leerstring angegeben ist, wird in der Regel der SQL-Treiber ein Fenster öffnen, das eine Liste der installlierten Datenbanktreiber anzeigen. Aus dieser Liste kann man dann den gewünschten Treiber wählen. Anschließend muß die Datenbank ausgewählt werden. Im Falle von dBASEDateien gilt als Datenbank ein Verzeichnis, das die entsprechenden dBASE-Tabellen enthält. Die Funktion @SQLINIT liefert 1 zurück, wenn die Anmeldung erfolgreich war, ansonsten 0. Ist kein ODBC-Treiber installiert, wird die Fehlermeldung "ODBC-DLL nicht gefunden" angezeigt. Wie der Initialisierungsstring genau auszusehen hat, ist von Datenbank zu Datenbank unterschiedlich. Entnehmen Sie die für Ihre Datenbank gültigen Angaben den entsprechenden Handbüchern. Zwei Beispiele, darunter eines für dBase-Dateien mit dem ODBC-Treiber von WinWord, finden Sie in der Referenz. Um SQL-Befehle an die Datenbank zu senden, gibt es in PROFAN² den Befehl SQLExec. Als ersten Parameter gibt es einen String, der einen gültiges SQL-Statement enthält. Der zweite Parameter kennzeichnet bei SELECT-Anweisungen den Ausgabemodus. Diese Einführung kann und will keine Einführung in SQL liefern. Diese finden Sie in der entsprechenden Fachliteratur und den Handbüchern zu Ihrer Datenbank bzw. Ihrer SQLSchnittstelle. An dieser Stelle seinen nur die wichtigsten Anweisungen kurz aufgeführt: Mit CREATE TABLE kann eine neue Tabelle erzeugt werden: CREATE TABLE <Tabellenname> (<Feldname> <Feldtyp> [,...]) Der Feldtyp kann z.B. CHAR(N) sein, wobei N die Größe des Feldes ist; oder auch DATE oder NUMERIC. Beispiel: SQLExec "CREATE TABLE KUNDEN \ ( VORNAME CHAR(25),\ NAME CHAR(25),\ GEBDAT DATE)",1 Im Falle einer dBASE-Datenbank würde entsprechenden Feldern erzeugt werden. die Seite 79 Tabelle "KUNDEN.DBF" mit den RGH-PROFAN² Um Datensätze hinzuzufügen wird der Befehl INSERT verwandt: INSERT INTO <Tabellenname> (<Feldliste>) VALUES (<Werteliste>) Beispiel: SQLExec "INSERT INTO KUNDEN (Vorname,Name) \ VALUES ('Hugo','Maier')",1 Geändert werden die Datensätze mit der UPDATE-Anweisung: UPDATE <Tabellenname> SET <Feldname>=Inhalt [,...] WHERE <Bedingung> Beispiel: SQLExec "UPDATE KUNDEN SET NAME = 'Mayer' \ WHERE NAME = 'Maier'",1 Zum Löschen dient der Befel DELETE: DELETE FROM <Tabellenname> WHERE <Bedingung> Die interessanteste Anweisung ist die SELECT Anweisung mit folgender Syntax: SELECT [ALL|DISTINCT] <Feldliste> FROM <Tabellenname> [WHERE <Bedingung>] [GROUP BY <Feldliste>] [HAVING <Bedingung>] [ORDER BY <Feldliste>] In eckigen Klammern stehende Teile können weggelassen werden. ALL oder DISTINCT kann wahlweise eingesetzt werden. Anstelle der ersten Feldliste kann auch ein * stehen, womit dann alle Felder der Tabelle angezeigt werden. Beispiele: SQLExec "SELECT * FROM KUNDE",1 SQLExec "SELECT * FROM KUNDE WHERE NAME = 'Maier'",1 Alleine über die SELECT-Anweisung könnte man ein eigenes Buch schreiben (und viele haben es auch getan), ganz zu schweigen von der JOIN-Klausel, mit der man Tabellen relational verbinden kann. Es lohnt sich, einen Blick in die entsprechende Fachliteratur zu werfen. An dieser Stelle sei auch der zweite Parameter von SQLEXEC kurz erklärt: Bei 0 wird das Ergebnis direkt angezeigt, bei 1 wird es in eine Listboxliste geschrieben und bei 2 wird es in eine Datei geschrieben. Mit SQLSetDel und SQLSetNull kann das Ausgabeformat eingestellt werden. Die Anzahl der von SQLEXEC bearbeiteten Datensätze wird in &SQLCount zurückgeliefert. Trat ein Fehler auf, wird -1 zurückgegeben. Der Befehl SQLDONE trennt die Verbindung zum Server. Seite 80 RGH-PROFAN² Abschließend ein kleines Beispielprogramm, welches Zugriff auf die dBASE-Tabellen im aktuellen Verzeichnis bietet. Es können beliebige SQL-Befehle ausprobiert werden. Beendet wird das Programm, indem man bei der InputBox auf "Abbruch" klickt, bzw. "Esc" drückt. Declare SQL$ Cls If @SQLInit("DSN=dBase-Dateien") Let SQL$=" " WhileNot @Equ$(SQL$,"") Let SQL$=@Input$("SQL-String eingeben:","PROFAN-SQL",SQL$) IfNot @Equ$(SQL$,"") ClearList SQLExec SQL$,1 Print "Bearbeitet: ";&SQLCount;" Datensätze" @ListBox$("Ergebnis:",2) EndIf Wend SQLDone EndIf End Seite 81 RGH-PROFAN² 21 - Dateien - Verzeichnisse - System - Zwischenablage Ein BASIC-Programmierer wird sich etwas umstellen müssen, da mir das Dateisystem von PASCAL flexibler erschien. In der aktuellen Version werden lediglich Textdateien unterstützt. 21.1 Dateien - Verzeichnisse - System Unter Windows 95 unterstützen die hier beschriebenen Befehle und Funktionen automatisch die langen Dateinamen auch in der 16-Bit-Version von PROFAN². Dateien Die meisten Befehle und Funktionen, die mit Dateien zu tun haben, erwarten als ersten Parameter die Dateikennung, quasi ein Handle auf die Datei. Mittels ASSIGN wird einer Dateikennung zwischen 1 und 8 der Name einer Datei zugewiesen. Bei den folgenden Befehlen darf die Datei nicht geöffnet sein: Um die Attribute einer Datei zu ermitteln, gib es die Funktion @GETFATTR. Mit SetFAttr können die Attribute einer Datei verändert werden. Das Datum der letzten Änderung läßt sich mit @GetFDate$ in Erfahrung bringen. Mit ERASE kann ich eine Datei löschen und mit RENAME umbenennen bzw. innerhalb einer Festplatte verschieben. Mit COPY kann eine Datei kopiert werden. Um herauszubekommen, welche Dateien überhaupt vorhanden sind, gibt es die Funktionen @FINDFIRST$ und @FINDNEXT$. In diesem Zusammenhang ist auch der Befehl ADDFILES interessant, mit dem der ListBoxListe eine Liste der Dateien hinzugefügt wird, die dem Suchstring entspricht. Verzeichnisse Das aktuelle Laufwerk ist in der Systemvaraiblen $DRIVE abgelegt und den aktuellen Pfad eines Laufwerkes ermittelt die Funktion @GETDIR$. Ebenso gibt es die Befehle MKDIR, CHDIR und RMDIR zum Anlegen, Wechseln und Löschen eines Verzeichnisses. System Für Installationsprogramme ist es wichtig, das Windowsverzeichnis und das WindowsSystemverzeichnis zu erkennen. Das ermittle ich über die Systemvariablen $WINPATH und $SYSPATH. In diesem Zusammenhang interessant sind auch die Systemvariablen $DOSVER und $WINVER, die die Windows- und DOS-Version ermitteln. HINWEIS: In der 32-Bit-Version von PROFAN² ist das Ergebnis von $DOSVER ohne Bedeutung, da es dort kein von Windows unabhängiges DOS gibt. Im Zusammenhang mit langen Dateinamen sei noch auf die Systemvariable %LFN verwiesen, die in der 16-Bit-Version ermittelt, ob das Betriebssystem Windows 95 ist und somit lange Dateinamen unterstützt werden. Oft wird auch die Möglichkeit gebraucht, Windows zu verlassen und gegebenenfalls wieder neu zu starten. Diese Möglichkeit ist mit dem Befehl EXITWINDOWS gegeben. Sind noch Dateien offen, erfolgt natürlich eine Sicherheitsabfrage. Seite 82 RGH-PROFAN² Das Windowseigene Hilfesystem kann mit WinHelp aufgerufen werden. Dabei kann auch ein Hilfethema gezielt angewählt werden, sodaß auch kontextsensitive Hilfe möglich ist. Um Hilfedateien zu erzeugen, sei an dieser Stelle exemplarisch auf die Tools "Visual Help" und "Help Magican" hingewiesen, die dies sehr vereinfachen. Sharewareversionen sollte jeder gutsortierte Shareware-Händler im Angebot haben. 21.2 Textdateien (sequentielle Dateien) In der Dateiverarbeitung werden grundsätzlich zwei verschiedene Zugriffsmethoden unterschieden: Der sequentielle Zugriff auf Textdateien und der direkte (binäre) Zugriff auf beliebige Dateien. Das herausragende Merkmal des sequentiellen Zugriffs ist, daß nicht auf einen beliebigen Datensatz zugegriffen werden kann, sondern immer nur - schön der Reihe nach - auf den nächsten. Dafür können die Datensätze - hier Zeilen genannt - unterschiedliche Längen von 0 bis 255 Zeichen haben. Die einzelnen Datensätze sind durch ein Zeilenende-Zeichen (@Chr$(13) und @Chr$(10)) voneinander getrennt. Sequentielle Dateien sind ideal, um Textdateien zu bearbeiten, Highscore-Tabellen abzulegen, Programmparameter zu verwalten etc. (Für andere Aufgaben, wie etwa Adressverzeichnis, Videokatalog etc. wird man eher auf die Datenbankfunktionen von PROFAN² zurückgreifen, denen ein eigenes Kapitel gewidmet ist.) Um auf eine Datei zugreifen zu können, muß einer Dateinummer (Handle) eine physikalische Datei zugewiesen werden. Das geschieht mit dem Befehl ASSIGN: Assign #1,"C:\TEST.DAT" Dateinummern von 1 bis 15 sind erlaubt. Mit dem ASSIGN-Befehl ist die Datei noch nicht geöffnet. Dazu benötigen wir die Befehle RESET, REWRITE bzw. APPEND. RESET öffnet die Datei zum Lesen. Mit REWRITE wird sie zum Neuschreiben geöffnet und mit APPEND zum Anfügen. Wenn ich eine existierende Datei mit REWRITE öffne, wird sie - ohne jede Warnung - gelöscht. Möchte ich an eine Datei zusätzlichen Text anhängen, ist APPEND zu verwenden: Assign #1,"C:\AUTOEXEC.BAT" Append #1 Print #1,"REM Hinzufügen von Share" Print #1,"SHARE" Close #1 Eine Datei, die ich mit RESET öffne, kann ich mit INPUT# lesen: Print "AUTOEXEC.BAT" Print Assign #2,"C:\AUTOEXEC.BAT" Reset #2 If %IOResult Print "Datei kann nicht geöffnet werden." Else WhileNot @EOF(#2) Input #2, Zeile$ Print Zeile$ Wend Close #2 EndIf WaitKey Seite 83 RGH-PROFAN² HINWEIS: Standardmäßig wird beim Öffnen einer Datei, egal ob es zum Lesen oder Schreiben geschieht, der FILEMODE 2 benutzt, d.h. dem Betriebssystem wird signalisiert, das die Datei zum Schreiben und Lesen geöffnet werden soll. Ist die Datei nun schreibgeschützt, wird das Betriebssystem sagen: Nein, das geht nicht! Damit auch eine schreibgeschützte Datei (z.B,. auf CD-ROM) gelesen werden kann, muß vor dem RESETBefehle der FILEMODE 0 (nur lesen) eingestellt werden. Geschlossen wird eine sequentielle (Text-)Datei mit CLOSE. Mit @EOF frage ich das Ende einer Datei ab, die ich zum Lesen geöffnet habe. Wird in eine Datei geschrieben und anschließend der Befehl CLOSE vergessen, gehen die geschriebenen Daten und möglichweise der Inhalt der Datei verloren! HINWEIS: Es solte nach Dateibefehlen immer mit %IOResult überprüft werden, ob auch alles gut gegangen ist, da PROFAN² (wie auch PASCAL mit der Direktive $I-) keine Fehlermeldung bringt, wenn etwas nicht funktioniert! 21.3 Binäre Dateien PROFAN² kann auch binär auf Dateien zugreifen, d.h. jedes einzelne Byte kann gelesen, verändert und geschrieben werden. Bevor eine Datei bearbeitet werden kann, muß ihr - wie auch bei den sequentiellen Dateien - mit ASSIGN ein Handle zugewiesen werden. Um die Datei zu öffnen, ist der Befehl OPENRW zu verwenden. Existiert die Datei bereits, wird sie zum Bearbeiten geöffnet, anderenfalls wird sie erzeugt. Soll eine bestehende Datei nur zum Lesen geöffnet werden, ist vor dem OPENRW der Befehl FILEMODE 0 zu verwenden. Nach dem Öffnen steht der Dateizeiger auf der ersten Position: auf 0, d.h. der nächste Schreib- oder Lesezugriff würde das erste Byte in der Datei betreffen. Will man Daten an die Datei anhängen, muß erst der Dateizeiger mit SEEK auf die erste Position nach dem Dateiende gesetzt werden. Das geschieht z.B. mit dem Befehl: SEEK #1,@GETFILESIZE(#1) Mit @GETFILESIZE wird die augenblickliche Größe der Datei in Bytes zu ermittelt. Dazu muß die Datei geöffnet sein. (Hingegen kann mit @FILESIZE die Größe jeder ungeöffneten Datei ermittelt werden.) Mit @GETBYTE wird ein Byte aus einer mit OPENRW geöffneten Datei gelesen. Der Dateizeiger wird auf das nächste Byte positioniert, sodaß der nächste Lesezugriff mit @GETBYTE das nächste Byte liest. Wird das Dateiende erreicht, ergibt @EOF den Wert 1 (für WAHR). Mit PUTBYTE kann ich in die Datei an der augenblicklichen Position des Dateizeigers schreiben. Auch hier wird der Dateizeiger automatisch hochgezählt, sodaß das nächste Byte richtigerweise an die nächste Position in der Datei geht. Wird durch häufige PUTBYTEBefehle das Dateiende überschritten wird die Datei entsprechend vergrößert. Mit BLOCKWRITE können beliebig lange Teilstücke einer Bereichsvariablen in eine Datei geschrieben werden. Ebenso kann nun mit @BLOCKREAD eine komplette Datei (in der 16Bit-Version von PROFAN² nur bis ca. 64 kB) in eine Bereichsvariable gelesen werden. Natürlich können auch beliebige Teile einer binären Datei an beliebige Adressen einer Bereichsvariablen gelesen werden. Seite 84 RGH-PROFAN² Es kann jederzeit mit SEEK der Dateizeiger neu positioniert werden. Wird er dabei hinter das Ende der Datei gelegt, wird die Datei bis dorthin vergrößert. Um die augenblickliche Position des Dateizeigers zu ermitteln, ist die Funktion @FILEPOS zu verwenden. WICHTIG: Nach der Bearbeitung muß die Datei mit CLOSERW wieder geschlossen werden, da ansonsten Daten verloren gehen, auch wenn nicht in die Datei geschrieben wurde! Zumeist findet man bei vergessenem CLOSERW nur noch eine 0 Byte große Ruine der Datei auf der Festplatte vor! Eine mit OPENRW geöffnete Datei muß mit CLOSERW geschlossen werden, da ansonsten ein Fehler auftritt! HINWEIS: Es solte nach Dateibefehlen immer mit %IOResult überprüft werden, ob auch alles gut gegangen ist, da PROFAN² (wie auch PASCAL mit der Direktive $I-) keine Fehlermeldung bringt, wenn etwas nicht funktioniert! 21.4 INI-Dateien Für Windows spezifisch sind die INI-Dateien. Auch diese kann man von PROFAN² aus schreiben und lesen. Dazu dienen die Funktion @READINI$ und der Befehl WRITEINI. Wenn Konfigurationsdaten, Spielstände, etc. gespeichert werden sollen, ist die Nutzung von INI-Dateien sehr zu empfehlen. Da sowohl Pfad als auch Dateiname angegeben werden können, besteht kein zwingender Grund, INI-Dateien im Windowsverzeichnis abzulegen, bzw. ihnen die Endung "INI" zu geben. Ins Windowsverzeichnis werden sie nur dann abgelegt, wenn kein Pfad angegeben wird. Da @PAR$(0) Pfad und Name des aktuellen Programmes wiedergibt, kann daraus der Programmpfad ermittelt werden und die INI-Datei dort abgelegt werden. Alle INI-Dateien sind gleich aufgebaut: Sie bestehen aus einem oder mehreren Abschnitten, deren Titel in eckigen Klammern steht. Unter dem Titel stehen die einzelnen Einträge. Ein Eintrag besteht aus einem Kennwort, gefolgt von einem Gleichheitszeichen und dem zugehörigen Text. Ein Beispiel: LET HighScore& = 25000 WRITEINI "SPIEL.INI","MeinProgramm",\ "HIGHSCORE"=@Str$(HighScore&) Diese Zeilen würden folgende INI-Datei erzeugen: [MeinProgramm] HIGHSCORE=25000 Existiert die Datei noch nicht, wird sie erzeugt. Existiert in der Datei der Abschnitt noch nicht, wird er hinzugefügt. Existiert im Abschnitt das Kennwort des Eintrages noch nicht, wird der Eintrag hinzugefügt. Gibt es die INI-Datei mit dem Abschnitt und dem Eintrag schon, wird nur der hinter dem Gleichheitszeichen stehende Text geändert. 21.5 Registry (nur 32 Bit) In Windows 95 und Windows NT übernimmt die Registry, die Systemregistrierung, weitgehen die Aufgaben der INI-Dateien. Auch die Registry wird mit @READINI$ und WRITEINI bearbeitet. Dabei wird anstelle des Dateinamens der INI-Datei die Klasse in der Registrierdatenbank angegeben. Die recht langen Klassennamen werden durch die kürzeren Bezeichnungen "HKEY_0" bis "HKEY_6" ersetzt: Seite 85 RGH-PROFAN² HKEY_CLASSES_ROOT HKEY_CURRENT_USER HKEY_LOCAL_MACHINE HKEY_USERS HKEY_PERFORMANCE_DATA HKEY_CURRENT_CONFIG HKEY_DYN_DATA = = = = = = = HKEY_0 HKEY_1 HKEY_2 HKEY_3 HKEY_4 HKEY_5 HKEY_6 Der zweite Parameter ist dann der komplette "Pfad" zum Eintrag. Der dritte Parameter ist der Schlüssel (Key), der geschrieben werden soll. Ist der Pfad und/oder der Schlüssel nicht vorhanden,m wird er angelegt. Sind Pfad und Schlüssel vorhanden, wird der entsprechende Wert geändert. Der letzte Parameter ist der Wert, den der Schlüssel bekommen soll. Einzelne Einträge des Pfades werden durch Backslashes (wie beim Verzeichnis) voneinander getrennt: Bei einem 32-Bit-Spiel könnte der Highscore etwa wie folgt gespeichert werden: LET HighScore& = 25000 WriteIni "HKEY_1","RGH-Soft\Spiele\MeinProgramm", \ "High-Score"=@Str$(HighScore&) Wollten wir jetz auch noch weitere Optionen speichern, könnten wir im selben Pfad einen anderen Schlüssel verwenden, etwa für die Sound-Einstellung: WriteIni "HKEY_1","RGH-Soft\Spiele\MeinProgramm","Sound"="EIN" Diese Zeile würde in der 16-Bit-Version im übrigen keinen Fehler produzieren, sondern eine INI-Datei "HKEY_1" im Windowsverzeichnis mit einem entsprechenden Eintrag erzeugen. Das kann durchaus gewollt sein und ermöglicht es, Programme zu schreiben, die unter 32 Bit die Registry nutzen und unter 16 Bit entsprechende INI-Dateien. Aus diesem Grund wurden statt der langen Klassennamen auch die kurzen Versionen HKEY_0 bis HKEY_6 für die PROFAN²-Syntax gewählt. ACHTUNG: Seien Sie vorsichtig beim Überschreiben bestehender Registry-Einträge! Ebenso wie es durch Ändern von SYSTEM.INI oder WIN.INI möglich ist, Windows weitgehend lahmzulegen, ist dies auch mit Änderungen der Registry noch viel effektiver möglich! Seite 86 RGH-PROFAN² 21.6 Die Zwischenablage PROFAN² unterstützt auch die Möglichkeit, Daten über das Clipboard (Zwischenablage) auszutauschen. PROFAN² kann mit PUTCLIP einen String in die Zwischenblage schreiben und mit @GETCLIP$ Text aus der Zwischenablage in einen String lesen. Mit CLEARCLIP wird die Zwischenablage gelöscht. Das eröffnet interessante Möglichkeiten des Datenaustausches (nur Text) mit anderen Programmen oder der Fernsteuerung eines PROFAN²-Programmes durch ein anderes. Mit SAVEBMPTOCLIP wird ein Bereich des Bildschirmes in die Zwischenablage kopiert und mit CLIPLOADBMP wird der Inhalt der Zwischenablage - so er eine Bitmap ist - mit dem angegebenen Abbildungsmodus auf den Bildschirm gebracht: CLEARCLIP SAVEBMPTOCLIP 0,0-180,180 CLIPLOADBMP 100,100;0 In diesem Zusammenhang sind auch die Botschaften wm_cut, wm_paste, wm_clear und wm_copy interessant mit denen z.B. auch Editierfelder oder gar andere Anwendungen angesprochen werden können. Mit @SENDMESSAGE werden die entsprechenden Botschaften an die Fensterelemente geschickt. Die wichtigsten Botschaften werden im entsprechenden Teil der Online-Hilfe ausführlich dargestellt. 21.7 Windows 95 und lange Dateinamen Ab Version 4.1 unterstützt PROFAN² vollautomatisch die langen Dateinamen unter Windows 95. Im Regelfall kann es dem PROFAN²-Programmierer bei 16-Bit-Programmen egal sein, auf welchem Zielsystem das Programm eingesetzt wird. Das Programm erkennt automatisch, ob es unter Windows 3.x oder Windows 95 gestartet wurde und reagiert entsprechend: Die Load- und Save-Dialoge werden an lange Dateinamen angepaßt und auch alle anderen Funktionen und Befehle können nun mit langen Dateinamen umgehen. (Eine Ausnahme bilden die Dateinamen von Datenbanktabellen und Indexdateien). In einigen Spezialfällen mag es aber sein, daß der Programmierer bewußt mit langen Dateinamen umgehen will. Hier bietet PROFAN² an Version 4.1 einige Hilfen: Mit %LFN kann ermittelt werden, ob die aktuelle Windowsversion (ab Windows 95) lange Dateinamen unterstützt. Dabei wird die Windows-Version abgefragt. Mit SETLFN kann man diese Abfrage auch bewußt steuern. So mag es aus Kompatibilitätsgründen in bestimmten Situationen notwendig sein mit SETLFN 0 die Verwendung langer Dateinamen zu unterbinden. Die Funktionen @LONGNAME$ und @SHORTNAME$ ermöglichen die Umwandlung von kurzen Dateinamen in langen Dateinamen und umgekehrt. HINWEIS: Da die 32-Bit-Version von PROFAN² Windows 95 (oder höher) vorraussetzt, werden hier die langen Dateinamen durchgehend unterstützt. SETLFN erzeugt zwar keinen Fehler, bleibt aber wirkungslos. Die Systemvariable %LFN liefert immer das Ergebnis 1 zurück. Seite 87 RGH-PROFAN² 22 - Die Verbindung zur Außenwelt Es gibt eine Welt außerhalb des Computers! PROFAN² bietet zahlreiche Möglichkeiten, mit dieser Welt Kontakt aufzunehmen. 22.1 Drucken mit PROFAN² PROFAN² unterstützt selbstverständlich auch direkt den Drucker. Unter Windows ist Drucken immer seitenorientiert. Ich teile also Windows mit, wenn eine neue Seite beginnen soll, erstelle diese Seite und gebe dann die Anweisung, diese Seite zu drucken. Mit dem Befehl STARTPRINT beginne ich eine neue Seite. Alle danach folgenden Ausgaben gehen nicht auf den Bildschirm, sondern auf den Drucker. Einige Befehle sind während des Druckens nicht erlaubt. Das betrifft insbesondere einige Befehle, die sich mit BitmapGrafiken befassen, wie z.B. MLOADBMP, MCOPYBMP, COPYSIZEDBMP oder COPYBMP. Ebenso ist der FILL-Befehl nicht gestattet. Alle anderen Befehle zur Text- oder Grafikausgabe funktionieren wie gewohnt. Ab Version 3.3 lassen sich mit LOADBMP und LOADSIZEDBMP Bitmapgrafiken direkt in ausgezeichneter Qualität auf den Drucker ausgeben. Der einzige Unterschied: Während der Bildschirm max. 640 Pixel breit und 480 Pixel hoch ist, hat die Druckseite eine Breite von 640 Einheiten und eine Höhe von 960 Einheiten. Ebenso wie auf dem Bildschirm lassen sich die Truetype-Fonts beliebig skalieren und drehen! Innerhalb eines Druckauftrages zwischen STARTPRINT und ENDPRINT wird mit NEXTPAGE eine neue Seite begonnen. Ist die Seite fertig, wird sie mit ENDPRINT ausgegeben. Beispiel: StartPrint Rectangle 100,100 - 550,850 DrawText 150,150,"Testtext" EndPrint Eine weitere Druckmöglichkeit besteht durch den Befehl SCREENCOPY. Wird er ohne Parameter aufgerufen, wird eine Hardcopy des aktuellen Bildschirmes auf den Drucker ausgegeben. Durch Parameter kann aber auch der Bereich eingeschränkt werden, der gedruckt wird: ScreenCopy ScreenCopy 20,20 - 400,300 Während SCREENCOPY nur den Client-Bereich des Hauptfensters (incl. der darauf liegenden Dialoge und Fenster) abbilden kann, kann mi dem Befehl WINCOPY jedes beliebige Fenster bzw. Fensterelement, dessen Handle bekannt ist, ausgedruckt werden. Beispiel zum Ausdruck des gesamten Bildschirmes: WinCopy %DeskTop 22.2 Die serielle Schnittstelle Set Version 4.0 kann PROFAN² auch über die serielle Schnittstelle kommunizieren. Sei es, daß ein Modem angesteuert wird, Verbindungen zu anderen Rechnern hergestellt werden oder Geräte gesteuert bzw. ausgelesen werden. Seite 88 RGH-PROFAN² Um eine serielle Schnittstelle zu nutzen, muß sie mit @OpenCom geöffnet werden. Der Rückgabewert dieser Funktion ist das Handle auf die Schnittstelle. Dieses wird für die anderen Funktionen benötigt. Beim Öffnen geben sie an, welche Schnittstelle Sie öffnen wollen und wie groß die Puffer für die Sende- und Empfangsdaten sind. Geben Sie diese Werte nicht zu klein an, damit keine Daten verloren gehen, während das System mit anderen Dingen beschäftigt ist. 1024 Bytes sollten mindestens für jeden Puffer vorgesehen werden: LET h% = @OpenCom("COM2",1024,1024) Die Schnittstelle wird mit Standardwerten geöffnet. Ist der Rückgabewert h% negativ, ist ein Fehler aufgetreten. Um die Schnittstellenparameter einzustellen, muß die Funktion @SetCom aufgerufen werden. Sie hat nur einen Parameter: Einen String, der dem ensprechenden DOS-Parameter für den MODE-Befehl entspricht: LET e% = @SetCom("COM2:9600,N,8,1") Hier wird COM2 auf 9600 Baud, keine Parität, 8 Datenbits, 1 Stopbit eingestellt. Ist ein Fehler aufgetreten, dann wird das Ergebnis e% negativ. Die Funktion muß nach @OpenCom aufgerufen werden! Sie kann auch mitten im Betrieb aufgerufen werden, um die Parameter zu ändern. Dabei ist jedoch zu berücksichtigen, daß Sende- und Empfangspuffer geleert werden. Es sollte vom Programm also sichergestellt werden, daß keine Daten verloren gehen. Weitere Einstellungsmöglichkeiten ergeben sich mit @SETCOMEXT. Gelesen werden die Daten, die an der seriellen Schnittstelle anliegen mit @READCOM$ und gesendet mit @WriteCom. Mit @COMERROR sollte jedes Lesen und Schreiben anschließend überprüft werden und nach einem Fehler die Schnittstelle wieder freigegeben werden. Vergessen Sie nicht, die Schnittstelle anschließend mit @CloseCom zu schließen. Das folgende Beispielprogramm stellt ein minimalistisches Terminal dar, daß mit "§" (<Shift><3>) beendet wird: Declare a$, f%, ende% Proc GetComInput '--------------Parameters id% Declare x$ Let x$=@readcom$(id%,1) @comerror(id%) Print x$; WhileNot @equ$(x$,"") Let x$=@readcom$(id%,1) @comerror(id%) Print x$; EndWhile EndProc Window 0,0-%MaxX,%MaxY Seite 89 RGH-PROFAN² Let f% = @OpenCom("COM2",1024,1024) @SetCom("COM2:2400,N,8,1") @WriteCom(f%,"ATZ\n") ' Modem initialisieren @ComError(f%) GetComInput f% ' Antwort abwarten und anzeigen Let ende% = 0 WhileNot ende% Let a$ = @inkey$() ' Tastatur abfragen If @Equ$(a$,"§") ' Ende mit SHIFT-3 Let ende%=1 Else IfNot @equ$(a$,"") ' Wurde ein Zeichen eingegeben, ' dann ans Modem damit @WriteCom(f%,a$) Endif GetComInput f% ' empfangene Zeichen lesen Endif Wend @CloseCom(f%) End Die Prozedur @GETCOMINPUT liest solange Zeichen aus der seriellen Schnittstelle, solange welche anliegen. Wenn man sicher ist, das nie mehr als 255 Zeichen anliegen, könnte man die Prozedur auch auf zwei Zeilen reduzieren: Let X$ = @ReadCom$(f%,255) Case @Len(X$):Print X$ 22.3 I/O-Ports HINWEIS: Unter Windows NT ist die direkte Kommunikation mit den Ports nicht mehr erlaubt! Speziell für Hardware-Erweiterungen ist es interessant direkt über die I/O-Ports des PC Kontakt mit der Umwelt aufzunehmen. Auch manche Hardwarekomponenten des PC können über die I/O-Ports direkt angesprochen werden, indem entsprechende Werte in die Register geschrieben werden. Hierfür bietet PROFAN² spezielle Befehle und Funktionen an: Mit OUTP wird ein 16-Bit Wert an die angegebene I/O-Adresse ausgegeben. Da hier ein 16 Bit-breiter Wert an die Außenwelt gegeben wird, werden zwei benachbarte Port-Adressen benutzt: Die im Befehl angegebene und die darauffolgende Adresse. Wenn gezielt nur ein 8Bit Wert ausgegeben werden soll, ist der Befehl OUTPB zu verwenden, wobei das zusätzliche B für Byte steht. Zum Lesen der Ports gibt es zwei entsprechende Funktionen, nämlich @INP und @INPB. Diese Befehle und Funktionen sollte man nur verwenden, wenn man genau weiß was man tut. Zum einen können einige Adressen selbst beim Lesen Windows zum Stillstand bringen und zum anderen kann nicht 100%ig ausgerschlossen werden, das durch bestimmte OUTBefehle die Hardware in Mitleidenschaft gezogen wird. So ist es zum Beispiel möglich, durch direktes Beschreiben der Register der Videokarte die Videokarte und/oder den Monitor zu beschädigen. Seite 90 RGH-PROFAN² 23 - Fertige Dialoge PROFAN² unterstützt zwar bereits seit Version 3.0 auch selbstdefinierte Dialoge, bietet aber trotzdem eine ganze Reihe von fertigen Standarddialogen an, die manche Programmierarbeit ersparen: 23.1 MessageBox Da ist zunächst einmal die Messagebox zur Ausgabe einer einfachen Meldung bzw. Frage auf den Bildschirm. Eine Messagebox hat drei Parameter: Der erste Parameter ist der Text der Meldung oder Frage, der zweite Parameter ist die Überschrift und der dritte Parameter ist eine Zahl und kennzeichnet die Fensterart, das Icon und die Anzahl der Buttons. Der Wert setzt sich zusammen aus BUTTONS + ICON + DEFAULT + FENSTERART: Werte für BUTTON: 0 1 2 3 4 5 - OK - OK Abbrechen - Abbrechen Wiederholen Ignorieren - Ja Nein Abbrechen - Ja Nein - Wiederholen Abbrechen Werte für ICON: 0 16 32 49 64 - Kein Icon - STOP - "?" - "!" - "i" Werte für DEFAULT-Knopf: 0 256 512 - 1. Knopf - 2. Knopf - 3. Knopf Werte für FENSTERART: 0 4096 - "normales" Fenster. - nicht verschiebbares "Fehler"-Fenster. Das Ergebnis der Messagebox-Funktion ist eine Zahl, die für den gewählten Button steht: 1 2 3 4 5 6 7 - OK - Abbrechen (Cancel) - Abbrechen (Abort) - Wiederholen - Ignorieren - Ja - Nein Seite 91 RGH-PROFAN² Ein kleines Beispiel: Declare Ende% Declare Knopf% 'Ende-Schalter 'Enthält Button-Wert Let Ende% = 0 WhileNot Ende% Let Knopf% = @MessageBox \ ("Willst Du schon aufhören?",\ "Ernstgemeinte Frage",292) Case @Equ(Knopf%,6): Let Ende% = 1 Wend Die 292 setzen sich wie folgt zusammen: Das Icon in der Messagebox ist ein Fragezeichen (=32), es soll eine "Ja/Nein" Messagebox sein (=4) und der zweite Button (der "Nein"-Knopf) soll vorgewählt sein (=256). Diese Werte addiert ergeben 292. Die 6 steht schließlich für den "Ja"-Knopf. Aus Gründen der Kompatibilität zu PROFAN 1.x gibt es auch noch den MessageBox-Befehl. Mit ihm sähe obiges Programm wie folgt aus: Declare Ende% Declare Knopf% 'Ende-Schalter 'Enthält Button-Wert Let Ende% = 0 WhileNot Ende% MessageBox "Willst Du schon aufhören?",\ "Ernstgemeinte Frage",292 Let Knopf% = %Button Case @Equ(Knopf%,6): Let Ende% = 1 Wend End Diese Form sollte jedoch nicht verwandt werden, da in künftigen Versionen von PROFAN² dieser Befehl nicht mehr zur Verfügung stehen wird. 23.2 InputBox und EditBox Ein weiterer Dialog ist die InputBox. Sie ermöglicht die Eingabe eines beliebigen Wertes. Die Funktion hat drei Parameter: Der erste Parameter ist der "Prompt", also die Frage bzw. Hilfe zur Eingabe. Der zweite Parameter ist die Überschrift des Dialoges und der dritte Parameter ein Vorgabewert. Dieser Vorgabewert steht schon beim Aufruf in der Inputbox und kann übernommen oder überschrieben werden. Ein Beispiel: Declare Text$ Let Text$ = "Mannheim" Let Text$ = @Input$("Wohin möchten Sie reisen?",\ "REISEZIEL",Text$) Print Text$ WaitKey End Seite 92 RGH-PROFAN² Ab PROFAN² 2.5 kann sowohl die Vorgabe als auch das Ergebnis numerisch sein. Die Funktion kann so zur Eingabe von Strings und numerischen Werten verwandt werden. Beispiel: Let Z&=@Input$("Neuer Wert:","Test",Z&) Neu in PROFAN² 3.2 war die mehrzeilige Inputbox, die EditBox, die die Editierung kompletter Texte bis 30 kB erlaubt. Der zu editierende Text ist in die Listboxliste einzulesen. Dann wird die Funktion @EditBox aufgerufen, um den Text zu editieren. Anschließend kann er wieder aus der Listboxliste in eine Datei geschrieben werden. Wenn die EditBox mit "OK" verlassen wurde, gibt die Funktion den Wert 1 zurück. Im Beispiel wird die Datei "TEST.PRF" editiert: Declare Text$,A% ClearList Assign #1,"C:\PROFAN33\TEST.PRF" Reset #1 WhileNot @Eof(#1) Input #1,Text$ AddString Text$ Wend Close #1 If @EditBox("Editiere TEST.PRF",2) Rewrite #1 Let A% = 0 WhileNot @Gt(A%,%GetCount) Print #1,@ListBoxItem$(A%) Inc A% Wend Close #1 EndIf End 23.3 ListBox Der mächtigste Dialog von PROFAN² ist die ListBox. Dazu gibt es ein eigenes String-Feld, das bis zu 32000 Einträge (16-Bit-Version: 16000 Einträge) haben kann. Diese Strings werden dann in der ListBox angezeigt und einer kann dann vom Anwender ausgewählt werden. Um diese ListBox-Liste zu leeren gibt es den Befehl CLEARLIST. Gefüllt werden kann diese Liste mit den Befehlen ADDSTRING und/oder ADDFILES und/oder ADDWINDOWS. ADDSTRING fügt einen Eintrag, der als Parameter angegeben wird, zur Liste hinzu. Mit ADDFILES werden die Dateinamen eines Verzeichnisses der Liste hinzugefügt, wobei Verzeichnisnamen in eckige Klammern gestellt werden. ADDFILES verlangt als Parameter eine Dateimaske und den Pfad. Wird der Pfad weggelassen, wird das aktuelle Verzeichnis gelesen. ADDWINDOWS liest die Titel der z.Zt. aktiven Programme, deren Titel mit dem als Parameter verwandten String beginnt, ein. Sollen alle Fenstertitel gelistet werden, ist der Leerstring als Parameterzu verwenden. Angezeigt wird der Dialog mit der @LISTBOX$-Funktion, die zwei Parameter hat: Der erste Parameter ist die Überschrift und der zweite Parameter gibt an, in welcher Form die ListBox angezeigt werden soll: 1 2 3 4 5 6 7 8 - groß - unsortiert - Systemschrift - groß - unsortiert - Courier 10 - groß - sortiert - Systemschrift - groß - sortiert - Courier 10 - klein - unsortiert - Systemschrift - klein - unsortiert - Courier 10 - klein - sortiert - Systemschrift - klein - sortiert - Courier 10 Seite 93 RGH-PROFAN² Aus Gründen der Kompatibilität zu PROFAN² 2.x ist auch noch der Parameter 0 erlaubt. Er hat die gleiche Wirkung wie 7! Die große (unsortierte) ListBox eignet sich insbesondere zur Darstellung von Texten. Diese werden eingelesen und dann angezeigt. Beispiele für ListBoxen: Declare Text$, Wahl$ 'Eine kleine ListBox mit verschiedenen Strings ClearList AddString AddString AddString AddString Let Wahl$ Print "Du "Rot" "Blau" "Grün" "Schwarz" = @ListBox$("Wähle ein Farbe:",7) hast ";Wahl$;" gewählt." 'Eine kleine ListBox mit Dateiliste ClearList AddFiles "C:\WIN31\*.*" Let Wahl$ = @ListBox$("Wähle eine Datei:",8) Print "Du hast aus ";%GetCount,\ " Einträgen ";Wahl$;" ausgewählt." 'Eine große Box zur Anzeige eines Textes ClearList Assign #1,"C:\WIN31\WIN.INI" Reset #1 WhileNot @Eof(#1) Input #1,Text$ AddString Text$ Wend Close #1 @ListBox$("WIN.INI",1) End Mit %GETCOUNT wird die Nummer des letzten Eintrags in der ListBox-Liste ermittelt. ACHTUNG: Da der erste Eintrag die Nummer 0 hat, ist die tatsächliche Anzahl der Einträge um 1 höher! Zusätzlich besteht die Möglichkeit, mit der Funktion @LISTBOXITEM$ einen speziellen Eintrag in der ListBox zu ermitteln. Mit dem Befehl LISTBOXITEM$ kann ein spezieller Eintrag ersetzt werden. %GETCURSEL gibt die Position des ausgewählten Eintrages in der ListBox an. Bei einer sortierten ListBox entspricht dies nicht der Position des Eintrages in der ListBoxListe! Seite 94 RGH-PROFAN² 23.4 LOAD- und SAVE-Dialoge Am häufigsten gebraucht werden Dialoge zum Laden und Speichern von Dateien. Daher gibt es diese in PROFAN² schon fix und fertig. Gewiß, es wäre auch möglich, solche Dialoge vermittels der Listbox abzuwicklen, aber so ist es einfacher: Declare Name$ Let Name$ = @LoadFile$("Lade ein Bild","*.BMP") LoadSizedBmp Name$,0,0-100,100 Let Name$ = @SaveFile$("Speichere das Bild","NEU.BMP") If NEqu$(Name$,"") SaveBmp Name$,0,0-100,100 EndIf WaitInput End Der Name "NEU.BMP" wird für das Speichern vorgeschlagen, kann aber jederzeit im Dialog geändert werden. Wenn das Ergebnis eines SaveFile-Dialoges der Leerstring ist wurde der Dialog mit "Abbruch" beendet. Probieren Sie bitte - wie immer - alle Beispiele aus. In der 32-Bit-Version werden die Systemdialoge zum Laden und Speichern verwandt. Diese erlauben den Einsatz mehrerer Dateifilter. Will man dieses Feature nutzen, kann man mehrere Dateifilter, die jeweils aus Beschreibunng und ndung bestehen, kombinieren. Wollten wir in unserem Beispiel neben *.BMP-Dateien auch *.RLE-Dateien laden, könnte die Zeile wie folgt aussehen: Let Name$ = @LoadFile$("Lade ein Bild", \ "Normal|*.BMP|komprimiert|*.RLE") Der senkrechte Strich wird mit [AltGr]+[<] erreicht. Außerdem gibt es noch den Verzeichniswechsel-Dialog. Er ähnelt dem SAVE-Dialog mit dem Unterschied, daß kein Dateiname eingegeben werden kann. Der Rückgabewert ist der gewählte Pfad: Let Pfad$ = @ChooseDir$("Verzeichnis wählen:") ChDir Pfad$ Bitte beachten: Der Dialog selbst wechselt nicht in den Pfad, sondern er gibt nur einen vorhandenen und gewählten Pfad zurück. Wird er mit "Abbruch" beendet, ist der Rückgabestring leer! Seite 95 RGH-PROFAN² 24 - Selbstdefinierte Dialoge Ursprünglich kannte PROFAN² nur vordefinierte Dialogboxen, die ohne Aufwand vom Programmierer eingesetzt werden können und für die meisten einfacheren Programme auch ausreichend sind: Eingabedialog mit @INPUT$, Listboxen mit @LISTBOX$, Dialoge zum laden und speichern und zur Auswahl eines Verzeichnisses. Mit nur einer Programmzeile lassen sich so die gängigsten Dialogboxen auf den Bildschirm zaubern. All dieses bleibt natürlich bestehen (und wird in künftigen Versionen noch erweitert). In PROFAN² 3.0 kamen frei definierbare Dialogboxen hinzu, damit der erfahrenere Programmierer die Möglichkeiten von Windows auch nutzen kann. Mit der PROFAN²Version 4.0 wurden die Dialogelemente für den PROFAN²-Programmierer wesentlich erweitert und durch den neuen Datentyp 'Bereich' erschließen sich weitgehende Möglichkeiten durch Nutzung der @SendMessage-Funktion. In Version 4.1 kamen nun auch noch die Scrollbalken als Dialogelemente dazu. Und seit Version 6.0 können mit @CONTROL beliebige Dialogelemente genutzt werden. 24.1 Dialoge - Grundlagen Selbstdefinierte Dialogboxen gibt es in zwei Ausprägungen: Einmal als Dialogbox mit fester Fenstergröße (@CREATEDIALOG) und zum zweiten als Dialogfenster (@CREATEWINDOW), dessen Stil mit WINDOWSTYLE eingestellt werden kann. In beiden Fällen handelt es sich um nichtmodale Fenster, d.h.: Wenn der Anwender außerhalb des Dialoges etwas anklickt, kann die Anwendung darauf reagieren. Soll der Anwender nichts anderes machen können, bevor der Dialog abgearbeitet ist muß das Programm (will heißen: Sie als Programmierer) dafür Sorge tragen, daß nur auf Ereignisse des Dialoges reagiert wird. Normalerweise wird man für jeden Dialog eine eigene Prozedur schreiben, die erst dann verlassen wird, wenn der Dialog beendet ist: PROC Dialog Declare hD%, hB%, OK%, <...> 'Dialogfenster erzeugen Let hD% = @CreateDialog(%HWnd,"Dialogfenster",10,10,100,100) 'Einen Button mit OK erzeugen Let hB% = @CreateButton(hD%,"&OK",50,50,20,20) <... hier werden die anderen Elemente definiert ...> Let OK% = 0 WhileNot Ok% WaitInput If @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 ElseIf <...> <... andere Abfragen und Aktionen ...> EndIf EndWhile 'Dialogfenster (incl. Button) entfernen @DestroyWindow(hD%) ENDPROC Die eckigen Klammern <...> stellen Platzhalter für Ihre Erweiterungen dar. Wie auch bei Menüs kann mit einem & der Hotkey, der unterstrichene Buchstabe markiert werden. Dieses Fensterobjekt kann dann mit ALT und diesem Buchstaben angewählt werden. Seite 96 RGH-PROFAN² In unserem Beispielprogramm gehört das Dialogfenster zum PROFAN-Hauptfenster (%HWnd) und sein Handle wird in hD% gespeichert. Die Fensterobjekte des Dialoges gehören zum Dialogfenster (hd%). Im Beispiel wird ein Button mit der Aufschrift "OK" erzeugt und sein Handle in hB% gespeichert. Anschließend folgt die in PROFAN übliche WHILE-Schleife mit dem WAITINPUT. WAITINPUT wartet auf ein Ereignis. Ein solches Ereignis ist z.B. das Anklicken eines Fensterobjektes oder das <Enter> in einem Eingabefeld oder Drücken eines über TAB angewählten Buttons mit SPACE ... Im Beispiel wird dann, wenn das Ereignis den "OK"-Button betrifft, die Variable OK% auf 1 gesetzt und damit die WHILE-Schleife verlassen. Vor Verlassen der Dialog-Prozedur wird das Dialogfenster entfernt und mit ihm auch der OK-Button, da dieser ja in der Fensterhierarchie ein dem Dialogfenster untergeordnetes Fenster war. (Man spricht hier auch von "Eltern- " und "Kindfenster", bzw. "Parentwindow" und "Childwindow".) Einzelne Dialogelemente (und Fenster) können mit ENABLEWINDOW deaktiviert (gesperrt) und wieder aktiviert werden. Ihre Position und Größe kann nachträglich mit dem Befehl SETWINDOWPOS verändert werden. Normalerweise wird in Dialogfenstern die in der Systemsteuerung eingestellte Systemschrift verwandt. Es gibt jedoch auch die Möglichkeit, die ganze Vielfalt der Schriften von Windows zu nutzen ... mit einer Einschränkung: Außer der Systemschrift ist nur eine weitere Schrift in einem Dialogfenster möglich. Um die Schrift einzustellen, muß diese wie gewohnt mit USEFONT eingestellt werden. Mit der Befehl SETDIALOGFONT 1 weisen Sie PROFAN² an, für die nachfolgenden @CREATE-Funktionen den eingestellten Font zu benutzen. Um wieder die Systemschrift zu verwenden geben Sie als Parameter bei SETDIALOGFONT den Wert 0 an. Um die Schrift eines Dialogelementes nach dem Erzeugen zu ändern, kann mit @SENDMESSAGE die Message wm_SetFont an das Element gesandt werden. HINWEIS: Es ist natürlich auch möglich, die einzelnen Dialogelemente direkt auf das Hauptfenster eines PROFAN²-Programmes (%HWnd) anzubringen. Da dieses Fenster aber intern nicht den Stil eines Dialogfensters hat, reagieren manche Dialogelemente etwas anders, als in einem Dialogfenster. So funktioniert z.B. das Wechseln von einem Element zum nächsten mit <TAB> nicht. Auch das Anwählen eines Buttons oder anderen Steuerelementes über ALT und dem unterstrichenen Buchstaben funktioniert nicht. Das Drücken eines Knopfes löst zwei Ereignisse aus: beim Drücken und beim Loslassen. (Im normalen Dialog-Fenster wird nur ein Ereignis beim Loslassen erzeugt.) Seit Version 5.0 ist es jedoch möglich, auch dem Hauptfenster mit WINDOWSTYLE den Stil eines Dialogfensters zuzuweisen. Dann reagiert es nahezu genau wie ein Dialogfenster. Beachten Sie bitte, daß damit auch Einschränkungen verbunden sind, da ein Dialogfenster kaum auf Tastaturereignisse reagiert, die über die oben erwähnten Hotkeys bzw. F1 hinausgehen. TIP: Um herauszubekommen, welche Aktion nun welches Ereignis auslöst und wie sich das in den entsprechenden Systemvariablen niederschlägt, füge ich in der Testphase folgende Zeile hinter dem WAITINPUT des entsprechenden Fensters/Dialoges ein: PRINT %MenuItem,%Key,%ScanKey,%GetFocus,%MoseKey,%MouseX,%MouseY So erhalte ich einen Überblick, was durch was ausgelöst wird und kann mein Programm entsprechend darauf abstellen. Seite 97 RGH-PROFAN² 24.2 Buttons, Checkboxen und Radiobuttons Diese drei Typen von Dialogelementen sind hier zusammen aufgeführt, weil sie einer Klasse von Dialogelementen angehören: Sie werden mit denselben Befehlen und Funktionen behandelt und verstehen dieselben Messages! Da gibt es zunächst den ganz normalen Button (neudeutsch für 'Druck-Knopf'). Wenn er gedrückt und losgelassen wird löst er ein Ereignis aus. Mit %GETFOCUS kann ermittelt werden, welches Dialogelement das Ereignis auslöste. Der Button hat einen Text, der mit SETTEXT auch noch nachträglich geändert werden kann. Wenn ein Buchstabe des Textes ein vorangestelltes & hat, wird er auf dem Button unterstrichen dargestellt und der Button kann im Dialog bzw. Dialogfenster mit ALT und dem Buchstaben angewählt werden. @GETTEXT$ ermittelt den Text eines Buttons. Eine Sonderform des Buttons ist der Default-Button, d.h. der standardmäßig aktivierte Button. Eine CheckBox ist ein kleines Kästchen, das angekreuzt sein kann oder auch nicht. Nach dem Erzeugen ist es zunächst nicht angekreuzt. Mit dem Befehl SETCHECK kann der Zustand der Checkbox eingestellt werden und mit der Funktion @GETCHECK kann er vom Programm abgefragt werden. Der Text wird links neben dem Kästchen dargestellt. Ansonsten gilt für ihn das gleiche, wie für den Text eines Buttons. Ein RadioButton ist ein rundes Kästchen. Mehrere Radiobuttons sind in der Regel in einer Gruppe zusammengefaßt und es kann immer nur einer markiert sein. Auch hier wird der Zustand mit SETCHECK eingestellt und mit @GETCHECK ausgelesen. Sollen mehrere Gruppen von Radiobuttons in einem Dialogfenster Verwendung finden, sind sie mit CREATEGROUPBOX zu gruppieren. Der Text eines Radiobuttons wird rechts neben dem Knopf dargestellt Neben den allgemeinen Messages wm_SetText und wm_SetFont sind im Zusammenhang mit Buttons und Checkboxen die Button-Messages interessant. So kann zum Beispiel mit bm_GetState herausbekommen werden, ob ein Button gerade gedrückt ist oder nicht. Die Messages werden mit @SendMessage an das betreffende Steuerelement gesandt. TIP: Wenn PROFAN² auch (noch) keine Buttons mit Bitmaps unterstützt, so können doch Buttons mit Symbolen unter Verwendung der Schrift "WingDings" erzeugt werden. Diese enthält nahezu alle gebräuchlichen Symbole. Vor dem entsprechenden USEFONT ist mit CHARSET 2 der Symbolzeichensatz einzustellen: <...> CharSet 2 'Zeichensatz wählen UseFont "WingDings",16,0,0,0,0 'Schrift wählen SetDialogFont 1 'Font für Dialog nutzen CreateButton(%Hwnd,"0",10,10,16,16) <...> Seite 98 RGH-PROFAN² 24.3 GroupBoxen, Texte und Icons Die hier beschriebenen drei Dialogemelemente gehören einer Klasse an, da sie eines gemeinsam haben: Sie sind statisch! Sie werden einmal erzeugt und bleiben dann unverändert. Lediglich der Text läßt sich mit @SETTEXT verändern. Beim Anklicken aber passiert gar nichts, das Element bleibt unverändert. Es wird zwar ein Ereignis erzeugt, nämlich der Mausklick, aber nichts weiter. Keine Systemvariable weiß, ob ein statisches Objekt angeklickt wurde. Genausogut hätte man auf den Dialoghintergrund klicken können. Lediglich aufgrund der Mausposition beim Anklicken kann das Programm feststellen, daß auf eine bestimmte Stelle geklickt wurde. Ein wichtiges Element im Zusammenhang mit den RadioButtons ist die GroupBox. Sie stellt einen rechteckigen Rahmen dar, der auch links oben einen Text enthalten kann. Wird in einem Dialog mir RadioButtons keine GroupBox verwandt, gehören alle RadioButtons des Dialoges einer Gruppe an. Wird einer angeschaltet (markiert), gehen alle anderen aus. Will man mehrere Gruppen von Radiobuttons bilden, muß man erst die erste Groupbox mit @CREATEGROUPBOX erzeugen, dann die entsprechen Radiobuttons mit @CREATERADIOBUTTON, dann die zweite Groupbox und ihre Radionbuttons und so weiter. Natürlich kann man Groupboxen auch ohne Radiobuttons zur Verschönerung des Dialoges verwenden. TIP: Wenn man keinen Text für die Groupbox angibt, erhält man ein schlichtes Rechteck. Linien lassen sich erzeugen, indem man als Ausdehnung der GroupBox in einer Richtung 0 angibt. Ein weiteres Dialogelement sind Icons. Alle in PROFAN² vorhandenen Icons können mit @CREATEICON in einem Dialog plaziert werden. Im Gegensatz zu allen anderen Dialogelementen kann für ein Icon keine Größe festgelegt werden, da sie vom System festgelegt ist. Ein Textfeld dient lediglich zur Anzeige von Text. Sollte es notwendig werden, kann der Text mit SETTEXT geändert und mit @GETTEXT gelesen werden. 24.4 Editierfelder Es gibt zwei unterschiedliche Eingabefelder: Einzeilige und mehrzeilige EditBoxen. Ein einzeilge EditBox kann bis zu 255 Zeichen Text enthalten. Die Funktion @CreateEdit gibt ein Handle auf das Eingabefeld zurück. Über dieses kann mit @GETTEXT das Eingegebene ausgelesen werden. Mit SETTEXT ist es möglich den Text im Eingabefeld per Programm zu bestimmen. Durch Eingabe einer negativen vertikalen Ausdehnung wird die Paßwortfunktion aktiviert: Eingegebene Zeichen werden als Sterne dargestellt. Die Paßwortfunktion gibt es nur bei einzeiligen Editierfeldern. Für längere Texte empfielt sich ein mehrzeiliges Editierfeld. Solange auch hier der Text nicht über 255 Zeichen lang ist, kann er mit SETTEXT zugewiesen und mit der Funktion @GETTEXT$ ermittelt werden. Für längere Texte ist hingegen die Funktion @MOVELISTTOEDIT zu verwenden oder mit der Message wm_SetText der Inhalt einer Bereichsvariablen an das Editierfeld zu senden. Eine Textdatei kann mit ReadText in eine Bereichsvariable eingelesen werden. Hierzu ein kleines Beispiel: DECLARE Edit%,Bereich# LET Edit% = @CreateMultiEdit(%HWnd,"",10,10,200,200) DIM Bereich#,@Add(@FileSize("C:\PROFAN40\LIESMICH.TXT"),2) ReadText Bereich#,"C:\PROFAN40\LIESMICH.TXT" @SendMessage(Edit%,$000C,0,Bereich#) WaitInput End Seite 99 RGH-PROFAN² Wird die vertikale Ausdehnung als negativer Wert angegeben, so wird zwar trotzdem der absolute Wert als Größe genommen, aber gleichzeitig die automatische WortumbruchFunktion aktiviert: Der horizontale Scrollbalken wird nicht angezeigt und ein Wort, das nicht mehr in eine Zeile paßt wird automatisch in die nächste Zeile gebracht. Mit der Funktion @GETLINE$ kann der Text eines mehrzeiligen Editierfeldes ausgelesen werden, wobei die Anzahl der Zeilen mittels @GETLINECOUNT ermittelt wird. Neben den allgemeinen Messages wm_SetText und wm_SetFont sind im Zusammenhang mit Editierfeldern die Edit-Messages interessant. Die Messages werden mit @SendMessage an das betreffende Editierfeld gesandt. ACHTUNG: Die Funktionen @MOVELISTTOEDIT, @GETLINE$ und @GETLINECOUNT sind nur auf Editierfelder anzuwenden! Werden Sie auf andere Steuerelemente angewandt liefern sie unerwartete Ergebnisse und können in einigen Fällen auch Windows oder die Anwendung zum Absturz bringen! 24.5 ListBoxen Auch die ListBox gibt es in zwei Varianten: Unsortiert und sortiert. In der unsortierten ListBox werden die Einträge in der "Reihenfolge des Eingangs" angezeigt, während sie in der sortierten ListBox alphabetisch sortiert werden. Die Einträge in der ListBox können mit zahlreichen Funktionen manipuliert werden: Mit @ADDSTRING und @INSERTSTRING werden der ListBox Einträge hinzugefügt. Mit @DELETESTRING können Einträge wieder entfernt werden. Die Anzahl der Einträge in einer Listbox wird mit @GETCOUNT ermittelt. Um herauszubekommen, welcher Eintrag markiert (ausgewählt) ist, muß die Funktion @GETCURSEL verwandt werden, welche den Index des gewählten Eintrages zurückgibt. Den zu einem Index gehörenden String ermittelt die Funktion @GETSTRING$. Mit @SELECTSTRING kann ein bestimmter Eintrag in der ListBox gesucht und selektiert werden, d.h. der Markierungsbalken wird auf diesen Eintrag gesetzt. @MOVELISTTOLIST kann verwandt werden, um den Inhalt der ListBoxListe einer ListBox hinzuzufügen. Im Zusammenhang mit ListBoxen sind die ListBox-Messages interessant. So kann zum Beispiel mit lb_Dir eine Verzeichnis-/Laufwerksliste erzeugt werden oder mit lb_ResetContent der Inhalt einer ListBox gelöscht werden. Mit lb_SetHorizontalExtend erhält die Listbox auch horizontale Scrollbalken. Die Messages werden mit @SendMessage an die betreffende ListBox gesandt. ACHTUNG: Die hier beschriebenen Funktionen sind nur auf ListBoxen anzuwenden! Werden Sie auf andere Steuerelemente (z.B. AuswahlBoxen) angewandt liefern sie unerwartete Ergebnisse und können in einigen Fällen auch Windows oder die Anwendung zum Absturz bringen! Der Befehl SETTEXT ist keinesfalls auf eine ListBox anzuwenden! Seite 100 RGH-PROFAN² 24.6 AuswahlBoxen Eine Auswahlbox ist eine Sonderform der sogenannten "Combobox": Durch Anklicken des Pfeiles nach unten kann aus einer Liste von Auswahlmöglichkeiten eine Zeile ausgewählt werden. Eine Eingabe von Zeilen ist nicht möglich. Eine Auswahlbox ist in PROFAN² immer alphabetisch sortiert. Mit der Funktion @ADDCHOICE kann der Auswahlbox ein Eintrag hinzugefügt werden. Mit @MOVELISTTOCHOICE wird die komplette ListBox-Liste, die z.B. zuvor mit ADDFONTS, ADDFILES oder ADDWINDOWS gefüllt wurde, der Auswahlbox hinzugefügt. Mit @DELETECHOICE kann ein Eintrag aus der Auswahlbox entfernt werden. Die ausgewählte Zeile kann mit der Funktion @GETTEXT$ ermittelt werden. Im Zusammenhang mit AuswahlBoxen sind die AuswahlBox-Messages interessant. So kann zum Beispiel mit cb_Dir eine Verzeichnis-/Laufwerksliste erzeugt werden oder mit cb_ResetContent der Inhalt einer AuswahlBox gelöscht werden. Mit cb_SetCurSel kann ein bestimmter Eintrag vorausgewählt werden. Die Messages werden mit @SendMessage an die betreffende ListBox gesandt. ACHTUNG: Die hier beschriebenen Funktionen sind nur auf AuswahlBoxen anzuwenden! Werden Sie auf andere Steuerelemente (z.B. ListBoxen) angewandt liefern sie unerwartete Ergebnisse und können in einigen Fällen auch Windows oder die Anwendung zum Absturz bringen! Der Befehl SETTEXT ist keinesfalls auf eine AuswahlBox anzuwenden! 24.7 ScrollBalken Ein Scrollbalken ist ein vertikaler oder horizontaler Schieberegler, mit dem Werte eingestellt werden können. Er läßt sich auch sehr gut für eine Fortschrittsanzeige verwenden. Beliebt ist der vertikale (senkrechte) Scrollbalken auch zur tastaturlosen Eingabe von Zahlenwerten. Durch Anklicken der äußeren Schaltfelder kann der Regler um eins erhöht bzw. erniedrigt werden. Der Regler kann mit der gedrückten Maustaste auch direkt positioniert werden. Anlicken des Scrollbalkens zwischen Regler und äußeren Schaltflächen erhöht oder erniedrigt den Wert um ein Zehntel des Bereiches. Standardmäßg hat ein Scrollbalken einen Bereich von 0 bis 100. Mit dem Befehl SetScrollRange kann der Bereich aber beliebig eingestellt werden. Wichtig ist, daß Anfangsund Endwert nicht mehr als 32767 auseinanderliegen. Mit SetScrollPos kann ein beliebiger Wert eingestellt werden. Mit der Funktion @GetScrollPos kann der aktuelle Wert ausgelesen werden. ACHTUNG: Die hier beschriebenen Funktionen sind nur auf Scrollbalken anzuwenden! Werden Sie auf andere Steuerelemente angewandt liefern sie unerwartete Ergebnisse und können in einigen Fällen auch Windows oder die Anwendung zum Absturz bringen! Der Befehl SETTEXT ist keinesfalls auf einen Scrollbalken anzuwenden! 24.8 Beliebige Dialogelemente Es gibt externe DLLs die eigene Dialogelemente enthalten und auch in Windows gibt es Dialogelemente die PROFAN² noch nicht unterstützt. Um diese zu verwenden wurde die Funktion @CONTROL geschaffen, die ein beliebiges Dialogelement anzeigen kann, dessen Klassenname registriert und bekannt ist. DLLs, die neue Dialogelemente beinhalten, enthalten in der Regel auch Routinen, um diese innerhalb von Wondws zu initialisieren und registrieren. Beispiel: DEF GridInit(1) *"GRIDDY.DLL","GridInit","%","%" ... Seite 101 RGH-PROFAN² Let hGridDLL% = @UseDLL("GRIDDY.DLL") Let hGrid% = @GridInit(%Hinstance) Let Style& = $50810000 Let hGridControl% = \ @Control("griddy","x",Style&,15,15,150,150,\ %Hwnd,100,%Hinstance) ... FreeDLL(hGridDLL%) In diesem Beispiel wird GRIDDY.DLL, eine von GFA-BASIC her bekannte DLL zum Anzeigen eines Tabellen-Controls, verwandt. Auch die bereits in PROFAN bekannten Dialogelemente lassen sich mit @CONTROL anzeigen und dabei Stile verwenden, die PROFAN² direkt nicht unterstützt. Folgendes Beispiel zeigt den Einsatz von @Control in definierten Funktionen, um Text mittig oder rechtsbündig anzuzeigen: ' Beispiel, das zeigt, wie mittels der @Control-Funktion ' Text zentriert und rechtsbündig angezeigt werden kann! ' Definieren der Funktionen (macht die Sache einfacher) DEF @CreateTextM(6) \ @control("STATIC",@$(2),$50000001,@%(3),@%(4), \ @%(5),@%(6),@%(1),100, %HInstance) DEF @CreateTextR(6) \ @control("STATIC",@$(2),$50000002,@%(3),@%(4), \ @%(5),@%(6),@%(1),101, %HInstance) ' Das Programm declare textr%, textm%, textl% cls let textl% = @CreateText (%Hwnd,"Bitte eine",0,20,630,20) let textm% = @CreateTextM(%Hwnd,"Taste", 0,40,630,20) let textr% = @CreateTextR(%Hwnd,"drücken!", 0,60,630,20) waitinput settext textl%,"Links" settext textm%,"Mitte" settext textr%,"Rechts" waitinput end Sehr interessant ist auch die Verwendung der PROFAN²-eigenen Fensterklassen mit der @CONTROL-Funktion, weil man dann zwar die Fenster mit beliebigen Stilkonstanten versehen kann, aber dennoch die Fensterprozeduren von PROFAN² greifen. Damit können in diesen Fenstern dann Tastatur-, Maus-, Menü- und sonstige Anfragen wie gewohnt behandelt werden. Die Fensterklasse des Hauptfensters in PROFAN² ist "FENSTER", die des mit @CreateWindow geöffneten Fensters ist "DIALOG". Seite 102 RGH-PROFAN² 25 - Kommunikation mit anderen Fenstern - Messages - DDE Das PROFAN²-Hauptfenster ist ja nicht das einzigste Windowsprogramm im System. PROFAN² bietet zahlreiche Zugriffsmöglichkeiten auf und Kommunikationsmöglichkeiten mit anderen Fenstern. 25.1 Einfacher Zugriff über das Handle Durch den Zugriff auf Fenster über ihr Handle kann ich auch auf andere Windowsanwendungen Einfluß ausüben. Über die Funktionen @FINDWINDOW und @GETACTIVEWINDOW kann ich das Handle anderer Fenster herausbekommen. Das Hintergrundfenster von Windows hat das Handle %DESKTOP. ACHTUNG: Bei 32-Bit-Programmen ist es durchaus denkbar, daß mit @GETACTIVEWINDOW ein aktives Fenster außerhalb der aktuellen Anwendung nicht ermittelt werden kann, da die Anwendungen hier untereinander deutlich mehr abgeschottet sind. Hier führt möglicherweise @FINDWINDOW zum Ziel! Im Zweifelsfall gilt hier wie überall auch: Ausprobieren! Wenn ich das Handle habe, könnte ich sogar einem fremden Fenster eine Dialogbox zuordnen oder Messages schicken ... aber das ist jetzt wirklich was für fortgeschrittene Programmierer. Ein kleines Beispiel, in dem der Windows-Editor geladen und zu einem Icon verkleinert wird: <...> Shell "NOTEPAD.EXE" 'Hierdurch wird der Editor aufgerufen 'und zum aktiven Fenster Let hE% = @GetActiveWindow() 'Das Handle des Editors wird gespeichert @ShowWindow(hE%,6) 'Der Editor wird zum Icon @SetActiveWindow(%HWnd) '... und das PROFAN-Fenster wieder aktiviert <...> Es gibt noch ein weiteres Handle: Wenn ich ein Programm nicht mit SHELL, sondern mit der Funktion @WINEXEC aufrufe, ist der Rückgabewert das Instanzhandle des Programmes (oder wenn er kleiner als 32 ist, eine Fehlernummer): 0235810 11 12 14 15 16 19 20 21 - Zuwenig freier Speicher oder die ausführbare Datei war beschädigt Datei nicht gefunden. Pfad nicht gefunden. Es gab einen Fehler beim gemeinsamen Zugriff bzw. einen Zugriffsfehler im Netzwerk. Ungenügender Speicher, um die Anwendung zu starten. Falsche Windows-Version. Ungültige .EXE-Datei (Keine Windows-.EXE-Datei oder Fehler im .EXEDarstellungsformat). Anwendung wurde für anderes Betriebssystem entworfen. Unbekannter .EXE-Dateityp. Versuch, im Protected Mode (Standardmodus oder erweiterter 386-Modus) eine für frühere Windows-Versionen erstellte .EXE-Datei zu laden Es wurde versucht, eine zweite Instanz einer ausführbaren Datei zu laden, die mehrfache (nicht Read-Only markierte) Datensegmente enthält. Es wurde versucht, eine komprimierte ausführbare Datei zu laden. Die Datei muß dekomprimiert werden, bevor sie geladen werden kann. Eine der DLLs, die zum Start dieser Anwendung notwendig ist, war fehlerhaft. Die Anwendung benötigt 32-Bit-Erweiterungen (WIN32S). Seite 103 RGH-PROFAN² Mit der Funktion @GETUSAGE habe ich dann die Möglichkeit, zu prüfen, ob das Programm noch läuft. So kann ich z.B. sicher gehen, daß eine Aktion erst dann ausgeführt wird, wenn ein externes Programm abgeschlossen ist. Beispiel: <...> Let hN% = @WinExec("NOTEPAD.EXE",1) 'Aufrufen und in Normalgröße zeigen If @LT(hN%,32) 'Fehler? MessageBox("Editor konnte nicht gestartet werden", \ "FEHLER:",0) Else While @GetUsage(hN%) 'Solange das Programm läuft ... Wend '... gehts nicht weiter EndIf <...> 25.2 Tastatureingaben simulieren Ebenso ist es möglich, an ein fremdes Fenster mit @SENDKEY simulierte Tastatureingaben zu schicken. Mit @SENDSTRING kann man einen kompletten Text an ein anderes Fenster übermitteln. Dabei wird weitgehend die gleiche Syntax wie z.B. in Visual Basic verwandt (siehe in der Referenz). Nur 16 Bit: Hier ist jedoch zu beachten, daß die Zeichen, die nur mit [AltGr] erreicht werden können, nicht gesandt werden. Häufig kann man dies jedoch mit einem Trick umgehen: Man kopiert einen String, der diese Zeichen enthält (z.B. @ \ [ ]), in die Zwischenablage und sendet dann an das Zielfenster die Botschaft wm_Paste, um die Zwischenablage einzufügen. Ein ausführliches Beispiel hierfür ist für die 16-Bit-Version WRITE.PRF im BeispielVerzeichnis. ACHTUNG: Beim Senden von Tastatureingaben können die Ergebnisse bei der 16- und 32Bit-Version von PROFAN² unterschiedlich sein, insbesondere, wenn ein 32-Bit-Programm Tastatureingaben an ein 16-Bit-Programm schickt bzw. umgekehrt. 25.3 Messages versenden Beim Versenden von Messages an andere Fenster sollte man genau wissen, was man tut, da es hier möglich ist Windows zum Absturz zu bringen. Hier nur ein kleines Beispiel, mit dem man ein fremdes Fenster schließen kann: <...> @SendMessage(hE%,$0010,0,0) 'Das Fenster mit dem Handle hE% wird geschlossen. <...> Die Benutzung der Funktion @SendMessage ist nur erfahrenen Programmierern anzuraten. Wie ehedem mit PEEK und POKE kann man zwar sehr viel erreichen, aber ein kleiner Irrtum oder Fehler kann leicht den Rechner zum Absturz bringen! ACHTUNG: Einige Messages nutzen in der 32-Bit-Version die Parameter anders als die 16-Bit-Version. Erfahrende Programmierer werden sich in der entsprechenden Fachliteratur informieren. Seite 104 RGH-PROFAN² Um in Erfahrung zu bringen, welche Message was bewirkt, hilft das Studium der entsprechenden Literatur für Windowsprogrammierer. Da dort häufig nur die von Microsoft geprägten Namen der Messages genannt werden, gibt es im Anhang eine Liste, die eine Zuordnung der Namen zu ihrem Wert erlaubt. Dort finden Sie z.B. die Zuordnung "wm_Close = $0010". Für einige für den PROFAN²-Programmierer interessanten Messages - besonders im Bereich der selbstdefinierten Dialoge - finden Sie dort auch weitergehende Hinweise. WICHTIG: Messages, die Zeiger auf Strings und/oder Datenbereiche nutzen oder zurückliefern, sind mit besonderer Vorsicht zu verwenden, da bei fehlerhafter Dimensionierung oder Bestückung des Bereiches Windows zum Absturz gebracht werden kann! (Allgemeine Schutzverletzung ...) 25.4 Fernsteuerung per DDE DDE steht für dynamischer Datenaustausch. Mittels DDE können Programme miteinander kommunizieren. Durch OLE hat DDE für den Datenaustausch von Programmen untereinander mittlerweile etwas an Bedeutung verloren, aber wenn es darum geht, andere Programme "fernzusteuern", hat DDE nach wie vor seine Berechtigung. Das meist gebrauchte Beispiel hierfür ist das Anlegen von Programmgruppen und Icons in denselben. Nahezu alle Windows-Oberflächen reragieren auf die DDE-Befehle für den Programm-Manager, so auch der Explorer von Windows 95. Natürlich muß man wissen, welche Themen und welche Befehle die fernzusteuernde Anwendung versteht und auf welchen Namen sie anspricht. Diese Hinweise findet man - wenn überhaupt - in der Dokumentation der Anwendung. Mit DDELINK stellt PROFAN² die Verbindung zum fremden Programm her, mit DDEEXECUTE werden die Befehle übermittelt und mit DDETERMINATE wird anschließend die Verbindung beendet. In der Systemvariablen %DDEWIN steht das Handle einer laufenden DDE-Verbindung bzw. 0, wenn keine aktiv ist. Für den Programm-Manager sind diese Dinge in dem ausführlich dokumentierten Beispiel DDE-TEST.PRF dokumentiert. Begriffserklärung: Handle In der Referenz ist oftmals vom Handle eines Fensters, eines Fensterobjektes die Rede. "Handle" ist englisch und heißt übersetzt "Griff". Ein Handle ist also ein Griff, mit dem ich Zugriff auf ein Objekt bekomme. Wenn ein Fenster oder Fensterobjekt unter Windows erzeugt wird, weist Windows diesem eine interne Verwaltungsnummer, eben dieses Handle zu. Dieser Wert ist ein 16-Bit-Wert (0 ... 65355). Der Wert als solcher ist völlig uninteressant, wichtig ist nur, daß er während des Programmlaufs unverändert bleibt und eindeutig das entsprechende Objekt bezeichnet. Alle @Create-Funktionen, die ein Fensterobjekt oder Fenster erzeugen, haben als Ergebnis das entsprechende Handle. Fensterobjekte sind z.B. Eingabefelder, Schaltflächen, Auswahlfelder, etc. Das Handle des Hauptfensters eines PROFAN-Programmes ist in der Systemvariablen %HWnd abgelegt, das Handle des Hintergrundfensters ist in %DeskTop Eine zweite Sorte ist das Instanzhandle. Mit diesem erhalte ich Zugriff auf die Instanz eines Programmes oder einer DLL unabhängig davon, ob es ein Fenster erzeugt oder nicht. Über dieses Instanzhandle erhalte ich Zugriff auf die Resourcen eines Programmes/einer DLL und kann ermitteln, ob dieses Programm noch läuft. Die Funktionen @WINEXEC und @USEDLL haben als Eregebnis das jeweile Instanzhandle. Seite 105 RGH-PROFAN² Begriffserklärung: Hierarchie der Fenster/Fensterobjekte Jedes Fenster/Fensterobjekt gehört immer zu einem übergeordnetem Fenster und wird automatisch geschlossen, wenn das übergeordnete Fenster geschlossen wird. Selbst das Hauptfenster von PROFAN² hat ein übergeordnetes Fenster, nämlich das Hintergrundfenster von Windows. Wenn Windows geschlossen wird, werden alle anderen Fenster geschlossen. Wenn man nun ein Fenster erzeugt, muß man ihm sagen, zu welchem übergeordnetem Fenster es gehört. In PROFAN² ist dies bei allen @CREATE-Funktionen der erste Parameter. Seite 106 RGH-PROFAN² 26 - Menüs und Mäuse Windows ist ein ereignisgesteuertes System. Bedeutende Ereignisse werden durch Menüs und PopUp-Menüs ausgelöst. 26.1 - Fenster-Menüs PROFAN² kennt zwei Sorten Menüs. Da ist zunächst das ganz normale Anwendungsmenü, das Fenster-Menü. Jedes PROFAN²-Programm läßt sich mit einem eigenen Menü ausstatten. Ein Fenster-Menü besteht aus mehreren Menüpunkten in der Menüzeile. In der Regel öffnen sich beim Anwählen dieser Menüpunkte PopUp-Menüs mit weiteren Punkten. Mit dem POPUP-Befehl wird der Menüzeile ein weiterer Menüpunkt hinzugefügt und mit APPENDMENU werden die einzelnen Punkte dieses PopUp-Menüs angehängt. Um einen Buchstaben unterstrichen darzustellen, damit man auch die Tastatur benutzen kann, setzt man das "&" davor. Die Zahl bei AppendMenü ist die Nummer dieses Menüpunktes. Über diese Nummer kann festgestellt werden, welcher Menüpunkt gewählt wurde. Werte zwischen 100 und 32766 (mit Ausnahme von 255) sind erlaubt. Mit dem Befehl SEPARATOR kann auch eine Trennlinie zwischen Menüpunkten eingeführt werden. Mit SUBPOPUP wird anstelle eines Menüpunktes ein weiteres Untermenü angehängt, das mit ENDSUB endet. Die maximale Verschachtelungstiefe von Menüs ist 10. Mit @MENUITEM wird abgefragt, ob der entsprechende Menüpunkt angewählt wurde. Der gewählte Menüpunkt ist auch in der Systemvariablen %MENUITEM gespeichert. Probieren Sie folgendes Beispiel aus, und Ihnen wird klar, was ich so umständlich zu erklären suche: Declare Ende% PopUp "&Datei" AppendMenu 101,"&Laden" AppendMenu 102,"&Speichern" AppendMenu 103,"Speichern &als" Separator AppendMenu 109,"&Ende" PopUp "&Bearbeiten" AppendMenu 111,"&Ausschneiden" AppendMenu 112,"&Kopieren" SubPopUp "&Schrift" AppendMenu 113,"&Arial" AppendMenu 114,"&Courier" EndSub PopUp "&Suchen" AppendMenu 121,"&Ersetzen" AppendMenu 122,"&Suchen" AppendMenuBar 130,"&Info" PROC Info @MessageBox("Testprogramm","Info",64) ENDPROC PROC Ueber @MessageBox("Ihr Copyright","Über ...",48) ENDPROC PROC WasAnderes Print "Gewählter Menüpunkt ";%MenuItem ENDPROC Let Ende% = 0 Seite 107 RGH-PROFAN² WhileNot Ende% WaitInput If @MenuItem(109) Let Ende% = 1 ElseIf @MenuItem(130) Info ElseIf @MenuItem(254) Ueber Else WasAnderes EndIf Wend End Dieses Beispiel zeigt, wie die Grundstruktur eines PROFAN²-Programmes mit Menü sein kann. Zwei Besonderheiten: Mit APPENDMENUBAR wird der Menüzeile ein Menüpunkt hinzugefügt, der keine weiteren Menüpunkte hat. Beim Anwählen dieses Punktes wird kein PopUp-Menü geöffnet, sondern sofort eine Aktion ausgeführt. Die zweite Besonderheit ist der Wert 254. Hier handelt es sich um die Anwahl des Copyright-Zeichens, dem vordersten Menüpunkt. Zusätzlich kann man Menüpunkte mit EnableMenu deaktivieren und wieder aktivieren oder auch mittels CheckMenu mit einem Häkchen versehen. Menüpunkte können mit DeleteMenu während des Programmlaufes entfernt werden oder mit InsertMenu ins Menü eingefügt werden. Das ist z.B. unabdingbar, wenn man Programme schreibt, die in der Hauptschleife kein WaitInput haben, aber trotzdem ein Menü besitzen. Nach Aufruf eines Menüpunktes muß dann mit diesem Befehl %MenuItem z.B. auf 0 gesetzt werden. Ein Sonderfall ist das Systemmenü, das immer dann vorhanden ist, wenn das Fenster den entsprechenden Stil hat. Normalerweise werden die Ereignisse, die dieses Menü hervorruft, automatisch von Windows behandelt. Will man aber gezielt auf dieses Menü, insbesondere auf den Befehl "Schließen", reagieren, so kann der Programmierer die Verantwortung übernehmen, indem der WindowsStil 256 zum Einsatz kommt. Solange das Programm nichts entsprechendes vorsieht, bleiben alle Auswahlen des Systemmenüs wirkungslos. Es werden aber folgende Menüpunkte in %MenuItem zurückgeliefert, die auch mit @MenuItem abgefragt werden können: -3808 -4064 -4048 -4000 -3792 Wiederherstellen Verkleinern (zum Symbol) Vergrößern (zum Vollbild) Schließen (Alt-F4) Wechseln zu ... (Taskmanager) Folgende Zeilen würden ins Programm einzubinden sein, damit es wieder "normal" funktioniert: ElseIf @MenuItem(-3808) ShowNormal ElseIf @MenuItem(-4064) ShowMin ElseIf @MenuItem(-4048) ShowMax ElseIf @MenuItem(-4000) End Der Vorteil gegenüber dem von Windows kontrollierten Fenster: Hier könnten wir vor dem END noch Sicherheitsabfragen einbauen, geänderte Dateien abspeichern und dergleichen mehr. Seite 108 RGH-PROFAN² Mit dem Windowsstil 512 können wir einem Hauptfenster den Dialogfensterstil zuweisen. In diesem Fall kann das Schließen des Fensters nur mit %Key = 2 abgefragt werden. Eine Kombination dieses Stils mit 128 oder 256 ist nicht sinnvoll. 26.2 - Unabhängige PopUp-Menüs Die zweite Sorte Menüs sind die unabhängigen PopUp-Menüs. Diese können an jedem Ort erzeugt werden und verschwinden nach Auswahl eines Menüpunktes wieder. Mit CREATEMENU beginnt ein solches Menü. Die Definition des Menüs erfolgt ebenso wie bei den PopUp-Menüs des Fenster-Menüs. Angezeigt wird das Menü mit dem Befehl TRACKMENU, dem als Parameter Koordinaten der oberen linken Ecke des Menüs folgen. Der Befehl TRACKMENU wartet, bis ein Menüpunkt ausgewählt wurde. Häufig werden bei kommerziellen Programmen solche Menüs dort angezeigt, wo die Maus gerade steht. Diese Menüs werden meist mit der rechten Maustaste geöffnet. Hierzu ein kleines Beispiel: Declare Ende% Let Ende% = 0 WhileNot Ende% If @Equ(%MouseKey,2) CreateMenu AppendMenu 101,"&blau" AppendMenu 102,"&rot" AppendMenu 103,"&grün" Separator AppendMenu 109,"&Ende" TrackMenu %MouseX,%MouseY If @MenuItem(109) Let Ende% = 1 Else Print "Ausgewählt:",%MenuItem EndIf EndIf Wend End Seite 109 RGH-PROFAN² 26.3 - Warten auf Ereignisse Im Zusammenhang mit Windows spricht man häufig von "ereignisorientierter Programmierung". Was ist darunter zu verstehen? Bei den meisten Programmen ist es doch so, daß immer nur dann etwas geschieht, wenn ich mit der Maus etwas anklicke oder irgendeine Taste drücke. Ansonsten wartet Windows darauf, daß etwas passiert.Windows wartet, bis ein Ereignis eintritt, um dann auf das Ereignis zu reagieren. Nach der Reaktion auf das Ereignis oder schon während der Reaktion wartet Windows auf das nächste Ereignis. In einem Windowsprogramm bedeutet dies, daß die meisten Routinen aufgrund eines Ereignisses aufgerufen werden. Unser obiges Menüprogramm ist dafür ein Beispiel: Windows wartet (bei WAITINPUT) auf ein Ereignis. Wenn dieses eintritt, wird überprüft, was für ein Ereignis es war und je nach Ereignis wird die entsprechende Routine aufgerufen. In PROFAN² kennen wir mehrere Befehle, um auf Ereignisse zu warten: WAITKEY wartet auf einen Tastendruck. Dabei sind nur die 'normalen' alphanumerischen Tasten gemeint, wobei auch deren Kombinationen mit <Strg> und <Shift> berücksichtigt werden. Auf Sondertasten (Funktionstasten, Kursortasten, etc.) und Mausklick wird nicht reagiert. Außerdem reagiert WAITKEY auch noch auf einige Systemereignisse, denen Codes zugeordnet sind, die es nicht als Tasten gibt. Welches Ereignis (= welche Taste) es war, steht in der Systemvariablen %KEY. Wollen wir zusätzlich auch die erwähnten Sondertasten abfragen, müssen wir WAITSCAN einsetzen. Das Ergebnis finden wir in %SCANKEY für die Sondertasten und in %KEY, falls es eine 'normale' Taste war. Sobald wir aber Buttons, ein Menü oder sonstige Dialogelemente mit im Programm haben, wird man immer auch die Maus mit abfragen wollen. Hier wird WAITINPUT eingesetzt. Er ist der umfassenste der Befehle, die auf ein Ereignis warten: WAITINPUT wartet, bis entweder eine Taste oder ein Button gedrückt wurde, ein Element aus einer Listbox gewählt wurde, ein Mausklick oder eine Menüauswahl erfolgte, in einem Editierfeld <Enter> gedrückt wurde, ... Einige Ereignisse können nur mit WAITINPUT abgefragt werden, wie etwa %wmPaint, %wmTimer oder F1 bei Dialogelementen. Das Ereignis %wmTimer wird dann ausgelöst, wenn der Zeitgeber (Timer) mit SetTimer N& eingestellt wurde, wobei N& den Zeitintervall in Millisekunden angibt. Alle N& Millisekunden wird das Ereignis ausgelöst. Hinweis: Das Timerereignis wird nur ausgelöst, wenn ein Hauptfenster existiert. Tip: Man kann auch unsichtbare Hauptfenster (Windowstyle 112, Größe 0,0-0,0) erzeugen. Ein zweites besonderes Ereignis ist %wmPaint, das je nach Einstellung durch SetAutoPaint ausgelöst wird, wenn das Dialogfenster und/oder das Hauptfenster neuzuzeichnen ist. Nähere Hinweise hieru finden sich im Kapitel über die Spezialitäten von PROFAN². Das Ergebnis von WAITINPUT finden wir demzufolge in &MENUITEM, &KEY, &SCANKEY, &MOUSEKEY, &MOUSEX und &MOUSEY. Wurde ein Dialogelement angeklickt, finden wir dieses in %GETFOCUS. %wmTimer und %wmPaint werden auch entsprechend gesetzt. Seite 110 RGH-PROFAN² Ein typisches Windowsprogramm hat pro Fenster (bzw. Dialog) nur eine Stelle an der das anliegende Ereignis ermittelt wird, gefolgt von Verzweigungen abhängig vom aufgetretenen Ereignis. Das Ganze befindet sich in einer Schleife, die solange durchlaufen wird, bis das Fenster verlassen wird (Programmende oder Beenden des Dialoges mit "OK"). Hier der Ausschnitt einer solchen Fensterroutine: Let Ende% = 0 WhileNot Ende WaitInput If @MenuItem.... ... ElseIf @MenuItem... ... ElseIf @GetFocus... ... ElseIf @KeyIn... ... ... EndWhile End Diese Schleife wird solange durchlaufen, bis die Variable Ende% einen von 0 verschiedenen Wert bekommt, etwa weil der Anwender den OK-Knopf drückt oder den Menüpunkt ENDE auswählt. Für jedes Fenster und jeden selbstdefinierten Dialog gibt es eine solche Schleife, in der das Programm verbleibt, bis das Fenster/der Dialog verlassen wird. Siehe hierzu auch die Grundstruktur eines Windowsprogrammes im Abschnitt FensterMenüs. Hinweis: Auch ohne WAITINPUT oder WAITMOUSE ist die aktuelle Mausposition in %MOUSEX und %MOUSEY vorhanden und die zuletzt gedrückte Maustaste in %MOUSEKEY. Die aktuell gedrückte Maustaste ist in %MOUSEPRESSED. Während %MOUSEKEY beim Auslesen auf 0 zurückgesetzt wird, hat %MouseKey solange den entsprechenden Wert, solange die Maustaste gedrückt wird Das Beispielprogramm für das unabhängige PopUp-Menü macht davon Gebrauch. Daher kommt es ohne einen WAIT-Befehl aus. Das Hauptmodul selbst (zwischen WHILE und ENDWHILE) ist die Warteschleife, die auf ein Ereignis wartet. Wenn auch die Abfrage der Systemvariablen ausreichen würde, um das Ereignis näher zu beschreiben, so gibt es in PROFAN² einige Funktionen, die dies erleichtern. Wollten Sie mit den Systemvaraiblen herausbekommen, ob sich die Maus in einem bestimmten Bereich befindet, ergäbe das eine recht lange verschachtelte Funktion mit mehreren @AND, @LT und @GT. Das erspart uns die Funktion @MOUSE, die zwei Koordinatenpaare als Parameter erwartet und den Wert 0 hat, wenn die Maus außerhalb dieses Rechteches ist: If @Mouse(10,10-60,60) Print "Die Maus ist im Rechteck 10,10 - 60,60 !" Else Print "Daneben!" EndIf Die Abfrage der Systemvariablen %MENUITEM wird durch die Funktion @MENUITEM vereinfacht, die Abfrage von %SCANKEY durch die Funktion @SKANKEY und die Abfrage von %KEY durch die Funktion @KEYIN. Seite 111 RGH-PROFAN² In Anlehnung an BASIC gibt es noch zwei weitere Funktionen, um die Tastatur abzufragen: Das ist einmal die Funktion @INKEY$(), die die augenblicklich gedrückte Taste zurückgibt und die Funktion @GETKEY$(), die auf einen Tastendruck wartet und die Taste als Zeichen zurückgibt. Seite 112 RGH-PROFAN² 27 - Spezialitäten für Fortgeschrittene 27.1 Die Programmierung von Bidschirmschonern Die Programmierung von Bildschirmschonern ist sicher eine sehr interessante Sache. Und ab Version 3.0 ist dies in PROFAN² auch problemlos möglich. Windows erlaubt über die Systemsteuerung die Einbindung von Bildschonern. Von diesen Bildschirmschonern werden bei Windows einige wenige (und reichlich unspektakuläre) mitgeliefert. Diese Bildschirmschonerdateien haben die Endung ".SCR". Tatsächlich aber ähnelt Ihr Aufbau sehr dem Aufbau gewöhnlicher ".EXE"-Dateien. Wer's nicht glaubt: Einfach eine ".SCR"-Datei in eine ".EXE"-Datei umbenennen! Nun kann sie zwar nicht mehr als Bildschirmschoner eingesetzt werden, dafür aber unabhängig gestartet werden. Nun könnte man auf den Gedanken kommen, es reiche aus, eine ".EXE"-Datei in eine ".SCR"-Datei umzubenennen. Das funktioniert aus verschiedenen Gründen leider nicht: Windows 3.x erkennt die Datei so nicht als Bildschirmschoner. Was hier noch fehlt, ist ein Eintrag im "Header" der Programmdatei, der Windows sagt, daß dies ein Bildschirmschoner ist und wie er heißt. Unter Windows 95 würde es prinzipiell gehen, aber hier wird das Programm schon bei der Auswahl mit dem Parameter "/P" aufgerufen und würde dann unvermittelt starten. Für Bildschirmschoner hat die Entwicklungsumgebung von PROFAN² einen eigenen Punkt. Wahlweise kann ein compiliertes PROFAN²-Programm zu einer gewöhnlichen EXE-Datei oder aber zu einem Bildschirmschoner gelinkt (verbunden) werden. Der PROFAN²-Linker trägt das Notwendige in den Header des Programmes ein und gibt ihm die Endung ".SCR". In der 16-Bit-Version wird nun als Name des Bildschirmschoners der Dateiname vorgeschlagen, aber Sie können einen anderen Namen eingeben. Windows 95 nutzt bei 32Bit-Bilschirmschonern grundsätzlich den Dateinamen. (Wenn Sie den Linker unabhängig von der Entwicklungsumgebung aufrufen, geben Sie nach dem Dateinamen den Parameter "/s" an. Beispiel: PROFLINK KREISE.PRC /s). Auf diese Weise könnten Sie selbst aus einem Spiel einen Bildschirmschoner erzeugen. Das würde aber wenig Sinn machen. Ein minimaler Bildschirmschoner sollte den Bildschirm löschen (und zwar schwarz) und bei beliebigem Tastendruck oder Mausbewegung verschwinden. Unter Windows 95 muß zudem noch der Start verhindert werden, wenn das Programm mit dem Kommandozeilenparameter "/P" aufgerufen wird. Damit wird der Bildschirmschoner bei der Auswahl aufgerufen. Normalerweise dient dies dazu, den Vorschau-Bildschirm zu füllen. Diese Funktion wird von PROFAN² noch nicht unterstützt. Das erste Problem ist, den ganzen Bildschirm zu löschen, ohne Titelzeile oder Menü anzuzeigen. Hierfür hat WindowStyle neue Stilelemente bekommen: 16 32 64 128 - Fenster hat zunächst kein Menü (also auch kein ©) - Fenster benutzt Bildschirmhintergrund als Hintergrund - Das Fenster hat keine Titelzeile - Das Programm kann weder mit <Strg-Esc>, <Alt-Tab> noch <Alt-F4> verlassen werden. Seite 113 RGH-PROFAN² Für den Bildschirmschoner benutzen wir all diese Elemente, macht zusammen 240 bzw. $F0. Den Stil 32 nehmen wir deshalb, damit der Bildschirm nicht zunächst weiß gelöscht wird. Das sieht so besser aus. Als nächstes öffnen wir das Fenster des Bildschirmschoners über den gesamten Bildschirm. Die Auflösung des Bildschirmes erfahren wir über die Systemvariblen %MaxX und %MaxY. Auch der CLS-Befehl wurde erweitert: Es ist jetzt möglich die Farbe anzugeben, in der der Bildschirm gelöscht wird. Der Bildschirm soll schwarz werden und deshalb nehmen wir die Farbe 0. Um den Mauszeiger verschwinden zu lassen setzten wir den Befehl SHOWCURSOR ein. WICHTIG: Vor dem Ende des Programmes muß der Mauszeiger wieder eingeschaltet werden ... es sei denn, sie wollen Windows ausschließlich mit der Tastatur bedienen. Als nächstes verharrt das Programm solange in der WHILE-Schleife, bis ein Tastendruck oder eine Mausbewegung erfolgt. Um dies festzustellen benutzen wir die Systemvariable %GETINPUTSTATE. Sie ist ungleich Null, sobald ein Maus- oder Tastaturereignis eintritt. Die Variable TEST% wird heruntergezählt, sobald %GETINPUTSTATE ein solches Ereignis meldet. Hat die Variable den Wert Null erreicht, wird die Schleife beendet, der Mauszeiger wieder eingeschaltet und das Programm beendet. Damit der Bildschirmschoner nicht schon beim Start gleich wieder endet, muß TEST% auf mindestens zwei gesetzt werden. Eine weitere Sache muß noch berücksichtigt werden: Wenn der Screensaver eingeschaltet ist, dann darf er nach der eingestellten Zeit nicht noch einmal eingeschaltet werden. Dieser Aspekt wird leider oft übersehen (und wurde es auch von mir in den bisherigen Versionen). Wenn man das nicht berücksichtigt, wird der Screensaver so oft gestartet, bis der Speicher voll ist und nichts mehr geht. Abgesehen davon, daß es bei so langer Abwesenheit vom Computer sinnvoller ist, wenigstens den stromfressenden Monitor auszuschalten, kann es unter Umständen bei der ersten Mausbewegung dann eine Weile dauern, bis all die Screensaver wieder geschlossen sind. Um dieses zu verhindern, wird beim Start des Screensavers der entsprechende Eintrag in der SYSTEM.INI (Abteilung [boot]) auf "(Kein)" gesetzt. Beim Verlassen des Screensavers wird wieder der usprüngliche Wert eingetragen, der zuvor in einer Textvariablen gesichert wurde. Hier das Listing eines minimalen Bildschirmschoners: Declare Test%,Ini$,P$ If %ParCount Let P$=@Upper$(@Par$(1)) EndIf If @Neq$(P$,"/P") Let Ini$=@ReadIni$("SYSTEM.INI","BOOT","SCRNSAVE.EXE") WriteIni "SYSTEM.INI","BOOT","SCRNSAVE.EXE"="(Kein)" WindowStyle $F0 Window 0,0 - %MaxX,%MaxY Cls 0 ShowCursor 0 Let Test% = 2 While @Gt(Test%,0) Case %GetInputState:Dec Test% Wend WriteIni "SYSTEM.INI","BOOT","SCRNSAVE.EXE"=Ini$ ShowCursor 1 EndIf End Mit %ParCount wird überprüft ob mindestens ein Parameter vorliegt. Dieser wird mit der Funktion @Par$ ermittelt und in Großbuchstaben umgewandelt. Daher erfolgt der Vergleich dann mit Großbuchstaben. Seite 114 RGH-PROFAN² Wenn wir diesen Bildschirmschoner über die Systemsteuerung (Abteilung "Desktop") einbinden, stellen wir fest, daß er auch dann startet, wenn wir nicht den Button "Test" drücken, sondern den Button "Einrichten" oder - unter Windows 95 - ein Paßwort einrichten wollen. In diesen Fällen ruft Windows nämlich den Bildschirmschoner auf, aber bei "Einrichten" wird noch der Kommandozeilenparameter "/c" angehängt und unter Windows 95 bei der Paßwortvergabe der Parameter "/a". Beim normalen Aufruf als Bildschirmschoner ist dieser Parameter ein "/s". In unserem zweiten Beispiel habe ich den Bildschirmschoner dahingehend erweitert, daß im Falle des Einrichtens eine MessageBox aufgerufen wird und nach dieser das Programm beendet wird. Außerdem habe ich den Schoner so erweitert, daß sich ein Icon über den Bildschirm bewegt: Declare X%,Y%,Test%,P$,Ini$ If %ParCount Let P$ = @Upper$(@Par$(1)) EndIf If @Equ$(P$,"/C") @MessageBox("©1994 Roland G. Hülsmann","Icons",64) ElseIf Neq$(P$,"/P") Let Ini$=@ReadIni$("SYSTEM.INI","BOOT","SCRNSAVE.EXE") WriteIni "SYSTEM.INI","BOOT","SCRNSAVE.EXE"="(Kein)" WindowStyle $F0 Window 0,0 - %MaxX,%MaxY Cls 0 ShowCursor 0 Let Test% = 2 Let X% = 0 Let Y% = 0 While @Gt(Test%,0) Case %GetInputState:Dec Test% Rectangle X%,Y% - @Add(X%,32),@Add(Y%,32) Add X%,2 Add Y%,4 Case @Gt(X%,%MaxX):Let X% = 0 Case @Gt(Y%,%MaxY):Let Y% = 0 DrawIcon "GESICHT",X%,Y% Wend WriteIni "SYSTEM.INI","BOOT","SCRNSAVE.EXE"=Ini$ ShowCursor 1 EndIf End Natürlich könnte man jetzt in der 16-Bit-Version anstelle der einfachen Messagebox eine Paßworteingabe einbauen. Dieses Paßwort könnte nun (verschlüsselt) in einer INI-Datei gespeichert werden. Ebenso müßte der Bildschirmschoner dann das Paßwort abfragen, sobald TEST% auf Null heruntergezählt wird. Wird ein falsches eingegeben müßte dann TEST% wieder auf mindestens 2 hochgesetzt werden. Da der Windowstil 128 mit verwandt wird, ist ein Abbruch der Paßwortabfrage über <Alt-F4>, <Strg-Esc> und dergleichen unmöglich. In der 32-Bit-Version würde man sinnvollerweise, die Paßworteingabe ermöglichen, wenn der Bildschirmschoner mit dem Paramer "/a" aufgerufen wird. ... und jetzt liegt es nur noch an Ihrer Phantasie und Kreativität, was Ihr Bildschirmschoner so auf den Bildschirm bringt ... ob mit Musik oder ohne ... ob er Videos abspielt oder wahlweise bunte Graphiken zeigt ... oder ob er gar ein Aquarium simuliert oder Toaster über den Bildschirm fliegen läßt ... Seite 115 RGH-PROFAN² 27.2 Neuzeichen selbst übernehmen Wenn ein Fenster vergrößert und/oder verschoben wird, müssen Teile des Bildschirmes und/oder Fensters neu gezeichnet werden.. Denn wenn es auch so aussieht, als ob der Windowsbildschirm ein dreidimensionales Vor- und Hintereinander kennt, so ist er in der Tat doch nur eine zweidimensionale Bitmap im Speicher, die der Grafikkartentreiber im Speicher der Grafikkarte darstellt und die von dort aus auf Ihren Monitor gebracht wird. Jetzt mag man als neuer Windowsprogrammierer hoffen, daß Windows diese Aufgabe des Neuzeichnens und Aktualisierens übernimmt, aber wer dann mit C, C++ oder Pascal anfängt wird in dieser Hoffnung enttäuscht. Was Windows macht ist folgendes: Es überwacht, ob ein Fenster neugezeichnet werden müßte und sendet dem Fenster bzw. dem dazugehörigen Programm die Aufforderung, sich neu zu zeichnen. Jetzt muß das Programm in der Lage sein, seinen Bildschirminhalt neu zu zeichnen. Im Normalfall nimmt Ihnen PROFAN² diese Arbeit ab. Solange in den Dialogboxen und Dialogfenstern nicht gezeichnet wird (siehe StartPaint EndPaint), benötgt das PROFAN²-Programm keine Kenntnis über diese Aufforderung. Wenn man in Dialogfenstern zeichnet, so übernimmt hier PROFAN² das Neuzeichnen nicht automatisch. Mit SetAutoPaint 1 sorgt man nun dafür, daß die Aufforderung zum Neuzeichnen eines Dialogfensters WaitInput verläßt und die Systemvariable %wmPaint gesetzt wird. Das Hauptfenster wird in diesem Fall weiterhin von PROFAN² automatisch versorgt. Es mag nun aber Fälle geben, wo der fortgeschrittene Programmierer auch dieses selbst in die Hand nehmen möchte, etwa weil er die Größe der Hintergrundbitmap immer an die Größe des Haupfensters angepaßt haben möchte. Dazu kann er mit SetAutoPaint 0 das automatische Aktualisieren des Bildschirmes ausschalten und es selber übernehmen. In diesem Fall wird die WindowsBotschaft wm_Paint, mit der Windows die Anwendung unterrichtet, daß neugezeichnet werden muß, an das Programm weitergereicht, indem ggf. ein WaitInput verlassen wird und die Systemvariable %wmPaint auf 1 gesetzt wird. Die Routine, die beim Auftreten einer wm_Paint-Meldung aufgerufen wird, um das Hauptfenster neu zu zeichnen, sollte in StartPaint %Hwnd - EndPaint eingeschlossen werden. Das ist dann dringend notwendig, wenn in der Routine ein LoadBmp oder LoadSizedBmp vorkommt, da diese Befehle sonst ein weiteres Neuzeichnen (zumindest im 256-Farben-Modus) hervorrufen würden, was in einer unangenehmen Endlosschleife enden würde. Andere Befehle, die ein Neuzeichnen des Bildschirmes nach sich ziehen, sind während des Neuzeichnens desselben tunlichst zu vermeiden, wie etwa RePaint, Window oder Messageboxen und die fertigen Dialoge. Folgendes Beispielprogramm zeigt eine Bitmap immer in der Größe des Programmfensters an und wird mit "Esc" beendet: Declare Ende% PROC MaleNeu StartPaint %Hwnd MCopySizedBmp 0,0-32,32 > 0,0-Width(%HWnd),Height(%HWnd);0 EndPaint ENDPROC CLS MLoadBmp "TEST.BMP" MaleNeu Seite 116 RGH-PROFAN² Let Ende% = 0 WHILENOT Ende% WaitInput IF %wmPaint MaleNeu ENDIF IF @Equ(%Key,27) Let Ende% = 1 ENDIF ENDWHILE END 27.3 Zeichnen in Dialogfenstern Bis einschließlich Version 4.5 war es in PROFAN² nicht möglich, in einem anderen als dem Hauptfenster zu zeichnen, Bitmaps zu laden und mit Drawtext Text zu plazieren. Jetzt ist es möglich, die Bildschirmausgaben auf ein anderes Fenster umzuleiten, dessen Handle bekannt ist. Zu diesem Zweck gibt es das Befehlspaar StartPaint / EndPaint. StartPaint hat als Parameter das Handle des Fensters, auf das die Ausgabe umgeleitet wird. Alle Grafikausgaben, die normalerweise auf das Hauptfenster erfolgen, erfolgen nun in das neue Fenster. Dazu zählt auch UseFont und DrawText. (Von der Umleitung ausgeschlossen sind jene Befehle, die den Textmodus von PROFAN² betreffen, wie etwa LOCATE, PRINT, TBOX, ...) So ist es nun möglich in beliebige Fenster, deren Handle man hat, zu malen, Text auszugeben, Bitmaps zu laden, etc. WICHTIG: Jedem StartPaint muß (!) ein EndPaint folgen. Nach dem EndPaint erfolgen die Ausgaben wieder auf das Hauptfenster (wenn eines existiert). Während der Druckausgabe mit StartPrint - EndPrint ist der Befehl verboten. NOCH WICHTIGER: Beim Zeichnen in DialogBoxen und DialogFenstern ist zu beachten, daß diese Zeichnungen nicht automatisch erneuert werden, wenn die Dialogbox z.B. durch ein anderes Fenster verdeckt wurde. Es ist also auf alle Fälle ratsam, mit SetAutoPaint 1 dafür zu sorgen, daß die Windowsbotschaft zum Neuzeichnen ausgewertet wird und eine Prozedur zum Neuzeichnen des entsprechenden Dialoges oder Fensters veranlaßt wird. Wenn AutoPaint mit SetAutoPaint 0 komplett ausgeschaltet ist, ist es durchaus sinnvoll (aber nicht notwendig) die Ausgaben auf das Hauptfenster auch in StartPaint - EndPaint einzuschließen, wobei dann als Fensterhandle %Hwnd zu nehmen ist. 27.4 Messageverwaltung selbst übernehmen Diese Abschnitte sind in der Regel nur etwas für Fortgeschrittene, die sich schon in den Tiefen der Windows-API auskennen. Dieses Handbuch kann und will keine Referenz der API-Funktionen und Messages für Windows sein. Es gibt ausreichend Faschliteratur, die sich mit diesem Thema beschäftigt. Für gewöhnlich nimmt PROFAN² dem Programmierer viel von der Komplexheit der Windowsprogrammierung ab und versteckt die komplizierteren Mechanismen in seinem Interpreter bzw. Runtime-Modul. Gerade professionelle PROFAN²-Programmierer geraten aber hin und wieder an die dadurch bedingten Grenzen von PROFAN². Schon in den vergangenen Versionen wurden diese Grenzen für den PROFI gelüftet, indem der beliebige Zugriff auf DLLs und Windows-API integriert wurde, die Resourcen genutzt und Messages verschickt werden können. Der fortgeschrittene Programmierer kann selbst das Neuzeichnen von Fenstern übernehmen. Seite 117 RGH-PROFAN² Der nächste Schritt in diese Richtung ist ein erweitertes Messagehandling: Der Befehl GETMESSAGE wartet auf die nächste Message für das PROFAN²-Programm. Sobald diese eintritt, werden die Systemvariablen %MESSAGE (seit 4.5 schon undokumentiert vorhanden), %MWND, &WPARAM und &LPARAM mit den entsprechenden Werten gefüllt. Anschließend wird die Messageverwaltung an Windows zurückgegeben. Das bedeutet, daß Messages, wie etwa Fenster vergrößern, verkleinern, verschieben etc. immer noch von Windows bearbeitet werden. Aber auch diese Messages können nun vom Programm zusätzlich behandelt werden. HINWEIS: Die PROFAN²-Systemvariablen, die für gewöhnlich von den WAIT-Befehlen gesetzt werden (etwa %SCANKEY, %KEY, %MENUITEM, etc.) werden bei GETMESSAGE in der Regel auch gesetzt. Diese Messages kommen unter Umständen erst gar nicht bei GETMESSAGE an. Hier ist im Zweifelsfalle Ausprobieren angesagt. %MESSAGE enthält die Nummer der zuletzt aufgetretenen Message. Eine Liste findet sich im Anhang des Handbuches zu PROFAN². %MWnd enthält das Handle des Fensters, an das die Message gerichtet war. &WPARAM und &LPARAM sind Message-abhängige Parameter, in denen zusätzliche Informationen stehen. Diese sind von Message zu Message verschieden. In der 16-BitVersion enthält &WPARAM nur einen 16-Bit-Wert (WordPARAMeter), &LPARAM hingegen einen 32-Bit-Wert (LongintPARAMeter). Im 32-Bit-Windws sind beide Parameter 32-Bit breit, die Namen wurden aber aus historischen Gründen beibehalten. In PROFAN² sind aus Kompatibilitätsgründen in beiden Versionen beide Systemvariablen als LongintSystemvariablen ausgelegt. (&WPARAM und &LPARAM entsprechen dem dritten und vierten Parameter bei @SENDMESSAGE und @POSTMESSAGE.) Seite 118 RGH-PROFAN² Mit %PEEKMESSAGE ist es möglich, die gerade anliegende Message abzufragen, ohne diese aus der Warteschlange zu entfernen oder zu verarbeiten. Hat die Systemvariable dem Wert 0, lag keine Message an, anderenfalls werden %MESSAGE, %MWND, &WPARAM und &LPARAM entsprechend gefüllt. Ein kleines Programm zum Austesten der Messages: CLS DECLARE %Ende LET Ende% = 0 WHILENOT %Ende GETMESSAGE LOCATE 0,0 PRINT "Meldung: ";%Message;" " PRINT "Fenster: ";%MWnd;" " PRINT "WParam: ";&WParam;" " PRINT "LParam: ",&LParam;" " IF @Equ(%Message,$0204) ' wm_RButtonDown LET %Ende = 1 ENDIF ENDWHILE END Das Programm wird durch Drücken der rechten Maustaste beendet. Es können mit auf diese Weise auch selbstdefinierte Messages behandelt werden. So ist es möglich, daß ein PROFAN-Programm auf Messages reagiert, die ihm ein anderes per @POSTMESSAGE sendet! Um nicht mit den Windowsmessages ins Gehege zu kommen, sollten selbstdefinierte Messages eine Messagenummer größer als $1000 haben! Wenn auch die üblichen WAIT-Befehle nicht auf alle Messages reagieren, so werden doch die Systemvariablen %MESSAGE, %MWND, &WPARAM und &LPARAM immer korrekt gefüllt. Das gilt auch für Schleifen ohne jeden WAIT-Befehl oder GETMESSAGE. 27.5 Zur Verwendung von DLLs Bis Version 5.0 wurde bei mehrfacher Verwendung von @USEDLL nur die zuletzt genutzte DLL im Speicher gehalten. Jeder @USEDLL-Aufruf hatte die zuvor geladene DLL aus dem Speicher entfernt. Das ist nun nicht mehr so. Es können nun beliebig viele DLLs geladen werden. Um sie aus dem Seicher zu entfernen ist der Befehl FREEDLL zu verwenden. @USEDLL und FREEDLL können auch sinnvoll sein, um häufige Aufrufe von DLLFunktionenm zu optimieren. Wenn eine DLL nämlich schon im Speicher ist, wie sie beim Aufruf der externen DLL-Funktion nicht erneut von Platte geladen, sondern die Kopie im Speicher verwandt. Bei externen DLLs, die Initialisierungsaufrufe beinhalten oder wo Eigenschaften von anderen DLL-Funktionen eingestellt werden können, ist es häufig sogar notwendig vor dem ersten Aufruf die DLL mit @USEDLL in den Speicher zu laden, damit die von einem Aufruf gemachten Einstellungen auch bei weiteren Aufrufen verfügbar sind. Wird nämlich mit einer definierten Funktion eine Funktion einer externen DLL aufgerufen, die sich noch nicht im Speicher befindet, wird diese für die Funktion geladen und anschließend wieder entladen. Das kostet zum Einen Zeit und zum Anderen gehen gemachte Einstellungen beim Entladen verloren. Seite 119 RGH-PROFAN² 28 - Kompatibilität zu früheren PROFAN-Versionen PROFAN 4.x / 5.x PROFAN² 6.0 ist 100%ig Quelltext-kompatibel zu PROFAN² 4.x und 5.x. Aus Kompatibilitätsgründen werden auch noch GOTO, GOSUB und Labels unterstützt. Es kann jedoch nicht garantiert werden, daß diese Befehle auch noch in künftigen Versionen vorhanden sind. Beim Upgrade auf die 32-Bit-Version kann es sein, daß die Funktionen, die einen Focus oder Fensterhandle ermitteln, andere Ergebnisse bringen, da die Trennung der Anwendungen untereinander (eigener Adreßraum, Multithreading, etc.) größer ist als unter Windows 3.1. Ebenso werden SENDKEY und SENDSTRING unter Umständen unterschiedlich funktionieren, insbesondere wenn ein 32 Bit Programm versucht, mit einem 16-Bit-Programm zu kommunizieren oder umgekehrt. Ein ausführlicher Test ist in jedem Fall also angesagt. DDE kennt jedoch keine Unterschiede. Die Messagenummern für Dialogelemente sind in der 16- und 32-Bit-Version unterschiedlich. Hier ist die Referenz bzw. einschlägige Fachliteratur zu Rate zu ziehen. Da das Format des Zwischencodes beibehalten wurde, ist eine Neucompilierung nicht notwendig. Das neue 6.0 Runtime-Modul kommt sowohl in der 32- als auch der 16-BitVersion mit den bisherigen PRC-Dateien (ab Version 3.0) klar. PROFAN 3.x PROFAN² 6.0 ist 100%ig Quelltext-kompatibel zu PROFAN² 3.x. Lediglich die Befehle und Funktionen, die aus Kompatibilität zu Version 1.x noch enthalten waren (DIM, LIST, @LIST ohne Datentypkennung) werden nicht mehr unterstützt. Ersetzen Sie diese einfach durch DIM%, LIST% und @LIST%. Da das Format des Zwischencodes beibehalten wurde, ist eine Neucompilierung nicht notwendig. Trotzdem ist es empfehlenswert, alle Programme neu zu compilieren, da in der neuen Version auch einige Bugs auzsgemerzt wurden. PROFAN 2.x PROFAN² 6.0 ist 100%ig Quelltext-kompatibel zu PROFAN² 2.x. Lediglich die Befehle und Funktionen, die aus Kompatibilität zu Version 1.x noch enthalten waren (DIM, LIST, @LIST ohne Datentypkennung) werden nicht mehr unterstützt. Ersetzen Sie diese einfach durch DIM%, LIST% und @LIST%. Das Format des Zwischencodes mußte jedoch (zur Temposteigerung etc.) verändert werden, sodaß es NICHT möglich ist, eine alte compilierte 2.x-PRC-Datei mit der neuen 6.0RUNTIME zu starten. Es reicht jedoch aus, den bisherigen Quelltext neu zu compilieren. Künftige PROFAN-Versionen Künftige PROFAN-Versionen werden - soweit technisch sinnvoll und möglich - 100%ig Quelltext-kompatibel zu PROFAN² 6.0 sein. Solange noch 16-Bit-Versionen nachgefragt werde, werden diese weiterentwickelt. Seite 120 RGH-PROFAN² Programmieren für Anwender P R O F A N ² 6.0 DIE einfache Programmiersprache für Windows 3.x und Windows 95 Teil 2: Programmierkurs Seite 121 RGH-PROFAN² 0 - Vorbemerkung Rufen Sie einfach PROFAN² über den Dateimanager auf und Sie gelangen in die Entwicklungsumgebung. Die Entwicklungsumgebung der 16-Bit-Version ist PROFED.EXE und die der 32-Bit-Version ist PROFED32.EXE. Hier können Sie Programme entwickeln, speichern und starten. Damit PROFAN² auch als Batchsprache seinen vollen Nutzen entwickeln kann, empfiehlt es sich, unter Windows 3.x in der Datei "WIN.INI" im Abschnitt "[Extensions]" folgende Zeile einzutragen: "PRF=C:\PROFAN\PROFAN.EXE ^.PRF", wobei Sie natürlich Ihren Pfad zu PROFAN.EXE eintragen müssen. Jetzt können Sie im Dateimanager PROFAN²-Programme durch Doppelklick starten ohne eigens PROFAN² aufrufen zu müssen. Unter Windows 95 ist die Verknüpfung entsprechend der Anleitung bzw. Hilfe zu Windows 95 zu erstellen. Natürlich können Sie auch PROFAN.EXE mit Kommandozeilenparameter starten, etwa "PROFAN MYLLDEMO.PRF". Ebenso können Sie PROFAN.EXE ohne Kommandozeilenparameter starten (etwa durch Doppelklick im Dateimanager) und mittels der sich dann öffnenden Datei-Auswahl-Box das passende Programm auswählen. Ich gehe davon aus, daß Sie die Syntax (Schreibweise) der Befehle in der Referenz zu PROFAN² nachsehen und verzichte im Kurs daher auf umfassende Syntax-Beschreibungen. Dieser Kurs soll Einführung und Referenz nicht ersetzen, sondern ergänzen. Hinweis: In eckigen KLammern sind in der Referenz gewöhnlich Parameter gezeigt, die auch weggelassen werden können. Seite 122 RGH-PROFAN² 1 - PROFAN² als Batchsprache Ein Batchprogramm dient in der Regel dazu, immer wiederkehrende Abläufe zu automatisieren. DOS hat dazu eine leistungsfähige BATCH-Sprache, aber unter Windows gibt es nichts dergleichen. In diese Lücke zielt PROFAN² als Batchsprache! PROFAN² startet den EDITOR Nehmen wir einmal an, Sie wollen Texte mit dem Windowseditor NOTEPAD.EXE bearbeiten. Aus Sicherheitsgründen wollen Sie sich immer eine Sicherheitskopie anlegen, die den Namen "KOPIE.DOK" haben soll. Ihre Textdokumente befinden sich im Verzeichnis "C:\DOKUS" und haben die Endung "DOK". Ohne PROFAN² müßten Sie nun zuerst mit dem Dateimanager den gewünschten Text nach "KOPIE.DOK" kopieren, den Editor aufrufen, die vorgegebene Endung mit "*.DOK" überschreiben, in das Verzeichnis wechseln und die gewünschte Datei laden. Sie könnten natürlich auch zuerst die Datei laden, under dem Namen "KOPIE.DOK" mit "SPEICHERN ALS" abspeichern und dann erneut die Datei laden, ... oder aber Sie schreiben Sich folgendes kleines PROFAN²-Programm: (1) (2) (3) (4) DECLARE Datei$ LET Datei$ = @LOADFILE$("Text laden","C:\DOKUS\*.DOK") COPY Datei$ > "C:\DOKUS\KOPIE.DOK" RUN @ADD$("NOTEPAD.EXE ",Datei$) Um das Programm zu schreiben, starten Sie den PROFAN²-Editor PROFED.EXE. Das geht auch direkt aus dem Programmanager über das entsprechende Icon in der PROFAN²Programmgruppe. Geben Sie nun das Programm (ohne die Zahlen in den runden Klammern) ein. Dieses Programm können wir z.B. unter dem Namen "DOKU.PRF" speichern. Dazu wählen wir den Menüpunkt "DATEI . SPEICHERN ALS". Über den Menüpunkt "PROFAN - AUSFÜHREN" können wir nun das Programm starten. Zu den Programmzeilen im Einzelnen: (1) In PROFAN² müssen Variablen vor Ihrer ersten Benutzung deklariert werden. Dies geschieht mit dem Befehl DECLARE. Hinter DECLARE können auch mehrere Variablen angegeben werden. Wie vom BASIC her gewohnt, wird die Art der Variable durch das letzte Zeichen (Postfix) angegeben: $ = String (max. Länge 255 Zeichen) % = Integer (Ganzzahl: -32767 - 32767) & = Langer Integer (Große Ganzzahl: ca. -2 Mia - 2 Mia) ! = Fließkommazahl (mind. 14 genaue Stellen) # = Bereichsvaiable (Speicherbereich - unter 16 Bit nur bis 64 kB) In unserem Fall wird eine Stringvariable mit Namen "Datei$" angelegt. (2) Hinter der Funktion @LOADFILE$ verbirgt sich ein kompletter Dialog zum Laden eines Dateinamens. Der erste Parameter ist die Überschrift des Datei-Dialoges, während der zweite Parameter Pfad und Suchmaske angibt. In unserem Beispiel werden alle Dateien mit der Endung "DOK" zur Auswahl angeboten, die sich im Verzeichnis "C:\DOKUS" befinden. Das Ergebnis der Wahl wird der Variablen "Datei$" zugewiesen. Übrigens: Alle Funktionen in PROFAN² können mit einem "@" beginnen. Zum einen kann das Programm dadurch übersichtlicher werden und zum anderen erkennt der Interpreter sofort, daß eine Funktion kommt, was das Programm im Interpretermodus (Batchbetrieb) schneller macht. Seite 123 RGH-PROFAN² (3) Als Nächstes kopieren wir diese Datei nach "KOPIE.DOK". Der COPY-Befehl ähnelt sehr dem gleichnamigen DOS-Kommando. Es ist aber darauf zu achten, daß zwischen Quelldatei und Ziel-Datei das Größer-Zeichen steht. Es symbolisiert die Richtung in die kopiert wird. Außerdem kann in PROFAN² immer nur eine Datei kopiert werden. (4) Mit dem Befehl RUN starten wir nun den Windows-Editor NOTEPAD.EXE. Mit der Funktion @ADD$ werden die Strings "NOTEPAD.EXE " und Datei$ zu einem String verbunden. Vergessen Sie nicht das Leerzeichen hinter NOTEPAD.EXE! Mit dem RUNBefehl endet unser PROFAN²-Programm und die Kontrolle wird an den aufgerufenen Editor übergeben. PROFAN² stellt Fragen Es kann nun natürlich auch der Fall eintreten, daß wir die Sicherungskopie nicht immer machen wollen. Es wäre ganz praktisch, den Anwender zu fragen, ob er eine Sicherheitskopie haben will. Anhängig von der Antwort muß das Programm dann die Sicherungskopie erstellen oder gleich die Datei öffnen. Erweitern wir also unser Programm: (1) (2) (3) (4) (5) (6) (7) DECLARE Datei$, Antwort% LET Datei$ = @LOADFILE$("Text laden","C:\DOKUS\*.DOK") LET Antwort% = @MESSAGEBOX ("Wollen Sie eine \ Sicherungskopie erstellen?","Frage:",36) IF @EQU(Antwort%,6) COPY Datei$ > "C:\DOKUS\KOPIE.DOK" ENDIF RUN @ADD$("NOTEPAD.EXE ",Datei$) Folgende Erweiterungen wurden notwendig: (1) In der ersten Zeile kommt die Variable ANTWORT% hinzu, um - wie der Name vermuten läßt, die Antwort auf unsere Frage aufzunehmen. (3) Mit der Funktion @MESSAGEBOX bringen wir eine windowstypische Dialogbox auf den Bildschirm. Die Funktion hat drei Parameter: Der erste Parameter ist der Meldungstext, der in der Box erscheint. Der zweite Parameter ist die Überschrift, die in der Titelzeile der Box auftaucht. Besonders wichtig ist der dritte Parameter: Er gibt Auskunft über Anzahl der Knöpfe, benutztes Symbol, etc.! Er setzt sich zusammen aus BUTTONS + ICON + DEFAULT + FENSTERART. Die entsprechenden Werte entnehmen wir der Referenz zu PROFAN². In der Referenz sind sie bei der Funktion @MESSAGEBOX aufgeführt. Zunächst sollen zwei Buttons vorhanden sein, nämlich "JA" und "NEIN". Der Wert für BUTTONS ist also die 4. Als Icon (Sinnbild) empfiehlt sich das Fragezeichen: 32. DEFAULT gibt an, welcher Knopf angewählt sein soll und mit ENTER angewählt wird. Das soll der erste, der "JA"-Knopf sein: 0. Da es eine normale Meldungsbox sein soll, ist auch der vierte Wert eine 0. Wenn wir die gefundenen Werte addieren (4 + 32 + 0 + 0), erhalten wir 36. Das ist der gesuchte Wert. Eine weitere Besonderheit zeigt Zeile 3: Der Backslash am Ende der Zeile zeigt an, daß der Befehl in der nächsten Zeile weitergeht, und zwar beim ersten Zeichen, das kein Leerzeichen ist. Auf diese Weise kann eine Befehlszeile auf mehre Textzeilen umgebrochen werden. Übrigens: Die maximale Länge einer Befehlszeile sind 254 Zeichen. Sobald wir einen der beiden Buttons betätigen, verschwindet die Messagebox vom Bildschirm und gibt den gedrückten Button zurück. Der Referenz entnehmen wir, daß der "JA"-Knopf den Wert 6 zurückliefert. Seite 124 RGH-PROFAN² (4) Hier steht der IF-Befehl. Hinter dem IF steht der Bedingungsausdruck. Wenn er den Wert 0 hat, ist die Bedingung nicht erfüllt und die Zeile(n) zwischen IF und ENDIF wird (werden) nicht ausgeführt. Der Bedingungsausdruck ist hier die Funktion @EQU. Diese Funktion überprüft die Gleichheit der beiden Werte. Sind beide Werte gleich (d.h. war der gedrückte Knopf das "JA") ist die Bedingung erfüllt, ansonsten eben nicht. Wenn die Bedingung erfüllt ist, wird Zeile (5) ausgeführt, ansonsten geht es gleich weiter zu Zeile (7). HINWEIS 1: Da PROFAN² keine Operatoren kennt (siehe Einführung), ist ein Ausdruck wie etwa "IF ANTWORT% = 1" nicht möglich. Aber für alle Operatoren und Verknüpfungen (* - + / AND OR ...) gibt es entsprechende Funktionen. HINWEIS 2: Das aus BASIC oder PASCAL bekannte "THEN" gibt es in PROFAN² nicht. HINWEIS 3: Natürlich gibt es auch "ELSE" und "ELSEIF". Die Referenz gibt darüber Auskunft. Eine letzte Ergänzung Zum Schluß des ersten Teils wollen wir noch festlegen können, welchen Namen die Sicherungskopie der Datei haben soll. Hierzu bietet PROFAN² die Funktion @SAVEFILE$: (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) DECLARE Datei$, Kopie$, Antwort% LET Datei$ = @LOADFILE$("Text laden","C:\DOKUS\*.DOK") LET Antwort% = @MESSAGEBOX ("Wollen Sie eine \ Sicherungskopie erstellen?","Frage",36) IF @EQU(Antwort%,6) LET Kopie$ = @SAVEFILE$("Name der Kopie", \ "C:\DOKUS\KOPIE.DOK") IF @NEQ$(Kopie$,"") COPY Datei$ > Kopie$ ENDIF ENDIF RUN @ADD$("NOTEPAD.EXE ",Datei$) (1) Zunächst brauchen wir eine weitere Variable, um den Namen für die Kopie zu speichern. Wir nennen diese Varaible sinnigerweise KOPIE$. (5) Die Funktion @SAVEFILE$ erinnert sehr an @LOADFILE$: Der erste Parameter ist die Überschrift des Dialoges und der zweite der vorgeschlagene Dateinahme. Im Dialog hat der Anwender die Möglichkeit, den Namen zu ändern oder auch ein anderes Verzeichnis zu wählen. Die Funktion gibt Pfad und Namen der tatsächlich gewählten Datei zurück. (6) Die Funktion @NEQ$ prüft zwei Strings auf Ungleichheit. Hier ist die Bedingung also erfüllt, wenn der Inhalt von KOPIE$ kein leerer String ist. Ein leerer String wäre er aber, wenn der Anwender im @SAVEFILE$-Dialog den Knopf "Abbrechen" gedrückt hätte. Das "$" am Ende des Funktionsnamens sagt hier aus, daß Strings (und keine Zahlenwerte) verglichen werden. Folgende Vergleichsfunktionen kennt PROFAN²: Für Zahlenwerte: @EQU Gleichheit @LT Kleiner als @GT Größer als @NEQ Ungleicheit Seite 125 RGH-PROFAN² Für Strings: @EQU$ Gleichheit @LT$ Kleiner als @GT$ Größer als @NEQ$ Ungleicheit Nähere Hinweise finden sich unter den betreffenden Stichworten in der Referenz der Hilfe zu PROFAN². Seite 126 RGH-PROFAN² 2 - EVA - Eingabe > Verarbeitung > Ausgabe EIN- UND AUSGABE Was fällt Ihnen bei EVA ein? Wahrscheinlich zunächst nicht ein grundlegendes Prinzip der Datenverarbeitung. Und doch wird mit EVA die grundlegende Funktion fast jedes Programmes bzw. Programm-Modules beschrieben: EINGABE - VERARBEITUNG AUSGABE. Die Daten werden zunächst in irgendeiner Form eingegeben, dann verarbeitet und schließlich die Ergebnisse ausgegeben. Die Eingabe erfolgt in vielen Fällen über die Tastatur oder über Dateien, die vom Programm gelesen werden. (Andere Eingabemöglichkeiten sind über zahlreiche Zusatzgeräte wie etwa Scanner, AD-Wandler, Schalter, Relais, ... aber auch Videokammera, Mikrophon, ...) Die Ausgabe der verarbeiteten Daten erfolgt bei uns meist über Bildschirm, Drucker und Dateien, in die die Daten geschrieben werden. (Natürlich gibt es auch Plotter, Soundkarten, Videogeräte und vielerlei mehr ... bis hin zur Steuerung von Modelleisenbahn, Stereoanlage und Roboter ...) Eine leistungsfähige Sprache für Windows benötigt natürlich Befehle, um die Ein- und Ausgabe von Daten zu ermöglichen. PROFAN² ist hier besonders vielseitig. BILDSCHIRM, TASTATUR UND DRUCKER IM TEXTMODUS Textmodus unter Windows? Nun, ein richtiger Textmodus ist es nicht, aber es wird der DOSBildschirm mit 80 Zeichen pro Zeile simuliert. Es gibt keinen Befehl, um in den Textmodus zu schalten: In PROFAN² ist der Textmodus - neben dem windowseigenen Grafikmodus immer verfügbar. Der Textmodus wurde eingebaut, um die Ein- und Ausgabe mit den von BASIC her bekannten Befehlen zu ermöglichen: CLS löscht den Bildschirm PRINT gibt Daten (Strings und Zahlen) aus LOCATE positioniert den Cursor COLOR stellt die Farben für den PRINT-Befehl ein INPUT ermöglicht die Eingabe von Daten Ein kleines Beispiel: EVA1.PRF ( 1) ( 2) ( 3) ( 4) ( 5) ( 6) ( 7) ( 8) ( 9) (10) (11) (12) (13) (14) DECLARE Name$, Alter% CLS LOCATE 2,2 PRINT "TESTPROGRAMM" LOCATE 4,2 PRINT "Wie heißt Du? "; INPUT Name$ LOCATE 6,2 PRINT "Wie alt bis Du? "; INPUT ALTER% LOCATE 8,2 PRINT "Du heißt",Name$,"und bist",ALTER%,"Jahre alt." WAITKEY END Seite 127 RGH-PROFAN² Einem BASIC-Programmierer kommt wahrscheinlich alles recht bekannt vor. Es gibt jedoch einige Unterschiede. Gehen wir das Programm Zeile für Zeile durch: ( 1) - Die Variablen werden declariert. Das gibt es in BASIC nicht. ( 2) - Der Bildschirm wird gelöscht. ( 3) - Der Cursor wird positioniert (Zeile 2,Spalte 2). ( 4) - Es wird Text ausgegeben. ( 6) - Die Frage wird ausgegeben. Das Semikolon am Ende der Zeile sorgt dafür, daß der folgende Befehl an der gleichen Cursor-Position aufsetzt: ( 7) - Der Name wird eingeben. Achtung: Bei INPUT darf keine Textausgabe (wie etwa in BASIC stehen). Hinter INPUT dürfen nur Variablennamen stehen. (10) - Das Alter wird eingegeben. (12) - Das Ergebnis wird ausgegeben. Das Komma sorgt jeweils dafür, daß die Ausgaben durch ein Leerzeichen getrennt sind. Bei einem Semikolon würde kein Leerzeichen kommen. (13) - WAITKEY wartet auf einen Tastendruck und END beendet das Programm. Wir können das Ergebnis auch in eine Datei schreiben. Dazu fügen wir zwischen WAITKEY und END noch folgende Zeilen ein (EVA2.PRF im BEISPIEL-Verzeichnis): (a) (b) (c) (d) (e) ASSIGN #1,"ERGEBNIS.DAT" REWRITE #1 PRINT #1,Name$ PRINT #1,Alter% CLOSE #1 (a) - Dem Kanal Nr. 1 wird mit ASSIGN der Dateiname "ERGBNIS.DAT" zugewiesen. (b) - Der Kanal wird mit REWRITE zum Schreiben geöffnet. Die Datei wird somit erzeugt. (c) Der Name wird mit in die Datei geschrieben. (d) Das Alter wird in die Datei geschrieben. (e) Der Kanal (und damit die Datei) wird geschlossen. Übrigens: PROFAN² kennt 15 Kanäle (1 - 15). BASIC-Programmierer werden sich über (a) und (b) wundern. Hier habe ich Anleihen von PASCAL genommen. In BASIC würden die beiden Zeilen zu einer zusammengefaßt: OPEN "ERGEBNIS.DAT" FOR OUTPUT AS #1 Mit folgendem kurzen Programm können wir die in "ERGEBNIS.DAT" geschrieben Daten wieder auslesen: ( 1) ( 2) ( 3) ( 4) ( 5) ( 6) ( 7) ( 8) ( 9) (10) DECLARE Name$, Alter% CLS ASSIGN #1,"ERGEBNIS.DAT" RESET #1 INPUT #1,Name$ INPUT #1,Alter% PRINT "Du heißt",Name$,"und bist",ALTER%,"Jahre alt." CLOSE #1 WAITKEY END Kurze Erläuterung: ( 4) - RESET öffnet den Kanal zum Lesen ( 5) - Der Name wird aus der Datei gelesen ( 6) - Das Alter wird aus der Datei gelesen Seite 128 RGH-PROFAN² Normalerweise ist ein Drucken im Textmodus nicht vorgesehen. Wenn Sie zwischen STARTPRINT und ENDPRINT den PRINT-Befehl versuchen, gibt PROFAN² eine entsprechende Fehlermeldung aus. Mit einem kleinen Trick gelingt es uns aber trotzdem: Wir weisen einem Kanal den Drucker zu, indem wir als Dateiname "PRN" angeben. Alle Ausgaben in diesen Kanal gelangen dann zum Drucker: ASSIGN #1,"PRN" REWRITE #1 PRINT #1,Name$;" ist ";Alter%;" Jahre alt." PRINT #1,@Chr$(12) CLOSE #1 HINWEIS: In der 16-Bit-Version müssen Sie vorher die Zeile SETLFN 0 einfügen, wenn Sie unter Windows 95 arbeiten. Ansonsten wird "PRN" nicht als Drucker erkannt. Mit @Chr$(12) geben wir das Zeichen mit dem ASCII-Code 12 an den Drucker. Das ist das Zeichen für das Seitenende. Wenn wir anstelle von "PRN" die serielle Schnittstelle ansprechen wollen, benutzen wir als Dateinamen "COM1" oder "COM2". Den Abschluß dieses Abschnittes bildet ein kleines Programm, mit dem wir unsere PROFAN²-Listings ausdrucken können. Es heißt "LLIST.PRF" und befindet sich im BEISPIEL-Verzeichnis Ihrer PROFAN²-Installation. Listing: LLIST.PRF Declare Datei$,Zeile$ SetLFN 0 Let Datei$ = @LoadFile$("PROFAN-Datei auswählen:","*.PRF") IFNOT @Equ$(Datei$,"") Cls Assign #1,Datei$ Reset #1 Assign #2,"PRN" Rewrite #2 WHILENOT @Eof(#1) Input #1,Zeile$ Let Zeile$ = @AnsiToOem$(Zeile$) Print #2,Zeile$ WEND Close #1 Print #2,@Chr$(12) Close #2 ENDIF END Drei Erläuterungen zu dem Programm: Die Befehle, die zwischen WHILENOT und WEND bzw. ENDWHILE stehen, werden solange wiederholt, solange die Bedingung nicht erfüllt ist. (Sollten Sie solange wiederholt werden, solange die Bedingung erfüllt ist, müßte die Schleife mit einem WHILE beginnen.) Die Bedingung heißt hier @EOF(#1). EOF steht für "End of File". Die Funktion hat dann den Wert 1 (= Bedingung erfüllt), wenn das Ende der Datei im angegebenen Kanal erreicht ist. In unserem Beispielprogramm, wird der eingelesene Text solange auf den Drucker gegeben, bis das Ende der PROFAN²-Datei erreicht ist. Seite 129 RGH-PROFAN² Der Drucker eines PC-Benutzers wird in der Regel auf den erweiterten ASCII-Zeichensatz eingestellt sein. (Bei Nadeldruckern heißt er meißt "IBM2", beim HP-Laserjet hingegen "PC8".) Windows hingegen nutzt in der Regel den ANSI-Zeichensatz, bei dem die deutschen Sonderzeichen andere Codes haben. Die Funktion @AnsiToOem$ wandelt einen String vom Ansi-Zeichensatz in den ASCII-Zeichensatz um. Der Windows-Modus Mit dem bisher Gelernten läßt sich ja schon einiges anstellen, aber wie richtige Windowsprogramme sehen die Ergebnisse noch nicht aus. Unter Windows geschieht viel mit Dialogboxen und Fenstern. Natürlich beherrscht dies auch PROFAN². Unser Beispielprogramm sähe dann so aus (EVA3.PRF): (1) (2) (3) (4) (5) (6) DECLARE Name$, Alter%, Text$ Let Name$ = @Input$("Wie heißt Du?","Frage:","") Let Alter% = @Input$("Wie alt bist Du?","Frage",99) Let Text$ = "Du heißt",Name$,"und bist",Alter%,"Jahre alt." @MessageBox(Text$,"Ergebnis:",64) END Einige Erläuterungen: (2) - Mit der Funktion @INPUT$ können sowohl Strings als auch numerische Werte eingelesen werden. Der erste Parameter ist die Frage, bzw. Erläuterung zur Eingabe. Der zweite Parameter ist die Überschrift des Eingabefensters. Der dritte Parameter ist der Vorgabewert, also der Wert, der im Eingabefeld als Vorschlag angeboten wird. (3) - Die Funktion funktioniert auch mit Zahlenwerten. In unserem Beispiel ist der Vorgabewert 99. (4) - Mit dem LET-Befehl können, durch Kommas oder Semikolons getrennt, wie beim PRINT-Befehl mehrere Strings zusammengefügt werden. Bei einem Komma wird ein Leerzeichen eingefügt. (5) - Die Messagebox kennen wir bereits aus dem letzten Kursteil. Da dieses Programm keine direkten Ausgaben in ein Hauptfenster macht, gibt es dieses nicht: Kein CLS und kein WINDOW-Befehl. Eine besondere Errungenschaft von Windows 3.1 waren die TrueType-Schriften. Endlich gab es brauchbare Schriften, die auf Bildschirm und Drucker (weitestgehend) gleich aussahen. Zudem ließen sich die TrueType-Schriften in beliebiger Richtung auf dem Bildschirm und Drucker ausgeben. Diese Möglichkeiten können wir auch unter PROFAN² ausschöpfen. Das Programm "TRUETYPE.PRF", das Sie im BEISPIEL-Verzeichnis finden, demonstriert dies eindrucksvoll. Listing: TRUETYPE.PRF Declare Grad%, Text$, Ende% Proc TextDemo Declare Winkel%,Groesse% TextColor @RGB(0,0,0),-1 Let Text$ = ".......... PROFAN²" Let Winkel% = 150 WhileNot @Gt(Winkel%,3600) Let Groesse% = @Div(Winkel%,100) Orientation Winkel% UseFont "Times New Roman",Groesse%,0,0,0,0 DrawText 250,180,Text$ Add Winkel%,150 Wend EndProc Seite 130 RGH-PROFAN² Proc Bildschirm Cls TextDemo EndProc Proc Drucker StartPrint TextDemo EndPrint EndProc WindowTitle "TrueType - Demo" Window 0,0 - 639,479 PopUp "&Ausgabe" AppendMenu 100,"&Bildschirm" AppendMenu 101,"&Drucker" Separator AppendMenu 109,"&Ende" Let Ende% = 0 WhileNot Ende% WaitInput Case @MenuItem(100):Bildschirm Case @MenuItem(101):Drucker Case @MenuItem(109):Let Ende% = 1 Wend End An dieser Stelle noch einige Erläuterungen zum Programm: PROFAN² kennt Prozeduren. Diese werden durch PROC, gefolgt vom Prozedurnamen, eingeleitet und mit ENDPROC abgeschlossen. Diese Prozedurdefinition muß vor dem ersten Aufruf erfolgen. Im Programm können dann die Prozeduren mit Ihrem Namen aufgerufen werden. In "TRUETYPE.PRF" werden drei Prozeduren definiert: TEXTDEMO Diese Prozedur leistet die eigentliche Arbeit. Mit TEXTCOLOR wird die Schriftfarbe eingestellt. Der erste Parameter ist die Vordergrundfarbe. Diese kann eine der 32768 in PROFAN² möglichen Farben sein. Die hier eingesetzte Funktion @RGB ermittelt aus den Werten für Rot, Grün und Blau (je von 0 bis 31) den entsprechenden Farbwert. In unserem Beispiel sind R, G und B jeweils 0, also ist die Farbe schwarz. Der zweite Parameter von TEXTCOLOR ist die Hintergrundbarbe. Die -1 bedeutet "transparent", d.h. es wird die vorhandene Hintergrundfarbe so gelassen wie sie ist. mit ORIENTATION stellen wir den Winkel der Textausgabe ein. Der Winkel wird in Zehntelgrad angegeben. In der Schleife wird der Winkel von 15 bis 360 Grad in Schritten zu je 15 Grad erhöht. Gleizeitig wird die Schriftgröße von 1.5 bis 36 erhöht. USEFONT stellt die Schrift ein. Der erste Parameter ist der Schriftname und der zweite die Größe der Schrift. Der dritte Parameter ist die Schriftbreite; ist er 0, wird eine Standardbreite benutzt. Die übrigen drei Paramer können die Werte 0 oder 1 annehmen uns stehen für fett, kursiv und unterstrichen. Mit DRAWTEXT wird der Text an die entsprechende Bildschirmposition bzw. Druckposition gebracht. Seite 131 RGH-PROFAN² BILDSCHIRM Der Bildschirm wird gelöscht und TEXTDEMO wird aufgerufen. DRUCKER Mit STARTPRINT wird die Ausgabe auf den Drucker umgeleitet. Dann wird TEXTDEMO aufgerufen. Alle DRAWTEXT-Befehle gehen jetzt auf den Drucker. Mit ENDPRINT wird die Druckseite abgeschlossen und die Ausgabe wieder auf den Bildschirm geleitet. Das anschließende Hauptprogramm stellt mit WINDOWTITLE die Fensterüberschrift ein und mit WINDOW die Größe. Da WINDOW das Fenster auch gleichzeitig auf den Bildschirm bringt, erübrigt sich hier ein CLS. Dann wird das Menü erzeugt und in der PROFAN²-typischen WHILE-Schleife je nach Menüauswahl verzweigt. Seite 132 RGH-PROFAN² 3 - Sound & Vision Die meisten Windowsprogrammiersprachen haben wenige bis gar keine Möglichkeiten zur Sounderzeugung oder Anzeige von Bitmaps. Visual Basic kann zwar sehr gut mit Bitmaps und Icons umgehen, bleibt aber stumm. Im Handbuch findet sich nur der Hinweis, daß die Befehle BEEP, SOUND und PLAY nicht unterstützt werden. Turbo- Pascal für Windows erlaubt wenigstens den Piepser (MessageBeep), aber fertige Routinen zum Anzeigen von Bitmap-Bildern sucht man vergebens ... wie überhaupt die Grafikprogrammierung unter Turbo-Pascal für Windows eine äußerst komplexe Geschichte ist ... PROFAN² hingegen kennt zahlreiche Möglichkeiten, Ihrem PC mit oder ohne Soundkarte Töne zu entlocken und auch die Anzeige von Bitmap-Grafiken ist problemlos ebenso möglich, wie das Zeichnen komplexer Grafiken. Auf eines soll allerdings hingewiesen werden: Die Töne BEEP, SOUND, PLAY und MUSIC funktionieren in der Regel problemlos über den eingebauten Lautsprecher. Bei einer Soundkarte hängt es davon ab, inwieweit der Treiber die diesen Befehlen zugrundeliegenden Windowsfunktionen unterstützt oder unverändert an den Lautsprecher weiterleitet. Microsoft selbst garantiert nicht, daß die Funktionen auch in künftigen Windowsversionen vorhanden sein werden, da die Möglichkeiten der Multimedia-Schnittstelle weitreichender seien. BEEP sollte aber auf alle Fälle funktionieren. Wenn Sie nichts hören, sollten Sie in der Systemsteuerung unter "Klänge" das Kästchen "Systemklänge aktivieren" ankreuzen. Der Piepser in Aktion Die einfachste Möglichkeit, ein Geräusch zu erzeugen, ist der BEEP Befehl. Er erzeugt einen kurzen Warnton. Wenn in der Systemsteuerung allerdings dem Ereignis 'Kritischer Abbruch' eine WAV-Datei zugewiesen ist, wird diese abgespielt. In folgendem Beispielprogramm zu Errechnung der Fakultäten von 1 bis 25 wird der BEEPBefehl benutzt, um den Anwender auf eine falsche Eingabe hinzuweisen: DECLARE A%,OK%,Ergebnis! WHILENOT OK% LET A%=@INPUT$("Bitte eine Zahl zwischen 1 und 25 eingeben:",\ "EINGABE",A%) IF @OR(@Lt(A%,1),@Gt(A%,25)) BEEP ELSE LET OK%=1 ENDIF WEND LET Ergebnis! = @Pow(A%,A%) DECIMALS 0 @MESSAGEBOX(@Str$(Ergebnis!),"ERGEBNIS",0) In der IF-Bedingung werden die beiden Bedingungen "A kleiner als 1" (@LT(A%,1)) und "A größer als 25" (@GT(A%,25)) mit der OR-Funktion verknüpft. Das heißt: Die Bedingung ist erfüllt wenn A kleiner als 1 ist ODER A größer als 25! Für komplexere Geräusche gibt es noch den SOUND-Befehl, der als Parameter die Tonhöhe in Hertz und die Dauer in 360tel Sekunden hat. Seite 133 RGH-PROFAN² Noten mit PLAY Will man nun kurze Tonfolgen programmieren, die auch nach etwas klingen, so ist es doch recht hinderlich, immer in einer Notentabelle nachzusehen, welcher Ton welche Frequenz hat. Mit PROFAN² ist dies auch nicht nötig, da es den PLAY-Befehl gibt. Der PLAY-Befehl hat drei Parameter, die es ermöglichen, jedweden Ton zu spielen: Tonhöhe: der erste Parameter ist die Tonhöhe ausgehend vom tiefsten Ton mit der Nummer 1. Von da wird in Halbtonschritten hochgezählt. Eine Oktave umfaßt 12 Halbtonschritte. Tonlänge: Hier wird die Tonlänge in einer für Musik brauchbaren Schreibweise angegeben: 1 steht für eine ganze Note, 2 für eine halbe, 4 für eine Viertel ... bis hin zu 32 für eine zweiundreißigstel. Daß Sie auch eine siebtel Note spielen könnten, mag zwar interessant klingen, ist aber für die Musik von relativ untergeordneter Bedeutung. Der dritte Parameter ermöglicht das Spielen punktierter Noten, indem er die Anzahl der Punkte angibt. Ein Punkt verlängert die Dauer einer Note um die Hälfte Ihrer Länge. Das folgende Beispielprogramm spielt eine Tonleiter in Viertel-Noten: PLAY PLAY PLAY PLAY PLAY PLAY PLAY PLAY 12,4,0 14,4,0 16,4,0 17,4,0 19,4,0 21,4,0 23,4,0 24,4,0 Bevor Sie aber jetzt anfangen, Ihren Lieblingssong auf diese Weise in ein Programm umzuwandeln, schauen Sie sich den mächtigsten der Tonbefehle an: MUSIC mit der Sprache in der Sprache Vielleicht kennen Sie von BASIC her den Befehl PLAY. Der dient dort nicht zum Abspielen einzelner Noten, sonderm zum Abspielen kompletter Melodien. Die einzelnen Noten werden mittels einer Music-Makro-Sprache in einen String gestellt und dieser wird dem Befehl als Parameter übergeben. Diese Makrosprache gibt es auch in PROFAN² und wird dort mit dem Befehl MUSIC ausgeführt. Auf einen Unterschied sei allerdings hingewiesen: Das Abspielen im Hintergrund ist nicht möglich. Ansonsten enthält die Makrosprache alle Befehle: Noten werden durch Ihre Bezeichnung dargestellt: MUSIC "C D E F G A B" Dieser Befehl spielt die C-Dur-Tonleiter. Die Leerzeichen zwischen den Tönen können auch weggelassen werden. HINWEIS: Im internationalen Gebrauch bezeichnet B den Ton, der im deutschen Sprachraum mit H bezeichnet wird. Wenn wir im deutschen Sprachraum B sagen, meinen wir das erniedrigte H. Natürlich können wir auch eine Oktave höher oder tiefer gehen. Dazu dienen das ">" und das "<". Direkt einstellen können wir die Oktave mit dem Befehl "O" gefolgt von der Nummer der Oktave, die zwischen 1 und 8 liegen darf: Seite 134 RGH-PROFAN² MUSIC "O3 C D E F G A B > C" Die ersten sieben Töne werden in der 3. Oktave gespielt und das letzte C in der vierten. Natürlich sind wir nicht auf C-DUR (bzw. A-MOLL) beschränkt, und können die Noten auch um je einen Halbton erhöhen und erniedrigen. Zum Erhöhen verwenden wir das "#" und zum Erniedrigen das "-". Hier die Tonleiter in G-DUR: MUSIC " O3 G A B > C D E F# G" Bisher wurden alle Noten in einer Länge gespielt. Voreingestellt sind viertel Noten. Die Länge können wir beeinflussen, indem wir mit "L" gefolgt von der Notenlänge die Länge aller folgenden Noten einstellen oder indem wir an Note die Längenbezeichnung direkt anhängen: MUSIC "L2 C D E F G4 A16" Hier werden die Noten C bis F als halbe Noten gespielt, das G ist eine viertel Note und das A eine sechzehntel. Um punktierte Noten zu spielen, wird an die Längenbezeichnung einfach ein Punkt angehängt: "G4." würde eine punktierte Viertelnote spielen. Auch das Grundtempo können wir angeben, indem wir den Befehl "T" verwenden, gefolgt von der Anzahl der Viertelnoten pro Minute. Voreingestellt ist der Standardwert von 120. Pausen spielen wir mit dem Notenwert "P". Neben der Kennzeichnung eines Tones mit der Notenbezeichnung, können wir eine Note auch über ihren Wert kennzeichnen, indem wir den Befehl "N" gefolgt von der Nummer der Note verwenden. Dabei werden die Töne vom tiefsten Ton mit der Nummer 1 einfach hochgezählt (wie der erste Parameter bei PLAY). Eine zusätzliche Angabe einer Notenlänge ist hier nicht möglich. Es wird immer der mit "L" eingestellte Wert verwandt. Mit den Befehlen "ML", "MN" und "MS" kann die Spielweise noch zwischen "Legato" (Töne gehen ineinander über), "Normal" und "Staccato" (Töne klingen abgehackt) variiert werden. Das Beispielprogramm CELLO.PRF spielt ein Stück für Cello in G- DUR. Listing: CELLO.PRF Music "t110 o2 l8 ml" Music Music Music Music "g > d b4 a b16 > c16 < b a g f# g d" "e g > c < a f# > d < b2 a. p16" "< a > f# > c4 < b > c16 d16 c < b a g f# e" "f# g16 a16 g f# e f# d4 < a4 d. p16" Music Music Music Music "g > d b4 a b16 > c16 < b a g f# g d" "e g > c < a f# > d < b2 a. p16" "< a > f# > c4 < b > c16 d16 c < b a g f# e" "f# g16 a16 g f# e f# d4 < a4 d. p16" Music Music Music Music "> "< "< "a d f# a4 g a16 b16 a g f# e d f#" b > d g# a b > d << a >> d c < b > c. p16" d# f# a > c < b a b e < g > a > c < b" g f# e < b > d# < e4 p > e d c" Music Music Music Music "< "> "> "d b > d g4 d e16 c# e a4 e f#16 d f# a > c < b < f# t94 g < b f32 g32 > d t84 p32 p32 < e d > f d e c < c b" g e f# d < d a" g b > d c e" f# g2." Seite 135 RGH-PROFAN² Selbstverständlich können die Strings auch Stringvariablen sein. Während des Abspielens eine Strings reagiert der Computer auf keinerlei Aktionen. Achten Sie also darauf, daß die einzelnen Strings nicht zu lang werden. VON BITMAPS UND ICONS Was wäre ein Windowsprogramm, wo ich nicht durch Anklicken von Icons irgendwas auswählen kann oder was lediglich einen langweiligen weißen Hintergrund bietet? Daß PROFAN² mehr kann, zeigen ja schon die Demos, die bei PROFAN² mitgeliefert werden. Die Anzeige von Bitmaps Was sind Bitmaps? Bitmaps sind in diesem Zusammenhang Bilder, wo jedes Bit für eine Grafik-Information steht; Bilder die pixelweise aufgebaut werden. Windows hat hier ein eigenes Bildformat, das durch die Endung .BMP gekennzeichnet ist. Zwei weitere Formate sind sehr ähnlich: nämlich das Format ".RLE" (komprimierte Bitmap-Bilder) und das Format ".DIB". All diese Formate können von PROFAN² mit den gleichen Befehlen geladen werden. In PROFAN² gibt es zwei Befehle um Bilder zu laden und auf den Bildschirm zu bringen: LOADBMP und LOADSIZEDBMP. Ersterer lädt das Bild und zeigt es in der Originalgröße an. Daher hat dieser nur vier Parameter: Name der Bilddatei (evtl. mit Pfad),X-Koordinate der linken oberen Ecke, Y-Koordinate der linken oberen Ecke und den Abbildungsmodus. Beispiel: LOADBMP "PARTY.BMP",10,10;0 Der Abbildungsmodus beschreibt, wie das Bild mit dem, was schon auf dem Bildschirm ist, verknüpft wird. Im Abbildungsmodus 0 wird das, was schon auf dem Bildschirm ist, überschrieben. Die weiteren Modi sind in der Referenz zu PROFAN² beschrieben. Wenn das Bild nun aber in einer anderen Größe angezeigt werden soll, müssen wir den zweiten Befehl verwenden. Hier geben wir auch noch die Breite und Höhe der Anzeige mit an. Beispiel: LOADSIZEDBMP "PARTY.BMP",10,10 - 100,100;0 Wenn wir für Länge und/oder Breite negative Zahlen einsetzen ist sogar eine "verdrehte" bzw. "gespiegelte" Anzeige möglich. VORSICHT: Je nach Grafiktreiber und Farbtiefe kann es bei 256farbigen Bildern zu unerwarteten Abbildungsergebnissen kommen, wenn sie mit LOADSIZEDBMP geladen werden. Hier hilft nur ausprobieren, was geht und was nicht geht. Wenn ich z.B. im 256-Farben-Modus ein Bild mit 256 Farben lade und verkleinere sieht das Ergebnis ziemlich schwarz aus. Bin ich hingegen im 16-Farben- oder 32000-Farben-Modus gibt es keine Probleme. Beim Laden mit LOADBMP sollte es hingegen immer optimal aussehen! Seite 136 RGH-PROFAN² Als Beispiel ein Programm zur Anzeige von Bitmaps: Declare Name$ WindowTitle "BILD-BETRACHTER" CLS ShowMax Let Name$=@LoadFile$("Bilddateien","*.BMP") WhileNot @Equ$(Name$,"") Cls LoadBmp Name$,0,0; 0 WindowTitle @Add$("BILD-BETRACHTER - [",@Add$(Name$,"]")) WaitMouse Let Name$=@LoadFile$("Bilddateien","*.BMP") EndWhile End Was wäre Windows ohne Icons? Auch PROFAN² kennt ICONS. Und da die DEMO-Programme davon reichlich Gebrauch machen, sei hier nur auf das Wesentliche hingewiesen: In PROFAN² gibt es zum einen die SYSTEM-Icons und zum anderen die PROFAN²-Icons. Die System-Icons sind die bekannten Symbole, die auch in den Messageboxen auftauchen. Sie sind durchnumeriert und werden mit dem Befehl DRAWSYSICON auf den Bildschirmgebracht: DRAWSYSICON 4,30,30 Der erste Parameter bezeichnet das Icon und die beiden anderen Parameter sind die Koordinaten, an denen das Icon angezeigt wird. Es gibt die Icons 0 bis 4: leeres Rechteck, STOP-Zeichen, Fragezeichen, Ausrufezeichen und Info-Zeichen. Desweiteren enthält PROFAN² 19 verwendbare Icons, die über Ihren Namen mit dem Befehl DRAWICON angezeigt werden: DRAWICON "EIMER",80,80 Folgende Icons sind in PROFAN² bekannt: PROFAN, KNOPF1, KNOPF2, BAUM, EIS, COMPUTER, DOS, WEG, TEXT, GESICHT, EDITOR, EIMER, MUELL, MUENZE, SAND, STEIN, WINDOWS und WASSER. Sie sind allerdings nicht auf diese Icons beschränkt. Mit vielen auf dem Shareware-Markt erhältlichen ICON-Managern, können Sie diese Icons verändern, gegen andere austauschen und gar noch welche hinzufügen. Das Programm muß in der Lage sein, Icons in EXEDateien zu bearbeiten. ACHTUNG: Da Sie bei diesen Vorhaben dann die EXE-Datei (PROFAN.EXE) verändern, machen Sie vorher eine Sicherheitskopie. Ein ausgezeichnetes Beispiel, wie Icons für Spiele als Sprites zu "mißbrauchen" sind, zeigt das Beispielprogramm "MÜLLSPIEL". Seite 137 RGH-PROFAN² 4 - Multimediaprogrammierung mit PROFAN² DIE MCI-SCHNITTSTELLE MCI steht für "Multimedia Controlling Interface", was wörtlich übersetzt MultimediaSteuerschnittstelle bedeutet. Diese Schnittstelle verbindet mich mit allen in Windows integrierbaren Multimediatreibern. Sobald ein neuer Treiber installiert ist, wie z.B. ein Treiber für Autodesk-Animationen, kann ich ihn über diese Schnittstelle ansprechen. Die Schnittstelle ist sehr einfach gehalten. Es gibt eigentlich nur drei Befehle bzw. Funktionen, über die ich mit den Treibern kommuniziere: 1. Ich sende einen Befehl an den Treiber. Die Syntax des Befehles wird u.A. auch vom Treiber mitbestimmt. (Nicht alle Treiber unterstützen alle Befehle.) 2. Als Ergebnis des Befehles liefert der Treiber a) unter Umständen ein Ergebnis und b) einen Fehlercode zurück, wobei 0 für eine fehlerfreie Funktion steht. Und da nur der Treiber weiß, was der Fehlercode bedeutet, gibt es eine dritte Funktion: 3. Ich übermittle dem Treiber die Fehlernummer und der Treiber liefert im Gegenzug die Fehlerbeschreibung im Klartext. Handelt es sich um deutsche Versionen der Treiber, sind diese sogar in Deutsch. Die mit Windows 3.1 mitgelieferten Treiber für CD, MIDI und WAVE liefern deutsche Fehlermeldungen. MCI MIT PROFAN² In PROFAN² sind die drei Funktionen mit einer Funktion und einer Systemvariablen realisiert: Mit der Funktion @MCISEND$ sende ich einen Befehl an die Multimediaschnittstelle. Konnte dieser Befehl fehlerfrei ausgeführt werden, liefert die Funktion gegebenenfalls das Ergebnis als String zurück. Im Fehlerfall wird hingegen die Fehlermeldung zurückgegeben. Damit ich als Programmierer nun weiß, ober der Rückgabestring ein Ergebnis oder eine Fehlermeldung ist, gibt es noch die Systemvariable %MCIERROR, die den Fehlercode enthält. Hat %MCIERROR einen von 0 verschiedenen Wert, hat die Funktion @MCISEND$ eine Fehlermeldung zurückgeliefert. Hier gleich ein erstes kurzes Programm, mit dem wir die MCI-Schnittstelle testen können. Das Programm macht nichts anderes, als einen eingegebenen Befehl an die MCISchnittstelle zu schicken und das Ergebnis mitzuteilen. Listing: MCITEST.PRF Declare Zeile%,Befehl$,Meldung$ WindowTitle "MCI-Testprogramm in PROBAT" Window 20,20-600,400 Let Zeile% = 0 Let Befehl$ = @Input$("Bitte geben Sie einen MCI-Befehl ein:",\ "MCI-BEFEHL","") Seite 138 RGH-PROFAN² WhileNot @Equ$(@Upper$(Befehl$),"ENDE") If @GT(Zeile%,20) Cls Let Zeile% = 0 EndIf Print "Befehl: ";Befehl$ Inc Zeile% Let Meldung$ = @MCISend$(Befehl$) If %MCIError Print "Fehler: "; Else Print "OK! "; EndIf Print Meldung$ Inc Zeile% Let Befehl$ = @Input$("Bitte geben Sie einen MCI-Befehl ein:",\ "MCI-BEFEHL","") EndWhile End Über die @INPUT$-Funktion wird der MCI-Befehl eingegeben. Sowohl der Befehl als auch das Ergebnis wird auf den Bildschirm gegeben, damit man die Ergebnisse der letzten Befehle vor Augen hat. Die Variable ZEILE% zählt die Zeilen, um den Bildschirm zu löschen, bevor er voll wird. Diese Prozedur wird solange wiederholt, bis der Anwender "Ende" eingibt: Die Schleife zwischen WHILENOT und WEND wird erst dann verlassen, bis die Abbruchbedingung hinter WHILENOT erfüllt ist. Die Funktion @UPPER$ wandelt den String in Großbuchstaben um, sodaß es egal ist, ober der Anwender "ENDE", "ende" oder gar "enDe" eingibt. Eine Besonderheit: Auch die deutschen Umlaute werden korrekt behandelt. Der Befehl INC erhöht die Integervariable (nur da ist er erlaubt) um 1. (Mit DEC erreichen wir das Gegenteil.) Ein Hinweis noch: Der Befehl WINDOW stellt die Fenstergröße ein. Damit läßt sich die Größe des Programmfensters beliebig einstellen. CD-PLAYER Am Beispiel des Abspielens einer CD im CD-ROM-Laufwerk schauen wir uns die Funktionsweise des Programmes und der MCI-Schnittstelle etwas genauer an: Jedes Multimediagerät muß zunächst geöffnet werden. Dabei ist es möglich, dem Gerät einen Alias-Namen zu geben. Das ist quasi eine Kurzform, um es einfacher ansprechen zu können. WICHTIG: Der gleiche Alias-Name darf nicht mehrmals zur gleichen Zeit in Gebrauch sein. Um ein Gerät zu öffnen, wird der Befehl OPEN benutzt, gefolgt von der Gerätebezeichnung. Diese wird vom Treiber festgelegt. Öffnen wir die CD: OPEN CDAUDIO ALIAS CD Geben Sie diesen Befehl in die Input-Box unseres Programmes ein. Wenn tatsächlich eine CD im Laufwerk liegt, wird kurz darauf ein "OK!" auf dem Bildschirm erscheinen. Jetzt wollen wir die Länge der CD in Erfahrung bringen. Um etwas über das geöffnete Gerät zu erfahren, gibt es den STATUS-Befehl, gefolgt vom Gerätenamen (oder der Kurzform) und der der Angabe, was wir wissen wollen: Seite 139 RGH-PROFAN² STATUS CD LENGTH Als Ergebnis wird die Länge der CD ausgeben. Nun wollen wir noch die Anzahl der Titel wissen: STATUS CD NUMBER OF TRACKS Bevor wir jetzt das Gerät abspielen können, müssen wir uns auf ein Zeitformat einigen. Hier gibt es mehrere Möglichkeiten. Für eine CD ist aber lediglich das TMSF-Format von Bedeutung. Das Zeitformat "TMSF" bedeutet, daß Start und Ende im PLAY-Befehl im Format "Track:Minute:Sekunde:Frame" angegeben werden, wobei eine Sekunde 75 "Frames" (kleinste Einheit) hat. Es könnten also beliebige Bruchstücke eines Titels gespielt werden. Wir wollen die CD aber ab dem 7. Titel spielen. Zum Abspielen gibt es den PLAYBefehl: PLAY CD FROM 7 Hätte uns nur ein Teil des Titels interessiert hätten wir auch eingeben können: PLAY CD FROM 7:1:0 TO 7:1:10 Jetzt werden gerade mal 10 Sekunden aus der Mitte des Titels gespielt. Wie wir hier sehen, können wir die nicht benötigten kleineren Unterteilungen der Zeitangabe weglassen. Wollten wir nur die dritte Minute des Titels spielen, geben wir ein: PLAY CD FROM 7:2 TO 7:3 HINWEIS: Die Titelnummern (Track) beginnen bei 1, Minuten und Sekunden beginnen bei 0. Wollen wir die CD anhalten geben wir ein: STOP CD Da wir den Treiber mit OPEN geöffnet haben schließen wir ihn nach getaner Arbeit wieder: CLOSE CD Natürlich können wir diese Befehle auch in einem Programm einbauen. Um z.B. den 3. bis 5. Titel einer CD abzuspielen, können wir schreiben: @MCISend$("open cdaudio alias cd") Print "Länge: ";@MCISend$("status cd length") Print "Titelzahl: ";\ @MCISend$("status cd number of tracks") @MCISend$("set cd time format tmsf") @MCISend$("play cd from 3 to 5") WaitInput HINWEIS: Wird das Programm beendet, bevor der 5. Titel fertig ist, spielt die CD anschließend weiter, da der CD-Spieler dann nicht mehr vom Programm bzw. der Multimediaschnittstelle von Windows kontrolliert wird. Weitere interessante MCI-Befehle zum Ansteuern der CD finden Sie in der Einführung zu PROFAN² unter der Rubrik "Multimedia". Seite 140 RGH-PROFAN² Einem selbstprogrammierten CD-Player steht nun nichts mehr im Wege. Ein Tip: Unter den Icons, die in PROFAN² integriert sind, gibt es zwei Knöpfe: Einer in ungedrückter und einer in gedrückter Form. Hiermit lassen sich die notwendigen Buttons auf den Bildschirm bringen, um den CD-Player zu steuern. Näheres hierzu unter DRAWICON in der Hilfe zu PROFAN². WAVE UND MIDI, FLI/FLC UND AVI MIT PROFAN² Beim Öffnen eines Gerätes, daß einen Dateinamen benötigt, gibt es eine Erweiterung des OPEN-Befehles: Mit TYPE muß ich angeben, um welchen Datei-Typ es sich handelt. Im Falle einer WAV-Datei ist der Type "WAVEAUDIO". Also öffnen wir eine Datei: OPEN TOCCATA.WAV TYPE WAVEAUDIO ALIAS TOCCATA WICHTIG: Damit keine Fehlermeldung kommt, muß sich die Datei TOCCATA.WAV im aktuellen Verzeichnis befinden. Um Sie zu spielen geben wir den PLAY-Befehl ein: PLAY TOCCATA Anschließend schließen wir das Gerät wieder: CLOSE TOCCATA Wenn wir eine WAV-Datei nicht mit unserem MCI-Testprogramm abspielen, sondern in einem Programm, können wir es wie folgt programmieren: @MCISend$("open toccata.wav type waveaudio alias toccata") @MCISend$("play toccata wait") @MCISend$("close toccata") Zwischen PLAY und CLOSE muß natürlich genug Zeit gelassen werden, die Datei zu spielen. Damit der Computer solange wartet, bis der PLAY-Befehl abgearbeitet ist, kann man den Zusatz WAIT mit angeben. Aber Achtung: Während dieser Zeit, ist keine weitere Aktion möglich. Der WAIT-Befehl ist daher nur mit Vorsicht einzusetzen. Unabdingbar ist er, wenn ich eine WAV-Datei aufnehmen will. Das geht mit folgender Befehlsfolge (das Mikrofon sollte angeschlossen und bereit sein): Zuerst teilen wir mit, daß wir eine neue Datei erzeugen wollen: OPEN NEW TYPE WAVEAUDIO ALIAS SPRUCH Nun setzen wir das Zeitformat auf Millisekunden: SET SPRUCH TIME FORMAT MILLISECONDS Und jetzt nehmen wir in 5 Sekunden unseren dümmsten Spruch auf: RECORD SPRUCH FROM 0 TO 5000 WAIT Natürlich wollen wir hören, wie die Aufnahme geworden ist: PLAY SPRUCH FROM 0 Seite 141 RGH-PROFAN² Wenn die Aufnahme gelungen ist, speichern wir sie ab: SAVE SPRUCH SPRUCH.WAV Die anderen in der Überschrift des Artikels genannten Dateitypen sind in der Behandlung sehr ähnlich. Genauer gesagt: Es ändert sich nur das Befehlswort, das hinter TYPE steht. Folgende Dateitypen beherrscht Windows 3.1 von Hause aus: *.WAV Sound-Dateien Typ: WAVEAUDIO *.MID MIDI-Dateien (Musik) Typ: SEQUENCER *.AVI Video für Windows Typ: AVIVIDEO Der Typ AVIVIDEO kann nur abgespielt werden, wenn Sie die "Microsoft Video for Windows"-Runtime installiert haben. Wenn Sie den Treiber für Autodesk-Animationen installiert haben, kommt noch ein Typ hinzu: *.FLC/*.FLI Animationen Typ: ANIMATION1 Für weitere interessante MCI-Befehle muß ich auch hier wieder auf die Einführung zu PROFAN² verweisen. Alle MCI-Befehle zu beschreiben würde den Rahmen dieses Artikels bei Weitem sprengen. MEDIEN-PLAYER IN PROFAN² Den Abschluß dieses Exkurses in die Multimediaprogrammierung bildet ein kompletter Medienspieler in PROFAN². Gewiß, in der vorliegenden Form kann er nicht mehr als der Medienspieler von Windows, dafür können Sie ihn aber beliebig ändern und erweitern. Listing: MEDITPLAY.PRF Declare Text$,Maske$,Ende%,Antwort% Proc SpieleAVI Parameters Datei$ Declare MCI$ Print Datei$ If @Neq$(Datei$,"") @MCISend$("CLOSE FILM") Let MCI$=@Add$(@add$("OPEN ",Datei$)," TYPE AVIVIDEO ALIAS FILM") Let MCI$=@MCISend$(MCI$) If %MCIError @MessageBox(MCI$,"Fehler:",16) Else @MCISend$("PLAY FILM") EndIf EndIf EndProc Seite 142 RGH-PROFAN² Proc SpieleFilm Parameters Datei$ Declare MCI$ Print Datei$ If @Neq$(Datei$,"") @MCISend$("CLOSE FILM") Let MCI$=@Add$(@add$("OPEN ",Datei$),\ " TYPE ANIMATION1 ALIAS FILM") Let MCI$=@MCISend$(MCI$) If %MCIError @MessageBox(MCI$,"Fehler:",16) Else @MCISend$("PLAY FILM WAIT") EndIf EndIf EndProc Proc SpieleWave Parameters Datei$ Declare MCI$ Print Datei$ If @Neq$(Datei$,"") @MCISend$("CLOSE SOUND") Let MCI$=@Add$(@add$("OPEN ",Datei$),\ " TYPE WAVEAUDIO ALIAS SOUND") Let MCI$=@MCISend$(MCI$) If %MCIError @MessageBox(MCI$,"Fehler:",16) Else @MCISend$("PLAY SOUND") EndIf EndIf EndProc Proc SpieleMidi Parameters Datei$ Declare MCI$ Print Datei$ If @Neq$(Datei$,"") @MCISend$("CLOSE SOUND") Let MCI$=@Add$(@add$("OPEN ",Datei$),\ " TYPE SEQUENCER ALIAS SOUND") Let MCI$=@MCISend$(MCI$) If %MCIError @MessageBox(MCI$,"Fehler:",16) Else @MCISend$("PLAY SOUND") EndIf EndIf EndProc Seite 143 RGH-PROFAN² Proc SpieleCD Declare MCI$,TitelZahl%,I% @MCISend$("CLOSE CD") Let MCI$=@MCISend$("open cdaudio alias cd") If %MCIError @MessageBox(MCI$,"Fehler:",16) Else Let MCI$=@MCISend$("status cd length") Print "Länge der CD: ";MCI$; Let MCI$=@MCISend$("status cd number of tracks") Print " - Titelzahl: ";MCI$ Let TitelZahl%=@Val(MCI$) Let I%=1 CreateMenu WhileNot @GT(I%,TitelZahl%) AppendMenu I%,@Add$("Titel ",@Str$(I%)) Inc I% Wend TrackMenu 30,30 If %MenuItem Print "Titel Nr: ";%MenuItem;" - Länge: "; @MCISend$("SET CD TIME FORMAT TMSF") Print @MCISend$(@Add$("STATUS CD LENGTH TRACK ",\ @Str$(%MenuItem))) @MCISend$(@Add$("PLAY CD FROM ",@Str$(%MenuItem))) EndIf EndIf EndProc WindowStyle 8 Window 10,10-400,60 WindowTitle "RGH-Medien-Player in PROFAN" Cls PopUp "&Datei" AppendMenu 11,"&Video für Windows" AppendMenu 12,"&Animation (FLI)" AppendMenu 13,"Animation (&FLC)" Separator AppendMenu 14,"&MIDI-Datei" AppendMenu 15,"Sound-Datei (&WAV)" Separator AppendMenu 16,"&CD-Titel spielen" Separator AppendMenu 17,"&Ende" AppendMenuBar 20,"&Info" Seite 144 RGH-PROFAN² WhileNot Ende% WaitInput Cls If @MenuItem(11) Print "Video für Windows" SpieleAVI @LoadFile$("Video-Datei:","*.AVI") ElseIf @MenuItem(12) Print "FLI-Animation" SpieleFilm @LoadFile$("FLI-Animation:","*.FLI") ElseIf @MenuItem(13) Print "FLC-Animation" SpieleFilm @LoadFile$("FLC-Animation:","*.FLC") ElseIf @MenuItem(14) Print "Midi-Datei" SpieleMidi @LoadFile$("Sound-Datei:","*.MID") ElseIf @MenuItem(15) Print "Sound-Datei" SpieleWave @LoadFile$("Sound-Datei:","*.WAV") ElseIf @MenuItem(16) Print "Musik-CD" SpieleCD ElseIf @MenuItem(17) Let Antwort%=@MessageBox("Wollen Sie den Medien-Spieler \ wirklich beenden?", \ "Seien Sie ehrlich:",36) Case @Equ(Antwort%,6):Let Ende% = 1 ElseIf @MenuItem(20) @MessageBox("Der Mulimedia-Player von RGH","Info",64) EndIf Wend @MCISend$("CLOSE FILM") @MCISend$("CLOSE SOUND") @MCISend$("CLOSE CD") End Der Medien-Player findet sich als "MEDIPLAY.PRF" im PROFAN²-Verzeichnis. Es kommt nicht allzuviel Neues im Programm vor, deshalb will ich im Folgenden nur kurz auf die eine oder andere Besonderheit eingehen: Vor dem Hauptprogramm stehen 5 Prozeduren, die die eigentliche Arbeit tun. Jede Prozedur in PROFAN² beginnt mit dem Befehl PROC und endet mit dem Befehl ENDPROC. Hinter dem PROC steht der Name der Prozedur. Unter diesem Namen wird sie im Hauptprogramm aufgerufen. Mit dem Befehl PARAMETERS übernehme ich Parameter, mit denen die Prozedur aufgerufen wurde. In unserem Beispiel wird der Name der abzuspielenden Datei als Parameter erwartet und in die Variable DATEI$ geschrieben. Alle Variablen die innerhalb der Prozedur mit PARAMETERS oder DECLARE definiert werden, sind auch nur innerhalb der Prozedur bekannt. Sicherheitshalber wird zu Beginn jeder Prozedur das entsprechende Gerät geschlossen. Nur so kann das gleiche Gerät während eines Programmlaufes mehrmals genutzt werden. Wurde das Gerät noch nicht geöffnet, wird zwar %MCIError auf einen Wert ungleich 0 gesetzt. Da wir diesen an dieser Stelle aber nicht abfragen ist das ohne Bedeutung. Seite 145 RGH-PROFAN² Eine Besonderheit gibt es beim Spielen der Musik-CD. Natürlich wird hier kein Dateiname übergeben. Hingegen ermittelt die Prozedur zunächst die Anzahl der Titel der CD. Mit CREATEMENU wird dann ein Pop-Up-Menü erzeugt. In der folgenden WHILE-Schleife wird dann für jeden Titel ein Menüpunkt (mit APPENDMENU) hinzugefügt, der als Nummer die Nummer des jeweiligen Titels und als Menüzeile das Wort "Titel " gefolgt von der Nummer erhält. Mit TRACKMENU wird das erzeugte Menü dann an der angegebenen Position angezeigt und auf eine Auswahl durch den Benutzer gewartet. Hat er einen Titel ausgewählt (und das Menü nicht durch <Esc> oder Danebenklicken verlassen) steht in %MENUITEM die Nummer des gewünschren Titels. Dieser wird angezeigt und gespielt. Nach den Prozeduren beginnt das Hauptprogramm mit der Festlegung der Fensterart, der Fenstergröße und des Fenstertitels. Als Nächstes wird das Menü der Anwendung erzeugt: Mit POPUP wird ein Neues Menü hinzugefügt und mit APPENDMENÜ werden dem Menü einzelne Punkte angehängt, die beim Anklicken von "Datei" aufklappen. Der SEPARATOR steht für eine Trennlinie zwischen zwei Menüpunkten. Das "&" steht jeweils vor dem Buchstaben, der im Menü unterrstrichen dargestellt ist und mittels dessen der Menüpunkt auch per Tastatur ausgewählt werden kann. Mit APPENDMENUBAR wird dem Menü schließlich noch der Menüpunkt "Info" hinzugefügt. "Info" steht zwar direkt neben "Datei", aber es klappt sich dort kein Menü auf. "Info" ist ein eigener Menüpunkt mit eigener Menünummer. Nach der Definition des Menüs folgt die Hauptschleife des Programmes, die solange durchlaufen wird, bis ENDE% einen Wert ungleich 0 aufweist. WAITINPUT wartet auf eine Eingabe vom Anwender, auf eine Auswahl aus dem Menü. Je nach gewähltem Menüpunkt, was mit der Funktion @MENUITEM abgefragt wird, wird die entsprechende Prozedur aufgerufen. Über die Funktion @LOADFILES wird ein ausgewählter Dateiname an die Prozedur übergeben. Bei Programmende werden alle Geräte geschlossen. ACHTUNG: Die CD läuft aber weiter. Soll diese bei Programmende auch anhalten, ist vor dem Befehl "CLOSE CD" der Befehl "STOP CD" abzusenden. Seite 146 RGH-PROFAN² 5 - Selbstdefinierte Dialoge Ab PROFAN² 3.0 gibt es frei definierbare Dialogboxen. Diese gibt es in zwei Ausprägungen: Einmal als Dialogbox mit fester Fenstergröße (@CREATEDIALOG) und zum zweiten als Dialogfenster (@CREATEWINDOW), dessen Stil mit WINDOWSTYLE eingestellt werden kann. In beiden Fällen handelt es sich um nichtmodale Fenster, d.h.: Wenn der Anwender außerhalb des Dialoges etwas anklickt, kann die Anwendung darauf reagieren. Soll der Anwender nichts anderes machen können, bevor der Dialog abgearbeitet ist muß das Programm (will heißen: Sie als Programmierer) dafür Sorge tragen, daß nur auf Ereignisse des Dialoges reagiert wird. Normalerweise wird man für jeden Dialog eine eigene Prozedur schreiben, die erst dann verlassen wird, wenn der Dialog beendet ist. Mit dem Dialoghelfer lassen sich komplette Dialogboxen sehr rasch realisieren. In diesem Kursteil werden wir ihn jedoch einmal beiseite lassen und Dialoge "zu Fuß" programmieren. Das Verständnis der Programmierung von Dialogboxen ohne Helfer ist eine unverzichtbare Hilfe beim Anpassen der vom Helfer erzeugten Programmgerüste! Ein erster minimalistischer Dialog Um einen ersten Dialog zu programmieren schreiben wir ein Mini-Programm mit einem kleinen Dialog. Das Programm hat nur ein Menü "Aktion" mit den beiden Menüpunkten "Dialog 1" und "Ende". Der Dialog bietet nicht mehr, als einen OK-Button, bei dessen Anklicken der Dialog beendet wird. Listing: Dialog 1 Declare Ende% PROC Dialog1 Declare hD%, hB%, OK% 'Dialogfenster erzeugen Let hD% = @CreateDialog(%HWnd,"Dialogfenster",80,90,180,160) 'Einen Button mit OK erzeugen Let hB% = @CreateButton(hD%,"&OK",120,100,40,25) 'Dialog-Schleife Let OK% = 0 WhileNot Ok% WaitInput If @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 EndIf Wend 'Dialogfenster (incl. Button) entfernen @DestroyWindow(hD%) ENDPROC Seite 147 RGH-PROFAN² 'Haupt-Programm '-------------Window 20,20-400,300 PopUp "&Aktion" AppendMenu 101,"&Dialog" Separator AppendMenu 199,"&Ende" Let Ende% = 0 WhileNot Ende% WaitInput If @MenuItem(101) Dialog1 ElseIf @MenuItem(199) Let Ende% = 1 EndIf Wend End Wie auch bei Menüs kann mit einem & der Hotkey, der unterstrichene Buchstabe markiert werden. Dieses Fensterobjekt kann dann mit ALT und diesem Buchstaben angewählt werden In unserem Beispielprogramm gehört das Dialogfenster zum PROFAN²- Hauptfenster (%HWnd) und sein Handle wird in hD% gespeichert. Die Fensterobjekte des Dialoges gehören zum Dialogfenster (hd%). Im Beispiel wird ein Button mit der Aufschrift "OK" erzeugt und sein Handle in hB% gespeichert. Anschließend folgt die in PROFAN² übliche WHILE-Schleife mit dem WAITINPUT. WAITINPUT wartet auf ein Ereignis. Ein solches Ereignis ist z.B. das Anklicken eines Fensterobjektes oder das <Enter> in einem Eingabefeld oder Drücken eines über TAB angewählten Buttons mit SPACE ... Im Beispiel wird dann, wenn das Ereignis den "OK"-Button betrifft, die Variable OK% auf 1 gesetzt und damit die WHILE-Schleife verlassen. Vor Verlassen der Dialog-Prozedur wird das Dialogfenster entfernt und mit ihm auch der OK-Button, da dieser ja in der Fensterhierarchie ein dem Dialogfenster untergeordnetes Fenster war. Da die WHILESchleife nur dann verlassen wird, wenn OK angeklickt wurde, reagiert das Programm nicht auf andere Ereignisse, wie z.B. Menüauswahl, bevor der Dialog beendet wird. Sollte unser Programm z.B. auch auf das Beenden durch den Menüpunkt Ende reagieren, müßte das Menüereignis auch in der Dialogschleife abgefragt und die Variable Ende% auf 1 gesetzt werden. Diese Variante fügen wird als Dialog2 in unser Programm ein. Seite 148 RGH-PROFAN² PROC Dialog2 Declare hD%, hB%, OK% 'Dialogfenster erzeugen Let hD% = @CreateDialog(%HWnd,"Dialogfenster",80,90,180,160) 'Einen Button mit OK erzeugen Let hB% = @CreateButton(hD%,"&OK",120,100,40,25) 'Dialog-Schleife Let OK% = 0 WhileNot Ok% WaitInput If @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 ElseIf @MenuItem(199) 'Menüpunkt "Ende" Let Ok% = 1 Let Ende% = 1 EndIf Wend 'Dialogfenster (incl. Button) entfernen @DestroyWindow(hD%) ENDPROC Ein Text in der Dialogbox ist manchmal angebracht Hin und wieder ist es sinnvoll, Dialogboxen zum Anzeigen von kurzen Texten zu verwenden. Wir wollen den Text "Ihre Festplatte wird formatiert!" anzeigen. Um in einer Dialogbox Text anzuzeigen, verwenden wir die Funktion @CREATETEXT. Da der Text nur angezeigt wird, benötigen wir sein Handle nicht, d.h. wir brauchen das Ergebnis keiner Variablen zuzuweisen. Fügen wir unserem Programm also noch einen dritten Dialog hinzu. PROC Dialog3 Declare hD%, hB%, OK% Let hD% = @CreateDialog(%HWnd,"Dialogfenster 3",80,90,180,160) Let hB% = @CreateButton(hD%,"&OK",120,100,40,25) @CreateText(hD%,"Ihre Festplatte wird formatiert", \ 20,5,140,50) 'Dialog-Schleife Let OK% = 0 WhileNot Ok% WaitInput If @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 EndIf Wend @DestroyWindow(hD%) ENDPROC Das Ergebnis ist ebenso beeindruckend wie erschreckend. Der Computer teilt mit, daß die Festplatte formatiert wird, und läßt als Antwort lediglich OK% zu. (Keine Angst: Natürlich formatiert das PROFAN²-Programm NICHT Ihre Festplatte. PROFAN² hat keinen Befehl, mit dem dies möglich wäre.) Die nächste Erweiterung wäre also ein zweiter Button, der Abbruch heißt. Natürlich soll auch dieser Button den Dialog beenden. Während bei "Abbruch" nichts geschehen soll, wird bei "OK" eine Aktion erfolgen. In unserem Beispiel wird "Ihre Festplatte wurde formatiert." in das Hauptfenster geschrieben. Seite 149 RGH-PROFAN² PROC Dialog4 Declare hD%, hB%, hA%, OK% Let hD% = @CreateDialog(%HWnd,"Dialogfenster 4",80,90,180,160) Let hB% = @CreateButton(hD%,"&OK",10,100,40,25) Let hA% = @CreateButton(hD%,"&Abbruch",100,100,60,25) @CreateText(hD%,"Ihre Festplatte wird formatiert", \ 20,5,140,50) 'Dialog-Schleife Let OK% = 0 WhileNot Ok% WaitInput If @GetFocus(hA%) 'ABBRUCH wurde angeklickt Let Ok% = 1 ElseIf @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 Print "Die Festplatte wurde formatiert!" EndIf Wend @DestroyWindow(hD%) ENDPROC Oftmals wird man eine solche Aktion aber erst nach dem Verlassen des Dialoges durchführen wollen. In diesem Fall gibt es prinzipiell zwei Möglichkeiten: Zum einen kann man eine Variable im Hauptprogramm deklarieren, der man dann je nach gedrücktem Button einen Wert zuweist. Zum anderen kann man eine zusätzliche Variable in der Dialogroutine deklarieren, deren Wert man direkt vor dem ENDPROC mittels RETURN <WERT> an das Hauptprogramm übergibt. Siehe hierzu die entsprechenden Ausführungen in der Hilfedatei (in der Referenz und dem Kapitel über Prozeduren). Eingabefelder Selbstverständlich sind auch normale Eingabefelder möglich. Ein Eingabefeld wird mit dem Befehl @CREATEEDIT erzeugt. Das Ergebnis dieser Funktion ist wie immer das Handle des Dialogelementes. Um nun herauszubekommen, welcher Text sich zu einem bestimmten Zeitpunkt im Eingabefeld befindet, ist die Funktion @GETTEXT zu verwenden, der als Parameter das Handle des Eingabefeldes übergeben wird. Diese Funktion ermittelt immer den Text des Dialogelementes mit dem angegebenen Handle. (Das kann also auch das Eingabefeld eines fremden Programmes sein, dessen Handle man mit %GETFOCUS ermittelt hat.) In einer Dialogbox oder Eingabemaske wird man den Inhalt der Eingabefelder nach dem Drücken der "OK"-Taste abfragen und ihn dann entsprechenden Stringvariablen zuordnen. In unserem Beispiel haben wir Eingabe-Felder für Name und Vorname. Seite 150 RGH-PROFAN² PROC Dialog5 Declare hD%, hB%, hA%, hV%, hN%, OK%, \ Name$, Vorname$ Let hD% = @CreateDialog(%HWnd,"Dialogfenster 5",80,90,180,160) @CreateText(hD%,"Vorname:", 10, 8,60,20) @CreateText(hD%,"Name:", 10,33,60,20) Let hV% = @CreateEdit(hD%,"",75, 5,85,24) Let hN% = @CreateEdit(hD%,"",75,30,85,24) Let hB% = @CreateButton(hD%,"&OK",10,100,40,25) Let hA% = @CreateButton(hD%,"&Abbruch",100,100,60,25) 'Dialog-Schleife @SetFocus(hV%) Let OK% = 0 WhileNot Ok% WaitInput If @Equ(%Key,2) 'Alt-F4 bzw. Schließen Let Ok% = 1 ElseIf @GetFocus(hA%) 'ABBRUCH wurde angeklickt Let Ok% = 1 Cls Print "... abgebrochen ..." ElseIf @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 Let Name$ = @GetText$(hN%) Let Vorname$ = @GetText$(hV%) Cls Print "Name: ";Vorname$,Name$ EndIf Wend @DestroyWindow(hD%) ENDPROC Bei den Eingabefeldern gibt es eine Besonderheit: Wenn der Parameter für die senkrechte Ausdehnung des Eingabefeldes negativ ist, wird die Paßwortfunktion aktiviert. Eingegebene Zeichen erscheinen als Sterne. Die Funktion @GETTEXT ermittelt trotzdem den eingegebenen Text. Mit dem Befehl SETTEXT könnte man auch vom Programm aus ein Eingabefeld mit einem Inhalt bestücken, wobei der erste Parameter der Funktion das Handle ist und der zweite der Text. Im Falle einer Dialogbox oder eines Fensters, ändert SETTEXT die Überschrift, bei Buttons und anderen Dialogelementen wird der entsprechende Text geändert. Um den Eingabekursor auf das erste Eingabefeld zu setzen, wird die Funktion @SETFOCUS verwandt. Wichtig ist, daß die Eingabefelder direkt nacheinander folgen, damit der Eingabekursor bei jedem Enter ein Feld weiter geht. Eine weitere Sache soll nicht unerwähnt bleiben: Bei den bisherigen Dialogfenstern blieb der Doppelklick auf das Systemmenü des Dialoges wirklungslos. Auch das Schließen über Alt-F4 bzw. den Menüpunkt "Schließen" funktionierte nicht. Im 5. Dialog ist dieses nun realisiert: Wenn die Systemvariable %KEY den Wert 2 hat, wurde eine der genannten Aktionen ausgeführt und ENDE% wird auf 1 gesetzt. Seite 151 RGH-PROFAN² Checkboxen, Radiobuttons und Icons Checkboxen sind die kleinen Kästchen zum Ankreuzen. Mit @CREATECHECKBOX werden sie erzeugt und mit @GETCHECK kann abgefragt werden, ob die Checkbox mit dem entsprechenden Handle angekreuzt ist oder nicht. In unserem Beispiel kann angekreuzt werden, ob der Name einem Kunden gehört oder nicht. Ein weiteres wichtiges Element sind die Radiobuttons. Sie treten in der Regel in Gruppenfeldern (neudeutsch: Groupboxen) auf und es kann in jeder Gruppe immer nur ein Radiobutton markiert sein. Wird keine GROUPBOX (das ist der Rahmen um die Gruppe) verwandt, gehören alle Radiobuttons eines Dialoges einer Gruppe an. Will man mehrere Gruppen von Radiobuttons bilden, muß man erst die erste Groupbox mit @CREATEGROUPBOX erzeugen, dann die entsprechen Radiobuttons mit @CREATERADIOBUTTON, dann die zweite Groupbox und ihre Radionbuttons und so weiter. Natürlich kann man Groupboxen auch ohne Radiobuttons zur Verschönerung des Dialoges verwenden. Und wenn man keinen Text für die Groupbox angibt, erhält man ein schlichtes Rechteck. Auch Radiobuttons werden mit @GETCHECK abgefragt und können mit SETCHECK gesetzt werden. Ein weiteres Dialogelement sind Icons. Alle in PROFAN² vorhandenen Icons können mit @CREATEICON in einem Dialog plaziert werden. Als letztes Beispiel ein Dialog, der alle bisher beschriebenen Elemente enthält. Seite 152 RGH-PROFAN² PROC Dialog6 Declare hD%, hB%, hA%, hV%, hN%, hK%, hGm%, hGw%, OK%, \ Name$, Vorname$ Let hD% = @CreateDialog(%HWnd,"Dialogfenster 6",80,90,180,200) @CreateText(hD%,"Vorname:", 10, 8,60,20) @CreateText(hD%,"Name:", 10,33,60,20) @CreateIcon(hD%,"PROFAN", 125,90) @CreateGroupBox(hD%,"Geschlecht",10,75,100,60) Let hV% = @CreateEdit(hD%,"",75, 5,85,24) Let hN% = @CreateEdit(hD%,"",75,30,85,24) Let hk% = @CreateCheckBox(hD%,"Kunde",10,55,60,24) Let hGw%= @CreateRadioButton(hD%,"weiblich",17, 93,80,20) Let hGm%= @CreateRadioButton(hD%,"männlich",17,113,80,20) Let hB% = @CreateButton(hD%,"&OK",10,140,40,25) Let hA% = @CreateButton(hD%,"&Abbruch",100,140,60,25) @SetFocus(hV%) SetCheck hGw%,1 '"weiblich" ankreuzen Let OK% = 0 WhileNot Ok% WaitInput If @Equ(%Key,2) 'Alt-F4 bzw. Schließen Let Ok% = 1 ElseIf @GetFocus(hA%) 'ABBRUCH wurde angeklickt Let Ok% = 1 Cls Print "... abgebrochen ..." ElseIf @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 Let Name$ = @GetText$(hN%) Let Vorname$ = @GetText$(hV%) Cls Print "Name: ";Vorname$,Name$ If @GetCheck(hGw%) Print "weiblich "; Else Print "männlich "; Endif If @GetCheck(hK%) Print "und Kunde!" Else Print "und noch nicht Kunde!" Endif EndIf Wend @DestroyWindow(hD%) ENDPROC Das Ganze fassen wir abschließend in ein Listing zusammen, welches am Ende dieses Kapitels abgedruckt ist. Der Vollständigkeit halber sei noch auf die weiteren Dialogelemente verwiesen, die PROFAN² 6.0 unterstützt: Es gibt sortierte und unsortierte Listoxen, mehrzeilige Editierfelder und Auswahlboxen, mit denen man aus einer Anzahl von Einträgen einen auswählen kann. Da diese aber ähnlich programmiert werden, wie die hier beschrieben Dialogelemente, soll in diesem Kursteil nicht näher darauf eingegangen werden. Ausführliche Hinweise finden sich im entsprechenden Kapitel der Einführung und in der Referenz! Seite 153 RGH-PROFAN² Noch ein wichtiger Hinweis In einem Dialog können Bildschirmelemente nur mit @CREATE... erzeugt werden. Alle anderen Ausgabebefehle, wie z.B. DRAWTEXT, PRINT oder die ganzen Grafikbefehle, wirken immer nur auf das Hauptfenster des PROFAN²-Programmes. Künftige PROFAN²Versionen werden hier möglicherweise flexibler sein. Seite 154 RGH-PROFAN² Listing: DIALOGE.PRF Declare Ende% PROC Dialog1 Declare hD%, hB%, OK% 'Dialogfenster erzeugen Let hD% = @CreateDialog(%HWnd,"Dialogfenster",80,90,180,160) 'Einen Button mit OK erzeugen Let hB% = @CreateButton(hD%,"&OK",120,100,40,25) 'Dialog-Schleife Let OK% = 0 WhileNot Ok% WaitInput If @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 EndIf Wend 'Dialogfenster (incl. Button) entfernen @DestroyWindow(hD%) ENDPROC PROC Dialog2 Declare hD%, hB%, OK% 'Dialogfenster erzeugen Let hD% = @CreateDialog(%HWnd,"Dialogfenster",80,90,180,160) 'Einen Button mit OK erzeugen Let hB% = @CreateButton(hD%,"&OK",120,100,40,25) 'Dialog-Schleife Let OK% = 0 WhileNot Ok% WaitInput If @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 ElseIf @MenuItem(199) 'Menüpunkt "Ende" Let Ok% = 1 Let Ende% = 1 EndIf Wend 'Dialogfenster (incl. Button) entfernen @DestroyWindow(hD%) ENDPROC PROC Dialog3 Declare hD%, hB%, OK% Let hD% = @CreateDialog(%HWnd,"Dialogfenster 3",80,90,180,160) Let hB% = @CreateButton(hD%,"&OK",120,100,40,25) @CreateText(hD%,"Ihre Festplatte wird formatiert", \ 20,5,140,50) 'Dialog-Schleife Let OK% = 0 WhileNot Ok% WaitInput If @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 EndIf Wend @DestroyWindow(hD%) ENDPROC Seite 155 RGH-PROFAN² PROC Dialog4 Declare hD%, hB%, hA%, OK% Let hD% = @CreateDialog(%HWnd,"Dialogfenster 4",80,90,180,160) Let hB% = @CreateButton(hD%,"&OK",10,100,40,25) Let hA% = @CreateButton(hD%,"&Abbruch",100,100,60,25) @CreateText(hD%,"Ihre Festplatte wird formatiert", \ 20,5,140,50) 'Dialog-Schleife Let OK% = 0 WhileNot Ok% WaitInput If @GetFocus(hA%) 'ABBRUCH wurde angeklickt Let Ok% = 1 ElseIf @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 Print "Die Festplatte wurde formatiert!" EndIf Wend @DestroyWindow(hD%) ENDPROC PROC Dialog5 Declare hD%, hB%, hA%, hV%, hN%, OK%, \ Name$, Vorname$ Let hD% = @CreateDialog(%HWnd,"Dialogfenster 5",80,90,180,160) @CreateText(hD%,"Vorname:", 10, 8,60,20) @CreateText(hD%,"Name:", 10,33,60,20) Let hV% = @CreateEdit(hD%,"",75, 5,85,24) Let hN% = @CreateEdit(hD%,"",75,30,85,24) Let hB% = @CreateButton(hD%,"&OK",10,100,40,25) Let hA% = @CreateButton(hD%,"&Abbruch",100,100,60,25) 'Dialog-Schleife @SetFocus(hV%) Let OK% = 0 WhileNot Ok% WaitInput If @Equ(%Key,2) 'Alt-F4 bzw. Schließen Let Ok% = 1 ElseIf @GetFocus(hA%) 'ABBRUCH wurde angeklickt Let Ok% = 1 Cls Print "... abgebrochen ..." ElseIf @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 Let Name$ = @GetText$(hN%) Let Vorname$ = @GetText$(hV%) Cls Print "Name: ";Vorname$,Name$ EndIf Wend @DestroyWindow(hD%) ENDPROC Seite 156 RGH-PROFAN² PROC Dialog6 Declare hD%, hB%, hA%, hV%, hN%, hK%, hGm%, hGw%, OK%, \ Name$, Vorname$ Let hD% = @CreateDialog(%HWnd,"Dialogfenster 6",80,90,180,200) @CreateText(hD%,"Vorname:", 10, 8,60,20) @CreateText(hD%,"Name:", 10,33,60,20) @CreateIcon(hD%,"PROFAN", 125,90) @CreateGroupBox(hD%,"Geschlecht",10,75,100,60) Let hV% = @CreateEdit(hD%,"",75, 5,85,24) Let hN% = @CreateEdit(hD%,"",75,30,85,24) Let hk% = @CreateCheckBox(hD%,"Kunde",10,55,60,24) Let hGw%= @CreateRadioButton(hD%,"weiblich",17, 93,80,20) Let hGm%= @CreateRadioButton(hD%,"männlich",17,113,80,20) Let hB% = @CreateButton(hD%,"&OK",10,140,40,25) Let hA% = @CreateButton(hD%,"&Abbruch",100,140,60,25) @SetFocus(hV%) SetCheck hGw%,1 '"weiblich" ankreuzen Let OK% = 0 WhileNot Ok% WaitInput If @Equ(%Key,2) 'Alt-F4 bzw. Schließen Let Ok% = 1 ElseIf @GetFocus(hA%) 'ABBRUCH wurde angeklickt Let Ok% = 1 Cls Print "... abgebrochen ..." ElseIf @GetFocus(hB%) 'OK wurde angeklickt Let Ok% = 1 Let Name$ = @GetText$(hN%) Let Vorname$ = @GetText$(hV%) Cls Print "Name: ";Vorname$,Name$ If @GetCheck(hGw%) Print "weiblich "; Else Print "männlich "; Endif If @GetCheck(hK%) Print "und Kunde!" Else Print "und noch nicht Kunde!" Endif EndIf Wend @DestroyWindow(hD%) ENDPROC 'Haupt-Programm '-------------Window 20,20-400,300 PopUp "&Aktion" AppendMenu 101,"Dialog AppendMenu 102,"Dialog AppendMenu 103,"Dialog AppendMenu 104,"Dialog AppendMenu 105,"Dialog AppendMenu 106,"Dialog Separator AppendMenu 199,"&Ende" &1" &2" &3" &4" &5" &6" Seite 157 RGH-PROFAN² Let Ende% = 0 WhileNot Ende% WaitInput If @MenuItem(101) Dialog1 ElseIf @MenuItem(102) Dialog2 ElseIf @MenuItem(103) Dialog3 ElseIf @MenuItem(104) Dialog4 ElseIf @MenuItem(105) Dialog5 ElseIf @MenuItem(106) Dialog6 ElseIf @MenuItem(199) Let Ende% = 1 EndIf Wend End Seite 158 RGH-PROFAN² Programmieren für Anwender P R O F A N ² 6.0 DIE einfache Programmiersprache für Windows 3.x und Windows 95 Teil 3: Referenz Seite 159 RGH-PROFAN² Übersicht Systemvariablen !Input $dbLUpdate $dbFName $dbFType $DosVer $Drive $GetInput $GetText $Input $ProfVer $SysPath $WinPath $WinVer %BitsPixel %BmpX %BmpY %Button %dbDeleted %dbEoF %dbFCount %dbFDecs %dbFLen %dbFNumber %dbHeader %dbMemo %dbRecSize %dbVersion %DDEWin %Desktop %Error %ErrNumber %Font %GetCount %GetCurSel %GetFocus %GetInputState %HDC %HDC2 %HINstance %HWnd %Input %IOResult %Key %LFN %MaxX %MaxY %MCIError %MenuItem %Message %MouseKey %MousePressed %MouseX %MouseY %MWnd (siehe %Message) %ParCount %PCount Seite 160 RGH-PROFAN² %PeekMessage %ScanKey %wmPaint %wmTimer %Win32 %WinTop %WinBottom %WinRight %WinLeft &BmpCol &dbRecCount &dbRecNo &GetTickCount &Input &LParam (siehe %Message) &SQLCount &WParam (siehe %Message) Seite 161 RGH-PROFAN² Übersicht Funktionen @! @$ @% @& @Abs @Add$ @Add @AddChoice @AddString @And @AnsiToOem$ @ArcTan @BlockRead @Bin$ @Byte @Char$ @ChooseDir$ @Chr$ @CloseCom @ComError @Control @Cos @Cot @CreateButton @CreateCheckBox @CreateChoiceBox @CreateDefButton @CreateDialog @CreateEdit @CreateExtDialog @CreateGroupBox @CreateHScroll @CreateIcon @CreateListBox @CreateMultiEdit @CreateRadioButton @CreateText @CreateSortedListBox @CreateVScroll @CreateWindow @CToD$ @Date$ @dbAppendBlank @dbClose @dbDelete @dbFind @dbGet$ @dbGetField$ @dbGetMemo @dbGo @dbIndex @dbOpen @dbPack @dbPut Seite 162 RGH-PROFAN² @dbPutField @dbPutMemo @dbPutRec @dbSeek @dbUndelete @dbUse @Del$ @DeleteChoice @DeleteString @DestroyWindow @DiskFree @DiskSize @Div& @Div @DToC$ @EditBox @Eof @Equ$ @Equ @Exp @ExtString$ @FilePos @FileSize @FindFirst$ @FindNext$ @FindWindow @Format$ @GetActiveWindow @GetBValue @GetByte @GetCheck @GetClip$ @GetCount @GetCurSel @GetDir$ @GetEnv$ @GetFAttr @GetFDate$ @GetFileSize @GetFocus @GetGValue @GetHandle @GetKey$ @GetLine$ @GetLineCount @GetPixel @GetRValue @GetString$ @GetText$ @GetUsage @GT @GT$ @Height @Hex$ (siehe @Bin$) Seite 163 RGH-PROFAN² @IconCount @If @Inkey$ @Inp @InpB @Input$ @Ins$ @InsertString @InStr @Int @KeyIn @Left$ @Len @Lg @List! @List$ @List% @List& @ListBox$ @ListBoxItem$ @Ln @LoadFile$ @Long @LongName$ @Lower$ @LT @LT$ @MCISend$ @MenuItem @MessageBox @Mid$ @MkStr$ @Mod @Mouse @MoveListToChoice @MoveListToEdit @MoveListToList @Mul @NEq @NEq$ @Not @Oct$ (siehe @Bin$) @OemToAnsi$ @Or @Ord @OpenCom @Par$ @Pi @Pow @PostMessage @Pwd$ Seite 164 RGH-PROFAN² @ReadCom @ReadIni$ @Right$ @RGB @Rnd @Round @SaveFile$ @ScanKey @SelectString @SendKey @SendMessage @SendString @SetActiveWindow @SetBit @SetCom @SetComExt @SetFocus @ShortName$ @ShowWindow @Sin @Space$ @SQLInit @Sqr @Sqrt @Str$ @String$ @Sub @SubStr$ @Tan @TestBit @Time$ @TMouse @Translate$ @Trim$ @Upper$ @UseDLL @Val @Width @WinExec @WinExecWait @Word @WriteCom @XOr Seite 165 RGH-PROFAN² Übersicht Befehle ´(Apostroph) Add AddFiles AddFonts AddString AddWindows Append AppendMenu AppendMenuBar Arc Assign Beep BlockWrite Byte Case CaseNot Char CharSet CheckMenu ChDir Chord ClearClip ClearList ClipLoadBMP Close CloseRW Cls Color Copy CopyBmp CopyBmpToMem CopySizedBmp CreateMenu DbCreate DbCreateIndex DDELink DDEExecute DDETerminate Dec Decimals Declare Def Dim Dim! Dim$ Dim% Dim& Dispose Seite 166 RGH-PROFAN² DrawIcon DrawExtBmp DrawExtIcon DrawLibIcon DrawSizedExtBmp DrawSysIcon DrawText Ellipse Else ElseIf EnableMenu EnableWindow EndIf End EndPaint EndPrint EndProc EndSub EndWhile Erase ExitWindows FileMode Fill Font FreeDLL GetMessage GoSub ... Return GoTo If ... ElseIf ... Else ... EndIf IfNot ... Else ... EndIf Inc Input Input# InsertMenu KillTimer Let Line LineTo ListBoxItem$ List! List$ List% List& LoadBmp LoadSizedBmp Locate Long MCLS MCopyBmp MCopySizedBmp MessageBox MkDir MoveTo Seite 167 RGH-PROFAN² Music Seite 168 RGH-PROFAN² NextPage NumWidth Orientation OpenRW OutP OutPB Parameters PassWord Pie Play PlaySound PopUp Print Print# Proc ... EndProc PutByte PutClip Randomize ReadText Rectangle Rem RemoveMenu Rename RePaint Reset Return Rewrite RmDir RoundRect Run SaveBmp SaveBmpToClip ScreenCopy Seek Separator SetAutoPaint SetCheck SetDialogFont SetErrorLevel SetFAttr SetLFN SetMenuItem SetPixel SetScrollPos SetScrollRange SetText SetTimer ... KillTimer SetTrueColor SetWindowPos Shell Seite 169 RGH-PROFAN² ShowCursor ShowMin ShowMax ShowNormal Sound String SQLDone SQLExec SQLSetNull SQLSetDel StartPaint ... EndPaint StartPrint ... EndPrint String StrWidth Sub SubPopUp TBox TextColor TraceOn TraceOff TrackMenu UseBrush UseCursor UseExtCursur UseExtMenu UseFont UseIcon UsePen WaitInput WaitKey WaitMouse WaitScan While ... EndWhile WhileNot ... EndWhile WinCopy Window WindowStyle WindowTitle WinHelp Word WriteIni Seite 170 RGH-PROFAN² 1. Systemvariablen Systemvariablen geben Auskunft über Zustände des Systems, z.B. die aktuelle Position der Maus, das aktuelle Laufwerk, etc. Es gibt vier Typen von Systemvariablen: $Name %Name &Name !Name - Der Ergebnistyp ist ein String - Der Ergebnistyp ist ein Integer - Der Ergebnistyp ist ein LongInt - Der Ergebnistyp ist ein Float Seite 171 RGH-PROFAN² !Input Der zuletzt mit Input eingegebene Float-Wert. Seite 172 RGH-PROFAN² $dbFName Name des aktuellen Feldes. Dieser enthält nur Großbuchstaben und den Unterstrich und maximal 10 Zeichen. $dbFType Typ des aktuellen Datenbank-Feldes: C = Character (String) N = Numerisch L = Logisch M = Memo D = Datum $dbLUpdate Datum der letzen Änderung der Datenbanktabelle in der Form TT.MM.JJ $DOSVer ermittelt die DOS-Version (z.B. "5.0" ) $Drive Das aktuelle Laufwerk (ohne Pfadangabe). $GetInput Der zuletzt mit der Funktion @Input$ eingegebene Text. $GetText Der zuletzt in einer Listbox (Funktion @ListBox$) ausgewählte Text. $Input Der zuletzt mit Input eingegebene String. $ProfVer Die aktuelle PROFAN²-Version in der Form "X.YY-ZZ". Dabei steht X für die Hauptversionsnummer, YY für die Unterversionsnummer und ZZ für die Bitzahl (16 = Windows 3.x- Version / 32 = Windows95/NT-Version). Für Version 5.0 für Windows 3.x wäre das Ergebnis z.B. "5.0-16", eine möglicherweise kommende Version 5.1a für Windows95 hätte das Kennzeichen "5.1a-32". Seite 173 RGH-PROFAN² $SysPath Windows-System-Pfad (z.B. "C:\WINDOWS\SYSTEM" ) $WinPath Windows-Pfad (z.B. "C:\WINDOWS" ) $WinVer ermittelt die Windows-Version (z.B. "3.10") Seite 174 RGH-PROFAN² %BmpX Breite des zuletzt geladenen oder gespeicherten LOADSIZEDBMP, MLOADBMP, SAVEBMP) Bildes. (nach LOADBMP, %BmpY Höhe des zuletzt geladenen oder gespeicherten Bildes. %BitsPixel Die Farbauflösung des aktuellen Bildschirmtreibers in Bits pro Pixel: 1 = 2 Farben 4 = 16 Farben 8 = 256 Farben 16 = 64k Farben (HighColor) 24 = 16M Farben (TrueColor) %Button Der in einer MessageBox oder einem der vordefinierten Dialoge gedrückte Knopf: 1234567- OK Abbrechen (Cancel) Abbrechen (Abort) Wiederholen Ignorieren Ja Nein Bei vordefinierten Dialogen wird entweder 1 für "OK" oder 2 für "Abbrechen" zurückgegeben. %dbDeleted Löschkennzeichen des aktuellen Datensatzes: 1 = Datensatz ist als gelöscht gekennzeichnet. 0 = Datensatz ist nicht als gelöscht gekennzeichnet. %dbEoF End-Of-File-Kennzeichen der aktiven Datenbanktabelle: 1 = Ende der Datenbanktabelle ist erreicht. 0 = ... ist noch nicht erreicht Seite 175 RGH-PROFAN² %dbFCount Zahl der Felder eines Satzes in der aktuellen Datenbank. %dbFDecs Dezimalstellen des aktuellen Datenbank-Feldes. Dieser Wert ist nur bei numerischen Feldern von Bedeutung. %dbFLen Länge des aktuellen Feldes. Bei numerischen Feldern zählt hier auch der Dezimalpunkt mit. Um zum Beispiel einen sechstelligen DM-Betrag mit zwei Nachkommastellen darzustellen, muß das Feld eine Länge von 9 haben. %dbFNumber Nummer des aktuellen Feldes. %dbHeader Länge des Headers der aktiven Datenbanktabelle. %dbMemo Gibt an, ob die geöffnete dBase-Tabelle Memofelder enthält. PROFAN² unterstützt nur das Memo- Format von dBase-III. %dbRecSize Länge eines Datensatzes der aktiven Datenbankabelle. %DDEWin Die Systemvariable enthält das Handle des DDE-Servers, wenn eine DDE-Verbindung erfolgreich aufgebaut wurde, ansonsten enthält sie 0. Sollte der DDE-Server während der Verbindung jedoch beendet werden, ändert die Systemvariable Ihren Wert nicht. Erst nach DDETERMINATE wird sie wieder auf 0 gesetzt. %DeskTop Handle des Hintergrundfensters. Seite 176 RGH-PROFAN² %Error Der zuletzt aufgetretene Fehlercode. Wie %IOResult wird %Error beim Auslesen wieder auf 0 gesetzt. Die Error-Werte: 012- kein Fehler Warnung Fehler %ErrNumber enthält die Nummer des zuletzt aufgetretenen Fehlers. Beim Auslesen wird %ERRNUMBER auf 0 zurückgesetzt. %Font Diese Systemvariable enthält ein Handle auf die mit USEFONT eingestellte Schrift. Kann verwendet werden, um mittels einer Message die Schrift eines Fensterelementes (Button, Liste, etc.) zu verändern. %GetCount Die Nummer des letzten Eintrags in der ListBox-Liste. ACHTUNG: Da der erste Eintrag die Nummer 0 hat, ist die tatsächliche Anzahl der Einträge um 1 höher! Beispiel: ClearList AddFiles "C:\WINDOWS\*.EXE" Print @add(%GetCount,1);" EXE-Dateien" %GetCurSel Nummer des in einer Listbox gewählten Eintrages. %GetFocus Handle des Fensterobjektes, das gerade aktiv ist. Im Gegensatz zu @GetActiveWindow() ermittelt %GetFocus das Handle des gerade aktiven Buttons, der aktiven Liste, des aktiven Editierfeldes, ... @GetActiveWindow() ermittelt das Handle des aktiven (Haupt)Fensters Wurde während eines WAITINPUT F1 gedrückt, während der Fokus in einer Dialogbox bzw. auf einem Diologelement ist, steht in %GetFocus der negative wert des Handles. Siehe auch: @GetFocus %GetInputState Augenblicklicher Eingabestatus: Wenn innerhalb der Anwendung ein Tastendruck oder eine Mausbewegung erfolgt, ist das Ergebnis <> 0! Notwendig ist diese Systemvariable bei der Programmierung von Bildschirmschonern. Siehe auch: %MousePressed Seite 177 RGH-PROFAN² Seite 178 RGH-PROFAN² %HDC Display-Context des Hauptfensters. Diese Systemvariable ist dann von Nutzen, wenn APIFunktionen aufrufen, die diesen Wert benötigen. %HDC2 Display-Context der Hauptfensterkopie (Diese enthält immer eine exakte Kopie des Fensters, um dieses bei Bedarf wieder neu aufzubauen.) %HInstance Das Instanz-Handle des aktuell laufenden PROFAN²-Programmes. Dieser Wert wird für diejenigen Funktionen und Befehle benötigt, die das Instanz-Handle eines Programmes benötigen, um auf dessen Resourcen zuzugreifen. Das Instanz-Handle anderer Programme ist der Rückgabewert von @WinExec bzw. @UseDLL. Mittels %HInstance kann auf die Resourcen (Strings, Icons, Bitmaps, Dialoge) des laufenden Programmes zugegriffen werden. Beispiel: Let Dlg% = @CreateExtDialog(%HInstance,%HWnd,"FileOpen") Hier wird der Dialog zum Laden einer Datei aus dem laufenden Programm angezeigt. (Im Interpreter ist dies PROFAN.EXE, beim fertigen zur EXE-Datei gelinkten Programm das Programm selbst.) Da z.B. mit dem "Resource Workshop" von Borland (vor dem Linken!) der PROFRUN.EXE Resourcen hinzugefügt, bzw. die bestehenden verändert werden können, eröffnen sich hier ungeahnte Möglichkeiten. Mit @GetUsage(%HInstance) kann ermittelt werden, wie oft ein Programm schon gestartet wurde. Folgende Zeilen am Anfang eines Programmes verhindern dessen Mehrfachstart: IF @Gt(@GetUsage(%HInstance),1) @MessageBox("Das Programm läuft bereits!","INFO",0) END ENDIF ACHTUNG: Die Funktion @GetUsage (entsprechend der API-Funktion GetModuleUsage) gibt es aus Gründen, die nur Microsoft kennt, nur im 16-Bit-Windows. Im 32-Bit-PROFAN² wird mittels eines Tricks diese 16-Bit-Funktion aufgerufen, da das 16-Bit-Windows in Windows 95 nahezu komplett enthalten ist. Unter Windows NT dürfte die Funktion eine Fehlermeldung erzeugen. %HWnd Handle des Hauptfensters eines PROFAN²-Programmes. %Input Der zuletzt mit Input eingegebene Integer-Wert. Seite 179 RGH-PROFAN² %IOResult Nach einer Dateioperation oder einer Directory-Suche enthält diese Variable den entsprechenden Wert: Die Werte entsprechenden den von Turbo-Pascal her bekannten Ergebnissen: 023512 15 16 17 18 100 101 102 103 104 105 106 - kein Fehler aufgetreten Datei nicht gefunden Pfad nicht gefunden Zugriff verweigert (ReadOnly?) Ungültiger Dateimodus Laufwerksnummer unzuzulässig Verzeichnis kann nicht gelöscht werden (noch Dateien drin?) RENAME nicht über Laufwerksgrenzen möglich (siehe Rename) Kein weiterer Eintrag (bei @FindFirst/@FindNext) Lesefehler von Diskette/Platte Schreibfehler auf Diskette/Platte Dateinummer ist keiner Datei mit ASSIGN zugeordnet (siehe Assign) Datei nicht offen (Reset, Rewrite oder Append fehlt) Datei nicht zum Lesen geöffnet (Reset fehlt) Datei nicht zum Schreiben geöffnet (Rewrite oder Append fehlt) Falsches Format (bei Input #N,..) %Key Der ANSI-Code der zuletzt gedrückten Taste. Anwendung nach den Befehlen WAITKEY und WAITINPUT: WaitInput If @Equ(Key,90) Print "Du hast 'Z' gedrückt" EndIf Außer auf Tastendrücken reagiert WAITKEY wie auch WAITINPUT noch auf folgende Ereignisse und bestückt %Key entsprechend: 1 2 4 5 13 255 Es wurde ein Eintrag in einer Listbox angewählt oder es wurde ein Eintrag einer Auswahlbox gewählt Es wurde in einer Dialogbox bzw. einem Dialogfenster auf das Systemmenü doppelgeklickt, bzw. "Schließen" ausgewählt Ein Fenster des Programmes wurde in der Größe verändert Es wurde F1 gedrückt, während der Fokus auf einem Dialogelement bzw. in einer Dialogbox war Es wurde in einem einzeiligen Editierfeld oder einer Listbox <Enter> gedrückt Es wurde ein Button, eine Checkbox oder ein Radiobutton angeklickt %LFN Die Systemvariable gibt an, ob lange Dateinamen verwandt werden. Normalerweise ermittelt die Systemvariable automatisch, ob Windows 95 (%LFN = 1) oder Windows 3.1 (%LFN = 0) genutzt wird. Sie kann allerdings durch SetLFN gesetzt werden. HINWEIS: In der 32-Bit-Version hat die Systemvariable immer den Wert 1! Seite 180 RGH-PROFAN² %MaxX Horizontale Auflösung des Bildschirmes. %MaxY Vertikale Auflösung des Bildschirmes. %MCIError Der zuletzt gemeldete Fehler beim Senden eines MCI-Strings zur Ansteuerung eines MultiMedia-Treibers (etwa CD, Soundkarte, MIDI-Gerät, etc.). Aussagekräftiger sind allerdings die von @MCISend$ zurückgelieferten Fehlermeldungen (in der Landessprache). %MenuItem Die Identifikationsnummer des zuletzt angewählten Menüpunktes. Wurde das CopyrightZeichen angeklickt, ist die Nummer 254, wurde kein Menüpunkt angeklickt ist sie 0. Die Nummern 1 .. 253 und 256 - 32766 können vom Programmierer verwandt werden. (255 und 32767 sind ohne Wirkung.) %Message - &WParam - &LParam - %MWnd Die Nummer der letzten aufgetretenen Message. Diese Systemvariable ist insbesondere in Zusammenhang mit dem Befehl GETMESSAGE und der Systemvariablen %PEEKMESSAGE sinnvoll, aber auch nach anderen WAIT-Befehlen oder gar in Schleifen ohne einen der genannten Befehle sinnvoll. Etwaige meldungsspezifische Daten finden sich in den Systemvariablen &LPARAM und &WPARAM, das Fenster für das die Message bestimmt ist in %MWND. %MouseKey Die zuletzt gedrückte Maustaste: 012- keine Taste gedrückt linke Maustaste rechte Maustaste Die Position der Maus findet sich in %MouseX und %MouseY. %MousePressed Gibt an, welche Taste augenblicklich gedrückt wird. Wird durch Abfrage nicht zurückgesetzt. Ergebnis: Siehe bei %MOUSEKEY %MouseX Die aktuelle X-Position der Maus. %MouseY Seite 181 RGH-PROFAN² Die aktuelle Y-Position der Maus. Anwendung besonders nach den Befehlen WAITMOUSE und WAITINPUT. Seite 182 RGH-PROFAN² %ParCount Die Anzahl der beim Programmaufruf übergebenen Kommandozeilen-Parameter. Parameter 0 ist beim Interpreter der Interpreter selber, bei der Runtime das Runtime-Modul und bei einer EXE-Datei die EXE-Datei. Parameter 1 ist bei Interpreter und Runtime das damit ausgeführte Programm. Weitere Hinweise siehe unter @PAR$. %PCount Gibt in die Anzahl der übergebenen Parameter des letzten Prozeduraufrufes wieder. Das ist dann nützlich, wenn man eine Prozedur schreibt, die mit einer variablen Anzahl von Parametern aufgerufen werden kann. Die Abfrage der Systemvariablen sollte möglichst am Anfang der Prozedur stehen. %PeekMessage Diese Systemvariable gibt an, ob eine Message anliegt. Wenn nicht, ist das Ergebnis 0, wenn ja werden die Systemvariblen %Message, &WParam, &LParam und %MWnd entsprechend gefüllt. Die Message wird nur gelesen, nicht aber aus der Messageschlange entfernt. Hierzu wäre der Befehl GETMESSAGE zu verwenden. %ScanKey Der Scancode (virtueller Code) der zuletzt gedrückten Taste. Wichtige Scancodes: 16 17 27 33 34 35 36 37 38 39 40 45 46 112 ... 123 - Shift Strg Esc BildHoch BildRunter Ende Pos1 Links Hoch Rechts Runter Einfg Entf F1 ... F12 %Win32 Diese Systemvariable ist bei PROFAN² für 16 Bit auf 0 gesetzt und bei PROFAN² für Windows 95 oder NT auf 1. Mit %Win32 ist es im Programm einfach, zwischen 16 und 32 Bit zu unterscheiden, was ja z.B. bei Messages und DLL-Aufrufen notwendig sein kann: IF %Win32 <Code für 32 Bit> ELSE <Code für 16 Bit> ENDIF %wmPaint Seite 183 RGH-PROFAN² Die Systemvariable wird auf 1 gesetzt, wenn das Eregnis wm_Paint ausgelöst wurde. Die Meldung wm_Paint sendet Windows immer dann an ein Programm, wenn sein Fenster aus welchen Gründen auchg immer ganz oder teilweise neu gezeichnet werden muß. Das geschieht also z. B. jedesmal dann, wenn ein anderes Fenster das Fenster verdeckt oder wenn das Fenster vergrößert wurde. Diese Meldung ist ein Ereignis, daß ein WAITINPUT beendet. wm_Paint wird nur ausgelöst, wenn das automatische Neuzeichnen mit SetAutoPaint ausgeschaltet wurde. Erst beim Auslesen wird %wmPaint wieder auf 0 gesetzt. Da es möglich ist, daß %wmPaint gesetzt wird, wenn auch andere Ereignisse auftreten, sollte es ggf. in einer eigenen IF-Struktur abgefragt werden. Beispiel: Seite 184 RGH-PROFAN² CLS SetAutoPaint 0 < ... Hier wird z.B. das Menü erzeugt, etc. ...> WhileNot %Ende WaitInput If %wmPaint <.. Fenster neu zeichnen ..> EndIf If ... <... übrige Abfragen ..> Endif EndWhile %wmTimer wm_Timer wird ausgelöst, sobald der Timer mit SetTimer eingestellt wurde und das Programm ein Hauptfenster hat. Das Ereignis beendet ein WAITINPUT. %wmTimer bleibt solange auf 1, bis die Systemvariable ausgelesen wird. Dadurch wird sie auf 0 zurückgesetzt. %WinTop Die y-Koordinate des oberen Fensterrandes %WinBottom Die y-Koordinate des unteren Fensterrandes %WinLeft Die x-Koordinate des linken Fensterrandes %WinRight Die x Koordinate des rechten Fensterrandes &BmpCol Farbanzahl des zuletzt mit LOADBMP oder LOADSIZEDBMP geladenen Bildes. &dbRecCount Anzahl der Datensätze der aktiven Datenbanktabelle &dbRecNo Nummer des aktuellen Datensatzes. Seite 185 RGH-PROFAN² &GetTickCount Die Systemvariable gibt die Anzahl von Millisekunden an, die vergangen sind, seit Windows gestartet wurde. Hinweis: Der interne Timer ist nach etwa 49 Tagen wieder bei Null angekommen, wenn Windows nicht vorher beendet wird. Die Systemvariable ermöglicht einfachere Zeitmessungen, als dies mit der @Time$-Funkton möglich ist. &Input Der zuletzt mit Input eingegebene LongInt-Wert. &SQLCount Anzahl der vom letzen SQL-Befehl bearbeiteten Datensätze. Hat &SQLCount den Wert -1, so ist ein Fehler aufgetreten. Seite 186 RGH-PROFAN² 2. Funktionen Eine Funktion gibt einen Wert zurück, der in der Regel von den Parametern der Funktion abhängig ist. Überall da, wo in PROFAN² Variablen oder konstante Werte (Literale) eingesetzt werden können, dürfen auch Funktionen stehen. Der Rückgabewert der Funktion sollte der gleiche Typ sein, wie der erwartete Wert. Alle Funktionsnamen in PROFAN² beginnen normalerweise mit einem @. Während viele Anwender mit mir der Meinung sind, daß das @ den Quellcode übersichtlicher macht, indem die Funktionen sofort erkennbar sind, gibt es auch einige, denen die Eingabe des @ (über <AltGr><Q>) zu umständlich ist. Ab dieser PROFAN²-Version (4.0) ist es möglich das @ überall wegzulassen. Im Interpretermodus kann dies zu Geschwindigkeitseinbußen führen. Die Performance der compilierten Programme ist davon unbeeinflußt. Funktionen, deren Funktionsnamen mit dem $ endet, geben in vielen Fällen einen String zurück, die übrigen Funktionen einen numerischen Wert. In einigen Fällen enden auch Vergeleichsfunktionen, die entweder 1 oder 0 zurückgeben mit einem $, um deutlich zu machen, das hiermit Strings verglichen werden. Wenn der Rückgabewert einer Funktion uninteressant ist, kann die Zuweisung auch weggelassen werden. Bis auf die immer noch notwendigen Klammern, wird die Funktion dann wie ein Befehl verwandt. Beispiel: @LISTBOX$("Das ist die Liste",0) In diesem Fall wird die Listbox nur zum Anschauen angezeigt oder aber das Ergebnis der Auswahl über die Systemvariable $GETTEXT gelesen. Seite 187 RGH-PROFAN² @!(N) N : Integer (0 ... 8) Ergebnis: Float Der N-te übergebene Parameter in einer selbstdefinierten Funktion (oder Prozedur) als Float. @$(N) N : Integer (0 ... 8) Ergebnis: String Der N-te übergebene Parameter in einer selbstdefinierten Funktion (oder Prozedur) als String. @%(N) N : Integer (0 ... 8) Ergebnis: Integer Der N-te übergebene Parameter in einer selbstdefinierten Funktion (oder Prozedur) als Integer. @&(N) N : Integer (0 ... 8) Ergebnis: LongInt Der N-te übergebene Parameter in einer selbstdefinierten Funktion (oder Prozedur) als LongInt. Der 0. Parameter ist nach Aufruf einer Prozedur oder einem Unterprogramm mit RETURN <Wert> zurückgegebene Wert. @Abs(N) N : Wert Ergebnis: Wert Absolutwert der Zahl N. Seite 188 RGH-PROFAN² @Add$(S1,S2) S1 : String S2 : String Ergebnis: String Verknüpfung der Strings S1 und S2. S2 wird an S1 angehängt. @Add(N1,N2) N1 : Wert - Summand N2 : Wert - Summand Ergebnis: Wert Die Summe von N1 und N2. Siehe auch: @Add$ @AddChoice(N,S) N: Integer - Handle der Auswahlbox S: String - hinzuzufügender String Ergebnis: Integer - Erfolg Der Auswahlbox mit dem Handle N wird der String S hinzugefügt. Er wird einsortiert. @AddString(N,S) N: Integer - Handle der Listbox S: String - hinzuzufügender String Ergebnis: Integer - Erfolg Der Listbox mit dem Handle N wird der String S hinzugefügt. Bei einer unsortierten Listbox wird er hinten angehängt, während er bei einer sortierten Listbox einsortiert wird. @And(N1,N2) N1 : Wert N2 : Wert Ergebnis: Wert Die Werte von N1 und N2 werden mit der AND-Funktion verknüpft. Das Ergebnis ist 0 wenn ein oder beide Werte 0 sind. Vergleiche: @OR, @NOT Seite 189 RGH-PROFAN² @AnsiToOem$(S) S : String Ergebnis: String Der String S wird von ANSI-Code in den ASCII-Code (OEM) umgewandelt. Diese Umwandlungen betreffen insbesondere die deutschen Sonderzeichen. Der ASCII-Code wird unter DOS verwandt, der ANSI-Code unter Windows. @ArcTan(N) N : Wert (Winkel in Bogenmaß) Ergebnis : Float Der Arcustangens des Winkels N. Seite 190 RGH-PROFAN² @Bin$(N) - @Oct$(N) - @Hex$(N) N : Integer oder LongInt - umzuwandelnder Wert Mir diesen Funktionen lassen sich Integerwerte (Integer und LongInt) in die Darstellung anderer Zahlensysteme übertragen. Hierbei steht BIN für die binäre Darstellung, OCT für die octale Darstellung und HEX für die Hexadezimale Darstellung. @Bin$(10) ergibt also "1010", @Oct$(10) ergibt "12" und @Hex$(10) ergibt "A". @BlockRead(#N,B,N1,N2) #N : Dateikennung B : Bereichsvariable N1 : LongInt - Adresse in der Bereichsvariablen N2 : LongInt - Anzahl Bytes Ergebnis: LongInt - tatsächlich gelesene Bytes Aus der mit OPENRW geöffneten Datei mit der Kennung #K werden maximal N2 Bytes (ausgehend von der aktuellen Position des Dateizeigers) gelesen und in der Bereichsvariablen B ab Adresse N1 abgelegt. Wird das Dateiende erreicht, bevor N2 Bytes gelesen wurden, wird als Ergebnis nur die Anzahl der tatsächlich gelesenen Bytes zurückgeliefert. Es können in der 16-Bit-Version nur max. 65520 Bytes gelesen werden. Beispiel: Declare B#,Anzahl% Dim B#,500 Assign #1,"TEST.DAT" OpenRW #1 Let Anzahl% = @BlockRead(#1,B#,0,500) CloseRW #1 Print Anzahl%;" Bytes gelesen!" @Byte(V,A) V: Bereichsvariable A: LongInt - Adresse Ergebnis: Integer - Wert Diese Funktion ermittelt der Wert des Bytes an der Adresse (Offset) A in der Bereichsvariablen V. Ist A außerhalb des mit DIM eingestellten Bereiches von V, erfolgt eine Fehlermeldung. Seite 191 RGH-PROFAN² @ChooseDir$(S) S : String - Titel der Dialogbox Ergebnis : String - gewählter Pfad Die Funktion ruft den Verzeichniswahl-Dialog auf. Er ähnelt dem SAVE-Dialog mit dem Unterschied, daß kein Dateiname eingegeben werden kann. Der Rückgabewert ist der gewählte Pfad: Let Pfad$ = @ChooseDir$("Verzeichnis wählen:") ChDir Pfad$ Bitte beachten: Der Dialog selbst wechselt nicht in den Pfad, sondern er gibt nur einen vorhandenen und gewählten Pfad zurück. Wird er mit "Abbruch" beendet, ist der Rückgabestring leer! @Chr$(N) N : Wert (0 .. 255) Ergebnis: String (1 Zeichen) Das Zeichen mit dem ANSI-Code N. @CloseCom(N) N:: Integer - Handle der Schnittstelle Ergebnis: Integer - Fehlercode Die Schnittstelle wird geschlossen. Im Fehlerfalle ist das Ergebnis negativ, ansonsten wird 0 zurückgegeben. @ComError(N) N: Integer - Handle der Schnittstelle Ergebnis: Integer - Fehlerstatus Die Funktion ermittelt den letzten Fehlerwert und den aktuellen Status für das angegebene Gerät. Tritt ein Schnittstellenfehler auf, sperrt Windows die Schnittstelle, bis der Fehler durch Aufruf der Funktion @COMERROR behoben wird. Daher sollte die Funktion nach jedem @READCOM bzw. @WRITECOM aufgerufen werden! Seite 192 RGH-PROFAN² Der Rückgabewert kann eine Kombination aus folgenden Werten sein: $0001 - Überlauf der Empfangswarteschlange. Entweder reicht der Platz in der Empfangswarteschlange nicht aus, oder die Übertragung wurde nach Erhalt des End-of-file-Zeichens fortgesetzt. $0002 - Ein Zeichen wird von der Hardware nicht rechtzeitig gelesen. Das Zeichen ist verloren. $0004 - Die Hardware stellte einen Parity-Fehler fest. $0008 - Die Hardware stellt einen Framing-Fehler fest. $0010 - Die Hardware stellte eine Abbruchbedingung fest. $0020 - Clear-to-send-Unterbrechung (time out). $0040 - Data-set-ready-Unterbrechung. $0080 - Receive-line-signal-detect-Unterbrechung. $0100 - Die Sendewarteschlange war voll. $0200 - Bei der Kommunikation mit der parallelen Schnittstelle trat ein Timeout auf. $0400 - Ein I/O-Fehler trat während des Versuchs der Kommunikation mit einer parallelen Schnittstelle auf. $0800 - Die parallele Schnittstelle war nicht gewählt. $1000 - Gerät an der parallelen Schnittstelle meldet Papierende. $8000 - Der gewünschte Modus wird nicht unterstützt, oder der Parameter H% ist fehlerhaft. @Control(S1,S2,N1,X,Y,DX,DY,N2,N3,N4) S1 : Klassenname (muß Windows bekannt sein) S2 : ggf. Text/Überschrift N1: Stil X,Y : linke, obere Ecke des Controls auf dem Fenster DX,DY : Größe des Controls N2 : Übergeordnetes Fenster N3 : Bei Fenstern mit Menüs das Menühandle Bei Dialogelementen die Nummer des Dialogelementes (Bei mehreren mit @Control erzeugten Dialogelementen eines Fensters sollte jedes einen anderen Wert erhalten. N4 : Instanz des Programmes (i.d.R. %HINSTANCE) Ergebnis : Integer - Handle des Dialogelementes Nähere Hinweise zu den Parametern finden Sie in der Windows-Literatur zur Erläuterung der API-Funktion "CreateWindow". Die Reihenfolge und Bedeutung der Parameter ist dort die Gleiche. Mit dieser Funktion können beliebige registrierte (Windows bekanntrgemachte) Dialogelemente, deren Klassenname und mögliche Stil-Werte bekannt sind, erzeugt werden. Neben neuen Controls, die etwa in DLLs geliefert werden, können auch die Standardcontrols verwandt werden und mit Eigenschaften versehen werden, die PROFAN² sonst nicht bietet. Zentrierter bzw. nach rechts ausgerichteter Text sind nun kein Problem mehr (Klasse "STATIC", Stil $50000001 bzw. $50000002). Hier die Klassennamen für die wichtigsten Standardcontrols und die Werte für die Wichtigsten Stile: Klassennamen: BUTTON, COMBOBOX, EDIT (ein- oder mehrzeilig, je nach Stil), LISTBOX, MDICLIENT, SCROLLBAR, STATIC (Text oder Icon, je nach Stil) Allgemeine Fensterstile: ws_Overlapped ws_Popup ws_Child ws_Minimize ws_Visible = = = = = $00000000 $80000000 $40000000 $20000000 $10000000 Seite 193 RGH-PROFAN² ws_Disabled ws_ClipSiblings ws_ClipChildren ws_Maximize ws_Caption ws_Border ws_DlgFrame ws_VScroll ws_HScroll ws_SysMenu ws_ThickFrame ws_Group ws_TabStop = = = = = = = = = = = = = $08000000 $04000000 $02000000 $01000000 $00C00000 $00800000 $00400000 $00200000 $00100000 $00080000 $00040000 $00020000 $00010000 ws_MinimizeBox ws_MaximizeBox = $00020000 = $00010000 { ws_Border + ws_DlgFrame } Seite 194 RGH-PROFAN² Edit-Control-Stile es_Left es_Center es_Right es_MultiLine es_UpperCase es_LowerCase es_Password es_AutoVScroll es_AutoHScroll es_NoHideSel es_OEMConvert = = = = = = = = = = = $0000 $0001 $0002 $0004 $0008 $0010 $0020 $0040 $0080 $0100 $0400 Button-Stile: bs_PushButton bs_DefPushButton bs_CheckBox bs_AutoCheckBox bs_RadioButton bs_3State bs_Auto3State bs_GroupBox bs_UserButton bs_AutoRadioButton bs_PushBox bs_OwnerDraw bs_LeftText = = = = = = = = = = = = = $00 $01 $02 $03 $04 $05 $06 $07 $08 $09 $0A $0B $20 Listbox-Stile lbs_Notify lbs_Sort lbs_NoRedraw lbs_MultipleSel lbs_OwnerDrawFixed lbs_OwnerDrawVariable lbs_HasStrings lbs_UseTabStops lbs_NoIntegralHeight lbs_MultiColumn lbs_WantKeyboardInput lbs_ExtendedSel lbs_Standard = = = = = = = = = = = = = $0001 $0002 $0004 $0008 $0010 $0020 $0040 $0080 $0100 $0200 $0400 $0800 lbs_Notify + lbs_Sort + ws_VScroll + ws_Border Combo-Box-Stile (Auswahlbox) cbs_Simple cbs_DropDown cbs_DropDownList cbs_OwnerDrawFixed cbs_OwnerDrawVariable cbs_AutoHScroll cbs_OEMConvert cbs_Sort cbs_HasStrings cbs_NoIntegralHeight = = = = = = = = = = $0001 $0002 $0003 $0010 $0020 $0040 $0080 $0100 $0200 $0400 Scroll-Bar-Stile: sbs_Horz sbs_Vert sbs_TopAlign sbs_LeftAlign sbs_BottomAlign sbs_RightAlign sbs_SizeBoxTopLeftAlign sbs_SizeBoxBottomRightAlign sbs_SizeBox = = = = = = = = = $0000 $0001 $0002 $0002 $0004 $0004 $0002 $0004 $0008 (Größenveränderungsbox) Seite 195 RGH-PROFAN² Static Control Constants (Stile für statische Controls - Text und Icon) ss_Left ss_Center ss_Right ss_Icon ss_BlackRect ss_GrayRect ss_WhiteRect ss_BlackFrame ss_GrayFrame ss_WhiteFrame ss_UserItem ss_Simple ss_LeftNoWordWrap ss_NoPrefix = = = = = = = = = = = = = = $00 $01 $02 $03 $04 $05 $06 $07 $08 $09 $0A $0B $0C $80 Dialog-Stile ds_AbsAlign ds_SysModal ds_LocalEdit ds_SetFont ds_ModalFrame ds_NoIdleMsg = = = = = = $01 $02 $20 $40 $80 $100 { { { { Edit items get Local storage } User specified font for Dlg controls } Can be combined with ws_Caption } wm_EnterIdle message will not be sent } Mehrere Stilkonstanten können durch Addition bzw. mittels OR kombiniert werden. Näheres, insbesondere die Erklärungen zu den Klassen und Stilen, entnehmen Sie bitte der einschlägigen Fachliteratur! @Cot(N) N : Wert (Winkel in Bogenmaß) Ergebnis : Float Der Cotangens des Winkels N. @Cos(N) N : Wert (Winkel in Bogenmaß) Ergebnis : Float Der Cosinus des Winkels N. @CreateButton(N,S,X1,Y1,X2,Y2) N : Integer - Handle des übergeordneten Fensters S : String - Text auf dem Button X1,Y1 : Integer - Linke obere Ecke des Buttons X2,Y2 : Integer - Größe des Buttons Ergebnis : Integer - Handle des Buttons Es wird ein Button (Schaltfläche) erzeugt. Parameter N ist das Handle der Dialogbox oder des Fensters auf dem sich der Button befindet. Die Koordinatenangaben sind relativ zu dieser Dialogbox oder diesem Fenster. Sie auch: @CreateDefButton Seite 196 RGH-PROFAN² Seite 197 RGH-PROFAN² @CreateCheckBox(N,S,X1,Y1,X2,Y2) N : Integer - Handle des übergeordneten Fensters S : String - Text rechts neben der Checkbox X1,Y1 : Integer - Linke obere Ecke der Checkbox X2,Y2 : Integer - Größe der Checkbox (inclusive Text) Ergebnis : Integer - Handle der CheckBox Es wird eine CheckBox (Kästchen zum ankreuzen) erzeugt. Parameter N ist das Handle der Dialogbox oder des Fensters auf dem sich die Checkbox befindet. Die Koordinatenangaben sind relativ zu dieser Dialogbox oder diesem Fenster. Siehe auch: @CreateRadioButton @CreateChoiceBox(N,S,X1,X2,Y1,Y2) N : Integer - Handle des übergeordneten Fensters S : String - muß ein Leerstring sein X1,Y1 : Integer - Linke obere Ecke der AuswahlBox X2,Y2 : Integer - Größe der AuswahlBox Ergebnis : Integer - Handle des erzeugten Objektes Es wird eine Auswahlbox erzeugt und ihr Handle zurückgegeben. Der zweite Parameter sollte ein Leerstring sein. Auch eine Zuweisung mit SETTEXT (oder äquivalenten Befehlen) sollte unterlassen werden, da dies zu unvorhersehbaren Reaktionen führen kann. Eine Auswahlbox ist eine Sonderform der sogenannten "Combobox": Durch Anklicken des Pfeiles nach unten kann aus einer Liste von Auswahlmöglichkeiten eine Zeile ausgewählt werden. Eine Eingabe von Zeilen ist nicht möglich. Die ausgewählte Zeile kann mit der Funktion @GETTEXT$ ermittelt werden. Eine Auswahlbox ist immer alphabetisch sortiert. @CreateDefButton(N,S,X1,Y1,X2,Y2) N : Integer - Handle des übergeordneten Fensters S : String - Text auf dem Button X1,Y1 : Integer - Linke obere Ecke des Buttons X2,Y2 : Integer - Größe des Buttons Ergebnis : Integer - Handle des Buttons Es wird ein Button (Schaltfläche) erzeugt. Parameter N ist das Handle der Dialogbox oder des Fensters auf dem sich der Button befindet. Die Koordinatenangaben sind relativ zu dieser Dialogbox oder diesem Fenster. Der Button ist defaultmäßig aktiviert. Siehe auch: @CreateButton Seite 198 RGH-PROFAN² @CreateDialog(N,S,X1,Y1,X2,Y2) N : Integer - Handle des übergeordneten Fensters S : String - Dialog-Überschrift X1,Y1 : Integer - Linke obere Ecke der Dialogbox X2,Y2 : Integer - Größe des Dialogbox Ergebnis : Integer - Handle des erzeugten Dialoges Es wird eine Dialogbox mit der Überschrift S erzeugt. Eine Dialogbox in PROFAN kann weder vergrößert oder verkleinert werden. Wenn CTRL3D.DLL im System ist, werden auch die selbsterzeugten Dialoge im 3D-Look angezeigt. In diese Dialogbox können alle in PROFAN möglichen Fensterobjekte plaziert werden. Wird die Dialogbox mit @DESTROYWINDOW zerstört, verschwinden auch alle von ihr abhängigen Fensterobjekte. @CreateEdit(N,S,X1,Y1,X2,Y2) N : Integer - Handle des übergeordneten Fensters S : String - Vorgabetext X1,Y1 : Integer - Linke obere Ecke des Eingabefeldes X2,Y2 : Integer - Größe des Eingabefeldes Ergebnis : Integer - Handle des erzeugten Objektes Es wird ein Eingabefeld zur Eingabe eines Strings erzeugt. S ist ein Vorgabewert für diesen String. Soll das Fenster anfänglich leer sein, ist ein Leerstring anzugeben. Parameter N ist das Handle der Dialogbox oder des Fensters auf dem sich das Eingabefeld befindet. Die Koordinatenangaben sind relativ zu dieser Dialogbox oder diesem Fenster. Wird Y2 als negativer Wert angegeben, so wird zwar trotzdem der absolute Wert als Größe genommen, aber gleichzeitig die Paßwortfunktion aktiviert: Alle eingegebenen Zeichen werden durch Sterne dargestellt. @CreateExtDialog I H S : Integer - Instanz-Handle der Datei, in der der Dialog ist : Integer - Handle des übergeordneten Fensters : String - Name des Dialogs Ergebnis : Integer - Handle des erzeugten Dialoges Es wird ein Dialog aus einer Resource angezeigt. Dialog-Resourcen können wahlweise durch einen Namen oder einen Integer gekennzeichnet sein. Daher darf der dritte Parameter ggf. auch ein Integer sein, etwa: Let Dlg% = @CreateExtDialog(I%,%HWnd,1001) Das Instanz-Handle wird bei DLLs mittels @UseDLL ermittelt und bei EXE-Dateien mittels @WinExec. Das Handle des ausführenden Programmes ist in der Systemvariablen %HInstance. Es ist also möglich, alle in einem Programm verwandten Dialoge mittels eines Tools wie des Resource-Workshops von Borland in eine DLL zu packen. Ebenso ist es z.B. möglich, die PROFRUN.EXE vor dem Linken entsprechend zu erweitern, bzw. die vorhandenen Dialoge zu benutzen. Mit @GetHandle ermitteln Sie die Handle der einzelnen Dialogelemente, wie Listboxen, Eingabefelder, etc. Seite 199 RGH-PROFAN² Hier ein einfaches Beispiel, daß den Datei-Öffnen Dialog aus PROFAN.EXE bzw. PROFRUN.EXE (Instanz-Handle = %HInstance) aufruft und angezeigt und ihn beim Drücken des OK-Buttons oder Abbruch-Buttons wieder verläßt. Mit dem Resource-Workshop von Borland läßt sich leicht ermitteln, daß der Dialog "FILEOPEN" heißt und der OK-Button den Wert 1 hat und der Abbruch-Button den Wert 2: Declare Ok%, Dlg%, Abbruch%, Ende% CLS Let Dlg% = @CreateExtDialog(%HInstance,%HWnd,"FILEOPEN") Let Ok% = @GetHandle(Dlg%,1) Let Abbruch% = @GetHandle(Dlg%,2) Let Ende% = 0 WHILENOT Ende% WaitInput IF @GetFocus(Ok%) Print "OK" Let Ende% = 1 ELSEIF @GetFokus(Abbruch%) Print "ABBRUCH" Let Ende% = 1 ENDIF ENDWHILE END @CreateGroupBox(N,S,X1,Y1,X2,Y2) N : Integer - Handle des übergeordneten Fensters S : String - Text, der links oben im Tahmen steht X1,Y1 : Integer - Linke obere Ecke des Gruppen-Rahmens X2,Y2 : Integer - Größe des Rahmens Ergebnis : Integer - Handle des erzeugten Objektes Es wird eine Gruppen-Rahmen erzeugt. Parameter N ist das Handle der Dialogbox oder des Fensters auf dem sich der Rahmen befindet. Die Koordinatenangaben sind relativ zu dieser Dialogbox oder diesem Fenster. Der Gruppen-Rahmen wird zur optischen Gruppierung innerhalb von Dialogboxen eingesetzt, aber auch zum gruppieren der Radiobuttons. @CreateHScroll(N,S,X1,X2,Y1,Y2) N : Integer - Handle des übergeordneten Fensters S : String - muß ein Leerstring sein X1,Y1 : Integer - Linke obere Ecke des Scrollbalkens X2,Y2 : Integer - Größe des Scrollbalkens Ergebnis : Integer - Handle des erzeugten Objektes Es wird ein horizontaler Scrollbalken erzeugt und sein Handle zurückgegeben. Der zweite Parameter sollte ein Leerstring sein. Standardmäßig ist der Wertebereich von 0 - 100 eigestellt; er kann aber mit SetScrollRange verändert werden. Mit @GetScrollPos kann der eingestellte Wert ausgelesen werden, mit SetScrollPos wird ein Wert eingestellt. @CreateIcon(N,S,X1,Y1) N : Integer - Handle des übergeordneten Fensters S : String - Name des Icons X1,Y1 : Integer - Linke obere Ecke des Icons Seite 200 RGH-PROFAN² Ergebnis : Integer - Handle des erzeugten Objektes Es wird ein Iconfeld zur Anzeige des Icons mit dem Namen S erzeugt. Parameter N ist das Handle der Dialogbox oder des Fensters auf dem sich das Iconfeld befindet. Die Koordinatenangaben sind relativ zu dieser Dialogbox oder diesem Fenster. @CreateListBox(N,S,X1,X2,Y1,Y2) N : Integer - Handle des übergeordneten Fensters S : String - muß ein Leerstring sein X1,Y1 : Integer - Linke obere Ecke der ListBox X2,Y2 : Integer - Größe der ListBox Ergebnis : Integer - Handle des erzeugten Objektes Es wird eine Listbox erzeugt und ihr Handle zurückgegeben. Der zweite Parameter sollte ein Leerstring sein. Auch eine Zuweisung mit SETTEXT (oder äquivalenten Befehlen) sollte unterlassen werden, da dies zu unvorhersehbaren Reaktionen führen kann. Siehe auch: @CreateSortedListbox @CreateMultiEdit(N,S,X1,X2,Y1,Y2) N : Integer - Handle des übergeordneten Fensters S : String - Text X1,Y1 : Integer - Linke obere Ecke der EditBox X2,Y2 : Integer - Größe der EditBox Ergebnis : Integer - Handle des erzeugten Objektes Es wird ein mehrzeiliges Editierfeld erzeugt und sein Handle zurückgegeben. Der zweite Parameter kann ein anfänglicher Text sein. Solange der Text nicht über 255 Zeichen lang ist, kann er mit SETTEXT zugewiesen und mit der Funktion @GETTEXT$ ermittelt werden. Für längere Texte ist die z.B. Funktion @MOVELISTTOEDIT zu verwenden oder mit der Funktion @SENDMESSAGE der Inhalt einer Bereichsvariablen an das Editierfeld zu senden. Beispiel: DECLARE Edit%,Bereich# LET Edit% = @CreateMultiEdit(%HWnd,"",10,10,200,200) DIM Bereich#,@Add(@FileSize("C:\PROFAN40\LIESMICH.TXT"),2) @ReadText Bereich#,"C:\PROFAN40\LIESMICH.TXT" @SendMessage(Edit%,$000C,0,Bereich#) WaitInput End Wird Y2 als negativer Wert angegeben, so wird zwar trotzdem der absolute Wert als Größe genommen, aber gleichzeitig die automatische Wortumbruch-Funktion aktiviert: Der horizontale Scrollbalken wird nicht angezeigt und ein Wort, das nicht mehr in eine Zeile paßt wird automatisch in die nächste Zeile gebracht. Seite 201 RGH-PROFAN² @CreateRadioButton(N,S,X1,Y1,X2,Y2) N : Integer - Handle des übergeordneten Fensters S : String - Text rechts neben dem RadioButton X1,Y1 : Integer - Linke obere Ecke des RadioButton X2,Y2 : Integer - Größe des RadioButton (inclusive Text) Ergebnis : Integer - Handle des erzeugten Objektes Es wird eine RadioButton erzeugt. Parameter N ist das Handle der Dialogbox oder des Fensters auf dem sich der RadioButton befindet. Die Koordinatenangaben sind relativ zu dieser Dialogbox oder diesem Fenster. Mehrere RadioButtons werden in einer Gruppe zusammengefaßt. Immer nur ein RadioButton einer Gruppe kann aktiviert sein. Eine neue Gruppe wird durch die Funktion @CREATEGROUPBOX markiert. Diese Gruppe ist "gültig" bis zum nächsten @CREATEGROUPBOX. Siehe auch: @CreateCheckBox @CreateSortedListBox(N,S,X1,X2,Y1,Y2) N : Integer - Handle des übergeordneten Fensters S : String - muß ein Leerstring sein X1,Y1 : Integer - Linke obere Ecke der ListBox X2,Y2 : Integer - Größe der ListBox Ergebnis : Integer - Handle des erzeugten Objektes Es wird eine sortierte Listbox erzeugt. Siehe auch: @CreateListBox @CreateText(N,S,X1,Y1,X2,Y2) N : Integer - Handle des übergeordneten Fensters S : String - Text X1,Y1 : Integer - Linke obere Ecke des Textes X2,Y2 : Integer - Größe des Textfeldes Ergebnis : Integer - Handle des erzeugten Objektes Es wird ein Textfeld zur Anzeige des Textes S erzeugt. Parameter N ist das Handle der Dialogbox oder des Fensters auf dem sich das Textfeld befindet. Die Koordinatenangaben sind relativ zu dieser Dialogbox oder diesem Fenster. Da in Dialogboxen bzw. Dialogfenstern die Befehle PRINT oder DRAWTEXT nicht anwendbar sind, ist das Textfeld dort die einzige Möglichkeit, Text anzuzeigen. @CreateVScroll(N,S,X1,X2,Y1,Y2) N : Integer - Handle des übergeordneten Fensters S : String - muß ein Leerstring sein X1,Y1 : Integer - Linke obere Ecke des Scrollbalkens X2,Y2 : Integer - Größe des Scrollbalkens Ergebnis : Integer - Handle des erzeugten Objektes Seite 202 RGH-PROFAN² Es wird ein vertikaler Scrollbalken erzeugt und sein Handle zurückgegeben. Der zweite Parameter sollte ein Leerstring sein. Standardmäßig ist der Wertebereich von 0 - 100 eigestellt; er kann aber mit SetScrollRange verändert werden. Mit @GetScrollPos kann der eingestellte Wert ausgelesen werden, mit SetScrollPos wird ein Wert eingestellt. @CreateWindow(N,S,X1,Y1,X2,Y2) N : Integer - Handle des übergeordneten Fensters S : String - Fenster-Überschrift X1,Y1 : Integer - Linke obere Ecke des Dialogfensters X2,Y2 : Integer - Größe des Dialogfensters Ergebnis : Integer - Handle des erzeugten Fensters Es wird ein Dialogfenster mit der Überschrift S erzeugt. Der Fensterstil kann vorher mit WINDOWSTYLE eingestellt werden. Da Das Dialogfenster alle in PROFAN² möglichen Fensterstile haben kann, kann es z.B. auch bei Bedarf verkleinert oder als Icon dargestellt werden. Ansonsten verhält sich ein Dialogfenster exakt so, wie die Dialogbox. Lediglich die 3D-Elemente werden nicht verwandt. @CToD$(S) S : String - Datum im landesspezifischen Format Ergebnis : String - Datum im Datenbankformat Diese Funktion wandelt ein Datum im landesspezifischen Format (z.B. "TT.MM.JJJJ") in das Format der Datenbank um. Seite 203 RGH-PROFAN² @Date$(N) N : Integer - Ausgabeform Ergebnis: String - Datum Die Funktion ermittelt das aktuelle Datum in verschieden Formaten: 0 : Kurzform im landesspezifischen Format (z.B. "09.04.1993") 1 : Langform (z.B. "9. April 1993") * 2 : Langform mit Tag (z.B. "Freitag, der 9. April 1993") * 3 : Datenbankformat JJJJMMTT (z.B. "19930409") 4 : Datumsformatkennung aus der WIN.INI Ausgabeform 4 gibt das in der WIN.INI eingestellte Datumsformat zurück, wobei das erste Zeichen das Trennzeichen ist und die drei folgenden für die Reihenfolge von Jahr (y), Monat (M) und Tag (d) stehen, z.B. ".dMy". * Die Formen 1 und 2 gelten nur für die deutsche Version von PROFAN² und geben immer die deutsche Form zurück. @dbAppendBlank() Ergebnis : LongInt - Nummer des aktuellen Datensatzes Ein leerer Datensatz wird an die Datenbank angehängt und kann nun bearbeitet werden. Das Ergebnis ist die Nummer des neuen Datensatzes. @dbClose(#N) N : Integer - Tabellenkennzeichen (1 .. 8) Ergebnis : LongInt - Anzahl der Datensätze Die Funktion schließt die Datenbanktaballe mit der Kennung N. Jede geöffnete Datenbanktabelle muß im Programm wieder geschlossen werden; anderenfalls können Daten verloren gehen. @dbDelete() Ergebnis : LongInt - Nummer des Datensatzes. Der aktuelle Datensatz wird als gelöscht gekennzeichnet. Seite 204 RGH-PROFAN² @dbFind(S,N) S : String - Suchbegriff N : Integer - Genauigkeit Ergebnis : Nummer des gefundenen Datensatzes Es wird der Datensatz gesucht, der S im Indexfeld enthält. (Bei mehreren Indices zählt der erste Index). N bestimmt, wie exakt gesucht wird: 0 - Es wird der erste Datensatz gefunden, der mit dem Suchbegriff S beginnt. 1 - Es wird der erste Datensatz gefunden, der mit dem Suchbegriff S identisch ist. Ergebnis: Datensatznummer des gefundenen Satzes. Es wird auf diesen Datensatz positioniert. Wurde keiner gefunden, ist das Ergebnis 0. (XBase: FIND S) Siehe auch: @dbSeek @dbGet$(S) S : String - Feldname Ergebnis : String - Feldinhalt Das Feld S des aktuellen Datensatzes wird gelesen. Das Ergebnis ist ein String. Beispiel: Let Name$ = @DBGet$("NAME") Bei numerischen Feldern kann der String mit @Str$ in eine entsprechende Zahl umgewandelt werden. Für die Umwandlung von Datumsfeldern gibt es die Funktion @DTOC$. Siehe auch: @dbGetField$ @dbGetField$(N) N : Integer - Nummer des Feldes Ergebnis : String - Feldinhalt Das Feld mit der Feldnummer N wird gelesen. Hier wird anstelle des Feldnamens die Feldnummer angegeben. Siehe auch :dbGet$ Seite 205 RGH-PROFAN² @dbGetMemo(S) S: String - Feldname Ergebnis: Integer - Abzahl der Zeichen im Memo-Text Wenn S ein Memo-Feld bezeichnet wird der dazugehörige Text aus der Memo-Datei in die Listboxliste übertragen. Zuvor wird sie geleert. Ist S kein Memo-Feld ist der Rückgabewert 0, ist S hingegen ein Memo-Feld ohne Text, wird 0 zurückgeliefert. Der Inhalt der Listboxliste kann z.B. mit @LISTBOX$ angezeigt oder mit @EDITBOX bearbeitet werden. Mit @DBPUTMEMO wird der geänderte Inhalt wieder zurückgeschrieben. Um in Erfahrung zu bringen, ob eine Tabelle überhaupt Memo-Felder hat, ist die Systemvariable %DBMEMO zu verwenden. Mit folgender Prozedur kann der dBase-Befehl MEMOEDIT nachgebildet werden, mit dem ein Memo-Feld gelesen, geändert und zurückgeschrieben wird: PROC MEMOEDIT Parameters FeldName$ @DBGETMEMO(FeldName$) IF @EDITBOX("Memo editieren",1) @DBPUTMEMO(FeldName$) ENDIF ENDPROC Aufgerufen wird die Prozedur mit dem Feldnamen des Memofeldes als Parameter. @dbGo(N) N : LongInt - Datensatznummer oder Datensatzbezeichner Ergebnis : LongInt - Datensatznummer Satz N wird zum aktuellen Datensatz und zum Bearbeiten aus der Tabelle in den Speicher geladen. Diese Arbeitskopie des Datensatzes wird mit den folgenden Funktionen gelesen und geändert. Anstelle der Satznummer N können auch folgende Datensatzbezeichner stehen: "|<" oder "TOP" ">|" oder "BOTTOM" ">" oder "NEXT" "<" oder "PREV" - geht geht geht geht zum zum zum zum ersten Datensatz letzten Datensatz nächsten Datensatz vorhergehenden Datensatz Beispiel: DBGO("NEXT") Wenn ein Index (oder mehrere Indices) geöffnet sind, wird dieser berücksichtigt. Das Ergebnis ist die Nummer des Datensatzes, zu dem positioniert wurde. Seite 206 RGH-PROFAN² @dbIndex(S) S : String - Namen der Indexdatei(en) Ergebnis : Integer - 1=OK, 0=Fehler Der Index wird genutzt. S enthält den (oder die) Namen der Indexdatei. Es können durch Kommata getrennt mehrere Indexdateien angegeben werden. Beispiel: LET X% = @DBIndex("IXNAME,IXORT") Das Ergebnis ist 1, wenn der Index gewählt werden konnte und 0, wenn ein Fehler auftrat, weil mindestens eine der Index-Dateien fehlen. (XBase: USE INDEX S) @dbOpen(#N,S) N : Integer - Tabellenkennzeichen (1 - 15) S : String - Dateiname der Datenbanktabelle Ergebnis : LongInt - Anzahl der Datensätze in der Tabelle Die Datenbanktabelle S (Tabelle im DBF-Format) wird geöffnet. N kann Werte von 1 bis 15 annehmen. Es können bis zu 15 Tabellen gleichzeitig geöffnet sein. Das Ergebnis ist die Anzahl der Datensätze in der Tabelle. Beispiel: LET Anz& = @DBOpen(#1,"KUNDEN.DBF") @dbPack() Ergebnis : Anzahl der Datensätze Alle als gelöscht markierten Datensätze werden endgültig aus der Datenbanktabelle entfernt. Das Ergebnis ist die Anzahl der verbleibenden Datensätze. Siehe auch: %dbDeleted @dbPut(S1,S2) S1 : String - Name des Feldes S2 : String - Neuer Inhalt Ergebnis : Integer (ohne Bedeutung: immer 1) Der String S2 wird in Feld S1 des aktuellen Datensatzes geschrieben. WICHTIG: Dieser Befehl betrifft nur die "Arbeitskopie" des Datensatzes im Speicher. Erst mit @DBPUTREC wird er endgültig in die Datenbanktabelle geschrieben. (XBase: REPLACE S1 WITH S2) Siehe auch: @dbPutField Seite 207 RGH-PROFAN² @dbPutField(N,S) N : Integer - Nummer des Feldes S : String - Neuer Inhalt Ergebnis : Integer (ohne Bedeutung: immer 1) Der String S wird in Feld Nummer N des aktuellen Datensatzes geschrieben. WICHTIG: Dieser Befehl betrifft nur die "Arbeitskopie" des Datensatzes im Speicher. Erst mit @DBPUTREC wird er endgültig in die Datenbanktabelle geschrieben. Siehe auch: @dbPut @dbPutMemo(S) S: String - Feldname Ergebnis: Integer - Erfolg Wenn S ein Memo-Feld bezeichnet, wird der Inhalt der Listboxliste in die dazugehörige Memo-Datei geschrieben und der Inhalt des Memofeldes (der Veweis auf die Memo-Datei) entsprechend aktualisiert. Trat ein Fehler auf oder bezeichnet S kein Memo-Feld, dann ist der Rückgabewert der Funktion 0, anderenfalls ist er 1. @dbPutRec(N) N : LongInt - Datensatznummer Ergebnis: LongInt - Nummer des geschriebenen Satzes Der aktuelle Datensatz (die Arbeitskopie im Speicher) wird als Datensatz an Position N in die Datenbanktabelle geschrieben. Hat N der Wert 0, wird der aktuell positionierte Datensatz mit den neuen Werten überschrieben. Ergebnis: aktuelle Datensatznummer. @dbSeek(S1,S2) S1 : String - Name des Feldes, in dem gesucht wird S2 : String - Suchbegriff N : Integer - Suchgenauigkeit (0, 1 oder 2) Ergebnis : Nummer des gefundenen Datensatzes Suche ohne Index in einem beliebigen Feld des Datensatzes. Es wird der erste Datensatz gefunden, der im gewünschten Feld den Suchbegriff enthält. Die Suche beginnt mit dem aktuellen Datensatz. Ergebnis: Datensatznummer des gefundenen Satzes. Es wird auf diesen Datensatz positioniert. Wurde keiner gefunden, ist das Ergebnis 0. Mir dem optionalen Parameter N kann die Suchgenauigkeit erhöht werden: Ist N gleich 0, funktioniert die Funktion so, als wäre N nicht vorhanden: S2 muß irgendwo im Feld vorhanden sein. Bei 1 muß das gesuchte Feld mit S2 beginnen und bei 2 muß der gesuchte Eintrag dem Suchwort S2 exakt entsprechen. Groß-/Kleinschreibung spielt allerdings keine Rolle. Siehe auch: @dbFind Seite 208 RGH-PROFAN² Seite 209 RGH-PROFAN² @dbUndelete() Ergebnis : LongInt - Nummer des Datensatzes. Die Löschmarkierung wird wieder entfernt. @dbUse(#N) N : Integer - Tabellenkennzeichen (1 - 15) Ergebnis : LongInt - Anzahl der Sätze in der Tabelle Die Datenbanktabelle mit der Kennung N wird zur aktuellen Datenbanktabelle. Alle weiteren Datenbankbefehle und -funktionen beziehen sich auf diese Tabelle. @Del$(S,N1,N2) S : String N1 : Wert - Position N2 : Wert - Zeichenzahl Ergebnis: String Ab der Position N1 werden N2 Zeichen aus dem String entfernt. @DeleteChoice(N1,N2) N1: Integer - Handle der AuswahlBox N2: Integer - Nr. des Eintrages (1. Zeile = 0) Ergebnis: Integer - Erfolg Der String mit dem Index N2 wird aus der Auswahlbox N1 entfernt. Dabei ist zu berücksichtigen, daß die erste Zeile den Index 0 hat. @DeleteString(N1,N2) N1: Integer - Handle der Listbox N2: Integer - Nr. der Zeile (1. Zeile = 0) Ergebnis: Integer - Erfolg Der String mit dem Index N2 wird aus der Listbox N1 entfernt. Dabei ist zu berücksichtigen, daß die erste Zeile den Index 0 hat. Seite 210 RGH-PROFAN² @DestroyWindow(N) N : Integer - Handle eines Fensterobjektes Ergebnis : Integer - 1=Erfolg / 0=Mißerfolg Das Fenster oder Fensterobjekt mit dem Handle N wird entfernt. War die Aktion erfolgreich, ist das Ergebnis 1 ansonsten ist es 0. @DiskFree(S) S : String - Laufwerksbezeichnung Ergebnis: LongInt Das Ergebnis ist der freie Speicher auf Laufwerk S in Byte. Ist das Ergebnis z.B. 2024, so sind noch 2 kB frei. Ist das Laufwerk nicht vorhanden oder nicht lesbar, ist das Ergebnis 0. Beispiel: Print @DiskFree("C:");" Bytes frei" @DiskSize(S) S : String - Laufwerksbezeichnung Ergebnis: Wert Das Ergebnis ist der Gesamtspeicher auf Laufwerk S in kB. Ist das Ergebnis z.B. 43000000, so hat das Laufwerk ca. 43000 kB bzw. ca. 43 MB. Ist das Laufwerk nicht vorhanden oder nicht lesbar, ist das Ergebnis 0. Beispiel: Print @DiskSize("C:");" Bytes" @Div&(N1,N2) N1 : Wert N2 : Wert Ergebnis: Integer / LongInt Ganzzahliges Ergebnis der Division von N1 durch N2. @Div(N1,N2) N1 : Wert N2 : Wert Ergebnis: Wert Ergebnis der Division von N1 durch N2. Bei PROFAN 1.x-Programmen sollte vor dem Neucompilieren überall das @Div durch @Div& ersetzt werden, da PROFAN 1.x nur ganzzahlige Rechenoperationen beherrschte. Seite 211 RGH-PROFAN² @DToC$(S) S : String - Datum im Datenbank-Format Ergebnis : String - Datum im landespezifischen Format Da Datumsfelder das Datum in der Form "JJJJMMTT" speichern, was für Vergleiche ganz hervorragend ist, wandelt diese Funktion das Datum S vom Datenbankformat in das lesbare Format (z.B. "TT.MM.JJJJ") um. Dabei werden die nationalen Einstellungen in der WIN.INI berücksichtigt. Auch die Funktion @GETFDATE$ hat als Ergebnis das Datum im Datenbankformat. Seite 212 RGH-PROFAN² @EditBox(S,N) S - String: Überschrift des Editier-Dialoges N - Integer: Schriftart Ergebnis: Integer Ab Version 3.2 gibt es einen weiteren fertigen Dialog: Den Editierdialog. S ist die Überschrift des Dialoges und N der Modus: 1 = Proportionalschrift 2 = Courier (fester Zeichenabstand) Editiert werden die Zeilen der Listbox-Liste. Um einen Text zu editieren, ist er zuvor in die Listbox-Liste einzulesen. Das Ergebnis des Editiervorganges steht wiederum in der ListboxListe und kann in eine Datei geschrieben werden. Der zu editierende Text darf maximal etwa 30 kB groß sein. Mit den Buttons "Kopieren", "Ausschneiden" und Editiermöglichkeiten über die Zwischenablage gegeben. "Einfügen" sind die üblichen Wurde der Editiervorgang mit "OK" beendet, hat %BUTTON den Wert 1 und die Funktion gibt den Wert 1 zurück, ansonsten ist %Button 2 und der Rückgabewert 0. @Eof(#N) N : Integer - Dateinummer (1..15) Ergebnis: Integer (0 oder 1) Wenn mit dem letzten Lesen aus der Datei das Ende der Datei erreicht wurde, ergibt @Eof(#N) den Wert 1, ansonsten ist es 0. (Wegen Kompatibilität zu PROFAN 1.x kann das # auch weggelassen werden.) @Equ$(S1,S2) S1 : String 1 S2 : String 2 Ergebnis: Integer (0 oder 1) Das Ergebnis ist WAHR (1), wenn beide Strings gleich sind, UNWAHR (0), wenn die Strings verschieden sind. @EQU(N1,N2) N1 : Wert - Wert 1 N2 : Wert - Wert 2 Ergebnis: Integer (0 oder 1) Das Ergebnis ist WAHR (1), wenn beide Werte gleich sind, UNWAHR (0), wenn die Werte verschieden sind. Seite 213 RGH-PROFAN² @Exp(N) N - Wert Ergebnis - Float Exponentialfunktion @ExtString$(I,N) I : Integer - Instanz-Handle der Datei, in der der String ist N : Integer - Nummer des Strings in der Resource Ergebnis : String - String in der Resource Mit dieser Funktion kann auf in Resourcen gespeicherten Srings zugegriffen werden. Das Instanz- Handle wird bei DLLs mittels @UseDLL ermittelt und bei EXE-Dateien mittels @WinExec. Das Handle des ausführenden Programmes ist in der Systemvariablen %HInstance. Es ist also möglich, alle in einem Programm verwandten Strings mittels eines Tools wie des Resource-Workshops von Borland in eine DLL zu packen. Ebenso ist es z.B. möglich, die PROFRUN.EXE vor dem Linken entsprechend zu erweitern. Da in PROFAN² die maximale Stringlänge 255 ist, muß darauf beim Erstellen der Resourcen geachtet werden. Wird der String nicht gefunden, ist das Ergebnis ein Leerstring. Sinnvoll ist diese Funktion z.B. um mehrsprachige Anwendungen zu schreiben, bei denen die Strings und Dialoge einer Sprache jeweils in einer DLL sind. Seite 214 RGH-PROFAN² @FilePos(#N) #N: Dateikennung Ergebnis: LongInt - Aktuelle Position in der Datei Die aktuelle Position des Dateizeigers einer mit OPENRW geöffneten Datei wird ermittelt, wobei 0 das erste Byte der Datei bezeichnet. @FileSize(S) S : String - Dateiname (auch mit Pfad) Ergebnis : LongInt - Größe der Datei in Bytes Die Funktion ermittelt die Größe der angegebenen Datei in Bytes. @FindFirst$(S) S : String - Datei-Maske Ergebnis: String Die Funktion sucht die erste Datei im aktuellen Verzeichnis, die der Dateimaske entspricht. Das Ergebnis ist die gefundene Datei. Handelt es sich um ein Verzeichnis, steht es in eckigen Klammern. @FindNext$() Ergebnis: String Findet die nächste Datei, die zur mit @FINDFIRST$(S) gegebenen Maske paßt. War die Suche erfolgreich, ist %IORESULT = 0! Beispiel: Print @FindFirst$("*.PRF") WhileNot %IOResult Print @FindNext$() Wend @FindWindow(S) S : String - Gesuchter Fenstertitel Ergebnis : Integer - Handle des Fensters Gibt das Handle des Fensters zurück, dessen Überschrift mit S beginnt. Gibt es kein solches Fenster ist das Ergebnis 0. Seite 215 RGH-PROFAN² @Format$(S,N) S: String - Formatbeschreibung N: Wert Ergebnis: String - formatierter Wert Die Funktion @Format$ formatiert den in N angegebenen Gleitkommawert in dem durch S angegebenen Format. Die folgenden Formatangaben werden in dem Formatstring unterstützt: 0 Wenn der zu formatierende Wert an der entsprechenden Stelle eine Zahl hat, so wird diese in den Ergebnisstring kopiert. Ansonsten wird eine '0' an dieser Stelle eingesetzt. # Stellenplatzhalter. Wenn der zu formatierende Wert an der entsprechenden Stelle eine Zahl hat, so wird diese in den Ergebnisstring kopiert. Ansonsten wird an diesere Stelle nichts eingesetzt. . Dezimalpunkt. Das erste Auftreten des Zeichens '.' im Formatstring legt die Position des Trennzeichens für den Dezimalteil fest; jedes weitere Vorkommen von '.' wird ignoriert. Das tatsächlich als Dezimaltrennzeichen verwendete Zeichen wird durch die Windows-Einstellung festgelegt. , Trennzeichen für die Tausenderstellen. Wenn der Formatstring ein oder mehrere ','-Zeichen enthält, wird in dem Ergebnisstring zwischen jeder Gruppe von drei Stellen links vom Dezimalkomma das Trennzeichen eingefügt. Die Position und Anzahl der Zeichen ',' im Formatstring hat keinen weiteren Einfluß auf den Ergebnisstring, mit der Ausnahme, daß hierdurch angegeben wird, daß Trennzeichen für die Tausenderstellen gewünscht sind. Das tatsächlich als Trennzeichen verwendete Zeichen wird durch die Windows-Einstellung festgelegt. E+ Wissenschaftliche Notierung. Wenn in dem Formatstring einer der Strings 'E+', 'E-', 'e+' oder 'e-' vorkommen, wird die Zahl in wissenschaftlicher Notierung dargestellt. Bis zu vier Zeichen '0' können unmittelbar auf 'E+', 'E-', 'e+' oder 'e-' folgen, um die minimale Anzahl Stellen für den Exponenten festzulegen. Die Angaben 'E+' und 'e+' bewirken, daß für positive Exponenten ein Pluszeichen und für negative Exponenten ein Minuszeichen eingefügt wird. Die Angaben 'E-' und 'e-' bewirken, daß lediglich für negative Exponenten ein Minuszeichen eingefügt wird. 'xx' Zeichen, die von einfachen Anführungszeichen umgeben sind, werden wie angegeben dargestellt und beeinflussen nicht die Formatierung. Seite 216 RGH-PROFAN² ; Trennt die Bereiche für positive und negative Werte sowie für Nullwerte im Formatstring. Um für positive und negative Werte sowie für Nullwerte unterschiedliche Formate zu ermöglichen, kann der Formatstring bis zu drei durch Semikolon getrennte Bereiche enthalten. - Ein Bereich: Der Formatstring wird auf alle Werte angewendet. - Zwei Bereiche: Der erste Bereich wird für positive Werte und Nullwerte angewendet, der zweite Bereich für negative Werte. - Drei Bereiche: Der erste Bereich wird für positive Werte, der zweite Bereich für negative Werte und der dritte Bereich für Nullwerte angewendet. Wenn der Bereich für negative Werte oder der Bereich für Nullwerte leer ist, d.h. nichts zwischen den Semikolons steht, die den Bereich begrenzen, wird stattdessen der Bereich für positive Werte verwendet. Die Position der in dem Formatstring vor dem Dezimalpunkt am weitesten links stehenden '0' und der nach dem Dezimalpunkt am weitesten rechts stehenden '0' legt die Anzahl Stellen fest, die in dem Ergebnisstring immer dargestellt werden. Die zu formatierende Zahl wird immer auf so viele Dezimalstellen gerundet, wie Stellenplatzhalter ('0' or '#') rechts vom Dezimalpunkt vorhanden sind. Wenn der Formatstring keinen Dezimalpunkt enthält, wird der zu formatierende Wert auf die nächste Ganzzahl gerundet. Wenn die zu formatierende Zahl mehr Stellen links vom Dezimaltrennzeichen hat, als Stellenplatzhalter links vom Zeichen '.' im Formatstring vorhanden sind, werden die zusätzlichen Stellen vor dem ersten Stellenplatzhalter in dem Ergebnisstring eingefügt. Beispiel: PRINT @Format$("###,##0.00 ' H';"###,##0.00 ' S'",Wert!) Wenn der Wert z.B. +1234,45 ist, würde "~~1.234,45 H" ausgegeben werden und bei -0,12 käme "~~~~~~0,12 S" heraus, wobei hier die Tilde für ein Leerzeichen steht. @GetActiveWindow() Ergebnis : Integer - Fenster-Handle Die Funktion ermittelt das Handle des gerade aktiven Fensters. @GetBValue(N) N: Integer - Farbwert Ergebnis: Integer - Blauanteil der Farbe Der entsprechende Farbanteil einer Farbe wird ermittelt. Je nach Farbmodus ist es ein Wert zwischen 0 und 31 bzw. zwischen 0 und 255. Der Farbwert kann z.B. mit der Funktion @GetPixel ermittelt worden sein. Seite 217 RGH-PROFAN² @GetByte(#N) #N: Dateikennung Ergebnis: Integer - Wert (0...255) Es wird ein Byte aus einer mit OPENRW geöffneten Datei gelesen. Der Dateizeiger wird auf das nächste Byte positioniert. Zum Positionieren des Zeigers ist der Befehl SEEK zu verwenden. @GetCheck(N) N : Integer - Handle des Fensterobjektes Ergebnis : Integer - Zustand: 0=nicht aktiviert / 1=aktiviert Die Funktion gibt den Zustand der Checkbox bzw. des Radiobuttons mit dem Handle N zurück: 0 - Checkbox/Radiobutton ist nicht aktiviert 1 - Checkbox/Radiobutton ist aktiviert Siehe auch: SetCheck @GetClip$() Ergebnis : String Die Funktion liest Text aus dem Clipboard (max. 255 Zeichen). Die Zwischenablage wird bei Lesen nicht gelöscht. Dazu ist der Befehl ClearClip zu verwenden. Sie auch: PutClip @GetCount(N) N: Integer - Handle der Listbox Ergebnis: Integer - Anzahl der Elemente Die Anzahl der Elemente (Zeilen) einer Listbox wird ermittelt. Bitte berücksichtigen Sie, daß das erste Element der Listbox den Index 0 hat und somit der Index des letzten Elementes um 1 niedriger ist, als die ermittelte Anzahl der Elemente! @GetCursel(N) N: Integer - Handle der Listbox Ergebnis: Integer - aktuelle Position in der Listbox Die Position des Kursors (Balkens) in der Listbox N wird ermittelt. Die erste Zeile hat den Index 0. Seite 218 RGH-PROFAN² @GetDir$(S) S : Laufwerkskennzeichen Ergebnis: String (Pfad) Der Pfad des angegebenen Laufwerks wird ermittelt, wobei "@" für das aktuelle Laufwerk steht. Beispiel: Let CPfad$=@GetDir$("C:") Let Pfad$=@GetDir$("@") @GetEnv$(S) S : String - Name der Variablen Ergebnis : String - Inhalt der Variablen Die Funktion liest die entsprechenden Environmentvariable aus. Beispiel: LET Pfad$ = @GetEnv$("PATH") @GetFAttr(#N) #N: Dateikennung Ergebnis: Integer - Attribut Das Attribut einer Datei wird ermittelt. Der Dateikennung muß zuvor mit ASSIGN eine Datei zugewiesen worden sein. Die Datei darf nicht geöffnet sein. Die Werte für Attribute: $01 = ReadOnly $02 = Hidden $04 = SystemDatei $08 = Label $10 = Directory-Eintrag $20 = Archiv Werden mehrer Attribute verwandt, so sind sie zu addieren. Eine Systemdatei, die zusätzlich versteckt (hidden) ist, hat demzufolge $06 als Attribut. @GetFDate$(#N) #N: Dateikennung Ergebnis: String- Datum im Format "JJJJMMTT" Das Datum der Datei wird ermittelt. Der Dateikennung muß zuvor mit ASSIGN eine Datei zugewiesen worden sein. Die Datei muß (z.B. mit RESET) geöffnet sein. Seite 219 RGH-PROFAN² @GetFileSize(#N) #N: Dateikennung Ergebnis: LongInt - Größe der Datei in Bytes Die aktuelle Größe einer mit OPENRW geöffneten (!) Datei in Bytes wird ermittelt. Um die Größe einer ungeöffneten Datei zu ermitteln ist die Funktion @FileSize zu ermitteln. Der Vorteil von @GetFileSize liegt darin, daß die Größe einer gerade zum Bearbeiten geöffneten Datei ermittelt werden kann. @GetFocus(N) N : Integer - Handle eines Fensterobjektes Ergebnis : Integer (0 oder 1) Die Funktion ermittelt, ob das Fensterobjekt mit dem Handle N den Focus hat. Wenn es ihn hat, ist das Ergebnis 1 ansonsten ist es 0. Um zu ermitteln, wer den Focus hat, ist die Systemvariable %GETFOCUS zu verwenden. Wurde während eines WAITINPUT F1 gedrückt, während der Fokus in einer Dialogbox bzw. auf einem Diologelement ist, steht in %GetFocus der negative wert des Handles. @GetGValue(N) N: Integer - Farbwert Ergebnis: Integer - Grünanteil der Farbe Der entsprechende Farbanteil einer Farbe wird ermittelt. Je nach Farbmodus ist es ein Wert zwischen 0 und 31 bzw. zwischen 0 und 255. Der Farbwert kann z.B. mit der Funktion @GetPixel ermittelt worden sein. @GetHandle(H,N) H N : Integer - Handle der Dialoges, der das Element enthält : Integer - Nummer des Dialogelementes im Dialog Ergebnis : Integer - Handle des Dialogelementes Hiermit wird aus der Identifikationsnummer eines Dialogelementes und dem Dialog zu dem es gehört das Handle ermittelt. Beim Erstellen eines Dialoges mit einem Resourcen-Editor wird jedem Dialogelement ein eindeutiger Wert zugewiesen: die Identifikationsnummer. Zur Laufzeit interessiert uns aber das eindeutige Windows-Handle des Dialogelementes, denn dieses wird von den PROFAN²- Funktionen und den Windows-Messages zur Identifikation benutzt. Da dieses Handle erst beim Erzeugen des Dialoges (mittels der Funktion @CreateExtDialog) vergeben wird, können wir es auch erst zur Laufzeit nach dieser Funktion, mit der der Dialog auf den Bildschirm gebracht wird, ermitteln. Dazu dient die Funktion @Gethandle. Ein Beispiel findet sich in der Beschreibung der Funktion @CreateExtDialog. (Übrigens: Auch PROFAN² selbst vergibt jedem mit @Create... erzeugten Dialogelement eine solche Identifikationsnummer. Das erste Element im Programm hat die Nummer 1000. Von da an wird bei jedem @Create... um 1 hochgezählt.) Seite 220 RGH-PROFAN² @GetKey$() Ergebnis: String (1 Zeichen) Wartet auf einen Tastendruck und gibt das Ergebnis zurück. @GetLine$(N1,N2) N1: Integer - Handle der EditBox N2: Integer - Nr. des Zeile (1. Zeile = 0) Ergebnis: String - Zeile N2 der EditBox Die Zeile N2 der mehrzeiligen Editierbox N1 wird ermittelt. @GetLineCount(N) N: Integer - Handle der EditBox Ergebnis: Integer - Anzahl der Zeilen Die Anzahl der Zeilen eines mehrzeiligen Editierfeldes wird ermittelt. Bitte berücksichtigen Sie, daß das erste Element den Index 0 hat und somit die letzte Zeile einen um 1 niedrigeren Index hat, als die ermittelte Anzahl der Zeilen! @GetPixel(X,Y) X : Integer - X-Koordinate Y : Integer - Y-Koordinate Ergebnis : Integer - Farbwert (RGB) Farbwert des Bildpunktes an Position x,y. ACHTUNG: Je nach Grafikmodus weicht dieser Wert von dem in SetPixel übergebenen Farbwert ab, da z.B. im 16-Farbmodus ein Punkt nur eine von 16 Farben haben kann. @GetRValue(N) N: Integer - Farbwert Ergebnis: Integer - Rotanteil der Farbe Der entsprechende Farbanteil einer Farbe wird ermittelt. Je nach Farbmodus ist es ein Wert zwischen 0 und 31 bzw. zwischen 0 und 255. Der Farbwert kann z.B. mit der Funktion @GetPixel ermittelt worden sein. Seite 221 RGH-PROFAN² @GetString$(N1,N2) N1: Integer - Handle der Listbox N2: Integer - Nr. des Eintrages (1. Zeile = 0) Ergebnis: String - Zeile N2 der Listbox Die Zeile mit dem Index N2 wird aus der Listbox N1 ausgelesen. @GetText$(N) N : Integer - Handle des Fensterobjektes Ergebnis : String - Text des Fensterobjektes Es wird der Text des Fensterobjektes mit dem Handle N ermittelt. Im Falle eines Eingabefeldes ist es der eingegebene Text, ansonsten die Fensterüberschrift, der Text des Buttons oder der Text neben der Checkbox oder dem Radiobutton. (Kurz: Der Text der mittels der @CREATE...-Funktion oder dem SETTEXT-Befehl in S an das Fensterobjekt übergeben wurde.) @GetUsage(N) N : Integer - Handle eines Programmes Ergebnis: Integer - Anzahl der Instanzen N ist das Handle der mit @WINEXEC gestarteten Anwendung. Das Ergebnis gibt an, wie oft diese Anwendung gestartet wurde und wird 0, wenn die letzte Instanz der Anwendung geschlossen wird. So kann man z.B. ein Programm starten und solange in einer Schleife verharren, bis das Programm beendet wird: ... LET X%=@WINEXEC("NOTEPAD.EXE",3) WHILE @GETUSAGE(X%) WEND ... HINWEIS. Die dieser Funktion zugrundeliegende API-Funktion ist in der 32-Bit-API von Windows 95 nicht mehr enthalten. Um sie trotzdem im 32-Bit-PROFAN² zu implementieren, wurde eine undokumentierte Windowsfunktion benutzt, sodaß damit zu rechnen ist, daß diese Funktion unter Windows NT nicht erwartungsgemäß funktioniert. Für obiges Beispiel ist daher die Funktion @WINEXECWAIT vorzuziehen. @GT(N1,N2) N1 : Wert - Wert 1 N2 : Wert - Wert 2 Ergebnis: Wert (0 oder 1) Das Ergebnis ist WAHR (1), wenn Wert 1 größer als (Greater Than) Wert 2 ist. Seite 222 RGH-PROFAN² @GT$(S1,S2) S1 : String 1 S2 : String 2 Ergebnis: Integer (0 oder 1) Das Ergebnis ist WAHR (1), wenn String 1 größer als (Greater Than) String 2 ist. @Height(H) H : Integer - Handle des Fensters, Dialoges, Dialogelementes Ergebnis : Integer - Höhe des Elementes innerhalb des Rahmens Oftmals benötigt man zum Zeichnen die Größe des Fensters bzw. Dialoges innerhalb des Rahmens (so einer vorhanden ist). Diese Fläche wird auch der Client genannt. Bei einem Fenster schließt diese Fläche Menü und Titelleiste nicht mit ein, sondern es wird nur der Teil ausgemessen, der auch tatsächlich zum Malen, Schreiben, etc. genutzt werden kann. Seite 223 RGH-PROFAN² @IconCount(S) S - String: Dateiname (mit Pfad) Ergebnis: Integer - Anzah der Icons Die Funktion liefert die Anzahl der in S enthaltenen Icons zurück. S kann sowohl eine EXEDatei, eine DLL als auch eine Icon-Datei sein. Beispiel: Let Anz% = @IconCount("PROGMAN.EXE") @If(N1,N2,N3) N1 : Wert - Bedingung N2 : Wert - Ergebnis bei erfüllter Bedingung N3 : Wert - Ergebnis bei nicht erfüllter Bedingung Ergebnis : Wert, abhängig von der Bedingung In Anlehnung an C gibt es das IF auch als Funktion. Die Funktion @IF hat drei Argumente: Das erste Argument ist die Bedingung; das zweite Argument ist der Wert, der zurückgegeben wird, wenn die Bedingung erfüllt ist und das dritte Argument ist schließlich der Wert, der bei unerfüllter Bedingung zurückgegeben wird. Beispiele: LET Text$ = @IF(@Equ(A%,1), "A ist gleich 1", \ "A ist ungleich 1") PRINT Text$ LET A% = @IF(@Gt(A%,1000),@Add(A%,200),@Add(A%,50)) PRINT A% Im zweiten Beispiel wird zu A% 200 addiert wenn es größer als 1000 ist; im anderen Fall kommen nur 50 dazu. @Inkey$() Ergebnis: String (1 Zeichen) Gibt als Ergebnis das Zeichen der aktuell gedrückten Taste zurück. @Inp(N) N : Integer - Port-Adresse Ergebnis : Integer - 16-Bit-Wert an Port N Es wird ein Datenwort (16 Bit bzw. 2 Byte) am Input-Port N (und N+1) gelesen. Das niederwertige Byte liegt an Port N und das höherwertige an Port N+1 an. ACHTUNG: Man sollte wissen, was man tut, da unter Windows nicht alle Port-Adressen gelesen werden können. Ein Absturz von Windows mit Datenverlust ist dadurch möglich. HINWEIS: Unter Windows NT sind direkte Zugriffe auf die Hardware nicht gestattet. Die Funktionen @INP und @INPW sind hier zu vermeiden. Seite 224 RGH-PROFAN² @InpB(N) N : Integer - Port-Adresse Ergebnis : Integer - 8-Bit-Wert (Byte) an Port N Es wird ein Byte (8 Bit) am Input-Port N gelesen. ACHTUNG: Man sollte wissen, was man tut, da unter Windows nicht alle Port-Adressen gelesen werden können. Ein Absturz von Windows mit Datenverlust ist dadurch möglich. HINWEIS: Unter Windows NT sind direkte Zugriffe auf die Hardware nicht gestattet. Die Funktionen @INP und @INPW sind hier zu vermeiden. @Input$(S1,S2,S3) S1 - String: Prompt (Frage) S2 - String: Fensterüberschrift S3 - String: Vorgabestring bzw. Vorgabewert Ergebnis: String bzw. Wert (Eingabe) Eine Dialogbox zur Eingabe eines Strings wird auf den Bildschirm gebracht. Diese Funktion sollte wo möglich anstelle des INPUT-Befehles verwandt werden. Ab PROFAN² 2.5 kann sowohl die Vorgabe als auch das Ergebnis numerisch sein. Die Funktion kann so zur Eingabe von Strings und numerischen Werten verwandt werden. Beispiele: Let Ort$=@Input$("Ort eingeben:,"Test","Köln") Let Z&=@Input$("Neuer Wert:","Test",Z&) @Ins$(S1,S2,N) S1 : String S2 : String N : Wert Ergerbnis: String Der String S1 wird in S2 an Position N eingegefügt. Seite 225 RGH-PROFAN² @InsertString(N1,N2,S) N1: Integer - Handle der Listbox N2: Integer - Position (gewünschte Zeile) S: String - einzufügende Zeile Ergebnis: Integer - Position des eingefügten Strings Die Zeile S wird an der Position N2 in der Listbox N1 eingefügt. Diese Funktion macht natürlich nur Sinn bei einer unsortierten Listbox. Hat N2 den Wert -1 wird die Zeile am Ende der Listbox angehängt. @Instr(S1,S2) S1 : String S2 : String Ergebnis: Wert Das Ergebnis gibt an, an welcher Position S1 in S2 vorkommt. Kommt S1 in S2 nicht vor, ist das Ergebnis 0. @Int(N) N : Wert Ergebnis : Integer / LongInt Ganzzahliger Anteil von N. Es wird nicht gerundet. (Gerundet wird bei Beschränkung der auszugebenden Stellen mit NUMWIDTH.) Seite 226 RGH-PROFAN² @KeyIn(S) S : String Ergebnis: Wert (0 oder 1) Das Ergebnis ist dann 1, wenn die zuletzt gedrückte Taste im String S vorkommt. Beispiel: WaitKey Case @KeyIn("AaBb"):Print "A oder B" Seite 227 RGH-PROFAN² @Left$(S,N) S : String N : Anzahl Zeichen Ergebnis : String Die N linken Zeichen des Strings werden zurückgegeben. @Len(S) S : String Ergebnis: Wert Länge des Strings S @Lg(N) N : Wert > 0 Ergebnis : Wert Dekadischer Logarithmus zum Wert N. @List!(N) N : Integer - Index (0 .. 32767 bzw. 16380) Ergebnis: Float Das Ergebnis ist der N. Eintrag der Float-Liste. Die Liste wird mit dem Befehl LIST! gefüllt. @List$(N) N : Integer - Index (0 .. 32767 bzw. 16380) Ergebnis: String Das Ergebnis ist der N. Eintrag der Stringliste. Die Liste wird mit dem Befehl LIST$ gefüllt. @List%(N) N : Integer - Index (0 .. 32767 bzw. 16380) Ergebnis: Integer Das Ergebnis ist der N. Eintrag der Integerliste. Die Liste wird mit dem Befehl LIST% gefüllt. Seite 228 RGH-PROFAN² @List&(N) N : Integer - Index (0 .. 32767 bzw. 16380) Ergebnis: LongInt Das Ergebnis ist der N. Eintrag der LongInt-Liste. Die Liste wird mit dem Befehl LIST& gefüllt. @ListBox$(S,N) S : String - Fenster-Überschrift N : Wert - Typ der Listbox (1 .. 8) Ergebnis: Ausgewählter String Der Inhalt der ListBox-Liste wird zur Auswahl (oder zum Durchblättern) angeboten. Der zweite Parameter gibt an, in welcher Form die ListBox angezeigt werden soll: 1 2 3 4 5 6 7 8 - groß - unsortiert - Systemschrift - groß - unsortiert - Courier 10 - groß - sortiert - Systemschrift - groß - sortiert - Courier 10 - klein - unsortiert - Systemschrift - klein - unsortiert - Courier 10 - klein - sortiert - Systemschrift - klein - sortiert - Courier 10 Die große (unsortierte) ListBox eignet sich insbesondere zur Darstellung von Texten. Diese werden eingelesen und dann angezeigt. Beispiel: ClearList AddFiles "*.BMP" Let Wahl$=@ListBox$("Wähle Bild:",7) LoadBmp Wahl$,10,10 Die Listbox-Liste wird ADDFILES, ADDWINDOWS und ADDSTRING gefüllt und mit CEARLIST geleert; %GETCOUNT enthält die Anzahl der Einträge und mit @LISTBOXITEM$ kann man einen einzelnen Eintrag auslesen. Siehe auch das Demo "Schnelleinstieg"! @ListBoxItem$(N) N : Integer (0 ... 9999) Ergebnis: String Der N-te Eintrag der ListBox-Liste wird ermittelt. Seite 229 RGH-PROFAN² @Ln(N) N : Wert > 0 Ergebnis : Wert Natürlicher Logarithmus zum Wert N. @LoadFile$(S1,S2) S1 : String - Überschrift S2 : String - Dateimaske (mit Pfad) Ergebnis: Dateiname (mit Pfad) Es wird eine Dateiauswahlbox zum Laden (Öffnen) mit der Überschrift S1 geöffnet. Das Ergebnis ist die gewählte Datei (mit Pfad), die geöffnet werden kann. Beispiel: LET NAME$=@LOADFILE$("ÖFFNE:","*.EXE") In der 32-Bit-Version werden die Systemdialoge zum Laden und Speichern verwandt. Diese erlauben den Einsatz mehrerer Dateifilter. Will man dieses Feature nutzen, kann man mehrere Dateifilter, die jeweils aus Beschreibung und Endung(en) bestehen, kombinieren. Wollten wir in unserem Beispiel neben *.EXE-Dateien auch *.PIF- und *:BAT-Dateien öffnen, könnte die Zeile wie folgt aussehen: Let Name$ = @LoadFile$("ÖFFNE","Programme|*.EXE;*.PIF|Batch|*.BAT") Der senkrechte Strich wird mit [AltGr]+[<] erreicht. @Long(V,A) V: Bereichsvariable A: Integer - Adresse Ergebnis: LongInt - Wert Diese Funktion ermittelt der Wert des 32-Bit-Wortes (4 Byte) an der Adresse (Offset) A in der Bereichsvariablen V. Ist A außerhalb des mit DIM eingestellten Bereiches von V, erfolgt eine Fehlermeldung. @LongName$(S) S: String - Mit @ShortName$ ermittelter Kurz-Name (8.3) einer Datei (incl. Pfad) Ergebnis: langer Name von Pfad und Datei Diese Funktion ermittelt zu einem kurzen Dateinamen (System 8.3) den dazugehörigen langen Dateinamen. Dabei darf der Dateiname auch einen Pfad enthalten. Wenn die Datei nicht (mehr) existiert wird ein Leerstring zurückgegeben. (Unter Windows 3.x, bzw. wenn die langen Dateinamen mit SetLFN 0 ausgeschaltet sind, wird immer der String S zurückgegeben.) Seite 230 RGH-PROFAN² @Lower$(S) S : String Ergebnis: String Der String S wird komplett in Kleinbuchstaben umgewandelt, wobei die nationalen Sonderzeichen (z.B. die deutschen Umlaute) korrekt berücksichtigt werden. @LT(N1,N2) N1 : Wert 1 N2 : Wert 2 Ergebnis: Wert (0 oder 1) Das Ergebnis ist WAHR (1), wenn Wert 1 kleiner als (Less Than) Wert 2 ist. @LT$(S1,S2) S1 : String 1 S2 : String 2 Ergebnis: Integer (0 oder 1) Das Ergebnis ist WAHR (1), wenn String 1 kleiner als (Less Than) String 2 ist. Seite 231 RGH-PROFAN² @MCISend$(S) S : String - MCI-Kommando Ergebnis: String (MCI-Ergebnis) Es wird der String S als Kommando gesandt. Das Ergebnis (oder ein Fehler) wird zurückgegeben. Beispiele: Ausgabe einer "WAV"-Datei: @MCISend$("open gong.wav type \ waveaudio alias gong") @MCISend$("play gong wait") 'Datei spielen @MCISend$("close gong") '... schließen Das "wait" veranlaßt den PC zu warten, bis der Vorgang beendet ist. WAV-Datei per Mikro aufnehmen: @MCISend$("open new type waveaudio \ alias test") 'Neue WAV-Datei @MCISend$("set test time format \ milliseconds") 'Zeitformat msec @MCISend$("record test from 0 to \ 5000 wait") '5 sec Aufnahme @MCISend$("Play test from 0 wait") 'abspielen @MCISend$("save test test.wav") 'speichern CD (Titel 3 - 5) abspielen: @MCISend$(open cdaudio alias cd") Print "Länge: ";@MCISend$\ ("status cd length") Print "Titelzahl: ";@MCISend$\ ("status cd number of tracks") @MCISend$("set cd time format tmsf") @MCISend$("play cd from 3 to 5 wait") @MCISend$("stop cd") @MCISend$("close cd") Auf diese Weise lassen sich alle Multimediageräte und auch Video für Windows steuern. Näheres finden Sie in der Anleitung und in der Fachliteratur. @MenuItem(N) N : Wert - Menü-Kennzeichen Ergebnis: Wert (1 oder 0) Wenn der aktuell gewählte Menüpunkt mit N (0 bis 32766) übereinstimmt, ist das Ergebnis 1, anderenfalls ist es 0. Ist N gleich 0, dann ist das Ergebnis 1, wenn kein Menüpunkt angewählt wurde. 254 steht für die Anwahl des Copyright-Zeichens. Seite 232 RGH-PROFAN² @MessageBox(S1,S2,N) S1 : String - Meldungstext S2 : String - Überschrift N : Integer - Art der MessageBox Ergebnis - Integer: gedrückter Knopf Eine MessageBox wird auf dem Bildschirm gebracht. N setzt sich zusammen aus BUTTONS + ICON + DEFAULT + FENSTERART. Werte für BUTTON: 0 1 2 3 4 5 - OK - OK Abbrechen - Abbrechen Wiederholen Ignorieren - Ja Nein Abbrechen - Ja Nein - Wiederholen Abbrechen Werte für ICON: 0 16 32 49 64 - Kein Icon - STOP - "?" - "!" - "i" Werte für DEFAULT (Der Wert gibt an, welcher Knopf defaultmäßig angewählt ist): 0 256 512 - erster Knopf - zweiter Knopf - dritter Knopf Werte für FENSTERART: 0 4096 - "normales" Fenster. - großes, nicht verschiebbares "Fehler"-Fenster. Das Ergebnis ist der gedrückte Knopf: 1 2 3 4 5 6 7 - OK - Abbrechen (Cancel) - Abbrechen (Abort) - Wiederholen - Ignorieren - Ja - Nein Seite 233 RGH-PROFAN² @Mid$(S,N1,N2) S : String N1 : Integer - Position N2 : Integer - Anzahl Ergebnis: String Das Ergebnis ist ein String, der N2 Zeichen ab Position N1 aus String S enthält. @Mod(N1,N2) N1 : Integer N2 : Integer Ergebnis: Integer Das Ergebnis ist N1 modulo N2. @MkStr$(S,N) S : String N : Anzahl Wiederholungen Ergebnis : String Es wird ein String zurückgegeben der N mal aus String S besteht. @MoveListToChoice(N) N: Integer - Handle der AuswahlBox Ergebnis: Integer - Erfolg Der Inhalt der Listbox-Liste (für die vorgefertigten Listbox-Dialoge) wird in die AuswahlBox N kopiert. @MoveListToEdit(N) N: Integer - Handle der EditBox Ergebnis: Integer - Erfolg Der Inhalt der Listbox-Liste (für die vorgefertigten Listbox-Dialoge) wird in die EditBox N kopiert. @MoveListToList(N) N: Integer - Handle der ListBox Ergebnis: Integer - Erfolg Seite 234 RGH-PROFAN² Der Inhalt der Listbox-Liste (für die vorgefertigten Listbox-Dialoge) wird in die Listbox N kopiert. So kann zum Beispiel die Listboxliste mit Befehlen wie ADDWINDOWS, ADDFILES oder ADDFONTS gefüllt werden und dann in eine beliebige Listbox kopiert werden. Seite 235 RGH-PROFAN² @Mouse(X1,Y1-X2,Y2) X1,Y1 : Integer - linke obere Ecke X2,Y2 : Integer - rechte untere Ecke Ergebnis: Integer (0 oder 1) Das Ergebnis ist 1, wenn beim letzten Mausklick die Maus im angegeben Bereich war. Beispiel: WaitMouse Case @Mouse(10,10-60,60):Gosub "Info" @Mul(N1,N2) N1 : Wert N2 : Wert Ergebnis: Wert Multiplikation von N1 mit N2. Seite 236 RGH-PROFAN² @Neq(N1,N2) N1 : Wert - Wert 1 N2 : Wert - Wert 2 Ergebnis: Integer (0 oder 1) Das Ergebnis ist UNWAHR (0), wenn beide Werte gleich sind, WAHR (1), wenn die Werte verschieden sind. @Neq$(S1,S2) S1 : String 1 S2 : String 2 Ergebnis: Integer (0 oder 1) Das Ergebnis ist UNWAHR (0), wenn beide Strings gleich sind, WAHR (1), wenn die Strings verschieden sind. @Not(N) N : Wert Ergebnis: Integer (0 oder 1) Das Ergebnis ist 1, wenn N den Wert 0 hat, ansonsten ist es 0. Seite 237 RGH-PROFAN² @OemToAnsi$(S) S : String Ergebnis: String Der String S wird von ASCII-Code in den Ansi-Code umgewandelt. Diese Umwandlungen betreffen insbesondere die deutschen Sonderzeichen. Der ASCIICode wird unter DOS verwandt, der ANSI-Code unter Windows. @OpenCom(COMx,N1,N2) COMx: String - Bezeichnung der Schnittstelle (z.B. "COM1" oder "COM2") N1: Integer - Puffergröße für zu sendende Daten N2: Integer - Puffergröße für zu empfangene Daten Ergebnis: Integer - Schnittstellen-Handle (größer oder gleich 0) bei Werten kleiner als 0 ist ein Fehler aufgetreten Die Schnittstelle wird mit der aktuellen Einstellung initialisiert und geöffnet. Die Puffergröße sollte so bemessen sein, daß die zu sendenden und zu empfangenden Daten Platz finden. Also nicht zu geizig mit den Bytes sein. Mit @SETCOM und @SETCOMEXT können anschließend die Parameter der Schnittstelle exakt eingestellt werden. @Or(N1,N2) N1 : Wert N2 : Wert Ergebnis: Integer ODER-Funktion: Das Ergerbnis ist ungleich 0, wenn N1 ODER N2 (oder beide) ungleich 0 sind. Anders ausgedrückt: Es ist nur dann 0, wenn beide Argumente 0 sind. @Ord(S) S : String Ergebnis: Integer Der ANSI-Code des ersten Zeichens von S. Seite 238 RGH-PROFAN² @Par$(N) N : Integer - Parameter-Nummer Ergebnis: String - Parameter Die Kommandozeilenparameter werden ausgelesen. Die Anzahl wird mit %PARCOUNT festgestellt. Aufrufmöglichkeiten: Interpreter: PROFAN <name.prf> <par2> <par3> ... Runtime (bzw. .EXE-Datei als Runtime): bzw. PROFRUN <name.prc> <par2> <par3> ... <name.exe> <name.prc> <par2> <par3> ... .EXE-Datei: <name.exe> <par1> <par2> <par3> ... Bei der .EXE-Datei versucht das integrierte Runtime-Modul zunächst, den ersten Parameter <par1> als PROFAN²-Compilat (*.prc) zu interpretieren. Handelt es sich um eine solches, wird es ausgeführt, ansonsten das Programm selbst. Eine PRC-Datei wird auch als solche erkannt, wenn sie eine andere Endung hat. @Pi() Ergebnis: Float - PI Die Kreitzahl PI (3,41...) @Pow(N1,N2) N1 : Wert N2 : Wert Ergebnis : Wert Potenzfunktion. Das Ergebnis ist N1 hoch N2 (in BASIC: N1^N2). Seite 239 RGH-PROFAN² @PostMessage(N1,N2,N3,N4) N1 : Integer - Handle des Empfängers N2 : Integer - Nummer der Meldung N3 : 16-Bit: Integer - 16-Bit meldungsabhängige Informationen 32-Bit: Longint - 32-Bit meldungsabhängige Informationen N4 : LongInt oder Bereich - 32-Bit meldungsabhängige Informationen Ergebnis : Integer - 1 = Erfolg, 0 = Mißerfolg Es wird eine Meldung an das Fenster bzw. Fensterobjekt mit dem Handle N1 gesandt. N2 bezeichnet die Meldung. Die Werte N3 und N4 sind von der gewählten Meldung abhängig. Im Gegensatz zu @SendMessage wird hier nicht auf das Ergebnis gewartet, sondern direkt mit einer Erfolgsmeldung (oder auch nicht) zum Programm zurückgekehrt. Erfolg heißt lediglich, daß die Meldung abgesetzt werden konnte. Eine Liste mit den Nummern der Meldungen findet sich im Anhang. @Pwd$(S) S: String - zu ver-/entschlüsselnder Text Ergebnis: String - ent-/verschlüsselter Text Mit dieser Funktion kann ein String verschlüsselt werden. Durch erneuten Aufruf wird der String wieder entschlüsselt. Damit das Ganze funktioniert, muß mit dem Befehl PASSWORD ein Paßwort definiert sein. Selbstverständlich muß zum Entschlüsseln das gleiche Paßwort eingestellt sein wie beim Verschlüsseln. Ist kein Paßwort eingestellt beziehungweise ist es ein Leerstring bewirkt die Funktion nichts. Die Funktion ist derart gestaltet, daß die Sortierreihenfolge der Strings sich nicht ändert. Sie kann also auch in Zusammenhang mit dBase-Dateien benötigt werden. HINWEIS: Diese Verschlüsselung erschwert zwar den Zugriff auf die Daten, ist aber (noch) nicht unknackbar! Seite 240 RGH-PROFAN² @ReadCom(N1,N2) N1: Integer - Schnittstellenhandle N2: Integer - Anzahl der zu lesenden Zeichen Ergebnis: String - die empfangenen Zeichen Der String wird aus der Schnittstelle gelesen, maximal jedoch N2 Zeichen. Ist der Ergebnisstring ein Leerstring, lagen entweder keine Daten an oder es trat ein Fehler auf. Der Fehler kann mit @COMERROR ermittelt werden. Das sollte nach jedem Aufruf von @WRITECOM geschehen! Die Schnittstelle muß mit @OPENCOM geöffnet worden sein. N ist das dabei ermittelte Handle. Siehe auch: @WriteCom, @SetCom, @CloseCom @ReadIni$(S1,S2,S3) S1 - String: Dateiname / Registry-Klasse (32 Bit) S2 - String: Anwendungsname (Rubrik) / Pfad in der Regsitry (32 Bit) S3 - String: Eintrag / Schlüssel Ergebnis: String (Wert des Eintrages) Ein Wert aus einer INI-Datei wird gelesen. Ermittlung des Druckers: Let Drucker$=@ReadIni$("WIN.INI",\ "Windows","Device") In der 32-Bit-Version ist es zusätzlich möglich, Werte aus der Registry (Registrierdatenbank) auszulesen. In diesem Fall muß als erster Parameter die Klasse mit "HKEY_0" bis "HKEY_6" angegeben werden: HKEY_CLASSES_ROOT HKEY_CURRENT_USER HKEY_LOCAL_MACHINE HKEY_USERS HKEY_PERFORMANCE_DATA HKEY_CURRENT_CONFIG HKEY_DYN_DATA = = = = = = = KKEY_0 HKEY_1 HKEY_2 HKEY_3 HKEY_4 HKEY_5 HKEY_6 Der zweite Parameter ist dann der komplette "Pfad" zum Eintrag. Der dritte Parameter ist der Schlüssel (Key), der ausgelesen werden soll. Ist der Pfad in der Registry nicht vorhanden, erfolgt eine Warnung. Einzelne Einträge des Pfades werden durch Backslashes (wie beim Verzeichnis) voneinander getrennt: Let Drucker$ = @ReadIni$("HKEY_5", \ "System\Current\Controlset\Control\Print\Printer","Default") Mit WriteIni können INI-Dateien erzeugt und beschrieben werden. In der 32-Bit-Version ist auch ein Schreiben von Registry-Einträgen möglich. @RGB(R,G,B) R,G,B : Wert - Farbwerte (0 .. 31 / 0 .. 255 im TrueColor-Modus) Ergebnis : Wert (0 .. 32767 / 0 .. 64 Mio im TrueColor-Modus) Seite 241 RGH-PROFAN² Die Funktion errechnet eine der 32767 (64 Millionen im TrueColor-Modus) in Profan möglichen Farben aus den Farbanteilen Rot, Grün und Blau: @RGB(0,0,0) = 0 (Schwarz) @RGB(31,31,31) = 32767 (Weiß) @Rnd(N) N : Wert Ergebnis: Integer bzw. LongInt Zufallszahl zwischen 0 und N-1. @Right$(S,N) S : String N : Anzahl Zeichen Ergebnis : String Die N rechten Zeichen des Strings werden zurückgegeben. @Round(N1,N2) N1: Float - Wert N2: Integer - Anzahl der Nachkommastellen Ergebnis: Float - Gerundeter Wert Die Zahl N1 wird auf N2 Stellen nach dem Komma gerundet. Da N2 auch negativ sein darf, kann auch auf volle 100er, 1000er etc. gerundet werden. Bei vollen Tausendern hätte N2 den Wert -3. Der zu rundende Wert N1 darf natürlich auch ein Integer oder LongInt sein! @SaveFile$(S1,S2) S1 : String - Überschrift S2 : String - Namensvorschlag Ergebnis: Dateiname (incl. Pfad) Es wird eine Dateiauswahlbox zum Speichern mit der Überschrift S1 geöffnet. Der Dateiname und/oder Pfad kann geändert werden. Das Ergebnis ist der Name (mit Pfad) unter dem gespeichert werden kann. @ScanKey(N) N : Integer - Scancode Ergebnis: Integer (1 oder 0) Wenn der letzte Scancode (virtueller Tastencode) mit N (0 bis 254) übereinstimmt, ist das Ergebnis 1, anderenfalls ist es 0. Tabelle der Scancodes siehe unter %SCANKEY. Seite 242 RGH-PROFAN² @SelectString(N1,N2,S) N1: Integer - Handle der Listbox N2: Integer - Start der Suche -1 S: String - Suchbegriff bzw. Anfang des Begriffes Ergebnis: Integer - Position des Suchbegriffes In der Listbox N1 wird die erste Zeile angewählt, die mit dem String S beginnt. Die Suche beginnt dabei nach Zeile N2. Soll die Suche am Anfang der Listbox beginnen, muß N2 der Wert -1 bekommen. Wird der Eintrag gefunden, dann wird der Auswahlbalken darauf gesetzt und die Liste nötigenfalls gescrollt, damit der gefundene Eintrag sichtbar wird. Seite 243 RGH-PROFAN² @SendKey(N1,N2) N1 : Integer - Handle des Fensterobjektes N2 : Integer - virtueller Tastaturcode (Scancode) Ergebnis : Integer An das Fenster/das Fensterobjekt mit dem Handle N1 wird ein simulierter Tastendruck gesandt, wobei N2 der virtuelle Tastaturcode ist: 8913 16 17 20 27 32 33 34 35 36 37 38 39 40 45 46 48 ... 57 65 ... 90 112 ... 135 - BackSpace Tab-Taste Return Shift Strg CapsLock Esc Space BildHoch BildRunter Ende Pos1 Links Hoch Rechts Runter Einfg Entf Taste 0 ... Taste 9 Taste A ... Taste Z F1 ... F24 HINWEIS: Diese Funktionen können unter Windows 3.x und Windows 95 unterschiedlich reagieren; insbesondere dann, wenn aus einer 32-Bit-Anwendung Tastencodes an eine 16Bit-Anwendung gesandt werden und umgekehrt. Seite 244 RGH-PROFAN² @SendMessage(N1,N2,N3,N4) N1 : Integer - Handle des Empfängers N2 : Integer - Nummer der Meldung N3 : 16-Bit-Version: Integer - 16-Bit meldungsabhängige Informationen 32-Bit-Version: LongInt - 32-Bit melfungsabhängige Informationen N4 : LomgInt oder Bereich - 32-Bit meldungsabhängige Informationen Ergebnis : Integer - Rückgabewert der Meldung Es wird eine Meldung an das Fenster bzw. Fensterobjekt mit dem Handle N1 gesandt. N2 bezeichnet die Meldung. Die Werte N3 und N4 sind von der gewählten Meldung abhängig. ACHTUNG: Meldungen die in N4 Zeiger auf Strings oder Datenstrukturen erwarten und/oder zurückliefern, sollten nur von erfahrenen PROFAN-Programmieren verwandt werden, da diese zum Absturz von Windows führen können. Auf jeden Fall ist darauf zu achten, daß die entsprechende Bereichsvariable ausreichend DIMensioniert ist! Die für den PROFAN²Programmierer wichtigsten Messages finden Sie im 4. Kapitel dieser Referenz und eine Liste mit den Nummern der Meldungen findet sich im Anhang. @SendString(N,S) N : Integer - Handle des Fensterobjektes S : Integer - String Ergebnis : Integer An das Fenster/das Fensterobjekt mit dem Handle N wird wird eine Reihe simulierter Tastendrücke gesandt, wobei S eine beliebige Zeichenkette ist. Sonderzeichen, Umlaute, Groß- und Kleinschreibung werden entsprechend umgesetzt. Jede Taste wird durch ein oder mehrere Zeichen repräsentiert. Um normale Buchstaben, Zeichen und Ziffern darzustellen, geben Sie diese als Zeichenkette an: @SendString(W%,"Dies ist ein Test!") Das Plus-Zeichen (+), Caret-Zeichen (^), Prozent-Zeichen (%), die Tilde (~) und Klammern () haben bei der SendString-Funktion spezielle Bedeutungen. Um eines dieser Zeichen anzugeben, schließen Sie das Zeichen in geschweifte Klammern ein. Um beispielsweise das Plus-Zeichen anzugeben, geben Sie {+} ein: @SendString(W%,"A {+} B = C") Um geschweifte Klammerzeichen zu senden, geben Sie {{} und {}} ein. Zur Angabe von Zeichen, die beim Drücken der zugehörigen Taste (z.B. EINGABETASTE oder TABULATORTASTE) nicht angezeigt werden, sowie von Tasten, die keine Zeichen darstellen, verwenden Sie den entsprechenden Codetext in geschweiften Klammern: @SendString(W%,"Das ist die Eingabe! {ENTER}") Die Codetexte für die Tasten: Taste Code -------------------------------------------BILD-HOCH {PGUP} BILD-RUNTER {PGDN} DRUCK {PRTSC} EINFG {INSERT} ENTER {ENTER} ENDE {END} Seite 245 RGH-PROFAN² ENTF ESC FESTSTELL HILFE LÖSCHTASTE LINKS HOCH RECHTS RUNTER NUM POS1 ROLLEN RÜCKTASTE TABULATOR UNTBR F1 ... F24 {DELETE} oder {DEL} {ESCAPE} oder {ESC} {CAPSLOCK} {HELP} {CLEAR} {LEFT} {UP} {RIGHT} {DOWN} {NUMLOCK} {HOME} {SCROLLLOCK} {BACKSPACE} oder {BS} oder {BKSP} {TAB} {BREAK} {F1} ... {F24} Um Tastenkombinationen anzugeben, die die UMSCHALTTASTE, die STRG-TASTE oder die ALT-TASTE enthalten, fügen Sie vor dem regulären Tastencode einen bzw. mehrere der folgenden Codes hinzu: + = UMSCHALTTASTE, ^ = STRG-TASTE und % = ALT-TASTE. Um eine Tastenkombination anzugeben, bei der eine oder mehrerer dieser Tasten gedrückt gehalten werden, während gleichzeitig mehrere andere Tasten gedrückt werden, schließen Sie den Code der Tasten in Klammern ein. Um beispielsweise die UMSCHALTTASTE gedrückt zu halten, während e und c gedrückt werden, verwenden Sie "+(ec)" (="EC"). Um die UMSCHALTTASTE gedrückt zu halten, während e gedrückt wird und das auf e folgende c ohne UMSCHALTTASTE gedrückt wird, verwenden Sie "+ec" (="Ec"). Um eine sich mehrmals wiederholende Taste anzugeben, verwenden Sie die Form Taste Anzahl, wobei Sie zwischen den Parametern Taste und Anzahl ein Leerzeichen einfügen müssen. Beispielsweise bedeutet LEFT 42, daß die NACH-LINKS-TASTE 42 Mal gedrückt wird; h 10 bedeutet, daß der Buchstabe h 10 Mal gedrückt wird. Zusätzlich können \a, \t und \n verwandt werden. (Zeichen, die nur mit ALTGR erreicht werden, werden bei der 16-Bit-Version leider nicht gesandt.) Wenn N den Wert 0 hat, wird an das Fensterobjekt mit dem Focus gesandt; 0 ist gleichbedeutend mit %GETFOCUS. HINWEIS: Diese Funktionen können unter Windows 3.x und Windows 95 unterschiedlich reagieren; insbesondere dann, wenn aus einer 32-Bit-Anwendung Tastencodes an eine 16Bit-Anwendung gesandt werden und umgekehrt. Seite 246 RGH-PROFAN² @SetActiveWindow(N) N : Integer - FensterHandle Ergebnis : Integer - Handle des vorher aktiven Fensters. Das Fenster mit dem Handle N wird zum aktiven Fenster. Siehe auch: %GetFocus, @GetFocus, @SetFocus @SetBit(N1,N2,N3) N1 : Integervariable (Integer/LongInt) - Wert N2 : Bitnummer (0 .. 15) N3 : Neuer Wert des Bits (0 oder 1) Ergebnis : LongInt Die Funktion setzt Bit Nr. N2 in Wert N1 auf N3. Es können also gezielt Bits gesetzt und zurückgesetzt werden. Beispiel: declare a% cls let a% = 5 print "a%: ";a% let a% = setbit (a%,5,1) print "a%: ";a% let a% = setbit (a%,5,0) print "a%: ";a% waitinput @SetCom(S) S: String - entsprechend dem Format des DOS-Befehles MODE Ergebnis: Integer - 0 = OK, <0 = Fehler Die Schnittstelle wird auf neue Werte eingestellt und die Puffer initialisiert. Die Schnittstelle muß zuvor mit @OPENCOM geöffnet worden sein. Der String S gibt die Einstellungen im Format des MODE-Befehles an: COMx:B,D,P,S COMx: Die Schnittstelle, z.B. COM2 B: Baud - Geschwindigkeit: 110, 150, 300, 600, 1200, 2400, 4800, 9600 oder 19200 P: Parity: O (Odd), E (Even), M (Mark), S (Space) oder N (None) D: Datenbits: 6, 7 oder 8 S: Stopbits: 1, 1.5 oder 2 Beispiel: Let E% = @SetCom("COM2:9600,N,8,1") Nähere Hinweise siehe im DOS-Handbuch. Wenn diese Einstellungsmöglichkeiten nicht ausreichen, bietet @SETCOMEXT noch weitere Möglichkeiten. @SETCOMEXT muß nach @SETCOM aufgerufen werden! Seite 247 RGH-PROFAN² Seite 248 RGH-PROFAN² @SetComExt(N1,N2.N3.N4.N5.N6.N7) N1: Integer - Handle der Schnittstelle N2: Integer - RlsTimeOut in ms N3: Integer - CtsTimeOut in ms N4: Integer - DsrTimeOut in ms N5: Integer - Flags: $0001 = Binärmodus (DCB.fBinary) $0002 = RTS nicht prüfen $0004 = Paritätsprüfung ein $0008 = CTS-Handshake bei Ausgabe $0010 = DSR-Handshake bei Ausgabe $0080 = DTR nicht prüfen $0100 = XON/XOFF bei Ausgabe ein $0200 = XON/XOFF bei Eingabe ein $0400 = Paritätsfehlerersatz ein $0800 = Null entfernen ein $1000 = Rx Zeichenereignis ein $2000 = DTR-Handshake bei Eingabe $4000 = RTS-Handshake bei Eingabe N6: Integer - Minimalzahl von Zeichen in der Empfangsschlange, bevor Xon gesendet wird N7: Integer - Maximalzahl von Zeichen in der Empfangsschlange, bevor Xoff gesendet wird Diese Funktion ist erwas für fortgeschrittene Programmierer, sie sich mit den Gegebenheiten der COM-Schnittstelle gut auskennen. Sie ist nach @SETCOM aufzurufen und erweitert dort gewählten Einstellungen. Dabei werden die Puffer initialisiert. Kombinationen der Flags werden durch Addition erzielt. Die angegebenen Werte sind HexWerte! Werte, die nicht verändert werden sollen, sind mit -1 zu belegen. Auf diese Weise kann mit der Funktion jeder einzelne Parameter der Schnittstelle gezielt geändert werden. HINWEIS: UNter Windows 95 sind in der 32-Bit-Version von PROFAN² die 3 TimeOutParameter ohne Bedeutung. Siehe auch: @OpenCom, @SetCom, @ComError @SetFocus(N) N : Integer - Handle des Fensterobjektes Ergebnis : Integer - Handle des vorherigen Fensterobjektes. Setzt den Focus auf das Fensterobjekt mit dem Handle N. Der Rückgabewert ist der Focus des des Fensterobjekts, das ihn vorher hatte. Der Focus ist quasi der Kursor unter Windows. Wenn ein z.B. Eingabefeld den Focus bekommt, erscheint dort der blinkende senkrechte Strich, die Schreibmarke, und es kann dort etwas eingegeben werden. Siehe auch: @SetActiveWindow, @GetFocus, %GetFocus Seite 249 RGH-PROFAN² @ShortName$(S) S: String - langer Dateiname einer Datei (incl. Pfad) Ergebnis: kurzer Name von Pfad und Datei Diese Funktion ermittelt den kurzen Dateinamen (System 8.3) zu einem langen Dateinamen. Dabei darf der Dateiname auch einen Pfad enthalten. Die Funktion ist dann sinnvoll, wenn Programme oder Funktionen aufgerufen werden sollen, die noch nicht für Windows 95 angepaßt sind und mit langen Dateinamen nichts anfangen können. Das gilt z.B. auch für die Dateinamen von Datenbanktabellen und Indextabellen in der 16-Bit-Version von PROFAN². Wenn die Datei nicht existiert wird ein Leerstring zurückgegeben. (Unter Windows 3.x, bzw. wenn die langen Dateinamen mit SetLFN 0 ausgeschaltet sind, wird immer der String S zurückgegeben.) @ShowWindow(N1,N2) N1 : Integer - Fenster-Handle N2 : Integer - Abbildungsmodus (1 .. 9) Das Fenster mit dem Handle N1 wird im Modus N2 angezeigt. Das Ergebnis ist 1 wenn das Fenster vorher sichtbar war oder 0, wenn es vorher versteckt (unsichtbar) war. 0 1 2 3 4 5 6 7 8 9 - verbirgt und deaktiviert das Fenster - aktiviert das Fenster und zeigt es in seiner ursprünglichen Größe - aktiviert das Fenster und verkleinert es zum Symbol - aktiviert das Fenster und zeigt es größtmöglich an - zeigt das Fenster in seiner normalen Größe. Das gegenwärtig aktive Fenster bleibt aktiv. - aktiviert das Fenster und zeigt es in aktueller Größe - deaktiviert das Fenster und verkleinert es zum Symbol - verkleinert das Fenster zum Symbol. Das gegenwärtig aktive Fenster bleibt aktiv. - Zeigt as Fenster im aktuellen Zustand. Das gegenwärtig aktive Fenster bleibt aktiv. - gleiche Wirkung wie Modus 1 @ScanKey(N) N : Integer - Scancode Ergebnis: Integer (1 oder 0) Wenn der letzte Scancode (virtueller Tastencode) mit N (0 bis 254) übereinstimmt, ist das Ergebnis 1, anderenfalls ist es 0. Tabelle der Scancodes siehe unter %SCANKEY. @Sin(N) N : Wert (Winkel in Bogenmaß) Ergebnis : Float Der Sinus des Winkels N. Seite 250 RGH-PROFAN² @Space$(N) N : Anzahl Zeichen Ergebnis : String Es wird ein String aus N Leerzeichen zurückgegeben @SQLInit S S - String: Initialisierungsstring Ergebnis: Integer Die Funktion verbindet das Programm mit dem Datenbankserver. S ist der Initialisierungsstring, um den Datenbankserver zu öffnen und zu initialisieren. Ist auf Ihrem System ODBC nicht installiert, kommt die Fehlermeldung "ODBC.DLL nicht gefunden". Geben Sie als S einen Leerstring an, wird bei den meisten ODBC-Treibern eine Dialogbox geöffnet, mit der Sie den Datenbankserver wählen können. Es gibt auch ODBC-Treiber für dBase-, Fox-Pro-, Paradox- und Access-Datenbanken. Ein solcher Treiber wird z.B. mit WORD 6.0 installiert. Damit ist es möglich auch ohne Netzwerk ODBC und SQL zu nutzen. Konnte der Datenbankserver nicht geöffnet werden, liefert die Funktion 0 zurück, ansonsten 1. Beispiele: @SQLINIT("DSN=SQLserver;UID=USER;DATABASE=TEST") @SQLINIT("DSN=dBase-Dateien") @SQLINIT("") Die genaue Syntax des Initialisierungsstrings entnehmen Sie bitte der Dokumentation zum jeweiligen ODBC-Treiber. @Sqr(N) N : Wert Ergebnis : Float Das Quadrat von N (N²). @Sqrt(N) N : Wert Ergebnis : Float Die Quadratwurzel zu N. @String$(V,A) V: Bereichsvariable A: Integer - Adresse Seite 251 RGH-PROFAN² Ergenis: String - Zeichenkette ab Adresse Diese Funktion ermittelt eine Zeichenkette ab Adresse (Offset) A in der Bereichsvariablen V. Dem String werden alle Zeichen ab A hinzugefügt bis entwerde ein Zeichen mit dem Code 0 vorkommt oder die maximale Stringlänge von 255 erreicht ist. Ist A außerhalb des mit DIM eingestellten Bereiches von V, erfolgt eine Fehlermeldung. Seite 252 RGH-PROFAN² @Str$(S) N : Wert S : String Der Wert von N wird in einen String ohne folgende Leerzeichen umgewandelt. Die Länge des Strings und (bei Float) die Anzahl der Nachkommastellen werden durch die Befehle NUMWIDTH und DECIMALS eingestellt. @Sub(N1,N2) N1 : Wert N2 : Wert Ergebnis: Wert N2 wird von N1 abgezogen (subtrahiert). @SubStr$(S1,N,S2) S1 - String: Der zu bearbeitende String N - Integer: Nummer des Teilstrings S2 - String: Trennzeichen Ergebnis: Substring aus S1 Aus dem String S1 wird der N-te Teilstring herausgefiltert, zwischen den Teilstrings ist. Beispiel: wobei S2 das Trennzeichen LET A$ = "eins,zwei,drei,vier,fünf" PRINT @SUBSTR$(A$,3,",") Das Ergebnis wäre der String "drei". Wird das Trennzeichen im String S1 nicht gefunden, ist das Ergebnis für den ersten Teilstring der gesamte String und für alle weiteren der Leerstring. Ist N kleiner als 1, erfolgt eine Fehlermeldung. Ist N hingegen größer als die Anzahl der vorhandenen Teilstrings, so ist das Ergebnis ein Leerstring. HINWEIS: S2 darf auch aus mehreren Zeichen bestehen! Seite 253 RGH-PROFAN² @Tan(N) N : Wert (Winkel in Bogenmaß) Ergebnis : Float Der Tangens des Winkels N. @TestBit(N1,N2) N1 : Integervariable (Integer/LongInt) - Wert N2 : Bitnummer (0 .. 15) N3 : Neuer Wert des Bits (0 oder 1) Ergebnis : LongInt Es wird geprüft ob in N1 das Bit Nr. N2 gesetzt ist. Das Ergenis ist der Wert des entsprechenden Bits. @Time$(N) N : Integer (0 .. 1) - Unterfunktion Ergebnis: String Die Funktion ermittelt die aktuelle Uhrzeit: N = 0 : Sunden und Minuten (z.B. "23:45") N = 1 : Sekunden und 100stel Sekunden (z.B. "39.67") @TMouse(X1,Y1 - X2,Y2) X1,Y1 : Integer - links oben X2,Y2 : Integer - rechts unten Ergebnis: Integer (0 oder 1) War beim letzten Mausklick die Maus innerhalb des Rechteckes, ist das Ergebnis 1. Die Koordinaten sind Textkoordinaten (wie bei LOCATE oder TBOX). @Translate$(S1,S2,S3) S1: String - der zu bearbeitende String S2: String - Suchtext S3: String - Ersatztest Ergebnis: String, in dem S2 durch S3 ersetzt wurde Alle Vorkommen des Strings S2 werden in S1 durch S3 ersetzt. @Trim$(S) S : String Seite 254 RGH-PROFAN² Ergebnis: String Die führenden und endenden Leerzeichen eines Strings werden abgeschnitten. Seite 255 RGH-PROFAN² @Upper$(S) S : String Ergebnis: String Der String S wird komplett in Großbuchstaben umgewandelt, wobei die deutschen Umlaute korrekt berücksichtigt werden. @UseDLL(S) S: String - Name der DLL-Datei (evt. mit Pfad) Ergebnis: Integer - Handle der DLL Die DLL S wird in den Speicher geladen. Ist sie schon geladen wird der Aufrufzähler um 1 erhöht. Das Ergebnis ist das Instanz-Handle der DLL. Dieses wird für den Zugriff auf die Resourcen der DLL benötigt. Ist das Ergebnis kleiner als 32, trat ein Fehler auf und die DLL konnte nicht aufgerufen werden. Zu den Fehlercodes siehe unter @WINEXEC. NEU ab Version 6.0: Es können nun beliebig viele DLL für PROFAN² im Zugriff sein. Wird eine neue DLL mit @USEDLL geladen, wird der Aufrufzähler der zuletzt geladenen DLL nicht mehr um 1 erniedrigt. Um die DLL zu entfernen ist der Befehl FREEDLL zu verwenden: Declare hDLL% Let hDLL%=@UseDLL("ICONS.DLL") DrawExtIcon hDLL%,"MSDOS",20,20 FreeDLL hDLL% Seite 256 RGH-PROFAN² @Val(S) S : String Ergebnis: Wert Der String S wird in einen numerischen Wert umgewandelt. Das Ergebnis ist 0, wenn der String nichtnumerische Zeichen enthält. Eine Fehlermeldung oder Warnung erfolgt in diesem Falle nicht. Als numerische Zeichen gelten auch Strings in binärer, octaler und hexadezimaler Schreibweise, etwa "%10001", "&0754" oder "$3FA2": LET A& = @VAL("%10100011") @Width(H) H : Integer - Handle des Fensters, Dialoges, Dialogelementes Ergebnis : Integer - Breite des Elementes innerhalb des Rahmens Oftmals benötigt man zum Zeichnen die Größe des Fensters bzw. Dialoges innerhalb des Rahmens (so einer vorhanden ist). Diese Fläche wird auch der Client genannt. Bei einem Fenster schließt diese Fläche Menü und Titelleiste nicht mit ein, sondern es wird nur der Teil ausgemessen, der auch tatsächlich zum Malen, Schreiben, etc. genutzt werden kann @WinExec(S,N) S : String - Programm (mit Pfad), das gestartet wird N : Integer - Abbildungsmodus (0 .. 9) Ergebnis : Integer - Handle des gestarteten Programmes Die Anwendung S wird mit dem Abbildungsmodus N gestartet: 0 1 2 3 4 5 6 7 8 9 - verbirgt und deaktiviert das Fenster - aktiviert das Fenster und zeigt es in seiner ursprünglichen Größe - aktiviert das Fenster und verkleinert es zum Symbol - aktiviert das Fenster und zeigt es größtmöglich an - zeigt das Fenster in seiner normalen Größe. Das gegenwärtig aktive Fenster bleibt aktiv. - aktiviert das Fenster und zeigt es in aktueller Größe - deaktiviert das Fenster und verkleinert es zum Symbol - verkleinert das Fenster zum Symbol. Das gegenwärtig aktive Fenster bleibt aktiv. - Zeigt as Fenster im aktuellen Zustand. Das gegenwärtig aktive Fenster bleibt aktiv. - gleiche Wirkung wie Modus 1 Seite 257 RGH-PROFAN² Das Ergebnis ist das Instanz-Handle der Anwendung. Das Instanz-Handle wird z.B. benötigt, um auf die Resourcen einer Anwendung zuzugreifen oder um festzustellen, ob die Anwendung noch aktiv ist. Ist das Ergebnis kleiner als 32, trat ein Fehler auf und die Anwendung konnte nicht gestartet werden. 0235810 11 12 14 15 16 19 20 21 - Zuwenig freier Speicher oder die ausführbare Datei war beschädigt Datei nicht gefunden. Pfad nicht gefunden. Es gab einen Fehler beim gemeinsamen Zugriff bzw. einen Zugriffsfehler im Netzwerk. Ungenügender Speicher, um die Anwendung zu starten. Falsche Windows-Version. Ungültige .EXE-Datei (Keine Windows-.EXE-Datei oder Fehler im .EXEDarstellungsformat). Anwendung wurde für anderes Betriebssystem entworfen. Unbekannter .EXE-Dateityp. Versuch, im Protected Mode (Standardmodus oder erweiterter 386-Modus) eine für frühere Windows-Versionen erstellte .EXE-Datei zu laden Es wurde versucht, eine zweite Instanz einer ausführbaren Datei zu laden, die mehrfache (nicht Read-Only markierte) Datensegmente enthält. Es wurde versucht, eine komprimierte ausführbare Datei zu laden. Die Datei muß dekomprimiert werden, bevor sie geladen werden kann. Eine der DLLs, die zum Start dieser Anwendung notwendig ist, war fehlerhaft. Die Anwendung benötigt 32-Bit-Erweiterungen (WIN32S). Beispiel: LET X%=@WINEXEC("NOTEPAD.EXE",3) Wenn kein Pfad angegeben ist, sucht Die Funktion @WinExec das Programm in folgender Reihenfolge: 1. 2. 3. 4. 5. 6. Im aktuellen Verzeichnis (@GetDir$("@")) Im Windows-Verzeichnis (%WinPath) Im Windows-Systemverzeichnis (%SysPath) Im Verzeichnis, das das aufrufende Programm enthält (@Par$(0)) In den Verzeichnissen, die in der Environment-Variablen PATH aufgeführt sind (@GetEnv$("PATH")) in den Verzeichnissen, die in einem Netzwerk (mit dem Befehl MAP) aufgeführt sind. ACHTUNG: Aus Gründen, die nur Microsoft (hoffentlich) kennt, darf der String S nicht länger als 141 Zeichen sein. Siehe auch: @GetUsage Seite 258 RGH-PROFAN² @WinExecWait(S,N) S N : String - Programm (mit Pfad), das gestartet wird : Integer - Abbildungsmodus Ergebnis : Integer - Erfolg: 1 = Ok, 0 = Fehler beim Aufruf Die Anwendung S wird mit dem Abbildungsmodus N gestartet. Im Gegensatz zu @WinExec wartet diese Funktion, bis das Programm beendet wurde. Erst danach geht's weiter. Außerdem wird kein Handle zurüchgeliefert, sondern nur der Erfolg oder Mißerfolg der Funktion. Beispiel: @WinExecWait("NOTEPAD.EXE",1) Wenn kein Pfad angegeben ist, sucht Die Funktion @WinExecWait das Programm in der oben angegebenen Reihenfolge. ACHTUNG: Aus Gründen, die nur Microsoft (hoffentlich) kennt, darf der String S nicht länger als 141 Zeichen sein. @WriteCom(N,S) N: Integer - Schnittstellenhandle S: String - Zu sendender Text Ergebnis: Integer - gesandte Bytes Der String S wird an die Schnittstelle gesandt. Das Ergebnis enthält die Anzahl der tatsächlich gesendeten Zeichen. Ist das negativ, trat ein Fehler auf und der Absolutwert entspricht die Anzahl der vor dem Fehler gesendeten Zeichen. Der aufgetretene Fehler läßt sich mit der Funktion @COMERROR ermitteln. Das sollte nach jedem Aufruf von @WRITECOM geschehen! Die Schnittstelle muß mit @OPENCOM geöffnet worden sein. N ist das dabei ermittelte Handle. Siehe auch: @ReadCom, @SetCom, @CloseCom @Word(V,A) V: Bereichsvariable A: Integer - Adresse Ergebnis: Integer - Wert Diese Funktion ermittelt der Wert des Datenwortes (2 Byte) an der Adresse (Offset) A in der Bereichsvariablen V. Ist A außerhalb des mit DIM eingestellten Bereiches von V, erfolgt eine Fehlermeldung. Seite 259 RGH-PROFAN² @XOr(N1,N2) N1 : Wert N2 : Wert Ergebnis: Integer Exklusive ODER-Funktion: Das Ergerbnis ist ungleich 0, wenn N1 ODER N2 (aber nicht beide) ungleich 0 sind. Anders ausgedrückt: Es ist nur dann 0, wenn beide Argumente gleich sind. ACHTUNG: Beide Argumente werden - wie auch bei @Or und @And - BITweise betrachtet! Seite 260 RGH-PROFAN² 3. Befehle Jede Programmzeile beginnt mit einem Befehl, wobei auch Funktionen wie Befehle verwandt werden können. So darf also auf keinen Fall bei einer Zuweisung das LET weggelassen werden. Nach dem Befehlswort muß immer mindestens 1 Leerzeichen stehen, ansonsten wird der Befehl nicht als solcher erkannt. In jeder Programmzeile darf auch immer nur ein Befehl stehen. Mehrere Befehle in einer Zeile (wie z.B. in BASIC, PASCAL oder C) sind nicht zulässig. Einige Ausnahme ist der CASE-Befehl. Seite 261 RGH-PROFAN² ' ... (Kommentarzeichen) Kommentarzeichen. Im Gegensatz zu REM kann (sollte) es auch hinter einem Befehl in einer Zeile stehen: ' Unterprogramm Let X%=125 'X-Position zuweisen Add VAR,N VAR - Variablenname (Integer) N - Integer N wird zur Variablen VAR addiert. (Ist schneller und einfacher als die @ADD-Funktion.) Beispiel: ADD Punkte%,10 AddFiles [*]S S : String - Dateimaske Mit diesem Befehl wird eine Dateiliste der Listbox-Liste hinzugefügt. Beispiel: ClearList AddFiles "*.RGH" @ListBox$("Ergebnis",1) NUR IN DER 32-BIT-VERSION: Wird vor dem String ein Stern angegeben, werden auch alle Dateien in den Unterverzeichnissen hinzugefügt, die der Dateimaske entsprechen. Beispiele: ClearList ChDir "C:\" AddFiles *"*.WAV" @ListBox$("Ergebnis",1) Es werden alle WAV-Dateien auf Laufwerk C: gefunden. ClearList ChDir "D:\" AddFiles *"CTL3D.DLL" @ListBox$("Ergebnis",1) Es werden alle Vorkommen der CTL3D.DLL auf Laufwerk D: gefunden. ACHTUNG: Bei zu tiefer Verschachtelung der Verzeichnisse (z.B. im Netzwerk) kann ein Stack-Überlauf (Stack-Overflow) erfolgen! AddFonts Der Listboxliste wird eine Liste der im System vorhandenen Schriften hinzugefügt. Beispiel: ClearList AddFonts Seite 262 RGH-PROFAN² AddString S S : String Mit diesem Befehl wird der String der Listbox-Liste hinzugefügt. Beispiel: ClearList AddString "Item 1" AddString "Item 2" Seite 263 RGH-PROFAN² AddWindows S S : String - Fenstertitel-Maske Fügt der Liste die vorhandenen Fenstertitel zu, die mit S beginnen. Ist S ein Leerstring, werden alle Fenster, die einen Titel haben, der Liste hinzugefügt. Versteckte Fenster (Fenster ohne Titel) werden nicht eingelesen. Der Befehl ist z.B. nützlich zum Programmieren von Taskmanagern. Append #N N: Wert - Dateinummer (1 .. 15) Die Datei #N wird geöffnet, um Daten anzufügen. Tritt ein Fehler auf, ist %IoResult größer als 0. Beispiel: Assign #1,"TEST.DAT" Append #1 Case %IoResult:MessageBox "Fehler:",\ "Kann Datei nicht öffnen!",16 Print #1,"Testdaten",56,Hugo$ Close #1 AppendMenu N,S N : Wert - Menünummer (1 .. 32766) S : String - Eintrag Dem PopUp-Menü wird der Eintrag S unter der Nummer N hinzugefügt. Ein vorangestelltes & sorgt für eine Unterstreichung. Ein Menüeintrag mit der Nummer 254 bleibt wirkungslos, 255 erzeugt immer die PROFAN-Copyright- Meldung. Beispiel: CreateMenu AppendMenu 100,"&Laden" AppendMenu 101,"&Speichern" AppendMenu 102,"Speichern &als" TrackMenu 20,130 Case @MenuItem(100):Goto "Laden" Case @MenuItem(101):Goto "Speichern" ... Weiteres Beispiel: PopUp "&Datei" AppendMenu 100,"&Laden" AppendMenu 101,"&Speichern" AppendMenu 102,"Speichern &als" Separator SubPopUp "Datei&typ" AppendMenu 110,"Exe" AppendMenu 120,"Com" EndSub AppendMenu 103,"&Ende" PopUp ..... Seite 264 RGH-PROFAN² AppendMenuBar N,S N : Wert - Menünummer (1 .. 32766) S : String - Eintrag Dem Haupt-Menü wird der Eintrag S unter der Nummer N hinzugefügt. Ein vorangestelltes & sorgt für eine Unterstreichung. Beispiel: AppendMenuBar 10,"&Laden" AppendMenuBar 11,"S&peichern" WaitMouse Case %MenuItem(10):Goto "Laden" Arc X1,Y1-X2,Y2; X3,Y3; X4,Y4 X1,Y1 : Wert - Links oben X2,Y2 : Wert - Rechts unten X3,Y3 : Start X4,X5 : Ende Es wird ein Kreisbogen gezeichnet. X1,Y1 und X2,Y2 bezeichnen das Rechteck, indem der Kreis sich befindet, die anderen Koordinaten Start und Ende des Kreisbogens. Assign #N,S N : Wert - Dateinummer (1 .. 8) S : String - Dateiname (+ Pfad) Der Datei Nummer N wird die Datei S zugewiesen. Beispiel: Assign #1,"DEMO.PRF" Reset #1 WhileNot @Eof(#1) Input #1,Zeile$ Print Zeile$ Wend Close #1 Seite 265 RGH-PROFAN² Beep Gibt einen Signalton aus. Zur Tonausgabe siehe auch unter SOUND und PLAY! BlockWrite #N,B,N1,N2 #N : Dateikennung einer mit OPENRW geöffneten Datei B : Bereichsvariable N1 : LongInt - Adresse in der Bereichsvariablen N2 : LongInt - Anzahl Bytes In die mit OPENRW geöffneten Datei mit der Kennung #N werden N2 Bytes ab Adresse N1 aus der Bereichsvariablen B geschrieben. Das Beispiel schreibt den Inhalt der Bereichsvariablen Test# in die Datei TEST.DAT: Declare Test# Dim Test#,500 Assign #1,"TEST.DAT" OpenRW #1 BlockWrite #1,B#,0,500 CloseRW #1 Byte V,A=N V: Bereichsvariable (muß mit DECLARE deklariert sein) A: Integer - Adresse in der Bereichsvatiablen N: Integer - Wert (0 ... 255) Das Byte an der Adresse (Offset) A im Speicherbereich V wird auf den Wert N gesetzt. Liegt A außerhalb des mit DIM zugewiesenen Speichers, erfolgt eine Fehlermeldung. Seite 266 RGH-PROFAN² Case N:BEF N : Wert - Bedingungsausdruck BEF : Profan Befehlszeile Hat der Ausdruck N einen Wert <> 0, wird BEF ausgeführt, ansonsten geht die Programmausführung in die nächste Zeile. CASE entspricht einem einzeiligem IF-Befehl. BEF muß eine komplette Befehlszeile sein; eine Funktion ohne LET-Zuweisung ist nun auch hier erlaubt. Beispiele: CASE @Equ$(A$,""):PRINT "A$ ist ein Leerstring" CASE @Neq(A%,0):Let A$=@ListBox$("Liste",5) CASE @Neq(A%,0):@ListBox$("Liste",5) CaseNot N:BEF N : Wert - Bedingungsausdruck BEF : Profan Befehlszeile Hat der Ausdruck N den Wert 0, wird BEF ausgeführt, ansonsten geht die Programmausführung in die nächste Zeile. CASENOT entspricht einem einzeiligem IFNOTBefehl. Ansonsten gilt das Gleiche, wie für CASE. Char V,A=S V: Bereichsvariable A: Integer - Adresse in der Bereichsvariablen S: String - Zeichenkette Der String S wird im Speicherbereich V ab Adresse (Offset) A abgelegt. Das Ende des Strings wird im Gegensatz zum Befehl STRING nicht mit einem Null-Byte gekennzeichnet. CharSet N N: Integer - Zeichenatz Der für den nächsten USEFONT-Befehl benutzte Zeichensatz wird festgelegt. 0 - ANSI 1 - ASCII 2 - Symbol Voreinstellung ist ANSI. Seite 267 RGH-PROFAN² ChDir S S : String - Pfadangabe Es wird zum Verzeichnis S gewechselt. Enthält S eine Laufwerksangabe, so wird auch das aktuelle Laufwerk gewechselt! Beispiel: ChDir "D:\TABELLEN\GRAFIK" LoadSizedBmp "Umsatz",10,30-400,600;1 CheckMenu N1,N2 N1: Integer - Menüpunkt N2: Integer - Modus (0, 1) Der Menüpunkt mit der Menünummer N1 wird mit einem Häkchen versehen, wenn N2 ungleich 0 ist. Hat N2 den Wert 0 wird ein etwaiges Häkchen entfernt. Beispiel: PopUp "Anzeige" AppendMenu 101,"50 %" AppendMenu 102,"100 %" CheckMenu 102,1 Der Menüpunkt "100 %" wird mit einem Häkchen versehen. Chord X1,Y1-X2,Y2; X3,Y3; X4,Y4 X1,Y1 : Wert - Links oben X2,Y2 : Wert - Rechts unten X3,Y3 : Start X4,X5 : Ende Es wird ein Kreisabschnitt gezeichnet. X1,Y1 und X2,Y2 bezeichnen das Rechteck, indem der Kreis sich befindet, die anderen Koordinaten Start und Ende des Kreisabschnittes. ClearClip Die Zwischenablage wird gelöscht. ClearList Die ListBox-Liste wird gelöscht, d.h. der Zeiger wird auf den Anfang gesetzt. Mit AddFiles, AddString und/oder AddWindows wird die Liste gefüllt. Seite 268 RGH-PROFAN² ClipLoadBmp X,Y;N X,Y : Position, wo die Bitmap gezeichnet werden soll N : Integer - Kopiermodus (-1 = transparent) Mit diesem Befehl kann eine Bitmap (ein Bild) aus der Zwischenablage auf den Bildschirm gebracht werden. Dabei ist es unerheblich ob die Bitmap von einem anderen PROFAN²Programm, einem anderen Programm oder sonstwie in die Zwischenablage kam. Der Kopiermodus ist der Gleiche wie bei LoadBmp oder CopyBmp. Beim Kopiermodus -1 (transparent) kennzeichnet der linkeste unterste Pixel der Bitmap die Farbe, die durchsichtig dargestellt wird. Close #N N : Wert - Dateinummer (1 .. 8) Die mit RESET, APPEND oder REWRITE geöffnete Datei mit der Dateinummer N wird geschlossen. Beispiel: Close #Nr% CloseRW #N N: Dateikennung (1.. 8) Eine im Binärmodus geöffnete (OpenRW) Datei wird wieder geschlossen. Hinweis: Wenn der Befehl auf eine mit RESET, APPEND oder REWRITE geöffnete Datei angwandt wird, erfolgt ein Fehler (%IOResult wird gesetzt), ebenso im umgekehrten Falle! Cls [N] N : Wert - Farbwert (0 .. 32767 bzw. 16 Mio) Löscht den Bildschirm. Ist noch kein Fenster offen, so wird eins geöffnet. Ab PROFAN² 3.0 kann auch eine Hintergrundfarbe mit angegeben werden. Beispiel: Cls @RGB(23,23,23) Diese Zeile würde den Bildschirm löschen und im 32k-Farbmodus ein helles Grau als Hintergrundfarbe verwenden. Color C1,C2 C1 : Wert - Textfarbe (0 .. 15) C2 : Wert - Hintegrund (0 .. 15) Die Farben des Textmodus (PRINT, TBOX, INPUT) werden festgelegt. Die Farben entsprechen den 16 Farben von MS-DOS im Textmodus. Beispiel: Color 15,0 Print "Hugo was here!" Copy S1 > S2 S1 : String - Quelldatei Seite 269 RGH-PROFAN² S2 : String - Zieldatei Die Quelldatei wird kopiert und erhält Zieldatei als Namen. Beide Strings können auch Pfadangaben enthalten. Wildcards sind jedoch nicht gestattet. Beispiel: COPY "C:\START.BAT" > "D:\BAK\START.BAK" Seite 270 RGH-PROFAN² CopyBmp X1,Y1-X2,Y2 > X3,Y3;N X1,Y1 : Wert : Quelle rechts oben X2,Y2 : Wert : Breite, Höhe X3,Y3 : Wert : Ziel rechts oben N : Wert : Kopiermodus (-1 = transparent) Der Bildschirmausschnitt der beginnend bei X1,Y1 eine Breite von X2 Pixel und eine Höhe von Y2 Pixel hat, wird an die Position X3,Y3 kopiert. ACHTUNG: X2,Y2 sind keine absoluten Koordinaten sondern Breite und Höhe des zu kopierenden Bereiches! Der letzte Parameter bestimmt den Kopiermodus: -1 01234- transparent normales Kopieren Quelle und Ziel mit UND verknüpft Quelle und Ziel mit ODER verknüpft Quelle und Ziel mit XOR verknüpft Zielbereich invertieren (Quellbereich wird nicht berücksichtigt) Beim Kopiermodus -1 (transparent) kennzeichnet der linkeste unterste Pixel der Bitmap die Farbe, die durchsichtig dargestellt wird. CopyBmpToMem X1,Y1-DX,DY > X2,Y2 X1,Y1 : Wert - linke obere Ecke der zu kopierenden Bitmap DX,DY : Wert - Größe der zu kopierenden Bitmap X2,Y2 : Wert - linke obere Ecke der Position im Memorybitmap, wo die Bitmap gezeichnet werden soll Der Bildschirmausschnitt, der beginnend bei X1,Y1 eine Breite von DX Pixel und eine Höhe von DY Pixel hat, wird vom Bildschirm an die Position X2,Y2 iin die Speicherbitmap kopiert. Die Speicherbitmap kann mit MLoadBMP geladen odere mit MCLS erzeugt worden sein. WARNUNG: Aus Performancegründen wird nicht überprüft, ob Koordinaten wirklich innerhalb der Speicherbitmap liegen. CopySizedBmp X1,Y1-X2,Y2>X3,Y3-X4,Y4;N X1,Y1 : Wert : Quelle rechts oben X2,Y2 : Wert : Breite, Höhe X3,Y3 : Wert : Ziel rechts oben X4,Y4 : Wert : Breite, Höhe N : Wert : Kopiermodus (-1 für transparent ist hier nicht erlaubt) Der Bildschirmausschnitt an X1,Y1 mit der Größe X2,Y2 wird an die Position X3,Y3 in der Größe X4,Y4 kopiert. ACHTUNG: X2,Y2,X4,Y4 sind keine absoluten Koordinaten, sondern die Größe! CreateMenu Erzeugt ein PopUp-Menü. Das Menü wird mit APPENDMENU gefüllt und mit TRACKMENU abgefragt. Das Ergebnis steht in der Systemvariablen %MENUITEM. Seite 271 RGH-PROFAN² dbCreateIndex S1 > S2 S1 : String - Index-Ausdruck (Feldname) S2 : String - Index-Name Es wird ein Index zum Feld S der aktuellen Datenbanktabelle gebildet. Ist keine Datenbanktabelle geöffnet, erfolgt eine Fehlermeldung. Das Indexfile erhält den Dateinamen S2. S2 darf keine Dateiendung enthalten, da diese mit ".NDX" (DBase-III-Format) fest vorgegeben ist. S1 darf auch durch "+" verbunden mehrere Datenbankfelder enthalten, über die der Index gebildet wird. Beispiel: @dbOpen(#1,"ADRESS.DBF") @dbUse(#1) dbCreateIndex "PLZ" > "IXPLZ" dbCreateIndex "NAME+VORNAME" > "IXNAME" Im Beispiel wird zunächst die Indexdatei "IXPLZ.NDX" erzeugt, die einen Index auf das Feld "PLZ" der aktuellen Datenbank-Tabelle enthält. Dann wird die Indexdatei "IXNAME.NDX" erzeugt, die einen Index auf "NAME" und "VORNAME" enthält. Das erste Sortierkriterium ist der Name, das zweite der Vorname. dbCreate S1 > S2 S1 : String - Name der Strukturdatei S2 : String - Name der erzeugten Tabelle (Bestandsdatei) Es wird eine Datenbanktabelle ausgehend von der Strukturdatei S1 erzeugt. Die Tabelle wird unter dem Dateinamen S2 erzeugt. Enthält S2 keine Dateiendung, wird ".DBF" angehängt. Die Tabelle hat DBase-III-Format. Die Strukturdatei ist eine reine ASCII-Datei, die die Struktur der Datenbanktabelle beschreibt. Für jedes Feld gibt es eine Zeile, in der durch Semikolons getrennt die notwendigen Angaben stehen: Feldname, Feldtyp, Feldlänge und Anzahl der Dezimalstellen. Beispiel einer Strukturdatei für eine einfache Adreßverwaltung: NAME; VORNAME; STRASSE; PLZ_ORT; TELEFON; GEBURT; GEHALT; C; C; C; C; C; D; N; 30; 30; 30; 30; 20; 8; 10; 0 0 0 0 0 0 2 Zu den Feldtypen siehe unter %DBFTYPE. Die Namen der Felder müssen den DBaseKonventionen entsprechen: Außer Großbuchstaben und Zahlen ist nur der Unterstrich zugelassen. Der Feldname muß mit einem Buchstaben beginnen. Die maximale Namenslänge ist 10 Zeichen. Sowohl Strukturdateien als auch die fertigen Datenbanktabellen können in der PROFAN²Entwicklungsumgebung mit dem Helfer "Datenbankstruktur" erzeugt werden. Seite 272 RGH-PROFAN² DDELINK S1,S2 S1: String - Anwendung S2: String - Thema Es wird eine DDE-Verbindung zur Anwendung bezüglich des entsprechenden Themas aufgebaut. Nach erfolgreichem Aufbau enthält die Systemvariable %DDEWIN das Handle der Anwendung. Kann sich die Anwendung nicht melden, kann es passieren, daß der Befehl "hängenbleibt": Er wartet auf die Antwort des gerufenen Programmes. Hier hilft ein beliebiger Tastendruck oder Buttonklick weiter. Wenn es sich nicht gerade um den Programmanager handelt, ist man auf der sicheren Seite, wenn man die gerufene Anwendung zuvor vermittels @WINEXEC startet. Sollte die Anwendung nicht verfügbar sein, erhält man hier schon einen Fehler. Im Falle des Programmanagers sollte jedoch ein Starten desselben unterbleiben, da mancher Anwender eben eine andere Shell für sein Windows benutzt, die sich jedoch auch beim Ruf nach dem Programmmanager angesprochen fühlt und entsprechend reagiert. Bei Erfolg enthält %DDEWin das Handle des gerufenen Programmes, ansonsten 0. Mit folgendem Befehl weist man den Programmanager (bzw. die aktuelle Shell, so z.B. unter Windows 95 den Explorer) an, zum Empfang von Befehlen bezüglich des Anlegens von Gruppen "auf Empfang" zu gehen: DDELINK "Progman","Progman" DDEExecute S S: String - Befehl Der Befehl S wird an die Anwendung greschickt zu der zuvor mit DDELINK eine Verbindung aufgebaut wurde. Die möglichen Befehle und die entsprechende Syntax ist der Dokumentation der Anwendung zu entnehmen. Sollte der DDE-Server nach dem Link beendet worden sein, kann DDEEXECUTE beim Warten auf eine Antwort "hängenbleiben". Ein Tastendruk oder Buttonklick hilft hier weiter. Folgender Befehl erzeugt eine Programmgruppe, zeigt diese und legt in ihr ein Icon an: IF %DDEWin let befehl$ = "[CreateGroup(PROFAN-Test,PROFTEST.GRP)]" let befehl$ = befehl$ ; "[ShowGroup(PROFAN-Test,1)]" let befehl$ = befehl$ ; "[AddItem(winfile.exe,Datei-Manager)]" DDEExecute befehl$ ENDIF DDETerminate Die aktuelle DDE-Verbindung wird beendet. Jedem DDELink muß (ggf. nach entsprechenden DDEExecute-Kommandos) ein DDETerminate zur Beendung der Verbindung erfolgen. Dec VAR VAR : Variablenname (Integer) VAR wird um 1 erniedrigt. (Ist identisch mit SUB VAR,1) Seite 273 RGH-PROFAN² Decimals N N: Integer - Stellenzahl Die Anzahl der auszugebenden Dezimalstellen wird bestimmt. Vorgabewert ist 6. Dieser Wert wird auch bei der @Str$-Funktion berücksichtigt. (Bei in PROFAN 1.x geschriebenen Programmen sollte grundsätzlich die Zeile "DECIMALS 0" eingefügt werden, bevor sie unter PROFAN² 2.x neu compiliert werden.) Declare VAR [,VAR[,VAR]...] VAR : Variablen-Name In PROFAN müssen alle Variablen (zeitlich) vor der ersten Benutzung deklariert werden. String-Variablen werden durch ein $, LongInt-Variablen durch ein &, Float-Variablen durch ein ! , Integer-Variablen durch ein % und Bereichsvariablen durch ein # gekennzeichnet. Beispiel: Mit Ausnahme der Bereichsvariablen sind alle Variablen, die in Prozeduren oder Unterprogrammen deklariert werden nur dort lokal gültig. Der verwandte Speicherplatz wird bei Verlassen des Unterprogrammes/der Prozedur wieder freigegegen. Decalare XPos%,YPos%,Text$ Def @<Name>(N) <Ausdruck> <Name> - Funktionsname N - Anzahl der Parameter <Ausdruck> - Funktion Eine neue Funktion wird definiert. <Name> ist der Name der neuen Funktion, N kennzeichnet die Anzahl der übergebenen Parameter und <Ausdruck> beschreibt die neue Funktion. Die Parameter sind in @$(n), @%(n), @!(n) und @&(n) enthalten. Declare A%,B% Def @Max(2) @If(@Gt(@!(1),@!(2)),\ @!(1),@!(2)) Let A%=34 Let B%=12 Print @Max(A%,B%) Diese Funktion ermittelt den größeren der beiden Werte. Seite 274 RGH-PROFAN² Def <Name>(N) *S1,S2,S3,S4 <Name> - Funktionsname N - Anzahl der Parameter S1 - Name der DLL S2 - Name der Funktion in der DLL S3 - Parametertypen S4 - Ergebnistyp Definiert eine externe Funktion, die in einer 16-Bit-DLL oder der 16-Bit-API vorhanden ist. Bei den Parametertypen bedeuten: % = Integer (auch Handles, Words, Bytes und Boolsche Werte sind so zu kennzeichnen) & = LongInt (auch unsigned Long und alle anderen 4-Byte-Werte) # = Bereich (hierunter fallen alle Zeiger auf Strings, Datenstrukturen, etc. Hier können auch Werte zurückgegeben werden, da ja die Adresse des Speicherbereiches übergeben wird.) Beim Ergebnistyp bedeutet: % = Integer (Handles, Words, Bytes, boolsche Werte) & = LongInt (4-Byte-Werte) Leerstring (kein Ergebniswert) Bereichsvariablen dienen dazu, Strings oder Datenstrukturen an die externe Funktion zu übergeben und/oder von ihr zu bekommen. Natürlich sind sie ausreichend zu dimensionieren. Beispiele: DEF DEF DEF DEF DEF DEF DEF @MoveWindow(6) *"USER","MoveWindow","%%%%%%","" @waveOutGetNumDevs(0) *"MMSYSTEM","waveOutGetNumDevs","","%" @GetWText(3) *"USER","GetWindowText","%#%","&" @GetApiPixel(3) *"GDI","GetPixel","%%%","&" @GetSysResources(1) *"USER","GetFreeSystemResources","%","%" @MsgBox(4) *"USER","MessageBox","%##%","%" @GetClientRect(2) *"USER","GetClientRect","%#","" Zwei ausführlich dokumentierte Beispielprogramme finden sich im Verzeichnis BEISPIEL: DLL- TEST.PRF und RES.PRF. Letzteres ermittelt die freien Systemresourcen und zeigt sie in einer Messagebox an. HINWEIS: Auch die 32-Bit-Version von PROFAN² unterstützt den Aufruf von Funktionen in 16-Bit-DLLs. Dazu muß allerdings die Datei "PROF16.EXE" ins Windowsverzeichnis kopiert werden. Diese dient als Mittler zwischen 32- und 16-Bit-Welt und ist selbst ein 16-BitProgramm. Seite 275 RGH-PROFAN² Def <Name>(N) !S1,S2 <Name> - Funktionsname N - Anzahl der Parameter S1 - Name der DLL S2 - Name der Funktion in der DLL Definiert eine externe Funktion, die in einer 32-Bit-DLL oder der 32-Bit-API vorhanden ist. Beispiele: DEF DEF DEF DEF DEF DEF @MoveWindow(6) !"USER32","MoveWindow" @waveOutGetNumDevs(0) !"WINMM","waveOutGetNumDevs" @GetWText(3) !"USER32","GetWindowTextA" @GetApiPixel(3) !"GDI32","GetPixel" @MsgBox(4) !"USER32","MessageBoxA" @GetClientRect(2) !"USER32","GetClientRect" Dim V,N V: Bereichsvariable (muß mit DECLARE deklariert sein) N: 16 Bit-Version: Integer - Größe (1 ... 64500) 32 Bit-Version: LongInt - Größe (abhängig vom Speicher) Der Bereichsvariablen wird ein Speicherbereich von N Bytes zugewiesen. Solange der Bereich nicht mit DISPOSE wieder freigeben wird, kann er von keinem anderen Programm überschrieben oder genutzt werden. Dim! N N : Integer - Anzahl 0 .. 32767 bzw. 16380 Festlegung der Größe des Float-Arrays. Der Befehl darf nur einmal im Programm vorkommen und muß vor dem ersten Gebrauch einer Float-Array-Variablen erfolgen. Beispiel: DIM! 56 LIST! 56 = 2345.67 Dim$ N N : Integer - Anzahl 0 .. 32767 bzw. 16380 Festlegung der Größe des Stringarrays. Der Befehl darf nur einmal im Programm vorkommen und muß vor dem ersten Gebrauch einer String- Array-Variablen erfolgen. Seite 276 RGH-PROFAN² Dim% N N : Integer - Anzahl 0 .. 32767 bzw. 16380 Festlegung der Größe des Integerarrays. Der Befehl darf nur einmal im Programm vorkommen und muß vor dem ersten Gebrauch einer Integer- Array-Variablen erfolgen. Dim& N N : Integer - Anzahl 0 .. 32767 bzw. 16380 Festlegung der Größe des LongInt-Arrays. Der Befehl darf nur einmal im Programm vorkommen und muß vor dem ersten Gebrauch einer LongInt- Array-Variablen erfolgen. Dispose V V: Bereichsvariable (muß mit DECLARE deklariert sein) Der Speicherbereich der Bereichsavariablen V wird wieder freigegeben. Bevor er wieder von PROFAN² genutzt werden kann, muß er wieder mit einem DIM-Befehl reserviert werden. WICHTIG: Jeder mit DIM zugewiesener Speicherbereich muß mit DISPOSE wieder freigeben werden, bevor das PROFAN²- Programm beendet wird. Ansonsten ist der Speicher für den Rest der Windows-Sitzung blockiert! DrawExtBmp I,S,X,Y;N I : Integer - Instanzhandle der EXE bzw. DLL, die die Bitmap enthält S : String - Name oder Nummer der Bitmap X,Y : Position, wo die Bitmap gezeichnet werden soll N : Integer - Kopiermodus (-1 = transparent) Mit diesem Befehl kann eine Bitmap (ein Bild) aus einem anderen Programm oder aus einer DLL benutzt und auf den Bildschirm gebracht werden. Dazu ist es notwendig den Namen oder die Nummer der Bitmap zu kennen. Bitmap-Resourcen können wahlweise durch einen Namen oder einen Integer gekennzeichnet sein. Das Instanz-Handle wird bei DLLs mittels @UseDLL ermittelt und bei EXE-Dateien mittels @WinExec. Das Handle des ausführenden Programmes ist in der Systemvariablen %HInstance. Es ist also möglich, alle in einem Programm verwandten Bitmaps mittels eines Tools wie des Resource- Workshops von Borland in eine DLL zu packen. Ebenso ist es z.B. möglich, die PROFRUN.EXE vor dem Linken entsprechend zu erweitern. Der Kopiermodus ist der Gleiche wie bei LoadBmp oder CopyBmp. Beim Kopiermodus -1 (transparent) kennzeichnet der linkeste unterste Pixel der Bitmap die Farbe, die durchsichtig dargestellt wird. Seite 277 RGH-PROFAN² DrawExtIcon N,S,X,Y N : Integer : Handle der externen Datei S : String : Icon-Name oder -Nummer X,Y : Wert : Koordinaten Das externe Icon S aus dem Modul mit dem Handle N wird an Position X,Y gezeichnet. Bei einer DLL wird das Handle mit @USEDLL ermittelt, bei einer EXE-Datei mit @WINEXEC. Auf die Icons einer EXE-Datei kann nur solange zugegriffen werden, solange die EXE-Datei ausgeführt wird. Beispiel: Declare hDLL% Let hDLL%=@UseDLL("ICONS.DLL") DrawExtIcon hDLL%,"MSDOS",20,20 DrawIcon S,X,Y S : String : Icon-Name X,Y : Wert : Koordinaten Das Icon S wird an Position X,Y gezeichnet. Beispiel: DrawIcon "Knopf1",12,12 18 Icons sind in PROFAN.EXE enthalten, können aber z.B. mit einem Resourcen-Toolkit verändert werden. Die Icons, die in Profan vorhanden sind: PROFAN KNOPF1 EIS BAUM KNOPF2 COMPUTER WEG TEXT GESICHT EIMER MUELL MUENZE STEIN WINDOWS WASSER DOS EDITOR SAND Es gibt auch Icon-Editoren, mit denen sie verändert werden können. DrawLibIcon S,N,X,Y S - String: Name der Icon-Datei (mit Pfad) N - Integer: Nummer des Icons in der Icon-Datei X,Y - Integer: Position des Icons Mit dem Befehl kann ein Icon aus einer beliebigen Icon-Datei verwandt werden. Die Nutzung von Icons aus EXE- und DLL-Dateien ist ebenso möglich wie die Verwendung einzelner Icons (*.ICO). Das erste Icon einer Datei hat die Nummer 0. Die Anzahl der Icons in einer Datei kann mit der Funktion @ICONCOUNT ermittelt werden. Beispiele: DrawLibIcon "PROGMAN.EXE",2,100,100 DrawLibIcon "SPIEL.ICO",0,200,100 Seite 278 RGH-PROFAN² DrawSizedExtBmp I,S,X1,Y1-X2,Y2;N I : Integer - Instanzhandle der EXE bzw. DLL, die die Bitmap enthält S : String - Name der Bitmap X1,Y1 : linke obere Ecke der Position, wo die Bitmap gezeichnet werden soll X2,Y2 : Größe der Bitmap N : Integer - Kopiermodus Dieser Befehl bewirkt das Gleiche wie DrawExtBmp mit dem Unterschied, daß das Bild beim Zeichnen verkleinert oder vergrößert werden kann: Mit dem zusätzlichen Paramaterpaar wird die Größe des zu zeichnenden Bildes angegeben. Der Kopiermodus -1 (transparent) ist hier nicht zulässig. DrawSysIcon N,X,Y N : Wert - Icon-Nummer (0 .. 4) X,Y : Wert - Koordionaten Das Windowseigene Icon mit der Nummer N wird an Position X,Y gezeichnet. 0 : Windows-Symbol 1 : STOP-Zeichen 2 : Fragezeichen 3 : Ausrufezeichen 4 : Info-Zeichen DrawText X,Y,S X,Y : Wert - Koordinaten S : String oder numerischer Wert Der Text S wird an der Bildschirmposition X,Y mit dem durch USEFONT eingestellten Font in der durch TEXTCOLOR eingestellten Farbe dargestellt. DrawText 10,50,"Highscore:" Ab Profan² 2.5 darf S auch ein numerischer Literal oder eine numerische Variable sein. Vor der Ausgabe wird sie unter Berücksichtigung von Numwidth und Decimals in einen String umgewandelt: DrawText 10,50,HighScore& Seite 279 RGH-PROFAN² Ellipse X1,Y1-X2,Y2 X1,Y1 : Wert - Links oben X2,Y2 : Wert - Rechts unten Es wird ein Kreis, bzw. eine Ellipse gezeichnet. X1,Y1 und X2,Y2 bezeichnen das Rechteck, indem die Ellipse sich befindet. EnableMenu N1,N2 N1: Integer - Menüpunkt N2: Integer - Modus (0, 1, 2) Der Menüpunkt mit der Menünummer N1 wird deaktiviert, wenn N2 den Wert 1 hat bzw. deaktiviert und grau gefärbt, wenn N2 den Wert 2 hat. Hat N1 den Wert 0 wird der Menüpunkt normal dargestellt und ist anwählbar. EnableWindow N1,N2 N1: Integer - Fensterhandle N2: Integer - 0 = gesperrt, 1 = normal Das Fensterobjekt mit dem Handle N1 wird gesperrt bzw. entsperrt. Wenn ein Element gesperrt (disabled) ist, ist ein Anklicken bzw. eine Eingabe unmöglich. End Programmende. Ohne weitere Abfrage wird das Profan-Programm verlassen. Erase #N S N : Wert - Dateinummer (1 .. 15) Die Datei mit dem Dateikennzeichen N wird gelöscht. Beispiel: ASSIGN #1,"TEST.BAK" ERASE #1 ExitWindows N N: Integer - Modus (0, 1) Mit diesem Befehl wird die Windowssitzung beendet und Windows (nach den üblichen Sicherheitsabfragen, falls noch Dateien offen sind) verlassen. Hat N den Wert 1 wird Windows anschließend gleich erneut gestartet. Das kann für Installationsprogramme, die z.B. die WIN.INI ändern sinnvoll sein. Seite 280 RGH-PROFAN² FileMode N N: Integer - Filemodus (siehe DOS-Dokumentation) Der Filemodus der für das Öffnen von Dateien (mit RESET, REWRITE oder OPENRW) und den Zugriff auf diesen gilt, wird eingestellt. Unter allen DOS-Versionen sind folgende Filemodi vorhanden: 0: 1: 2: Nur lesen Nur schreiben Lesen und Schreiben Neuere DOS-Versionen kennen noch weitere Modi, die besonders im Netzwerk von Interesse sind. Standardmäßig wird bei allen oben genannten Befehlen FileMode 2 benutzt. Will man jedoch eine Datei lesen, die das Attribut ReadOnly (Nur lesen) hat, so muß vor dem RESET bzw. OPENRW der FileMode auf 0 gesetzt werden. Fill X,Y,C X,Y : Wert - Koordinaten C : Wert - RGB-Farbwert der Grezfarbe Ausgehend von Punkt X,Y wird alles bis zu einem Rahmen, der die Farbe C hat, mit dem aktuellen Pinsel (USEBRUSH) gefüllt. Beispiel: Fill 20,50,@RGB(0,0,31) Font N N : Wert - Font - Nummer (0 .. 2) Der Font N für den Textmodus (Textausgabe mit PRINT) wird gewählt: 0 : System-Font (ANSI-Zeichensatz) 1 : OEM-Font (ASCII-Zeichensatz) 2 : ANSI-Font Seit Version 4.5a bestimmt dieser Befehl auch, welchen Zeichensatz PROFAN² in den dBase-III-Tabellen benutzt! Bei 1 wird der OEM-Zeichensatz gewählt. Dieser ist dann zu verwenden, wenn etwa von anderen Programmen auf die Daten zugegriffen werden soll. Diese erwarten bei einer dBase-III-Datei in der Regel den ASCII- bzw. OEM-Zeichensatz; das gilt auch für die ODBC-Treiber. FreeDLL H H : Integer - Handle der DLL Der Aufrufzähler der DLL mit dem Handle H wird um 1 erniedrigt. Erreicht der Zähler 0, wird die DLL aus dem Speicher entfernt. Zu jedem @UseDLL innerhalb eines Programmes muß es ein FreeDLL geben. Seite 281 RGH-PROFAN² GetMessage Dieser Befehl wartet auf die nächste für das Programm bestimmte Message, bestückt die Systemvariablen %Message, %MWnd, &WParam und &LParam entsprechend und leitet die Message an Windows weiter. WICHTIG: In einer While-Schleife kann entweder ein GetMessage ODER ein anderer der WAIT-Befehle stehen! Die PROFAN²-Systemvariablen, die für gewöhnlich von den WAITBefehlen gesetzt werden (etwa %SCANKEY, %KEY, %MENUITEM, etc.) werden von GETMESSAGE nicht gesetzt. Hier muß der Programmierer die Messages selbst auswerten! If N ... [ElseIf N ...] [Else ... ] EndIf N : Wert . Bedingungsausdruck Die zwischen IF und ENDIF stehenden Zeilen werden nur dann ausgeführt, wenn N ungleich 0 ist. Beispiel: If @Equ(Test%,78) Print "Test% ist 78!" Print "-------------" EndIf Auch eine Abrage auf mehrere Bedingungen (z.B. bei der Auswertung eines Menüs) ist mit ELSEIF möglich. Sobald eine Bedingung erfüllt ist, wird der zugehörige Programmteil abgearbeitet und anschließend mit der Zeile nach dem ENDIF fortgefahren: IF @Lt(A%,1) COLOR 1,15 PRINT "A ist ELSEIF @Equ(A%,1) COLOR 2,15 PRINT "A ist ELSEIF @Equ(A%,2) COLOR 3,15 PRINT "A ist ELSE PRINT "A ist ENDIF kleiner als 1" gleich 1" gleich 2" größer als 2" ACHTUNG: Hinter ELSEIF muß ein Bedingungsausdruck stehen. Fehlt dieser würde der Interpreter das ELSEIF zwar wie ELSE behandeln, aber das Runtime-Modul würde den Fehler merken und mit einer Fehlermeldung "Zu wenig Parameter" abbrechen. Seite 282 RGH-PROFAN² IfNot N ... [ElseIf N ... ] [Else ...] EndIf Als Kurzform für If @Not(N) kann auch das kürzere (und schnellere) IfNot verwandt werden: IfNot @Equ(Test%,78) Print "Test% ist nicht 78!" Print "-------------------" EndIf Inc VAR VAR - Variablenname (Integer) VAR wird um 1 erhöht. (Ist identisch mit ADD VAR%,1) Input #N,VAR N : Wert - Dateikennzeichen (1..8) VAR : Variable Aus der Datei #N wird ein Wert in die Variable gelesen. Beispiel: Assign #1,"TEST.DAT" Reset #1 Input #1,Titel$ Input #1,Anzahl% Close #1 Input VAR VAR : Variable Von der Tastatur wird ein Wert in die Variable gelesen (Textmodus). Beispiel: Print Input Print Input "Geben Sie den Titel ein: "; Titel$ "Geben Sie die Anzahl ein: "; Anzahl% Windowstypischer ist jedoch die Verwendung des Eingabedialoges mit der Funktion @Input$. InsertMenu N1,N2,S N1: Integer - Menüpunkt vor dem eingefügt wird N2: Integer - Neuer Menüpunkt (0 .. 32766) S: String - Text des neuen Menüpunktes Vor dem Menüpunkt mit der Nummer N1 wird ein neuer Menüpunkt mit der Menünummer N2 und dem Menütext S eingefügt. Für Menünummer und -text gilt das gleiche, wie für APPENDMENU. Seite 283 RGH-PROFAN² Let VAR=N|S VAR : Variablenname N : Wert S : String Einer zuvor mit DECLARE deklarierten Variablen wird ein Wert zugewiesen. Das LET darf nicht weggelassen werden! Beim LET-Befehl für Stringvariablen können nun - ähnlich wie beim PRINT-Befehl - mehrere Stringausdrücke durch Semikolon bzw. Komma getrennt angegeben werden. Werden zwei Stringausdrücke mit einem Komma getrennt, wird ein Leerzeichen eingefügt. Diese Methode ist einfacher und deutlich (!) schneller als das Zusammenfügen von Strings mittels der @ADD$-Funktion. Beispiel: LET Text$ = "Du hast",@Str$(Score%),"Punkte erzielt!" HINWEIS: Die automatische Typumwandlung funktioniert bei einfachen Variablen. Bei Funktionen, die einen numerischen Wert zurückggeben, wird nicht immer automatisch umgewandelt, daher ist hier immer die Funktion @Str$ zu verwenden! Line X1,Y1-X2,Y2 X1,Y1 : Wert - Startkoordinaten X2,Y2 : Wert - Endkoordinaten Es wird eine Linie zwischen den angegebenen Punkten in der mit USEPEN eingestellten Linienart und Strichstärke gezeichnet. LineTo X1,Y1 X1,Y1 : Wert - Endkoordinaten Es wird eine Linie vom zuletzt gezeichneten (oder mit MOVETO gesetzten) Punkt zum angegebenen Punkt in der mit USEPEN eingestellten Linienart und Strichstärke gezeichnet. ListBoxItem$ N = S N : Integer - Index (0 .. 9999) S : String Der String S wird wird an Position N in die ListBox-Liste übernommen. List! N1 = N2 N1 : Integer - Index (0 .. 32767 bzw. 16380) N2 : Float - Wert Der Wert N2 wird an Position N1 in die Float-Liste übernommen. Beispiel: List& 1 = 5.67 List& 2 = 1045.324 Print @List!(1),@List!(2) Seite 284 RGH-PROFAN² List$ N = S N : Integer - Index (0 .. 32767 bzw. 16380) S : String Der String S wird wird an Position N in die Stringliste übernommen. List% N1 = N2 N1 : Integer - Index (0 .. 32767 bzw. 16380) N2 : Integer - Wert Der Wert N2 wird an Position N1 in die Integerliste übernommen. List& N1 = N2 N1 : Integer - Index (0 .. 32767 bzw. 16380) N2 : LongInt - Wert Der Wert N2 wird an Position N1 in die LongInt-Liste übernommen. LoadBmp S, X,Y ;N S : String - Name der Bilddatei X,Y : Wert - Koordinaten N : Wert - Kopiermodus (-1 = transparent) Eine Windows-Bild-Datei (BMP-Format) wird geladen und unter Berücksichtigung des Kopiermodus angezeigt. Das Bild muß im BMP- oder RLE-Format vorliegen. Es wird an der Position X,Y in Originalgröße angezeigt. Beispiel: -1 01234- transparent normales Kopieren Quelle und Ziel mit UND verknüpft Quelle und Ziel mit ODER verknüpft Quelle und Ziel mit XOR verknüpft Zielbereich invertieren (Quellbereich wird nicht berücksichtigt) S kann auch Pfadangaben enthalten. Das Bild muß im BMP-Format vorliegen. Es wird an der Position X,Y in Originalgröße angezeigt. Beispiel: LoadBmp "C:\WINDOWS\PAPER.BMP",10,10;0 Der letzte Parameter bestimmt den Kopiermodus. Beim Kopiermodus -1 (transparent) kennzeichnet der linkeste unterste Pixel der Bitmap die Farbe, die durchsichtig dargestellt wird. LoadSizedBmp S, X1,Y1-X2,Y2;N S : String - Name der Bilddatei X1,Y1 : Wert - Koordinaten X2,Y2 : Wert - Größe N : Wert - Kopiermodus (-1 ist hier nicht erlaubt) Seite 285 RGH-PROFAN² Eine Windows-Bild-Datei (BMP-Format) wird geladen und unter Berücksichtigung des Kopiermodus angezeigt. Das Bild wird an der Position X1,Y1 in der angegebenen Größe angezeigt.Durch negative Werte für X2 bzw. Y2 sind auch Spiegelbilder realisierbar. Locate X,Y X : Wert - Zeile Y : Wert - Spalte Der nächste PRINT- oder INPUT-Befehl positioniert auf Zeile X, Spalte Y. Wirkt nur für Textmodus-Befehle. Long V,A=N V: Bereichsvariable (muß mit DECLARE deklariert sein) A: LongInt - Adresse in der Bereichsvatiablen N: LongInt - Wert (0 .. 4,29 Milliarden) Das Word (32-Bit-Wert = 4 Byte) an der Adresse (Offset) A im Speicherbereich V wird auf den Wert N gesetzt. Liegt A außerhalb des mit DIM zugewiesenen Speichers, erfolgt eine Fehlermeldung. HINWEIS: Da vier Byte geschrieben werden, werden die Adressen A bis A+3 benutzt, wobei an Adresse A das niedrigstwertige und an Adresse A+3 das höchstwertige Byte geschrieben wird. Sollen mehere LongInt in den Bereich geschrieben werden, etwa um ein Array zu simulieren, so ist zwischen den Adressen ein Abstand von 4 einzuhalten. Beispiel: DECLARE Bereich# DIM Bereich#,12 LONG Bereich#,0 =231056 LONG Bereich#,4 =510251 LONG Bereich#,8 = 516 PRINT @LONG(Bereich#,0) PRINT @LONG(Bereich#,4) PRINT @LONG(Bereich#,8) DISPOSE Bereich# Seite 286 RGH-PROFAN² MCLS DX,DY DX,DY : Wert - Breite, Höhe Es wird eine leere Speicher-Bitmap in dere Größe DX, DY angelegt. Mit CopyBmpToMem oder per Umleitung mit StartPaint -1 kann diese Bitmap bearbeitet werden. Mit MCopyBmp und MCopySizedBmp können beliebige Teile auf den Bildschirm kopiert werden. MCopyBmp X1,Y1-X2,Y2 > X3,Y3;N X1,Y1 : Wert : Quelle rechts oben X2,Y2 : Wert : Breite, Höhe X3,Y3 : Wert : Ziel rechts oben N : Wert : Kopiermodus (-1 = transparent) Der Bildschirmausschnitt der beginnend bei X1,Y1 eine Breite von X2 Pixel und eine Höhe von Y2 Pixel hat, wird aus dem mit MLOADBMP geladenem Bild an die Position X3,Y3 kopiert. ACHTUNG: X2,Y2 sind keine absoluten Koordinaten sondern Breite und Höhe! Der letzte Parameter bestimmt den Kopiermodus: -1 01234- transparent normales Kopieren Quelle und Ziel mit UND verknüpft Quelle und Ziel mit ODER verknüpft Quelle und Ziel mit XOR verknüpft Zielbereich invertieren (Quellbereich wird nicht berücksichtigt) Beim Kopiermodus -1 (transparent) kennzeichnet der linkeste unterste Pixel der Bitmap die Farbe, die durchsichtig dargestellt wird. MCopySizedBmp X1,Y1-X2,Y2 > X3,Y3-X4,Y4;N X1,Y1 : Wert - linke obere Ecke der zu kopierenden Bitrmap X2,Y2 : Wert - Größe der zu kopierenden Bitmap X3,Y3 : Wert - linke obere Ecke der Position, wo die Bitmap gezeichnet werden soll X4,Y4 : Wert - Größe der Bitmap N : Wert - Integer - Kopiermodus (-1 ist hier nicht erlaubt) Der Bildschirmausschnitt der beginnend bei X1,Y1 eine Breite von X2 Pixel und eine Höhe von Y2 Pixel hat, wird aus dem mit MLOADBMP geladenem Bild an die Position X3,Y3 X4,Y4 kopiert. ACHTUNG: X2,Y2 und X4,Y4 sind keine absoluten Koordinaten sondern Breite und Höhe! Der letzte Parameter bestimmt den Kopiermodus. MLoadBMP S S : String - Dateiname der Bilddatei (evtl. mit Pfad) Die Bilddatei S wird in den Speicher geladen, aber nicht angezeigt. Mit MCOPYBMP können Teile des Bildes (oder auch die ganze Bild) auf den Bildschirm kopiert werden. HINWEIS: Es kann immer nur eine Bilddatei im Speicher sein. Bei jedem Aufruf von MLOADBMP wird die vorher geladene Bilddatei überschrieben. MkDir S Seite 287 RGH-PROFAN² S : String - Pfadangabe Das Verzeichnis S wird angelegt. Im Falle eines Fehlers hat %IORESULT einen von 0 verschiedenen Wert. Beispiel: MkDir "C:\WINDOWS\TEST" Siehe auch: ChDir, RmDir Seite 288 RGH-PROFAN² MoveTo X1,Y1 X1,Y2 : Wert - Koordinaten Der Grafik-Kursor wird zum angegebenen Punkt bewegt, ohne eine Linie zu zeichnen. Praktisch ist dieser Befehl nur im Zusammenhang mit nachfolgendem LINETO-Befehl sinnvoll. Music S S: String (Noten) Der Parameter S ist ein String in einer eigenen Makrosprache. Diese Makrosprache ist kompatibel zur Music-Makro-Sprache, wie sie von BASIC her (für den PLAY-Befehl) bekannt ist: A..G On > < Ln Pn Tn MN ML MS entsprechende Note: # - Erhöhung + - Erhöhung - Erniedrigung . - Punktiert n - kennzeichnet die Notenlänge. 4 steht für Viertel, 2 für Halbe, etc. Wird n weggelassen, wird die Standardlänge verwandt. Oktave n (0..6) wird gewählt Eine Oktave höher Eine Oktave niedriger Setzt die Standardlänge Pause in der Länge n. Tempo: Anzahl der Viertelnoten pro Minute. Defaultwert ist 120. normale Musik. Jede Note wird 7/8 der Zeit gespielt Legato. Die Töne gehen in einander über. Staccato. Jede Note wird nur 3/4 der Zeit gespielt. Um eine Tonleiter in Viertel-Noten in der 3. Oktave zu spielen, reicht folgender Befehl: MUSIC "O3 C4 D4 E4 F4 G4 A4 B4 > C4" Erhöhungs- und Erniedrigungszeichen sind genauso möglich, wie auch Punktierungen: MUSIC "C#2 F-8 G4." Pausen haben den Notenwert "P". Für Soundkartebesitzer wurde die Makrosprache erweitert: Der Befehl MUSIC gibt nun bei vorhandenem MIDI-Gerät (Soundkarte oder MIDI-Schnittstelle) die Musik über das MIDIGerät aus. Die Musik-Makro-Sprache von PROFAN² wurde dazu um folgende Befehle erweitert: In Kn Vn Instrument n (0 ... 127) wird auf den aktuellen Kanal gelegt. Kanal n (0..15) wird wiedergegeben. Der aktuelle Kanal wird auf Lautstärke n (0...127) eingestellt. Voreingestellt ist Kanal 0 mit Instrument 0 (= Klavier) in der Laustärke 100. Diese Erweiterungen wirken nur dann, wenn das MIDI-Gerät korrekt installiert ist, ansonsten erfolgt die Ausgabe in der 16-Bit-Version über den Lautsprecher und in der 32-Bit-Version überhaupt nicht. Seite 289 RGH-PROFAN² NextPage Mit NEXTPAGE wird innerhalb des Druckauftrages zwischen STARTPRINT und ENDPRINT eine neue Seite begonnen. NumWidth N N: Integer - Mindestweite Mindestweite der Ausgabe numerischer Werte. Dieser Wert wird auch von der @STR$Funktion und dem Befehl DrawText verwandt. Ist der Ausgabestring kürzer wird er mit führenden Leerzeichen aufgefüllt. Standarteinstellung ist 0. Siehe auch: Decimals Seite 290 RGH-PROFAN² OpenRW #N #N: Dateikennung (1 - 8) Die Datei mit der Kennung #N wird im Binärmodus zum Lesen und Schreiben geöffnet. Es können beliebige Bytes aus der Datei gelesen (@GetByte) und beliebige Bytes in die Datei geschrieben (PutByte) werden. Mit @FilePos kann die Position des Dateizeigers ermittelt werden und mit SEEK wird sie verändert. Orientation N N : Integer - Winkel (in Zehntel-Grad!) Bestimmt den Winkel der Textausgabe; wird durch den nächsten USEFONT- Befehl aktiviert. (Sinnvoll nur bei TRUE-Type-Fonsts.) Beliebige Textausrichtungen auf dem Bildschirm und Drucker sind somit möglich! OpenRW #N N: Dateikennung (1 - 15) Die Datei mit der Kennung #N wird im Binärmodus zum Lesen und Schreiben geöffnet. Es können beliebige Bytes aus der Datei gelesen (@GetByte) und beliebige Bytes in die Datei geschrieben (PutByte) werden. Mit @FilePos kann die Position des Dateizeigers ermittelt werden und mit SEEK wird sie verändert. Siehe auch: Rewrite, Append und Reset. OutP N1,N2 N1 : Integer - Port-Adresse N2 : Integer - Auszugebender Wert An Port N1 (und N1+1) wird der Wert N2 ausgegeben, wobei N2 als ein Datenwort (=2 Byte bzw. 16 Bit) interpretiert wird. Das niederwertige Byte wird an Port N1 ausgegeben und das höherwertige Byte an Port N1+1. Um ein Byte auszugeben, ist OUTPB zu verwenden. Mit der Funktion @INP kann ein Datenwort am Port gelesen werden. OutPB N1,N2 N1 : Integer - Port-Adresse N2 : Integer - Auszugebender Wert (0 ... 255) An Port N1 wird der Wert N2 ausgegeben, wobei N2 als ein Byte interpretiert wird. Mit der Funktion @INPB kann ein Byte am Port gelesen werden. ACHTUNG: Die beiden OUT-Befehle sollte man nur verwenden, wenn man genau weiß, was man macht. Sinn machen die Befehle vor allem dann, wenn man eine I/O-Karte, deren Adressen man kennt, mit einem Programm ansprechen will. Falsche Werte können Windows zum Absturz bringen oder z.B. im Falle der Register der Grafikkarte den Monitor in Mitleidenschaft ziehen. Ein Ausprobieren ohne Plan kann Ihre Hardware beschädigen und zu Datenverlust führen! Seite 291 RGH-PROFAN² Parameters VAR [,VAR[,VAR] ...] VAR - Variablennamen Die Aufrufparameter einer Prozedur werden Variablen zugewiesen, die innerhalb der Prozedur bekannt sind. Ein Beispiel findet sich unter PROC. Die Anzahl der Variablen sollte gleich der Anzahl der Übergabeparameter sein; überprüft wird dieses aber ebensowenig, wie die Datentypen. Gegebenenfalls erfolgt eine automatische Umwandlung. Siehe auch: Proc PassWord S S: String - Paßwort Dieser Befehl setzt das Paßwort, daß für die Funktion @PWD$ zum Ver- und Entschlüsseln von Strings verwandt wird. WICHTIG: Das Entschlüsseln funktioniert nur dann korrekt, wenn das gleiche Paßwort wie beim Verschlüsseln benötigt wird. Soll die Verschlüsselungsfunktion ausgeschaltet werden, ist der Befehl mit einem Leerstring zu benutzen: PASSWORD "" HINWEIS: Diese Verschlüsselung erschwer zwar den Zugriff auf die Daten, ist aber (noch) nicht unknackbar! Dafür bleibt die Sortierreihenfolge der Daten weitgehend erhalten. Pie X1,Y1-X2,Y2; X3,Y3; X4,Y4 X1,Y1 : Wert - Links oben X2,Y2 : Wert - Rechts unten X3,Y3 : Start X4,X5 : Ende Es wird ein Kreisteil (Tortenstück) gezeichnet. X1,Y1 und X2,Y2 bezeichnen das Rechteck, indem der Kreis sich befindet, die anderen Koordinaten Start und Ende des Kreisteiles. Play N1,N2,N3 N1 : Wert - Notenwert (0 = Pause) N2 : Wert - Dauer N3 : Wert - Punkte Die Notenwerte werden in Halbtonschritten hochgezählt. Die Dauer wird reziprok angegeben: 4 bedeutet z.B. 1/4 Note; 2 = 1/2 Note. Im Beispiel wird eine halbe punktierte Note gespielt: Play 24,2,1 PLAY wurde für die MIDI-Wiedergabe über die Soundkarte erweitert: Werden statt eines Notenwertes mehrere durch Semikolon getrennt angegeben, werden diese gleichzeitig über die verschiedenen Kanäle wiedergegeben. Die Kanäle 1 bius 16 entsprechen den MIDIKanälen mit dem Unterschied, das der 4. und 10. Kanal vertauscht wurden. Das Schlagzeug befindet sich also bei General-MIDI jetzt auf Kanal 4, was das Erzeugen dreistimmiger Songs mit Schlagzeugbegleitung vereinfacht. Seite 292 RGH-PROFAN² Wenn Dauer größer als 0 ist, werden die Töne entsprechend lang gespielt und das Programm verharrt. Ist die Dauer 0, wird der Ton angestoßen und der Ton klingt im Hintergrund solange bis er ausgeschaltet wird. Ausgeschaltet wird ein Ton, indem mit vorangestelltem Minus-Zeichen ausgegeben wird. Ist die Dauer -1, wird kein Ton erzeugt, sondern die Werte N1 bis N16 als Instrumente interpretiert, die den 16 Kanälen zugewiesen werden. Das Beispiel spielt einen C-Akkord (25;27;29) auf der Kirchenorgel (20. Instrument / Die Zählung beginnt hier bei 0) solange, bis eine Taste gedrückt wird: Play 19;19;19,-1,0 Play 25;27;29,0,0 WaitKey Play -25;-27;-29,0,0 HINWEIS: Dieser Befehl funktioniert in der 16-Bit-Version auch ohne Soundkarte und benutzt dann den internen Lautsprecher. Befehle mit einer Dauer kleiner als 1 werden dann jedoch ignoriert und bei mehreren Notenwerten wird nur der erste benutzt. PlaySound S,N S : String - Dateiname (mit Pfad) N : Integer - Spielmodus Eine WAV-Datei wird über die Soundkarte (oder den SPEAKER-Treiber) abgespielt. Ist kein Soundtreiber vorhanden, passiert nichts. Beispiel: PlaySound "C:\MMDATA\GONG.WAV",1 Mögliche Werte für N: 01816 - Die Sound wird im Vordergrund gespielt. Das Programm wird solange angehalten. Die Sound wird im Hintergrund gespielt. Das Programm läuft weiter. Ein Sound wird solange wiederholt, bis ein neuer gestartet wird. Der Sound wird nur gestartet, wenn kein anderer z.Zt. gespielt wird. Kombinationen sind durch Addition möglich. Bei 8+0 gibts keine Wiederkehr! PopUp S S : String - Name des Menüs Ein PopUp-Menü wird an das FensterMenü angehängt. Existiert noch kein Fenstermenü, so wird es erzeugt. PopUp "&Datei" AppendMenu "&Laden" AppendMenu "&Speichern" PopUp "&Bearbeiten" ... Seite 293 RGH-PROFAN² Print #N,f;f,f ... N : Wert - Dateikennzeichen (1..15) f : druckbarer Ausdruck Der Ausdruck, bzw. die Ausdrücke werden in die mit N bezeichnete Datei geschrieben. Steht zwischen den Ausdrücken ein Semikolon, so werden sie direkt aneinander gehängt, bei einem Komma wird ein Leerzeichen eingefügt. Siehe auch unter ASSIGN, REWRITE, APPEND und CLOSE. Print f;f,f... f : druckbarer Ausdruck Der Ausdruck, bzw. die Ausdrücke werden auf den Bildschirm geschrieben. Steht zwischen den Ausdrücken ein Semikolon, so werden sie direkt aneinander gehängt, bei einem Komma wird ein Leerzeichen eingefügt. Siehe auch unter LOCATE. Beispiel: Print "Dies ist der",N%;". Test" Proc <Name> ... EndProc <Name> : Name der Prozedur Eine Prozedur wird definiert, die im nachfolgenden Programm wie ein neuer Befehl verwandt werden kann. Über den PARAMETERS-Befehl werden die übergebenen Parameter eingelesen. Beispiel: PROC Wiederhole PARAMETERS Text$, Anzahl% DECLARE I% LET I%=0 WHILE @LT(I%,Anzahl%) PRINT Text$ INC I% WEND ENDPROC Wiederhole "Testtext",10 Die in der Prozedur über PARAMETERS oder DECLARE deklarierten Variablen sind nur innerhalb der Prozedur bekannt (lokal). Alle Variablen, die außerhalb (oberhalb) der Prozedur definiert wurden sind in der Prozedur auch bekannt (wie in PASCAL). Die Prozedur kann auch schon vor Erreichen der Zeile ENDPROC über RETURN verlassen werden, wobei dann die Übergabe eines Wertes an das aufrufende Programm möglich ist. Seite 294 RGH-PROFAN² PutByte #N1,N2 #N1: Dateikennung (1 - 15) N2: Integer - zu schreibender Wert (0 ... 255) Das Byte N2 wird an die aktuelle Position des Dateizeigers in die Datei mit der Kennung #N1 geschrieben und der Dateizeiger um 1 weitergesetzt. Befindet sich dadurch der Zeiger hinter dem Ende der Datei, liefert @EOF(#N) den Wert 1. Durch weitere Schreiboperationen mit PUTBYTE würde die Datei vergößert werden. Siehe auch: @GetByte PutClip S S : String Schreibt die Zeichenkette S (es kann auch ein numerischer Wert sein) als Text in die Zwischenablage. Beispiele: PutClip "Das ist ein Test!" PutClip Text$ Die Zwischenablage wird vor dem Schreiben nicht gelöscht. Mittels der Zwischenablage können somit Daten zwischen verschiedenen Programmen ausgetauscht werden. Es ist sogar denkbar, daß ein Programm ein anderes über die Zwischenablage fernsteuert. Siehe auch: ClearClip @GetClip$() Seite 295 RGH-PROFAN² Randomize Sorgt dafür, daß die Zufallszahlen (@RND) auch wirklich zufälligen Charakter haben. ReadText V,S V: Bereichsvariable S: String - Dateiname (ggf. mit Pfad) Die Textdatei S wird komplett in den Speicherbereich (beginnend ab Offset-Adresse 0) eingelesen. Die Zeilen werden mit CR/LF (Zeichen 13 + 10) getrennt. Am Ende wird ein NullByte angehängt. Paßt der Text nicht in den mit DIM zugewiesenen Bereich, wird er abgeschnitten und es erfolgt eine Warnung. Rectangle X1,Y1-X2,Y2 X1,Y1 : Wert - Links oben X2,Y2 : Wert - Rechts unten Es wird ein Rechteck innerhalb der angegebenen Koordinaten gezeichnet. Rem ... Alles was dahinter steht, ist Kommentar. REM steht immer am Anfang der Kommentarzeile. Für Kommentare hinter anderen Befehlen ist das ' zu benutzen. RemoveMenu N N: Integer - Menüpunkt Der Menüpunkt mit der Nummer N wird aus dem aktuellen Fenster-Menü entfernt. Rename #N,S N : Wert - Dateikennzeichen (1..15) S : String - neuer Name (mit Pfad) Die Datei mit dem Kennzeichen N wird in S umbenannt. Enthält S eine Pfadangabe (mit oder ohne Laufwerksbezeichnung), so wird sie verschoben. Verschieben ist nur innerhalb eines Laufwerks möglich. Beispiel: Assign #3,"C:\TEST.DAT" Rename #3,"C:\UTILS\TOAST.DAT" RePaint Malt den Bildschirm neu. Ist nur dann zu benutzen wenn bestimmte Befehlskombinationen (u.U. in Zusammenhang mit PopUp-Windows) den Bildschirm etwas durcheinander bringen. Dies sollte in der aktuellen PROFAN²-Version nicht mehr vorkommen. Seite 296 RGH-PROFAN² Reset #N N : Wert - Dateikennzeichen (1..15) Die Datei N wird zum Lesen geöffnet. Beispiel: Declare Zeile$ Assign #2,"TEST.DAT" Reset #2 WhileNot @Eof(#2) Input #2,Zeile$ Print Zeile$ Wend Siehe auch: Rewrite, Append und OpenRW. Return [<Wert>] Beenden einer Prozedur. Es ist möglich einen Wert zurückzugeben. Dieser steht dann in @$(0), @%(0), @&(0) und/oder @!(0): PROC Test Print "Das ist ein Test" Return "OK!" ENDPROC Print "Im Hauptprogramm" Test Print "Wieder zurück! Ergebnis:",@$(0) Der zurückgegebene Wert darf im Falle einer Prozedur auch eine lokale Variable sein. WICHTIG: Auch wenn eine Prozedur mit RETURN verlassen wird, muß die Definition der Prozedur mit ENDPROC abgeschlossen werden. Rewrite #N N : Wert - Dateikennzeichen (1..15) Die Datei N wird zum Schreiben geöffnet. Der bisherige Dateiinhalt geht verloren. Existiert sie nicht, wird sie erzeugt. Beispiel: Assign #2,"C:\UTILS\TEST.DAT" Rewrite #2 Print #2,Zeile$ Close #2 Um eine bestehende Datei zu erweitern, ist der Befehl APPEND zu verwenden. Siehe auch: Reset und OpenRW. RmDir S S : String - Verzeichnisnamen Das Verzeichnis S wird gelöscht. Enthält es noch Dateien oder Unterverzeichnisse, kann es nicht gelöscht werden. Bei erfolgreicher Operation hat %IORESULT den Wert 0. Sie auch: ChDir MkDir Seite 297 RGH-PROFAN² RoundRect X1,Y1-X2,Y2; X3,Y3 X1,Y1 : Wert - Links oben X2,Y2 : Wert - Rechts unten X3,Y3 : Wert - Rundung Es wird ein abgerundetes Rechteck gezeichnet. X1,Y1 und X2,Y2 bezeichnen das Rechteck, die anderen Parameter den Grad der Rundung in waagrechter und senkrechter Richtung. Run S S : String - Programmname Das Programm S wird aufgerufen und das aufrufende Profanprogramm beendet. Es können alle Windowsprogramme - auch mit Parametern - aufgerufen werden. Beispiele: Run "NOTEPAD HILFE.TXT" Run "E:\PROFAN\PROFAN DEMO.RGH" Run "WRITE" Seite 298 RGH-PROFAN² SaveBmp S,X1,Y1-X2,Y2 S: String - Dateinahme (mit Pfad) X1,Y1: Integer - linke obere Ecke X2,Y2: Integer - rechte untere Ecke Der angegebene Teil des Bildschirmes wird in eine BMP-Datei gespeichert. Die Dateiendung ".BMP" ist mit anzugeben. Beispiel: SaveBmp "TESTBILD.BMP",10,10-200,140 SaveBmpToClip X,Y - DX,DY X,Y : Integer - linke obere Ecke DX,DY: Integer - Größe des zu speichernden Bildes Der angegebene Teil des Bildschirmes wird in die Zwischenablagew gespeichert. Von dort aus kann die Bitmap von anderen Programmen benutzt werden. Screen X,Y X,Y : Ausmaße des virtuellen Screens Das Koordinatensystem des Hauptfensters bzw. des mit STARTPAINT aktivierten Fensters wird auf Breite X und Höhe Y festgelegt. Alle weiteren Koordinatenangaben beziehen sich auf das mit Screen eingestellte Koordinatensystem. Auf diese Weise sind Bildschirmausgaben möglich, die sich immer an die aktuelle Fenstergröße anpassen. Die dritte Zeile des Beispiels setzt das Koordinatensystem wieder auf Angaben in Pixel zurück: Cls Screen 3000,2000 Line 10,10 - 2900,1900 Screen Width(%Hwnd),Height(%Hwnd) WaitInput ScreenCopy [X1,Y1-X2,Y2] X1,Y1: Integer - linke obere Ecke X2,Y2: Integer - rechte untere Ecke Der angegebene Bereich wird auf den Drucker kopiert und die Seite ausgedruckt. Ist kein Bereich angegeben, wird der gesamte Bildschirm ausgedruckt. Beispiele: ScreenCopy 10,10 - 600,100 ScreenCopy Siehe auch das Befehlspaar STARTPRINT ... ENDPRINT und WINCOPY. Seek #N,A #N: Dateikennung (1 - 15) A: LongInt - Position in der Datei Der Dateizeiger der im Binärmodus geöffneten Datei mit der Kennung #N wird auf die Position A gesetzt. Das erste Byte in der Datei hat die Position 0. Hinweis: SEEK Seite 299 RGH-PROFAN² #N,@GETFILESIZE(#N) setzt den Zeiger hinter das letzte Byte. Damit wird die Datei vergrößert. Separator Fügt dem PopUp-Menü eine Trennungslinie hinzu. Beispiel: PopUp "&Datei" AppendMenu AppendMenu AppendMenu AppendMenu Separator AppendMenu 100,"&Neu" 101,"&Laden" 102,"&Speichern" 103,"Speichern &als" 104,"&Ende" Seite 300 RGH-PROFAN² SetAutoPaint N N : Integer - 0: AutoPaint ist ausgeschaltet, %wmPaint wird immer gesetzt 1: AutoPaint ist eingeschaltet, von Dialogfenstern wird %wmPaint gesetzt 2: AutoPaint ist eingeschaltet, %wmPaint wird niemals gesetzt (Standard) Wenn ein Fenster vergrößert und/oder verschoben wird, müssen Teile des Bildschirmes und/oder Fensters neu gezeichnet werden. Im Normalfall nimmt Ihnen PROFAN² diese Arbeit ab, indem es auf die entsprechende Aufforderung durch Windows reagiert. Solange in den Dialogboxen und Dialogfenstern nicht gezeichnet wird (siehe StartPaint - EndPaint), benötgt das PROFAN²- Programm also keine Kenntnis über diese Aufforderung. Wenn man in Dialogfenstern zeichnet, so übernimmt hier PROFAN² das Neuzeichnen nicht automatisch. Mit SetAutoPaint 1 sorgt man nun dafür, daß die Aufforderung zum Neuzeichnen eines Dialogfensters WaitInput verläßt und die Systemvariable %wmPaint gesetzt wird. Das Hauptgfenster wird in diesem Fall weiterhin von PROFAN² automatisch versorgt. Es mag nun aber Fälle geben, wo der fortgeschrittene Programmierer auch dieses selbst in die Hand nehmen möchte, etwa weil er die Größe der Hintergrundbitmap immer an die Größe des Haupfensters angepaßt haben möchte. Dazu kann er mit SetAutoPaint 0 das automatische Aktualisieren des Bildschirmes ausschalten und es selber übernehmen. %wmPaint wird nun auch gesetzt, wenn das Hauptfenster neu gezeichnet werden muß. Folgendes Beispielprogramm zeigt eine Bitmap immer in der Größe des Programmfensters an und wird mit "Esc" beendet: Declare Ende% PROC MaleNeu MCopySizedBmp 0,0-32,32 > 0,0-Width(%HWnd),Height(%HWnd);0 ENDPROC SetAutoPaint 0 CLS MLoadBmp "TEST.BMP" MaleNeu Let Ende% = 0 WHILENOT Ende% WaitInput IF @Equ(%Key,27) Let Ende% = 1 ELSEIF %wmPaint MaleNeu ENDIF ENDWHILE END SetCheck N1,N2 N1 : Integer - Handle des Fensterobjektes N2 : Integer - 1 = setzen / 0 = zurücksetzen Die Checkbox bzw. der Radiobutton mit dem Handle N wird gesetzt (angekreuzt), bzw. zurückgesetzt. Seite 301 RGH-PROFAN² SetDialogFont N N:Integer - Modus (0 = Systemfont / 1 = gewählter Font) Hat N den Wert 1 wird für die nachfolgend erstellten Dialogelemente (mit @CREATE...) der mit USEFONT eingestellte Font benutzt. Ansonsten wird - wie bisher - der Systemfont verwandt. SetErrorLevel N N: Integer - Errorlevel Je nach Wunsch kann der Errorlevel auf einen der möglichen Werte gesetzt werden. Damit wird das Verhalten des Systems bei Auftreten eines Fehlers oder einer Warnung definiert: 210-1 - Für ganz Vorsichtige: Warnungen werden wie Fehler behandelt und führen zu einer Fehlermeldung mit Programmabbruch. Für die Programmentwicklung: Auch Warnungen werden ausgeben, aber das Programm läuft auf Wunsch weiter. Der Normalzustand: Warnungen werden nicht angezeigt. Diesen Errorlevel sollte man bei einem fertigen Programm verwenden. Fast schon kriminell: Auch Fehlermeldungen werden übergangen.Das kann unter Umständen zu einem Windowsfehler oder Absturz desSystemes mit Datenverlust führen. Warnungen treten auf, wenn ein Ausdruck nicht als numerischer Wert zu interpretieren ist oder z.B. eine Bilddatei nicht gefunden wird ... SetFAttr #N1,N2 #N1: Dateikennung N2: Integer - Attribut(e) Setzt das Attribut der Datei #N. Der Kennung #N muß eine Datei mit ASSIGN zugewiesen worden sein. Die Datei darf aber nicht geöffnet sein. Geöffnet wird eine Dartei durch die Befehle REWRITE, APPEND, RESET oder OPENRW. Die Attribute: $01 = ReadOnly $02 = Hidden $04 = SystemDatei $08 = Label $10 = Directory-Eintrag $20 = Archiv Werden mehrer Attribute verwandt, so sind sie zu addieren. Seite 302 RGH-PROFAN² SetLFN N N: Integer - -1, 0 oder 1 (nur 16-Bit-Version) Die Benutzung von langen Dateinamen wird bestimmt: -1 0 1 Das System erkennt automatisch, ob Windows 95 (oder neuer) aktiv ist. Lange Dateinamen sind ausgeschaltet lange Dateinamen sind eingeschaltet Bei Windows 3.x führt das Einschalten der langen Dateinamen unweigerlich zu einem Systemfehler, daher ist diese Einstellung mit Vorsicht zu genießen. Der Befehl ist dafür gedacht, lange Dateinamen dort zu erlauben, wo die automatische Erkennung dieser Fähigkeit versagt, z.B. unter Windows 3.x NT. Wird SetLFN auf 0 oder 1 gesetzt, zeigt dies die Systemvariable %LFN auch entsprechend an. Bei -1 zeigt sie das Ergebnis der automatischen Erkennung an. WICHTIG: In der 32-Bit-Version von PROFAN ist dieser Befehl ohne Wirkung! SetMenuItem N N: Integer - Menünummer Die Systemvariable %MENUITEM, die auch von der Funktion @MENUITEM ausgewertet wird, wird auf den Wert N gesetzt. SetPixel X,Y,C X,Y : Wert - Koordinaten C : Wert - RGB-Farbewert Setzt an die Position X,Y ein Pixel in der Farbe C (bzw. der C am nächsten liegenden darstellbaren Farbe). Beispiel: SetPixel 10,10,@RGB(13,20,3) SetPixel 11,11,0 SetScrollPos N1,N2 N1: Integer - Handle des Scrollbalkens N2: Integer - Wert Der Wert des Scrollbalkens (und damit der Schieberegler) wird gesetzt. Zum Auslesen des Wertes ist die Funktion @GETSCROLLPOS zu verwenden. SetScrollRange N1,N2,N3 N1: Integer - Handle des Scrollbalkens N2: Integer - niedrigster Wert (-32767 - 32767) N3: Integer - höchster Wert (-32767 - 32767) Der Wertebereich des Scrollbalkens wird gesetzt. Niederigster und höchster Wert dürfen nicht mehr als 32767 auseinanderliegen! Standardmäßig ist der Wertebereich eines Scrollbalens auf 0 - 100 eingestellt. Seite 303 RGH-PROFAN² SetText N,S N : Integer - Handle des Fensterobjektes S : String - Neuer Text Dem Fensterobjekt mit dem Handle N% wird der Text S$ zugewiesen. Bei einem Eingabeoder Textfeld ist das der Text im Feld. Bei einem Iconfeld der Name des Icons, bei einem Button der Text der Schaltfläche, bei einem Fenster der Fenstertitel, ... Mit @GETTEXT$ kann dieser Text ausgelesen werden. Dieser Befehl ist nur in der Vollbersion vorhanden! SetTimer N - KillTimer N : LongInt - Timer-Intervall in Millisekunden Mit SetTimer wird ein Zeitgeber eingestellt, der alle N Millisekunden ein Timer-Ereignis ausgelöst. Dieses Ereignis führt dazu, daß ggf. ein WAITINPUT verlassen wird und die Systemvariable %wmTimer auf 1 gesetzt wird. Erst beim Auslesen wird sie wieder auf 0 gesetzt. Da die Anzahl der möglichen Zeitgeber in Windows sehr begrenzt ist, erlaubt PROFAN² nur die Nutzung eines Zeitgebers, was aber in aller Regel ausreichend ist. Es ist durchaus statthaft, den Zeitgeber mit einem erneuten SetTimer neu einzustellen. Vor dem Enden des Programmes muß der Zeitgeber, so er im Programm mindestens einmal genutzt wurde, mit KillTimer wieder freigegeben werden. Folgendes Beispiel zeigt eine Schleife, die erst nach 10 Sekunden (= 10000 Millisekunden) verlassen wird, aber den Prozessor nicht belastet: PROC Schlafe Parameters N& Declare Ende% SetTimer N& Let Ende% = 0 WHILENOT Ende% WaitInput Case %wmTimer:Let Ende% = 1 ENDWHILE KillTimer ENDPROC CLS Print "Der Timer startet ..." Schlafe 10000 Print "... und weiter geht's" WaitKey End Hinweis: Das Timerereignis wird nur ausgelöst, wenn ein Hauptfenster existiert. Tip: Man kann auch unsichtbare Hauptfenster (Windowstyle 112, Größe 0,0-0,0) erzeugen. Seite 304 RGH-PROFAN² SetTrueColor N N: Integer - 0 oder 1 0 - 32768 Farben 1 - 16 Millionen Farben Standardmäßig nutzt PROFAN bei den eigenen Zeichenbefehlen 32768 Farben, wobei der Rot-, Grün- und Blau-Anteil zwischen 0 und 31 liegen darf. Mit SETTRUECOLOR 1 wird auf 16 Millionen Farben umgeschaltet, wobei die Farb- anteile jetzt zwischen 0 und 255 liegen dürfen. SetWindowPos W=X,Y-DX,DY W: Integer - Fensterhandle X,Y: Integer - Linke obere Ecke des Fensters DX,DY: Integer - Neue Größe des Fensters Die Position und Größe des Fensters bzw. Fensterobjektes mit dem Handle W wird auf die neuen Werte gesetzt. Dieser Befehl kann natürlich auf jedes Windowsobjekt, dessen Handle bekannt ist, angewandt werden! Shell S S : String - Programmname Das Programm S wird aufgerufen und das aufrufende Profanprogramm läuft weiter. Es können alle Windowsprogramme - auch mit Parametern - aufgerufen werden. Beispiel: Shell "NOTEPAD HILFE.TXT" Vergleiche auch: Run, @WinExec ShowCursor N N : Integer - 0 = verstecken / 1 = anzeigen Der Kursor kann versteckt oder gezeigt werden. Bei Bildschirmschonern ist in der Regel kein sichtbarer Mauskursor gewünscht. Jede Anwendung, die den Kursor versteckt, sollte ihn auch wieder anzeigen. 1 - Der Kursor wird angezeigt 0 - Der Kursor wird versteckt ShowMax Das Bildschirmfenster wird zu seiner Maximalgröße erweitert. Der Befehl ist identisch mit dem Anklicken des Pfeiles nach oben an der rechten oberen Ecke des Rahmens. Seite 305 RGH-PROFAN² ShowMin Das Profanprogramm wird zum Icon verkleinert und läuft allerdings weiter. Vergrößert wird es entwededer durch SHOWNORMAL oder SHOWMAX oder aber durch entsprechendes Auswahl im Systemmenü [-] des Programmes. ShowNormal Das Bildschirmfenster des Profanprogrammes wird in normaler Größe angezeigt, das heißt z.B. in der Größe, die es vor dem Verkleinern (zum Icon) oder Vergrößern hatte. Vergleiche auch: @ShowWindow Sound N1,N2 N1 : Wert - Frequenz in Hertz N2 : Wert - Dauer in 360tel Sekunden Es wird ein Ton mit angegebener Frequenz und Dauer ezeugt und über den Lautsprecher wiedegegeben. Während der Tonerzeugung wird das Programm angehalten. Folgende Zeile spielt eine Sekunde lang den Kammerton A: SOUND 440,360 HINWEIS: Dieser Befehl funktioniert nicht in der 32-Bit-Version unter Windows 95, da die Windows 95 - API nicht mehr die Wiedergabe von Tönen über den Lautsprecher vorsieht. Unter Windows NT hingegen sollte es funktionieren. Seite 306 RGH-PROFAN² SQLExec S,N S - String: SQL-Befehl N - Integer: Ergebnismodus Sendet einen SQL-Befehl an die Datenbank. S ist das Ergebnismodus: 0: 1: 2: SQL-Statement und N der Das Ergebnis wird angezeigt. Jeder Datensatz ist ein Zeile und kann maximal 255 Zeichen enthalten. Das Ergebnis wird in die Listbox-Liste geschrieben und kann dann z.B. mit der @LISTBOX$-Funktion betrachtet werden. Jeder Datensatz ist ein Eintrag in der Liste und kann maximal 255 Zeichen enthalten; maximal 10000 Datensätze passen in die Liste. Das Ergebnis wird in die Datei "SQL.DAT", die im aktuellen Pfad erzeugt wird, geschrieben. Jeder Datensatz ist eine Zeile. In &SQLCOUNT wird zurückgeliefert, wieviele Datensätze bearbeitet wurden oder -1, wenn ein Fehler auftrat. Beispiel: SQLEXEC "SELECT * FROM KUNDEN",1 SQLSetNULL S S - String: NULL-Zeichen Legt fest, das NULL als S im Ergebnis dargestellt wird. Ein Datensatzfeld hat den Wert NULL, wenn ihm kein Wert zugewiesen wurde. NULL steht also für nichts. SQLSetDel S S - String: Trennzeichen Legt fest, mit welchem Zeichen die einzelnen Felder im Ergebnis getrennt werden. Voreingestellt ist "|". Wenn S zwei Zeichen groß ist, legt das zweite Zeichen fest, mit welchem Zeichen die Feldinhalte begrenzt werden. Voreingestellt ist hier der Leerstring. Das zweite Zeichen wirkt nur, wenn das Ergebnis des SQL-Befehles in eine Datei ausgegeben wird (Modus 2). Will man zum Beispiel erreichen, daß in der Ergebnisdatei die Feldinhalte in Anführungszeichen stehen und die Felder mit einem Komma getrennt werden, müßte S$ die Zeichen , und " enthalten: SQLSETDEL @ADD$(",",@CHR$(34)) SQLDone Der Befehl beendet die Verbindung zum SQL-Server und gibt die von ODBC.DLL belegten Speicherbereiche wieder frei. Seite 307 RGH-PROFAN² StartPaint H - End Paint H : Integer - Handle des Fensters, in das gezeichnet werden soll / -1 = Memorybitmap Mit diesem Befehl können die Bildschirmausgaben auf ein anderes Fenster, etwa eine DialogBox oder ein DialogFenster umgeleitet werden. (Von der Umleitung ausgeschlossen sind jene Befehle, die den Textmodus von PROFAN² betreffen, wie etwa LOCATE, PRINT, TBOX, ...) So ist es nun möglich in beliebige Fenster, deren Handle man hat, zu malen, Text auszugeben, Bitmaps zu laden, etc. WICHTIG: Jedem StartPaint muß (!) ein EndPaint folgen. Nach dem EndPaint erfolgen dies Ausgaben wieder auf das Hauptfenster. Während der Druckausgabe mit StartPrint - EndPrint ist der Befehl verboten. Wenn als Fensterhandle -1 angegeben wird erfolgt die Ausgabe in ein "unsichtbares Fenster", nämlich in die Memorybitmap, die mit MCLS oder MLOADBMP erzeugt wurde. Beim Zeichnen in DialogBoxen und DialogFenstern ist zu beachten, daß diese Zeichnungen nicht automatisch erneuert werden, wenn die Dialogbox z.B. durch ein anderes Fenster verdeckt wurde. Auch wenn AutoPaint eingeschaltet ist, erzeugen DialogBoxen und DialogFenster eine wm_Paint-Botschaft, die ggf. das WaitInput verläßt und die Systemvariable %wmPaint auf 1 setzt. Wenn AutoPaint mit SetAutoPaint 0 komplett ausgeschaltet ist, ist es durchaus sinnvoll (aber nicht notwendig) die Ausgaben auf das Hauptfenster auch in StartPaint - EndPaint einzuschließen, wobei dann als Fensterhandle %Hwnd zu nehmen ist. StartPrint [S] ... NextPage ... EndPrint Zwischen diesen beiden Befehlen werden alle grafischen Bildschirmausgaben (DRAWTEXT, RECTANGLE, ...) auf eine Druckeseite ausgegeben. "Textmodus"- und einige BitmapBefehle sind nicht gestattet. LOADBMP und LOADSIZEDBMP funktionieren hingegen wie gewohnt und sind ideal um Bitmap-Grafiken zu drucken. Mit ENDPRINT wird der Druck der Seite veranlaßt. Die Druckseite hat horizontal eine Weite von 640 Punkten und senkrecht eine Höhe von 960 Punkten. (Der Drucker sollte auf DIN A4 - Hochformat eingestellt sein.) Wahlweise kann dem Druckauftrag mit dem Strinparameter S ein Name gegeben werden, der anstatt des Standartnamens im Druckmanager erscheint. Mit NEXTPAGE wird innerhalb des Druckauftrages zwischen STARTPRINT und ENDPRINT eine neue Seite begonnen. String V,A=S V: Bereichsvariable A: Integer - Adresse in der Bereichsvariablen S: String - Zeichenkette Der String S wird im Speicherbereich V ab Adresse (Offset) A abgelegt. Das Ende des Strings wird durch ein Null-Byte gekennzeichnet. Paßt der String nicht mehr ganz in den mit DIM zugewiesenen Bereich, wird er entsprechend abgeschnitten. Liegt A außerhalb des Bereiches erfolgt eine Fehlermeldung. HINWEIS: Sollen mehrere Strings in einen Bereich geschrieben werden, ist darauf zu achten, daß sich die Strings nicht überschreiben. Dabei ist zu berücksichtigen, daß ein String für jedes Zeichen ein Byte belegt plus ein zusätzliches Byte für das abschließende Byte mit dem Wert 0! Seite 308 RGH-PROFAN² StrWidth N N: Integer (Mindestweite) Die Mindest-Ausgabeweite für Strings (mittels des PRINT-Befehles) wird festgelegt. Strings, die kürzer als N sind, werden entsprechend mit vorangestellten Leerzeichen verlängert. Voreingestellt ist der Wert 0 (= "normales" Verhalten der Strings). Sub VAR,N VAR - Variablenname (Integer) N - Integer N wird von Variablen VAR subtrahiert. (Ist schneller und einfacher als die @SUB-Funktion.) Beispiel: SUB Punkte%,10 SubPopUp ... EndSub Ein Untermenü zu einem Popup-Menü wird erzeugt. Eine Verschachtelung ist (bis zu einer Tiefe von 10) möglich: ... AppendMenu 210,"&Auswahl 3" SubPopUp "&Schriften ..." AppendMenu 211,"Schrift &1" AppendMenu 212,"Schrift &2" ... EndSub AppendMenu ... Seite 309 RGH-PROFAN² TBox X1,Y1 - X2,Y2; N X1,Y1 : Wert - linke obere Ecke X2,Y2 : Wert - rechte untere Ecke N : Rahmentyp Es wird im Textmodus eine Box gezeichnet. Die Koordinaten werden wie bei LOCATE in Zeichen eingegeben. Benutzt werden die Grafikzeichen des OEM-Zeichensatzes. 0 - Einfacher Rahmen 1 - Doppelter Rahmen 2 - Senkrecht doppelt/waagrecht einf. 3 - Ohne Rahmen TextColor C1,C2 C1 : Wert - Vordergrundfarbe (RGB) C2 : Wert - Hintergrundfarbe (RGB) Die Farben für die Ausgabe mittels DRAWTEXT werden festgelegt. Bei -1 als Hintergrundfarbe, ist diese transparant, d.h. der vorhandene Hintergrund wird genommen. Beispiel: TextColor @RGB(15,15,31),-1 DrawText 23,67,"Hugo was here!" TraceON TRACEON schaltet in den TRACE-Modus. Vor Abarbeitung einer Zeile wird diese in einer Messagebox angezeigt. Mit "Abbrechen" kann das Programm beendet werden. Der Befehl ist nur im Interpreter sinnvoll und daher im Runtimemodul bzw. bei compilierten Programmen wirkungslos. TraceOFF TRACEOFF schaltet den TRACE-Modus aus. TrackMenu X,Y X,Y : Wert - Position Das Programm zeigt das mit CREATEMENU und APPENDMENU erzeugte Menü an der gewünschten Position an und erwartet die Auswahl. Das Ergebnis steht in %MENUITEM. Beispiel: TrackMenu 20,130 Case %MenuItem(100):Gosub "Speichern" Case %MenuItem(120):End Seite 310 RGH-PROFAN² UseBrush N,C N : Wert - Art des Pinsels C : Wert - Farbe des Pinsels (RGB) Der Pinsel wird benutzt, um die Grafiken (RECTANGLE, ROUNDRECT, etc.) auszufüllen. C ist die benutzte RGB-Farbe (0 ... 32767), N bezeichnet die Art des Pinsels: 0 : Transparant (nicht ausgefüllt) 1 : Solid (voll gefüllt) 2 .. 8 : verschiedene Schraffuren Schraffuren: 2 - waagrecht ===== 3 - senkrecht ||||| 4 - diagonal \\\\\ 5 - diagonal ///// 6 - kariert ##### 7 - diag.kar. XXXXX Die Schraffur wird in der Farbe C ausgeführt. UseCursor N N : Wert - Cursortyp (0 .. 11) Ändert das Aussehen des Mauszeigers. Es sind alle 11 von Windows vorgegebenen Mauszeiger verwendbar und zusätzlich ein Druckersymbol (während des Druckens.). Der Sanduhr-Zeiger sollte immer dann eingesetzt werden, wenn der Anwender warten muß und eh' keine Eingaben machen kann, z.B. beim Speichern und Laden. Die Bedeutung von N: 0 - Zeiger (Standard) 1 - Texteingabe (senkr. Strich) 2 - Sanduhr (Bitte warten ...) 3 - Fadenkreuz 4 - Großer senkrechter Pfeil 5 - Vierfach-Pfeil (+) 6 - Icon (kleines Quadrat in Größerem 7 - Doppel-Pfeil (\) 8 - Doppel-Pfeil (/) 9 - Doppel-Pfeil (-) 10 - Doppel-Pfeil (|) 11 - Drucker Vergleiche auch: ShowCursor Seite 311 RGH-PROFAN² UseExtCursur I,S I S : Integer - Instanzhandle der EXE bzw. DLL, die den Cursor enthält : String - Name des Cursors Das Instanz-Handle wird bei DLLs mittels @UseDLL ermittelt und bei EXE-Dateien mittels @WinExec. Das Handle des ausführenden Programmes ist in der Systemvariablen %HInstance. Es ist also möglich, alle in einem Programm verwandten Mauszeiger mittels eines Tools wie des Resource-Workshops von Borland in eine DLL zu packen. Ebenso ist es z.B. möglich, die PROFRUN.EXE vor dem Linken entsprechend zu erweitern. Vergleiche auch: UseCursor, ShowCursor UseExtMenu I,S I S : Integer - Instanzhandle der EXE bzw. DLL, die das Menu enthält : String - Name oder Nummer des Menüs Das Instanz-Handle wird bei DLLs mittels @UseDLL ermittelt und bei EXE-Dateien mittels @WinExec. Das Handle des ausführenden Programmes ist in der Systemvariablen %HInstance. Es ist also möglich, alle in einem Programm verwandten Menüs mittels eines Tools wie des Resource- Workshops von Borland in eine DLL zu packen. Ebenso ist es z.B. möglich, die PROFRUN.EXE vor dem Linken entsprechend zu erweitern. UseFont S,N1,N2,N3,N4,N5 S : String - Fontname N1 : Wert - Zeichenhöhe N2 : Wert - Zeichenbreite N3 : Wert - Fett? (0 .. 1) N4 : Wert - Kursiv? (0 .. 1) N5 : Wert - Unterstrichen? (0 .. 1) Der Font für die Ausgabe von Text mittels DRAWTEXT wird festgelegt. N1: Zeichenhöhe. Steht hier 0, wird ein Defaultwert für Breite und Höhe genommen. N2: Zeichenbreite. Steht hier 0, wird ein Defaultwert genommen N3: 1 = fett , 0 = normal N4: 1 = kursiv, 0 = normal N5: 1 = unterstrichen, 0 = normal UseIcon S S : String - Name des Icons Es wird das Icon ausgewählt, das für das Programm verwandt wird, wenn es verkleinert wird. Standardmäßig ist es das Profan-Icon. Es kann aber jedes der 18 "eingebauten" Icons verwandt werden. Seite 312 RGH-PROFAN² UsePen N1,N2,C N1 : Wert - Linienart (0 .. 5) N2 : Wert - Linienstärke C : Wert - RGB-Farbe Die hier eingestellten Werte werden von den Zeichenbefehlen für die Rahmen bzw. Linien benutzt. Beispiel: UsePen 1,5,@RGB(0,0,31) Rectangle 10,10 - 150,100 Linienart: 0 - durchgezogen __________ 1 - gestrichelt _ _ _ _ _ _ 2 - gepunktet ............. 3 - Strich-Punkt _._._._._. 4 - Strich-Punkt-Punkt _.._.._.. 5 - keine Linie Die Werte 1 bis 5 sind nur bei einer Strichstärke von 1 sinnvoll. Seite 313 RGH-PROFAN² WaitInput Wartet auf einen Mausklick oder Tastendruck im Profan-Fenster. Das Ergebnis steht in den Systemvariablen %MOUSEKEY, %MOUSEX, %MOUSEY, %SCANKEY und %KEY. Außer auf Tastendrücken reagiert WAITKEY wie auch WAITINPUT noch auf folgende Ereignisse und bestückt %Key entsprechend: 1 2 4 5 13 255 Es wurde ein Eintrag in einer Listbox angewählt oder es wurde ein Eintrag einer Auswahlbox gewählt Es wurde in einer Dialogbox bzw. einem Dialogfenster auf das Systemmenü doppelgeklickt, bzw. "Schließen" ausgewählt Ein Fenster des Programmes wurde in der Größe verändert Es wurde F1 gedrückt, während der Fokus auf einem Dialogelement bzw. in einer Dialogbox war. Das Handle des Elementes steht als negativer Wert in %GetFocus. Es wurde in einem einzeiligen Editierfeld oder einer Listbox <Enter> gedrückt Es wurde ein Button, eine Checkbox oder ein Radiobutton angeklickt WaitKey Wartet auf einen Tastendruck. Das Ergebnis steht in der Systemvariablen %KEY. (Funktionstasten, sog. "virtuelle Tastencodes" werden nicht erkannt. Wird dies benötigt, ist WAITSCAN zu verwenden.) WaitMouse Wartet, bis eine Maustaste (im Profan-Fenster) gedrückt wird. Welche Taste es war, und die Position der Maus steht in den Systemvariablen %MOUSEKEY, %MOUSEX und %MOUSEY. WaitScan Wartet auf einen beliebigen Tastendruck. Auch Funktionstasten, Kusortasten, Shift- und Ctrltasten werden erkannt. Das Ergebnis steht in als virtueller Tastencode in %SCANKEY und - im Falle einer "normalen" Taste - als ANSI- Code in %KEY. Wichtige Scancodes: 16 17 27 33 34 35 36 37 38 39 40 45 46 112 ... 123 - Shift Strg Esc BildHoch BildRunter Ende Pos1 Links Hoch Rechts Runter Einfg Entf F1 ... F12 Seite 314 RGH-PROFAN² Die übrigen lassen sich durch Ausprobieren mit folgendem Programm leicht austesten: Cls While 1 'Endlosschleife! WaitScan Print %ScanKey Wend End While N ... EndWhile N : Wert - Bedingungsausduck Die zwischen WHILE und WEND stehenden Befehle werden solange wiederholt, solange N ungleich 0 ist. Beispiel: While N% Print "Gebe eine Zahl ein: "; Input N% Wend Anstelle von ENDWHILE kann auch die von Basic her gewohnte Schreibweise WEND verwandt werden. WhileNot N ... EndWhile N : Wert - Bedingungsausduck Die zwischen WHILENOT und WEND stehenden Befehle werden solange wiederholt, solange N gleich 0 ist. Beispiel: WhileNot @Eof(#2) Input #2,Zeile$ Print Zeile$ Wend Window X1,Y1-X2,Y2 X1,Y1 : Wert - linke obere Ecke X2,Y2 : Wert - Größe in Pixeln Das Fenster wird in der angegebenen Größe geöffnet. X1 und Y1 sind absolute Bildschirmkoordinaten. Jedes Programm, daß Ausgaben auf das Hauptfenster des PROFANProgrammes macht muß dieses entweder mit WINDOW oder CLS öffnen. Wenn CLS zum Öffnen des Fensters verwandt wird, benutzt Profan den ganzen (Standard-VGA-)Bildschirm (640 * 480 Pixel). Seite 315 RGH-PROFAN² WindowStyle N N : Wert - Stil des Fensters (0 ... 255) Das Aussehen des Programmfensters wird festgelegt. Folgende Eigenschaften können definiert werden: 1 2 4 8 16 32 64 128 512 - Fenster hat Vergrößerungsbox (Pfeil nach oben) und kann vergrößert werden - Fenster hat Verkleinerungsbox (Pfeil nach unten) und kann zum Icon werden - Dicker Rahmen (Größe des Fensters ist veränderbar) - Fenster hat System-Menü - Fenster hat zunächst kein Menü (also auch kein ©) - Fenster benutzt Bildschirmhintergrund als Hintergrund - Das Fenster hat keine Titelzeile - Das Programm kann weder mit <Strg-Esc>, <Alt-Tab> noch <Alt-F4> verlassen werden. - Dialogfensterstil für Hauptfenster (s.u.) Kombinationen werden durch Addition der einzelnen Werte erreicht. Damit der Befehl Wirkung zeigt, muß er vor dem ersten Öffnen des Programmfensters erfolgen! Soll der Bildschirmhintergrund als Hintergrund verwandt werden, muß das Fenster mit WINDOW (und nicht mit CLS) geöffnet werden. Beispiel: WindowStyle 31 Ideal für Bildschirmschoner: WindowStyle $F0 Der Dialogfenster-Stil (512 bzw. $200) erlaubt es, daß Dialogelemente auf einem Hauptfenster erbenso reagieren, wie in einem Dialogfenster, d.h. es kann mit TAB zwischen Ihnen umgeschaltet werden, Buttons reagieren nur beim Loslassen des Knopfes, etc. Ebenso wie ein Dialogfenster regiert das Hauptfenster nun auch nicht mehr auf das Schließen des Fensters, sondern dieses muß mittels %Key gleich 2 abgefragt werden, was sicher häufig erwünscht ist. Auch beim Anklicken des neuen Knopfes zum Schließen in Windows 95 wird %Key auf 2 gesetzt. Ein Standardfenster mit Dialogeigenschaften hat so z.B. den Stil $20F. Die Stile $100 (256) und $80 (128) sind nicht mit dem neuen Stil zusammen zu verwenden. Der Stil $200 ist dann zu verwenden, wenn ein Programm auf dem Hauptfenster Dialogelemente anlegt. HINWEIS: Unter Windows 95 sind nicht alle Kombinationen wirkungsvoll: Verkleinerungsund Vergrößerungsbox werden nur dann angezeigt, wenn auch ein Systemmenü vorhanden ist. (Der Befehl existiert nur in der Vollversion!) WindowTitle S S : String Die Überschrift des Programmfensters wird festgelegt. Beispiel: WindowTitle "Mein erstes Programm" Wenn im Programm keine Überschrift festgelegt wird, wird eine voreingestellte Überschrift benutzt. (Der Befehl existiert nur in der Vollversion!) Seite 316 RGH-PROFAN² WinCopy W W: Integer - Handle des zu druckenden Fensters Das Fenster mit dem Handle W wird komplett und größtmöglich auf den Drucker gegeben. Mit WINCOPY %DESKTOP läß sich also problemlos der komplette Bildschirm drucken, während z.B. WINCOPY %HWND das Fenster des aktuellen PROFAN²-Programmes druckt. Im Gegensatz zu SCREENCOPY, das nur den inneren Bereich des Fensters ohne Rahmen und Menü druckt, wird dabei das komplette Fenster gedruckt. Jedes Fenster, dessen Handle bekannt kann somit auf den Drucker gegeben werden. WinHelp S1,S2 S1: String - Name der Hilfedatei (mit Endung) S2: String - Suchwort Die Windowshilfe wird mit der Datei S1 aufgerufen. S1 muß die Endung der Hilfedatei (meißt "HLP") enthalten und darf auch eine Pfadangabe haben. Der zweite Parameter bezeichnet das Schlüsselwort des Hilfeabschnittes der angezeigt werden soll. So ist kontext-sensitive Hilfe möglich. Ist S2 ein Leerstring, wird die Hilfe mit dem Suchfenster gestartet! Ist S2 ein Fragezeichen ("?") wird die Hilfe zur Hilfe angezeigt und bei einem Stern ("*") wird der Inhalt der Hilfedatei angezeigt. Word V,A=N V: Bereichsvariable (muß mit DECLARE deklariert sein) A: Integer - Adresse in der Bereichsvatiablen N: Integer - Wert (0 .. 65535) Das Word (16-Bit-Wert = 2 Byte) an der Adresse (Offset) A im Speicherbereich V wird auf den Wert N gesetzt. Liegt A außerhalb des mit DIM zugewiesenen Speichers, erfolgt eine Fehlermeldung. HINWEIS: Da zwei Byte geschrieben werden, wird Adresse A und A+1 benutzt, wobei an Adresse A das niederwertige und an Adresse A+1 das höherwertige Byte geschrieben wird. Sollen mehere Integer in den Bereich geschrieben werden, etwa um ein Integer-Array zu simulieren, so ist zwischen den Adressen ein Abstand von 2 einzuhalten. Beispiel: DECLARE Bereich# DIM Bereich#,6 WORD Bereich#,0 =1056 WORD Bereich#,2 =10251 WORD Bereich#,4 = 516 PRINT @WORD(Bereich#,0) PRINT @WORD(Bereich#,2) PRINT @WORD(Bereich#,4) DISPOSE Bereich# Seite 317 RGH-PROFAN² WriteIni S1,S2,S3=S4 S1: String - INI-Datei (auch mit Pfad) / Registry-Klasse (32 Bit) S2: String - Anwendung/Rubrik/Abschnitt/Registry-Pfad (32 Bit) S3: String - Eintrag/Schlüssel S4: String - Wert des Eintrages Ein Eintrag in einer INI-Datei wird geändert bzw. erstellt. Existiert die INI-Datei nicht, wird sie im angegebenen bzw. im Windowsverzeichnis erstellt. Beispiel: In der Datei SPIEL.INI soll "HIGHSCORE=25000" stehen: unter der Rubrik [MeinProgramm] der Eintrag: LET HighScore& = 25000 WRITEINI "SPIEL.INI","MeinProgramm",\ "HIGHSCORE"=@Str$(HighScore&) Um die WIN.INI nicht zu überlasten, sollte jedes Programm eine eigene INI-Datei anlegen. Dateiname und Pfad sind frei wählbar. In der 32-Bit-Version ist es zusätzlich möglich, Werte in die Registry (Registrierdatenbank) zu schreiben. In diesem Fall muß als erster Parameter die Klasse mit "HKEY_0" bis "HKEY_6" angegeben werden: HKEY_CLASSES_ROOT HKEY_CURRENT_USER HKEY_LOCAL_MACHINE HKEY_USERS HKEY_PERFORMANCE_DATA HKEY_CURRENT_CONFIG HKEY_DYN_DATA = = = = = = = HKEY_0 HKEY_1 HKEY_2 HKEY_3 HKEY_4 HKEY_5 HKEY_6 Der zweite Parameter ist dann der komplette "Pfad" zum Eintrag. Der dritte Parameter ist der Schlüssel (Key), der geschrieben werden soll. Ist der Pfad und/oder der Schlüssel nicht vorhanden,m wird er angelegt. Sind Pfad und Schlüssel vorhanden, wird der entsprechende Wert geändert. Der letzte Parameter ist der Wert, den der Schlüssel bekommen soll. Einzelne Einträge des Pfades werden durch Backslashes (wie beim Verzeichnis) voneinander getrennt: Bei einem 32-Bit-Spiel könnte der Highscore etwa wie folgt gespeichert werden: LET HighScore& = 25000 WriteIni "HKEY_1","RGH-Soft\Spiele\MeinProgramm", \ "High-Score"=@Str$(HighScore&) Wollten wir jetz auch noch weitere Optionen speichern, könnten wir im selben Pfad einen anderen Schlüssel verwenden, etwa für die Sound-Einstellung: WriteIni "HKEY_1","RGH-Soft\Spiele\MeinProgramm","Sound"="EIN" Diese Zeile würde in der 16-Bit-Version im übrigen keinen Fehler produzieren, sondern eine INI-Datei "HKEY_1" im Windowsverzeichnis mit einem entsprechenden Eintrag erzeugen. Das kann durchaus gewollt sein und ermöglicht es, Programme zu schreiben, die unter 32 Bit die Registry nutzen und unter 16 Bit entsprechende INI-Dateien. Aus diesem Grund wuden statt der langen Klassennamen auch die kurzen Versionen HKEY_0 bis HKEY_6 für die PROFAN²-Syntax gewählt. Seite 318 RGH-PROFAN² ACHTUNG: Seien Sie vorsichtig beim Überschreiben bestehender Registry-Einträge! Ebenso wie es durch Ändern von SYSTEM.INI oder WIN.INI möglich ist, Windows weitgehend lahmzulegen, ist dies auch mit Änderungen der Registry noch viel effektiver möglich! Seite 319 RGH-PROFAN² 4. Wichtige Messages In PROFAN² werden Messages (Botschaften) mit folgender Funktion versandt: @SendMessage(N1,N2,N3,N4) N1 ist das Handle des Fensters, das die Sendung bekommt. N2 ist die Nummer der Botschaft, die in den folgenden Listen im hexadezimalen Format angegeben ist. N3 (Integer in der 16-Bit-Version / LongInt bzw. Bereich in der 32-Bit-Version) und N4 (LongInt oder Bereich) sind gegebenenfalls zu übermittelnde Parameter. Werden diese bei einer bestimmten Message nicht gebraucht, sind sie auf 0 zu setzen. Hinweis für 32Bit-Version: Die folgenden Angaben wurden unter 16-Bit getestet. Der größte Teil dütfte auch unter 32-Bit genauso funktionieren, wenn auch nicht ausgeschlossen werden kann, daß in einigen wenigen Messages die Parameter anders bestückt werden. Im Zweifelsfall die entsptrechende Fachliteratur konsultieren ... oder ausprobieren. Bei den Messages zu den Dialogelementen sind außerdem die Messagenummern verschoben. Dort werden beide Werte angegeben. Seite 320 RGH-PROFAN² Button-Messages Diese Botschaften sind für alle Arten von Buttons (Knöpfen) einzusetzen; dazu zählen auch die Radiobuttons und Checkboxen. ACHTUNG: Diese Messages bitte nicht bei anderen Windowsobjekten einsetzen, da dort die gleichen Botschaftsnummern eine andere Bedeutung haben! Der erste Wert ist für die 16-Bit-Version, der zweite für die 32-Bit-Version. bm_GetCkeck = $0400 / $00F0 ermittelt, ob ein Radiobutton oder eine Ckeckbox markiert ist oder nicht Rückgabewert: 0 = nicht markiert; >0 = markiert bm_GetState = $0402 / $00F2 ermittelt den Status eines Buttons Rückgabewert: 0 = nicht gedrückt; >0 = gedrückt bm_SetCheck = $0401 / $00F1 markiert einen Radiobutton oder eine Checkbox N3: 0 = nicht markieren; 1 = markieren bm_SetState = $0403 / $00F3 setzt den Status eines Buttons N3: 0 = normal; 1 = hervorgehoben Seite 321 RGH-PROFAN² ComboBox-Messages Diese Botschaften sind für alle Arten von ComboBoxen einzusetzen; dazu zählt auch die von PROFAN unterstützte AuswahlBox. Andere ComboBox-Typen erlauben z.B. auch die Eingabe in der obersten Zeile oder zeigen ständig beide Teile der ComboBox an: Editierfeld und Listbox. ACHTUNG: Diese Messages bitte nicht bei anderen Windowsobjekten einsetzen, da dort die gleichen Botschaftsnummern eine andere Bedeutung haben! Der erste Wert ist für die 16-Bit-Version, der zweite für die 32-Bit-Version. cb_AddString = $0403 / $0143 Fügt einen String zur Liste einer Auswahlbox hinzu. Der String Bereichsvariablen. steht in der N4: Bereich = hinzuzufügender String Rückgabewert: <0 = Fehler Beispiel: Let S$ = "Das ist ein Test!" String V#,0 = S$ @SendMessage(W%,$0403,0,V#) Hierbei ist W% das Handle der Auswahlbox. cb_DeleteString = $0404 / $0144 Löscht einen String aus Liste einer Auswahlbox. N3: Index des zu löschenden String (erster String = 0) Rückgabewert: <0 = Fehler cb_Dir = $0405 / $0145 Fügt eine Liste der Dateien aus dem aktuellen Verzeichnis zur Auswahlliste hinzu. Bei der Auswahl wird das Dateiattribut (siehe unter @GetFAttr) berücksichtigt. Um zusätzlich die Laufwerke aufzulisten, ist $4000 dem Attribut hinzuzufügen. Die Bereichsvariable enthält die Suchmaske. N3: Integer = Dateiattribut N4: Bereich = Datei-Suchmaske (z.B. "*.*") Rückgabewert: <0 = Fehler (z.B. zu wenig Platz in der Liste) >=0 = Index des letzten Eintrages (erster Eintrag = 0) Beispiel: Let S$ = "*.*" String V#,0 = S$ @SendMessage(W%,$0405,$4037,V#) Hierbei ist W% das Handle der Auswahlbox. Um nur eine Laufwerksliste zu erzeugen, ist als Attribut in N3 der Wert $4000 einzusetzen. Seite 322 RGH-PROFAN² cb_FindString = $040C / $014C Es wird der Eintrag ermittelt, der mit dem Suchstring beginnt. N3: Integer = Index des Eintrages vor dem die Suche beginnt; Soll sie am Anfang beginnen, muß er -1 sein. N4: Bereich = Suchstring Rückgabewert: <0 = Fehler (nicht gefunden) >=0 = Index des gesuchten Eintrages (erster Eintrag = 0) cb_GetCount = $0406 / $0146 Anzahl der Einträge in der Liste. Rückgabewert: Index des letzten Eintrages (erster Eintrag = 0) cb_GetCurSel = $0407 / $0147 Index des aktuell ausgewählten Eintrages der Liste. Rückgabewert: Index des Eintrages (erster Eintrag = 0) cb_GetLBText = $0408 / $0148 Kopiert einen String aus der Liste in die Bereichsvariable. ACHTUNG: Das abschließende Byte mit dem Wert 0 ist aufgrund des Rückgabewertes selbst zu setzen! HINWEIS: Die Bereichsvariable muß ausreichgend dimensioniert sein! N3: Integer = Index des gewünschten Eintrages N4: Bereich = Bereich, der den String aufnehmen soll Rückgabewert: Länge des Strings cb_GetLBTextLen = $0409 / $0149 Ermittelt die Länge eines String aus der Liste. N3: Integer = Index des gewünschten Eintrages Rückgabewert: Länge des Strings cb_ResetContent = $040B / $014B Löscht die Liste der Auswahlbox. cb_SetCurSel = $040E / $014E Wählt einen Eintrag aus der Liste aus und rollt ihn in den sichtbaren Bereich. N3: Integer = Index des gewünschten Eintrages -1: Kein Eintrag wird ausgewählt Seite 323 RGH-PROFAN² cb_SelectString = $040D / $014D Es wird der Eintrag ermittelt, der mit dem Suchstring beginnt. Der Eintrag wird markiert und in den sichtbaren Bereich der Liste gerollt. N3: Integer = Index des Eintrages vor dem die Suche beginnt; Soll sie am Anfang beginnen, muß er -1 sein. N4: Bereich = Suchstring Rückgabewert: <0 = Fehler (nicht gefunden) >=0 = Index des gesuchten Eintrages (erster Eintrag = 0) cb_ShowDropDown = $040F / $014F Zeigt die Auswahlliste eines Auswahlfensters. N3: 1 = Auswahlliste zeigen; 0 = Auswahlliste schließen Seite 324 RGH-PROFAN² Edit-Messages Diese Botschaften sind für alle Arten von Editierfeldern einzusetzen. ACHTUNG: Diese Messages bitte nicht bei anderen Windowsobjekten einsetzen, da dort die gleichen Botschaftsnummern eine andere Bedeutung haben! Der erste Wert ist für die 16-Bit-Version, der zweite für die 32-Bit-Version. em_CanUndo = $0416 / $00C6 ermittelt, ob ein Editierfeld korrekt auf em_Undo reagieren kann Rückgabewert: 0 = kann nicht reagieren; 1 = kann reagieren em_GetModify = $0408 / $00B8 ermittelt, ob ein Editierfeld geändert wurde Rückgabewert: Veränderungsflag em_LimitText = $0415 / $00C5 bestimmt die maximale Anzahl von Zeichen, die ein Editierfeld aufnehmen darf N3: Anzahl der Zeichen (0 = unbegrenzt) Rückgabewert: 0 = Fehler aufgetreten em_SetModify = $0409 / $00B9 setzt das Veränderungsflag N3: Veränderungsflag em_SetReadOnly = $041F / $00CF setzt eine Editierfeld in den Nur-Lesen-Status N3: 1 = Nur-Lesen; 0 = Lesen + Schreiben em_Undo = $0417 / $00C7 macht die letze Aktion im Editierfeld rückgängig Rückgabewert: 0 = Undo konnte nicht ausgeführt werden Seite 325 RGH-PROFAN² Listbox-Messages Diese Botschaften sind für Listboxen zu verwenden. ACHTUNG: Diese Messages bitte nicht bei anderen Windowsobjekten einsetzen, da dort die gleichen Botschaftsnummern eine andere Bedeutung haben! Der erste Wert ist für die 16-Bit-Version, der zweite für die 32-Bit-Version. lb_AddString = $0401 / $0180 Fügt einen String zur Liste einer Listbox hinzu. Der String steht in der Bereichsvariablen. N4: Bereich = hinzuzufügender String Rückgabewert: <0 = Fehler Beispiel: Let S$ = "Das ist ein Test!" String V#,0 = S$ @SendMessage(W%,$0401,0,V#) Hierbei ist W% das Handle der Listbox. lb_DeleteString = $0403 / $0182 Löscht einen String aus Liste einer Listbox. N3: Index des zu löschenden String (erster String = 0) Rückgabewert: <0 = Fehler lb_Dir = $040E / $018D Fügt eine Liste der Dateien aus dem aktuellen Verzeichnis zur Liste hinzu. Bei der Auswahl wird das Dateiattribut (siehe unter @GetFAttr) berücksichtigt. Um zusätzlich die Laufwerke aufzulisten, ist $4000 dem Attribut hinzuzufügen. Die Bereichsvariable enthält die Suchmaske. N3: Integer = Dateiattribut N4: Bereich = Datei-Suchmaske (z.B. "*.*") Rückgabewert: <0 = Fehler (z.B. zu wenig Platz in der Liste) >=0 = Index des letzten Eintrages (erster Eintrag = 0) Beispiel: Let S$ = "*.*" String V#,0 = S$ @SendMessage(W%,$040E,$4037,V#) Hierbei ist W% das Handle der Listbox. Um nur eine Laufwerksliste zu erzeugen, ist als Attribut in N3 der Wert $4000 einzusetzen. Seite 326 RGH-PROFAN² lb_FindString = $0410 / $018F Es wird der Eintrag ermittelt, der mit dem Suchstring beginnt. N3: Integer = Index des Eintrages vor dem die Suche beginnt; Soll sie am Anfang beginnen, muß er -1 sein. N4: Bereich = Suchstring Rückgabewert: <0 = Fehler (nicht gefunden) >=0 = Index des gesuchten Eintrages (erster Eintrag = 0) lb_GetCount = $040C / $018B Anzahl der Einträge in der Liste. Rückgabewert: Index des letzten Eintrages (erster Eintrag = 0) lb_GetCurSel = $0409 / $0188 Index des aktuell ausgewählten Eintrages der Liste. Rückgabewert: Index des Eintrages (erster Eintrag = 0) lb_GetText = $040A / $0189 Kopiert einen String aus der Liste in die Bereichsvariable. ACHTUNG: Das abschließende Byte mit dem Wert 0 ist aufgrund des Rückgabewertes selbst zu setzen! HINWEIS: Die Bereichsvariable muß ausreichend dimensioniert sein! N3: Integer = Index des gewünschten Eintrages N4: Bereich = Bereich, der den String aufnehmen soll Rückgabewert: Länge des Strings lb_GetTextLen = $040B / $018A Ermittelt die Länge eines String aus der Liste. N3: Integer = Index des gewünschten Eintrages Rückgabewert: Länge des Strings lb_ResetContent = $0405 / $0184 Löscht die Liste der Listbox. Seite 327 RGH-PROFAN² lb_SelectString = $040D / $018C Es wird der Eintrag ermittelt, der mit dem Suchstring beginnt. Der Eintrag wird markiert und in den sichtbaren Bereich der Liste gerollt. N3: Integer = Index des Eintrages vor dem die Suche beginnt; Soll sie am Anfang beginnen, muß er -1 sein. N4: Bereich = Suchstring Rückgabewert: <0 = Fehler (nicht gefunden) >=0 = Index des gesuchten Eintrages (erster Eintrag = 0) lb_SetCurSel = $0407 / $0186 Wählt einen Eintrag aus der Liste aus und rollt ihn in den sichtbaren Bereich. N3: Integer = Index des gewünschten Eintrages -1: Kein Eintrag wird ausgewählt lb_SetHorizontalExtend = $0415 / $0194 Normalerweise entspricht die tatsächliche Breite einer Listbox der Breite, die am Bildschirm zu sehen ist: Es gibt keinen horizontalen Scollbalken. Diese Message setzt die Breite der Listboxliste in Pixel. Ist die Breite größer als der angezeigte Bereich, erhält die Liste einen horizontalen Scrollbalken. N3: Integer = Breite der Liste in Pixel Seite 328 RGH-PROFAN² Allgemeine Windows-Botschaften (Nummern gelten für 16 und 32 Bit) wm_Clear = $0303 löscht die aktuelle Auswahl in einem Fenster wm_Close = $0010 schließt das betreffende Fenster wm_Copy = $0301 kopiert den markierten Text in die Zwischenablage wm_Cut = $0300 kopiert den markierten Text in die Zwischenablage. Der markierte Text wird gelöscht. wm_GetText = $000D Ermittelt den Text eines Steuerelementes und überträgt ihn in die Bereichsvariable. Diese muß ausreichen dimensioniert sein. ACHTUNG: Das abschließende Byte mit dem Wert 0 ist aufgrund des Rückgabewertes selbst zu setzen! Diese Botschaft entspricht der PROFAN²-Funktion @GETTEXT mit dem Unterschied, daß auch Texte gelesen werden können, die länger als 255 Zeichen sind. N3: Integer = maximal zu lesende Anzahl der Zeichen N4: Bereich = nimmt den Text auf Rückgabewert: Anzahl der gelesenen Zeichen wm_GetTextLength = $000E ermittelt die Länge des Textes im angegebenen Steuerelement Rückgabewert: Länge des Textes in Bytes wm_Paint = $000F fordert das Fenster zum Neuzeichnen auf wm_Paste = $0302 fügt Daten aus der Zwischenablage in das Fenster an der aktuellen Mauszeigerposition ein Seite 329 RGH-PROFAN² wm_SetFont = $0030 Setzt den Font (die Schrift) für das entsprechende Fenster bzw. Fensterelement. Auf diese Weise können Editierfelder, Listboxen, Buttons, etc. mit einem frei wählbaren Font ausgestattet werden. In der Systemvariablen %FONT ist das Handle zum zuletzt mit USEFONT eingestellten Fonts enthalten. N3: Integer = Handle des Fonts (0 = Systemfont) N4: >0 = Element sofort neuzeichnen. wm_SetText = $000C Einem Fensterelement wird der in der Bereichsvariablen gespeicherte Text übergeben. Diese Botschaft entspricht dem PROFAN²-Befehl SETTEXT mit dem Unterschied, daß auch Texte übergeben werden können, die länger als 255 Zeichen sind. N4: Bereich = enthält den Text wm_Undo = $0304 macht die letzte Aktion (z.B. Cut oder Paste) wieder rückgängig Seite 330 RGH-PROFAN² Programmieren für Anwender P R O F A N ² 6.0 DIE einfache Programmiersprache für Windows 3.x und Windows 95 Anhang Seite 331 RGH-PROFAN² ANHANG 1: Fehlermeldungen Folgende Fehlermeldungen und Warnungen werden vom Interpreter bzw. Compiler und Runtime-System erzeugt: Programm-Struktur 100 : 101 : 102 : 103 : 104 : 105 : 106 : 107 : 108 : 109 : 110 : 111 : 112 : 113 : 114 : 115 : 116 : 117 : 118 : 119 : 120 : 121 : 122 : 123 : 124 : 125 : Systemvariable unbekannt: Funktion unbekannt: Befehl unbekannt: Integer-Variable erwartet! Dateikennung erwartet! Tabellenkennung erwartet! ENDIF bzw. ELSE nicht gefunden! ENDIF nicht gefunden! Zu tiefe WHILE-Verschachtelung! ENDWHILE bzw. WHILE nicht gefunden! WHILE fehlt! GOSUB/PROC fehlt! PROC fehlt! Label nicht gefunden: Zu tiefe GOSUB/PROC-Verschachtelung! ENDPROC nicht gefunden! "DIM%" darf nur einmal verwandt werden! "DIM&" darf nur einmal verwandt werden! "DIM$" darf nur einmal verwandt werden! "DIM!" darf nur einmal verwandt werden! STARTPRINT fehlt! Bereichs-Variable erwartet! Variablenbezeichner fehlerhaft: Variablenname zu lang: STARTPAINT fehlt! SUBPOPUP fehlt! Ungültige/fehlende Parameter 200 : 201 : 202 : 203 : 204 : 205 : 206 : 207 : 208 : 209 : 210 : 211 : 212 : 213 : 214 : 215 : 216 : 217 : 218 : 219 : Ungültiger Funktionswert! Division durch 0! Falscher Typ für @DTOC$ ! Falscher Typ für @CTOD$ ! String-Index ist < 1 ! Substring-Nr ist < 1 ! So viele Elemente sind nicht da! Bereichsgrenze überschritten: Kommandozeilenparameter fehlt! Datei nicht gefunden: Dateinummer nicht im erlaubten Bereich! Parameterzahl muß zwischen 0 und 12 liegen! Zu wenig Parameter! Funktionsargument fehlt! Keine Zahl: Variable nicht deklariert: Falscher Parametertyp: Speicher für Integer-Variablen erschöpft! Speicher für LongInt-Variablen erschöpft! Speicher für String-Variablen erschöpft! Seite 332 RGH-PROFAN² 220 : 221 : 222 : 223 : 224 : 225 : 226 : 227 : 228 : 229 : 230 : 231 : 232 : 233 : 234 : 235 : 236 : 237 : 238 : 239 : 240 : 241 : 242 : 243 : 244 : 245 : 246 : 247 : 248 : 249 : 250 : 251 : 252 : 253 : 254 : Speicher für Float-Variablen erschöpft! Während der Druckausgabe verboten: Box nicht innerhalb des Fensters! Negative Fenstergröße! ICON nicht vorhanden: ICON nicht vorhanden! (Nur 0..4) Fehler bei der Menüerstellung! Zu tiefe Menüverschachtelung! Bitmap nicht ladbar: Bitmap konnte nicht gespeichert werden: Cursor nicht vorhanden! (Nur 0..11) Es sind lediglich 0 bis 9999 Elemente erlaubt! Zu viele Elemente! Das Element gibt es nicht! Fehler bei der Tonerzeugung! Drucken ist nicht möglioch! Fehler bei der HardCopy! Der Befehl setzt ein Fenster vorraus! Stringende fehlt! Speicher für Bereichs-Variablen erschöpft! Zu wenig Speicher für Bereichs-Variable! Bereichsvariable ist bereits DIMensioniert! Ungültiges Fenster-Handle! Bereichsvariable ist nicht DIMensioniert! Der Text paßt nicht komplett in die Bereichsvariable! Die Parameterzahl unterscheidet sich von der Parameterbeschreibung! Ungültiger Typ in der Parameterbeschreibung! Fehler beim Laden der DLL: Funktion in DLL nicht vohanden: Zwischen STARTPAINT/ENDPAINT verboten: SETTIMER fehlt! Der TIMER ist schon eingestellt! Menü ist nicht ladbar: Speicher für Array-Variablen erschöpft! Maximal drei Dimensionen erlaubt! IO-Fehler 300 : 301 : 302 : 303 : 304 : 305 : Datei kann nicht gelesen werden: Datei kann nicht erzeugt werden: Fehler beim Lesen: Fehler beim Schreiben: PROF16.EXE nicht ausführbar oder fehlt! REGISTRY: ODBC-Fehler und Meldungen 500 : 501 : 502 : 503 : 504 : 505 : 506 : 507 : ODBC ist nicht initialisiert! Fehler bei der ODBC-Initialisierung! ODBC.DLL nicht gefunden! ODBC-Fehler Sätze bearbeitet! Operation erfolgreich! Ergebnisdatei kann nicht geöffnet werden! Zu große Ergebnismenge! Seite 333 RGH-PROFAN² DatenBank-Fehler 600 : 601 : 602 : 603 : 604 : 605 : 606 : 607 : 608 : 609 : 610 : 611 : 612 : 613 : 614 : 615 : 616 : dB-Fehler: Datei nicht gefunden Doppelter Feldname Ungültige Feldlänge Ungültige Dezimalstellen Index-Datei nicht in Ordnung Feld nicht gefunden Dateiname fehlerhaft Schlüsselfeld nicht in Ordnung Tabellennummer nicht im erlaubten Bereich! Tabellennummer noch nicht vergeben! Formel nicht in Ordnung Feld beim Lesen nicht gefunden Feldnummer beim Lesen nicht gefunden Feld zum Schreiben nicht gefunden Feldnummer zum Schreiben nicht gefunden Index-Dateiname fehlerhaft: Sonstige Fehler 900 : 901 : 902 : 903 : 904 : 905 : 906 : Dieser Befehl ist in der Sharewareversion nicht vorhanden! Nur 32767 bzw. 16380 Zeilen sind erlaubt! Zeile zu lang (max. 254 Zeichen)! INCLUDE-Datei nicht gefunden! INCLUDE-Verschachtelung verboten! Keine gültige PROFAN² Datei! Programmdatei fehlerhaft! Seite 334 RGH-PROFAN² Anhang 2: Messages (Botschaften) Für einige Botschaften, die für den PROFAN²-Programmierer besonders interessant sind, gibt es im Kapitel 4 dieser Referenz und in der Online-Hilfe zu PROFAN² 4.0 eine ausführlichere Beschreibung. Die Parameter und Funktion der übrigen Botschaften sind der Fachliteratur zur Windowsprogrammierung zu entnehmen, z.B. "Das große Buch zu Turbo Pascal für Windows" aus dem DATA-Becker-Verlag oder "Schnell-Ünbersicht Turbo Pascal für Windows" aus dem Markt&Technik-Verlag. Da die Botschaften dort in der Regel nur mit Ihrem Namen genannt werden, folgt hier nun eine Zuordnung der Botschafts-Nummern zu ihren Namen. Diese Liste erhebt keinen Anspruch auf Vollständigkeit. Besonders unter Windows 95 sind noch einige Botschaften hinzugekommen. Allgemeine Windows-Botschaften (Nummern gelten für 16 und 32 Bit) $0007 $0008 $000A $000B $000C $000D $000E $000F $0010 $0011 $0012 $0013 $0014 $0015 $0016 $0018 $0019 $001A $001B $001C $001D $001E $001F $0020 $0021 $0022 $0023 $0024 $0026 $0027 $0028 $002A $002B $002C $002D $002E $002F : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : wm_SetFocus wm_KillFocus wm_Enable wm_SetRedraw wm_SetText wm_GetText wm_GetTextLength wm_Paint wm_Close wm_QueryEndSession wm_Quit wm_QueryOpen wm_EraseBkGnd wm_SysColorChange wm_EndSession wm_ShowWindow wm_CtlColor wm_WinIniChange wm_DevModeChange wm_ActivateApp wm_FontChange wm_TimeChange wm_CancelMode wm_SetCursor wm_MouseActivate wm_ChildActivate wm_QueueSync wm_GetMinMaxInfo wm_PaintIcon wm_IconEraseBkGnd wm_NextDlgCtl wm_SpoolerStatus wm_DrawItem wm_MeasureItem wm_DeleteItem wm_VKeyToItem wm_CharToItem Seite 335 RGH-PROFAN² $0030 $0031 : wm_SetFont : wm_GetFont $0037 $0039 $0041 $0044 $0046 $0047 : : : : : : wm_QueryDragIcon wm_CompareItem wm_Compacting wm_CommNotify wm_WindowPosChanging wm_WindowPosChanged $0081 $0082 $0083 $0084 $0085 $0086 $0087 $00A0 $00A1 $00A2 $00A3 $00A4 $00A5 $00A6 $00A7 $00A8 $00A9 : : : : : : : : : : : : : : : : : wm_NCCreate wm_NCDestroy wm_NCCalcSize wm_NCHitTest wm_NCPaint wm_NCActivate wm_GetDlgCode wm_NCMouseMove wm_NCLButtonDown wm_NCLButtonUp wm_NCLButtonDblClk wm_NCRButtonDown wm_NCRButtonUp wm_NCRButtonDblClk wm_NCMButtonDown wm_NCMButtonUp wm_NCMButtonDblClk $0100 $0101 $0102 $0103 $0104 $0105 $0106 $0107 : : : : : : : : wm_KeyDown wm_KeyUp wm_Char wm_DeadChar wm_SysKeyDown wm_SysKeyUp wm_SysChar wm_SysDeadChar $0110 $0111 $0112 $0113 $0114 $0115 $0116 $0117 : : : : : : : : wm_InitDialog wm_Command wm_SysCommand wm_Timer wm_HScroll wm_VScroll wm_InitMenu wm_InitMenuPopup $011F $0120 $0121 : wm_MenuSelect : wm_MenuChar : wm_EnterIdle $0200 $0201 $0202 $0203 $0204 $0205 $0206 $0207 $0208 $0209 : : : : : : : : : : wm_MouseMove wm_LButtonDown wm_LButtonUp wm_LButtonDblClk wm_RButtonDown wm_RButtonUp wm_RButtonDblClk wm_MButtonDown wm_MButtonUp wm_MButtonDblClk Seite 336 RGH-PROFAN² $0210 : wm_ParentNotify $0220 $0221 $0222 $0223 $0224 $0225 $0226 $0227 $0228 $0229 $0230 $0233 : : : : : : : : : : : : $0300 $0301 $0302 $0303 $0304 $0305 $0306 $0307 $0308 $0309 $030A $0305 $030D : wm_Cut : wm_Copy : wm_Paste : wm_Clear : wm_Undo : wm_RenderFormat : wm_RenderAllFormats : wm_DestroyClipboard : wm_DrawClipboard : wm_PaintClipboard : wm_VScrollClipboard : wm_SizeClipboard : wm_ChangeCBChain $030E $030F $0310 $0311 : wm_HScrollClipboard : wm_QueryNewPalette : wm_PaletteIsChanging : wm_PaletteChanged wm_MDICreate wm_MDIDestroy wm_MDIActivate wm_MDIRestore wm_MDINext wm_MDIMaximize wm_MDITile wm_MDICascade wm_MDIIconArrange wm_MDIGetActive wm_MDISetMenu wm_DropFiles Button-Messages Diese Botschaften sind für alle Arten von Buttons (Knöpfen) einzusetzen; dazu zählen auch die Radiobuttons und Checkboxen. ACHTUNG: Diese Messages bitte nicht bei anderen Windowsobjekten einsetzen, da dort die gleichen Botschaftsnummern eine andere Bedeutung haben! Der erste Wert gilt für 16, der zweite für 32 Bit. $0400 / $00F0 $0401 / $00F1 $0402 / $00F2 $0403 / $00F3 $0404 / $00F4 : : : : : bm_GetCheck bm_SetCheck bm_GetState bm_SetState bm_SetStyle Seite 337 RGH-PROFAN² Edit-Messages Diese Botschaften sind für alle Arten von Editierfeldern einzusetzen. ACHTUNG: Diese Messages bitte nicht bei anderen Windowsobjekten einsetzen, da dort die gleichen Botschaftsnummern eine andere Bedeutung haben! Der erste Wert gilt für 16, der zweite für 32 Bit. $0400 / $00B0 $0401 / $00B1 $0402 / $00B2 $0403 / $00B3 $0404 / $00B4 $0405 / $00B5 $0406 / $00B6 $0408 / $00B7 $0409 / $00B9 $040A / $00BA $040B / $00BB $040C / $00BC $040D / $00BD $040E / $00BE $0411 / $00C1 $0412 / $00C2 $0413 / $00C3 $0414 / $00C4 $0415 / $00C5 $0416 / $00C6 $0417 / $00C7 $0418 / $00C8 $0419 / $00C9 $041A / $00CA $041B / $00CB $041C / $00CC $041D / $00CD $041E / $00CE $041F / $00CF $0420 / $00D0 $0421 / $00D1 $0422 / $00D2 : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : em_GetSel em_SetSel em_GetRect em_SetRect em_SetRectNP em_Scroll em_LineScroll em_GetModify em_SetModify em_GetLineCount em_LineIndex em_SetHandle em_GetHandle em_GetThumb em_LineLength em_ReplaceSel em_SetFont em_GetLine em_LimitText em_CanUndo em_Undo em_FmtLines em_LineFromChar em_SetWordBreak em_SetTabStops em_SetPasswordChar em_EmptyUndoBuffer em_GetFirstVisibleLine em_SetReadOnly em_SetWordBreakProc em_GetWordBreakProc em_GetPasswordChar Seite 338 RGH-PROFAN² Listbox-Messages Diese Botschaften sind für Listboxen zu verwenden. ACHTUNG: Diese Messages bitte nicht bei anderen Windowsobjekten einsetzen, da dort die gleichen Botschaftsnummern eine andere Bedeutung haben! Der erste Wert gilt für 16, der zweite für 32 Bit. $0401 / $0180 $0402 / $0181 $0403 / $0182 $0405 / $0184 $0406 / $0185 $0407 / $0186 $0408 / $0187 $0409 / $0188 $040A / $0189 $040B / $018A $040C / $018B $040D / $018C $040E / $018D $040F / $018E $0410 / $018F $0411 / $0190 $0412 / $0191 $0413 / $0192 $0414 / $0193 $0415 / $0194 $0416 / $0195 $0418 / $0197 $0419 / $0198 $041A / $0199 $041B / $019A $041C / $019B $041F / $019E $0420 / $019F $0421 / $01A0 $0422 / $01A1 $0423 / $01A2 : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : lb_AddString lb_InsertString lb_DeleteString lb_ResetContent lb_SetSel lb_SetCurSel lb_GetSel lb_GetCurSel lb_GetText lb_GetTextLen lb_GetCount lb_SelectString lb_Dir lb_GetTopIndex lb_FindString lb_GetSelCount lb_GetSelItems lb_SetTabStops lb_GetHorizontalExtent lb_SetHorizontalExtent lb_SetColumnWidth lb_SetTopIndex lb_GetItemRect lb_GetItemData lb_SetItemData lb_SelItemRange lb_SetCaretIndex lb_GetCaretIndex lb_SetItemHeight lb_GetItemHeight lb_FindStringExact Seite 339 RGH-PROFAN² ComboBox-Messages Diese Botschaften sind für alle Arten von ComboBoxen einzusetzen; dazu zählt auch die von PROFAN unterstützte AuswahlBox. Andere ComboBox-Typen erlauben z.B. auch die Eingabe in der obersten Zeile oder zeigen ständig beide Teile der ComboBox an: Editierfeld und Listbox. ACHTUNG: Diese Messages bitte nicht bei anderen Windowsobjekten einsetzen, da dort die gleichen Botschaftsnummern eine andere Bedeutung haben! Der erste Wert gilt für 16, der zweite für 32 Bit. $0400 / $0140 $0401 / $0141 $0402 / $0142 $0403 / $0143 $0404 / $0144 $0405 / $0145 $0406 / $0146 $0407 / $0147 $0408 / $0148 $0409 / $0149 $040A / $014A $040B / $014B $040C / $014C $040D / $014D $040E / $014E $040F / $014F $0410 / $0150 $0411 / $0151 $0412 / $0152 $0413 / $0153 $0414 / $0154 $0415 / $0155 $0416 / $0156 $0417 / $0157 $0418 / $0158 : : : : : : : : : : : : : : : : : : : : : : : : : cb_GetEditSel cb_LimitText cb_SetEditSel cb_AddString cb_DeleteString cb_Dir cb_GetCount cb_GetCurSel cb_GetLBText cb_GetLBTextLen cb_InsertString cb_ResetContent cb_FindString cb_SelectString cb_SetCurSel cb_ShowDropDown cb_GetItemData cb_SetItemData cb_GetDroppedControlRect cb_SetItemHeight cb_GetItemHeight cb_SetExtendedUI cb_GetExtendedUI cb_GetDroppedState cb_FindStringExact DDE-Messages (Nummern gelten für 16 und 32 Bit) $03E0 $03E1 $03E2 $03E3 $03E4 $03E5 $03E6 $03E7 $03E8 : wm_dde_Initiate : wm_dde_Terminate : wm_dde_Advise : wm_dde_Unadvise : wm_dde_Ack : wm_dde_Data : wm_dde_Request : wm_dde_Poke : wm_dde_Execute Seite 340 RGH-PROFAN² ANHANG 3: Technische Daten PROFAN² gibt es sowohl als 16- als auch als 32-Bit-Version. Hierbei wurde auf größtmögliche Kompatibilität in beiden Richtungen gedacht. Daher ist der Befehls- und Funktionsumfang in beiden Versionen identisch. Gerinfügige technisch bedingte Abweichungen in der Funktion einiger weniger Befehlen und Funktionen sind in der Referenz entsprechend vermerkt. Aus Gründen der Kompatibilität ist in der 32-Bit-Version sogar der Aufruf von Funktionen in 16-Bit DLLs möglich, wenn PROF16.EXE ins Windowsverzeichnis kopiert wird. Wird eine 32Bit-Anwendung weitergegeben, die 16-Bit-Funktionen aufruft, muß PROF16.EXE mit weitergegeben werden! Das Format der PRC-Dateien (Kompilate) ist identisch, sodaß es durchaus möglich ist, das gleiche kompilierte Programm einmal mit einer 16-Bit-Runtime und das andere Mal mit einer 32-Bit-Runtime zu starten. 32-Bit-Version von PROFAN² 6.0 32767 Programmzeilen mit je max. 255 Zeichen (PROFAN² 4.5:16380) 32767 Einträge je Array (PROFAN² 4.5: 16380) 10000 Einträge in der Listboxliste 500 Variablen je Typ (PROFAN² 4.5: 200) max. Parameterzahl bei Prozeduren/Funktionen: 12 (PROFAN² 4.5: 8) max. Größe Bereichsvariable: Speicher (PROFAN² 4.5: 64 kB) While-Wend-Verschachtelung: 10 Proc-Endproc-Verschachtelung: 150 (PROFAN² 4.5: 10) Anzahl offene Dateien: 15 (PROFAN² 4.5: 8) Offene Datenbanktabellen: 15 (PROFAN² 4.5: 8) Größe Datensatz: 16000 Zeichen (DBase III/PROFAN² 4.5: 4000 Zeichen) Felder pro Satz: 1024 (DBase III/PROFAN² 4.5: 128) 16-Bit-Version von PROFAN² 6.0 16380 Programmzeilen mit je max. 255 Zeichen 16380 Einträge je Array 10000 Einträge in der Listboxliste 200 Variablen je Typ max. Parameterzahl bei Prozeduren/Funktionen: 12 (PROFAN² 4.5: 8) max. Größe Bereichsvariable: 64 kB While-Wend-Verschachtelung: 10 Proc-Endproc-Verschachtelung: 50 (PROFAN² 4.5: 10) Anzahl offene Dateien: 15 (PROFAN² 4.5: 8) Offene Datenbanktabellen: 15 (PROFAN² 4.5: 8) Größe Datensatz: 16000 Zeichen (DBase III/PROFAN² 4.5: 4000 Zeichen) Felder pro Satz: 1024 (DBase III/PROFAN² 4.5: 128) HINWEIS: Da eine Prozedur sich selbst aufrufen kann (Rekursion), gibt die Proc-EndProcVerschachtelung gleichzeitig die max. Rekursionstiefe an. Seite 341