V”llig unzureichende Anleitung (tm) zur Winlib/Demo (c) 1993 by sm Achtung! Wichtig! Die absolute Buchempfehlung: Garp und wie er die Welt sah (The world according to Garp) von John Irving, zB bei rororo Die 'Anleitung' zu den XRSRC-/MyDial-Routinen befindet sich am Ende (nach 'anl-xm' suchen). Aufbau: 0. Epilog 1. Ziele (was will/wozu die Winlib?) 2. Definitionen, Wortvereinbarungen 2.1 Was Sie noch nie ber Fenster wissen wollten 3. Klassen von Funktionen 4. Die wichtigsten Funktionen 5. Die weiteren Funktionen 0. Das am Ende geschriebene Vorwort So, die Anleitung steht, nicht wackeln bitte. Ich bin fest davon berzeugt, daž sie ihrem Anspruch (siehe oben) gerecht wird ... aber sie ist doch deutlich besser als nichts. Grundlegende Kenntnisse der GEM-Programmierung werden allerdings vorausgesetzt (laber, schwall). Wem's nicht reicht: die Demo bietet viele Beispiele und ist ziemlich brauchbar programmiert, sollte also weiterhelfen. Immer ran: Abgucken bildet, wenn mans richtig macht. Weitere Literatur: GFA-Basic-Handbuch und das Profibuch sollten v”llig reichen. Kenntnis von Tim Oren's 'Professional GEM' und anderem schadet sicher nicht, sollte aber nicht n”tig sein. Schluts jetz. Wer noch Fragen hat: siehe Manifest. Seine Majest„t am 20.4.93 um 17:29 und v”llig am Ende 1. Ziele Ziel der Winlib ist, Fensterprogrammierung soweit m”glich zu vereinfachen. Die Winlib ... - handelt die AES-Fenstermeldungen korrekt und effizient ab (inkl. Redraw!) - handelt Buttonklicks in Fenster korrekt und effizient ab - beschr„nkt die Besch„ftigung mit den unterschiedlichen Koordinatensystemen aufs Minimum beschr„nkt (obwohl ein neues eingefhrt wird ;-) - erm”glicht feste Fensterkennungen (Stichwort Feldindizierung!) - verwaltet auf Wunsch den Cursor (auch fr mehrere Fenster!) - untersttzt aufl”sungsunabh„ngige Fensterprogrammierung - untersttzt ne Art 'Desktop'-Fenster (fr zB Icons) - erlaubt 2 nicht-scrollende Fensterbereiche - strickt, kocht und h”rt sich Ihre Sorgen an (ab Version 4.00, to come soon) Was die Winlib nicht tut, ist ... - Ihnen vorschreiben, wie Ihre Programme aussehen sollen (wie es meiner Meinung nach zB das ACS macht): die wesentlichen Schnittstellen sind offen (und: der _Quelltext_!) - eigene D”sk”ppe (engl.: desktops) untersttzen (dafr macht sie sie praktisch v”llig berflssig) - Ihr Auto waschen (auch nicht, wenn Sie keines haben) 2. Definitionen, Wortvereinbarungen 'Wenn ich im folgenden oder in den Kommentaren zur Winlib von a spreche, meine ich b' a: ich, der Autor, seine Majest„t, sm, WIR b: mich a: die Programmiererin b: Sie a: die Benutzerin b: der arme Mensch, der IHR Machwerk sp„ter benutzen soll/muž a: die Applikation, das Programm b: Ihr Programm a: die Demo b: die Demo (zur Winlib etc.) a: Funktion(en), Routinen b: Prozeduren OR Funktionen a: OR b: und/oder (eben OR) a: GFA b: GFA-Basic 3.x (ST/TT) a: Bier, Alt b: Potts Alt, prost Anmerkung: wie unschwer zu erkennen ist, sind alle personenbezogenen Begriffe in der weiblichen Form. Selbstverst„ndlich sind damit auch M„nner gemeint. Auch die Chauvis, die sich darber aufregen. Diese Anmerkung ist der Brokratie in Deutschland gewidmet. 2.1 Was Sie schon immer ber Fenster wissen wollten 'Denk ich an Fenster in der Nacht, dann bin ich um den Schlaf gebracht' (Heine) 'Fenster sind die Augen zur Seele' (?) 'Gesegnet, die auf Erden Fenster stiften!' (Shakespeare "how's he spelled in your edition?") 'Fensterprogrammierung unter GEM is eigentlich total trivial. Und die Erde ist eine Scheibe. qed.' (sm) DON'T PANIC! (sorry, mir is die freundliche rote Farbe ausgegangen) Die Idee, Fenster in GUIs (graphical user interfaces, zB GEM, Windoof) Fenster zu nennen, entsprang wasweižichwelcher šberlegung. Es gibt sicher Parallelen; man sollte sich aber nicht krampfhaft daran festbeižen. W„hrend ich mein Fenster aufmachen kann und frische Luft reinlassen, kann ich mein Fenster verschieben und mir Dateien drin anzeigen lassen. Alles klar, gelle? Also, Definition: Fenster in GUIs (im folgenden nur noch Fenster) sind Objekte mit bestimmten Eigenschaften. Diese Eigenschaften sind nun interessant. Fenster kann man verschieben. Man kann sie ”ffnen und schliežen. Man kann in ihnen viel mehr (oder weniger) darstellen, als auf den Bildschirm pažt. Man kann sie toppen (in den Vordergrund holen) usw. Vieles davon wird vom GEM erheblich vereinfacht, ja fast voll bernommen. Prinzipiell is die Fensterprogrammierung darum auch einfach: man sagt den AES Bescheid, daž man Fenstermittelungen bekommen m”chte (zB ON MENU MESSAGE GOSUB window_event), holt sich ein Fenster-Handle (Handle: ne Kennung, oft eine Zahl) mit wind_create() und ”ffnet das Fenster. Die AES revanchieren sich nun, indem sie ne Nachricht senden 'mach mal n Redraw ' (Redraw: Fensterinhalt neu zeichnen), und den macht man dann 'mal eben'. Wenn die Benutzerin dann das Fenster verschiebt, kriegt man wieder ne Nachricht ('hey, Dein Fenster is nach x,y verschoben worden'). Und man sagt den AES dann per wind_set(), daž das ok is. Usw. Die Nachrichten trudeln in window_event ein, und alles is in Butter. Von wegen. H”chstens in Margarine, und alles schon gar nicht. _Einige_ der Nachrichten k”nnen sehr leicht behandelt werden. Ein paar andere sind aber durchaus geeignet, der Programmiererin Nervenzusammenbrche zu bescheren. Speziell der Redraw ist _das_ Sorgenkind (die Sliderverwaltung is auch nicht ohne ... die hat mich fast mehr Nerven gekostet): angenommen, man hat n Fenster, in dem man 1000 Zeilen und 200 Spalten darstellen m”chte - zB nen Text. Den Text hat man zB in nem Feld stehen (a$(1000)). Ganz sicher is, daž nicht der ganze Text auf den Bildschirm pažt, deshalb hat man ja das Fenster. Wenn jetzt n Bereich neu zu zeichnen ist, sagen einem die AES zB 'zeichne mal von 300,200 (x,y) den Bereich der Breite 80 und der H”he 50 neu. Genaueres hab ich Dir in die Rechteckliste gepackt.'. Und man darf dann die Rechteckliste abklappern und den Text neu ausgeben. Wenn man nicht wie ein Weltmeister rechnen will (Sie werden noch verstehen: dies ist Eigenlob ;-), gibt man pro Rechteck in der Liste den ganzen Text aus, mit ordentlich berechnetem (rc_intersect()) Clipping versteht sich (und unter Bercksichtigung der Sliderpositionen). Das is natrlich v”llig ineffizient (eigentlich mužten vielleicht nur 2 Zeilen gezeichnet werden ... und die meisten der 1000 Zeilen gibt man aus, obwohl sie garnicht sichtbar sind), aber es is einfach und klappt. Gerade noch. Denn schon bei 3000 Zeilen Text der Zeichenh”he 16 Pixel kommt das VDI nicht mehr mit: mit WORD-Parametern deckt man eben nur n Bereich von -32768 bis 32767 ab. Kurz nachgerechnet: 3000 * 16 macht 48000, man ruft also die VDI-Textfunktion (in GFA TEXT x,y,a$) fr die letzten fast 1000 Zeilen mit Werten auf, mit denen GFA (und das VDI) garnix mehr anfangen kann. Man kann so sehr sch”n Bomben erzeugen: CLIP 0,0,WORK_OUT(0),WORK_OUT(1) FOR i&=1 TO 3000 TEXT 0,i&*16,STR$(i&) NEXT i& Wrde das VDI mit LONGs arbeiten ... nun, dann wrde es eben sp„ter knallen, und mit FLOATs noch sp„ter. Und schneller wrds auch nicht werden, und unser Programm auch nicht effizienter. So geht es also nicht. Wie denn dann? Nunja: indem man eben wie ein Weltmeister rechnet. Und zwar sich ausrechnet, welche Zeilen/Spalten neu gezeichnet werden mssen. Anders ausgedrckt: man rechnet die von den AES erhaltenen Koordinaten in ein eigenes Koordinatensystem um und bercksichtigt dabei die Fensterposition und die Sliderpositionen. Man jongliert also mit 3 Koordinatensystemen: Bildschirmkoordinaten, Fensterkoordinaten und eigene Koordinaten (Koordinaten dessen, was man in dem Fenster darstellen will) ... (Protestrufe aus dem Hintergrund: 'Aufh”ren, aufh”ren!', gefolgt von Tomaten und frischen Eiern. Leider mag ich keine Eier. 'K”nnt Ihr nicht mit Radieschen werfen?') Nun gut, Schluts damit. Vielleicht haben Sie nen kleinen Einblick gewonnen, vielleicht nicht. In letzterem Fall muž ich Sie eben bitten, mir zu glauben: die Winlib macht die Programmierung wirklich erheblich einfacher. Nicht ganz so einfach, wie ohne Fenster und nur mit festen Koordinaten, aber _fast_ so einfach. Und das alles GEM-konform, aufl”sungsunabh„ngig usw. 3. Klassen von Funktionen der Winlib Die Winlib kann man teilen in folgende Klassen von Funktionen: a) Abfragefunktionen (Auskunftsfunktionen) b) Setzfunktionen (Funktionen, die etwas bewirken) Diese Unterteilung ist nicht neu und nicht weltbewegend. Interessanter ist folgende: a) solche, die die Programmiererin fllen OR erg„nzen OR „ndern muž b) solche, die die Programmiererin benutzen darf c) verbotene Frchte „h Funktionen Das is auch nicht neu und sicher nicht weltbewegend, aber es ist interessanter. Fr Sie. Ich weiž das schon ;-) Beides vermischt, ergibt das wirkliche Bild - so isses: a) Funktionen, die Sie fllen OR erg„nzen OR „ndern mssen b) Abfragefunktionen, die Sie benutzen drfen c) Setzfunktionen, die Sie benutzen drfen d) verbotene Funktionen (mit 2 'halbverbotenen', sp„ter mehr) Verboten heižt: benutzen Sie die nicht! 1. weil ich sie jederzeit „ndern k”nnte (Namen/Funktion), 2. (wichtiger) weil das unn”tig sein sollte. Wenn Sie feststellen, daž man etwas mit der Winlib nicht machen kann, was man machen k”nnen sollte: melden Sie sich bei mir (siehe Manifest). Wenn ich Ihnen nicht helfen kann, is immer noch frh genug, sich auf glattes Eis zu begeben (sprich, die verbotenen Funktionen zu benutzen). Verboten sind auch jegliche Zugriffe auf Winlib-Variablen, auch lesende. Auch deren Namen zu „ndern behalte ich mir n„mlich vor. Das einzige, was ich garantiere: globale Variablen der Winlib haben immer 'winlib_' vorangestellt, das sollte reichen, um Konflikte mit Variablen Ihres Programms zu verhindern. Wenn Ihnen ne Abfragefunktion fehlt: melden! Die Funktionen sind nach den genannten Klassen in der Winlib sortiert, und innerhalb der Klassen (streng) alphabetisch. Sollte es Namenskonflikte zwischen Funktionen der Winlib und denen Ihres Programms geben: die verbotenen Funktionen kann ich (und werde ich wahrscheinlich) umbenennen (zB 'winl_' oder so voranstellen). Die Abfragefunktionen haben (fast) alle ein 'win_' vorangestellt, die anderen sind nicht SO viele. Mit anderen Worten: aužer was die verbotenen Funktionen betrifft werde ich wahrscheinlich ziemlich taub auf Umbenennungswnsche reagieren (zumal diese einen Rattenschwanz an Žnderungen, zB in dieser Anleitung, nach sich ziehen wrden). Wenn es gar nicht anders geht: schreiben Sie sich n Konverter. Sorry, besser hab ichs nicht (schlechter aber auch nicht). Im folgenden werden nur die nicht-verbotenen Funktionen behandelt. 4. Die wichtigsten Funktionen Diese sind: - change_wind() (Klasse c) - cursor_wind() (Klasse c) - define_wind() (Klasse c) - fill_window() (Klasse a) - init_winlib() (Klasse c) - open_wind() (Klasse c) - window_event (Klasse c) - button_event (Klasse d) fill_window() mssen Sie selber ausfllen. Sie werden Ihren Spaž dran haben ;-) ... n„heres gleich. Erstmal mssen Sie n paar andere Funktionen kennenlernen. window_event und button_event sind die 2 speziellen verbotenen Funktionen: die _mssen_ sie aufrufen _lassen_, und deren Namen sind auch garantiert. In der Tat haben Sie mit denen nicht viel mehr zu tun, als in Ihr Programm 'ON MENU MESSAGE GOSUB window_event' und 'ON MENU BUTTON GOSUB button_event' zu schreiben (natrlich vor der ON MENU-Schleife). window_event handelt die Fensternachrichten der AES ab, button_event die Buttonnachrichten. Beide rufen diverse Funktionen auf und eventuell ber Umwege fill_window(). init_winlib() mssen sie am Anfang aufrufen, bevor Sie irgendeine weitere Funktion der Winlib aufrufen. Keine Regel ohne Ausnahme: delete_wind() drfen Sie auch vorher schon aufrufen, doch dazu sp„ter mehr (tomorrow's just another day ;-). init_winlib() kennt nur 2 Parameter: PROCEDURE init_winlib(nr&,std_err_alert$) nr: Anzahl der vom Programm ben”tigten Fenster std_err_alert$: Standard-String fr form_alert(), wenn kein Fenster mehr verfgbar ist, zB "[3][Es kann kein Fenster mehr|ge”ffnet werden. Abhilfe:|schliessen Sie eines!][OK]" Dieser String darf nur einen Button enthalten!! init_winlib() exportiert diverse Variablen/Felder mit der Kennung 'winlib_' als Pr„fix. Der Speicherbedarf der Winlib is natrlich von der Anzahl der gewnschten Fenster abh„ngig (einfach proportional). N„heres im Kommentar in der Funktion (Quelltext). change_wind() muž ich noch schreiben ;-) ... damit wird man die Angaben eines Fensters (die man bei define_wind() gemacht hat, auch die Attribute) „ndern k”nnen. cursor_wind() ist _die_ Funktion der Cursorverwaltung: FUNCTION cursor_wind(nr&,msg$,no%) <- BOOLEAN nr: programminterne Fensterkennung msg$: Nachricht an cursor_wind() no: Anzahl der Zellen, um die der Cursor bewegt werden soll cursor_wind() versteht folgende Nachrichten: "BOTTOM", "TOP" : setzen den Cursor _ganz_ an das Ende bzw. den Anfang des Inhaltes (in vielen Programmen erreicht man das ber Shift+Home bzw. Home). no hat hier keine Bedeutung. "^","v",">","<" : hoch, runter, rechts, links um no Zellen "PG^", "PGv", "PG>", "PG<" : jeweils um eine Seite (engl.: page -> PG) nach oben, unten, rechts, links. Eine bedeutet dabei den 'Anzahl der sichtbaren Zeilen bzw. Spalten im Fenster - 1'. Mit no kann dies beeinflužt werden: ist no=1, so wird der Cursor um den vollen Inhalt versetzt. no kann natrlich auch negativ sein. Ausprobieren! Rckgabe: TRUE, wenn sich die Cursorposition ge„ndert hat, sonst FALSE. Im brigen verschiebt cursor_wind() natrlich falls n”tig auch den Inhalt (schickt ne Redraw-Meldung) und setzt die Slider um. Und: es funkt auch mit Fenstern, fr die man keinen Cursor angemeldet hat!! Zum Setzen des Cursors und zur Abfrage gibt es auch Funktionen, sp„ter dazu. Empfehlung: "^","v",">","<" bei Cursor-hoch, -runter, -rechts, -links "PG^" usw. bei Shift+Cursor-hoch usw. "TOP" bei Home, "BOTTOM" bei Shift+Home Beispiele: siehe Funktion 'my_cursor()' der Demo (dort werden auch Control+Cursor untersttzt) define_wind() definiert Fenster und holt ein Handle: PROCEDURE define_wind(nr&,attr&,x%,y%,w%,h%,cellw&,cellh&,x_off&,y_off&, alert$,flags%) nr: Fensternummer (programminterne Kennung) attr: Attribute x: x-Koordinate des Fensters (virtuell, 0-1.000.000) y: y-Koordinate des Fensters (virtuell, 0-1.000.000) w: gewnschte Breite des Arbeitsbereichs (absolut) h: gewnschte H”he des Arbeitsbereichs (absolut) cellw: Breite der Zellen im Fenster (abs.) cellh: H”he der Zellen im Fenster (abs.) x_off: H”he des oberen 'Info'-Bereichs (abs.) Diese beiden: y_off: Breite des linken 'Info'-Bereichs (abs.) nicht zu grož w„hlen! alert$: String fr form_alert; wenn dieser leer ist ("") und der bei init_winlib() angegebene nicht leer, wird letzterer ausgegeben, wenn kein Handle mehr frei ist, ansonsten dieser - es sei denn, der hier angegebene String ist "NO", dann wird garnix ausgegeben flags%: 31 (!) Bits fr diverse Zwecke (knftige Erweiterungen, Parameter) Bit 0: Scrollen soweit m”glich ber VDI-Copy-Raster-Funktionen Bit 1: im Fenster wird ein Cursor dargestellt Bit 2: Fenster kann nicht durch Anklicken getoppt werden Hier muž ich diverses erkl„ren: - bei den Attributen kann man die fr Slider und Size-Feld des Fensters weglassen, define_wind() kann selber feststellen, ob sie n”tig sind. Kann man absehen, daž sie (nach Žnderungen der anf„nglichen Werte) n”tig sein werden (also zB bei nem Editor-Fenster, das ja 'ber alle Grenzen' grož werden kann), sollte man sie angeben (muž aber nicht, change_wind() wird alles bercksichtigen!). Das Size-Feld sollte man fast immer angeben. - das virtuelle Koordinatensystem der Winlib: ein Koordinatensystem von 0-1.000.000 * 0-1.000.000 (1 Million zum Quadrat). Dieses dient dazu, Fenster aufl”sungsunabh„ngig zu positionieren. Gibt man zB in diesem System an, daž ein Fenster an der Position 500.000, 500.000 stehen soll, dann wird dies bei einer wirklichen Bildschirmaufl”sung von 640 * 400 auf (ca.) 320 * 200 umgerechnet (ca. wg. Menleiste). Dieses System ist _sehr_ genau; es ist eher zu genau als zu ungenau - sicher is sicher. - das gesagte zusammen: angenommen, Sie wollen ein Fenster haben, dessen Arbeitsbereich (der Inhalt, also ohne Slider usw.) 300 * 200 sein soll. Dieses Fenster soll (abh„ngig von der Aufl”sung) Slider haben oder keine: es soll in einem Viertel des Bildschirms stehen, wenn es dort komplett reinpažt (zB Grožbildschirm), soll es eben keine Slider haben. Dann gibt man fr attr die gewnschten Attribute _ohne_ Slider an und fr x und y je 500.000: define_wind() schaut dann nach, ob ein Fenster, das an der Position 500.000, 500.000 (wird natrlich umgerechnet) steht und die entsprechende Breite und H”he hat ohne Slider auskommt. Wenn nicht, werden die n”tigen Slider erg„nzt (also ev. nur der horizontale usw.!). Beispiel: alle Fenster der Demo (Demo mal in versch. Aufl”sungen starten) - Zellen im Fenster: ein Beispiel: bei einer Aufl”sung von 640 * 400 kann man 80 * 25 Zeichen der Gr”že 8 * 16 darstellen: 640=80*8, 400=25*16. Ein Fenster, das 80 * 25 Zeichen der Gr”že charw * charh darstellen k”nnen soll, sollte man mit einer gewnschten Breite von 80 * charw, einer gewnschten H”he von 25 * charh, Zellbreite charw und Zellh”he charh definieren. Zellen in einer 2dimensionalen Matrix: das sind die Zellen im Fenster. Funkt natrlich auch mit Grafik usw. cellw und cellh sollten nicht zu grož (in der regel deutlich kleiner als 50) angegeben werden und mssen mindestens 1 sein - und _glatte Teiler_ der gewnschten Breite/H”he!! Wichtig! - xoff/yoff: mit diesen kann man 2 Bereiche definieren, die nicht mitgescrollt werden, einen am oberen Rand horizontal (mit _y_off!!), den anderen am linken Rand vertikal (mit xoff!). Fr diese Bereiche verwaltet die Winlib gesondert Koordinaten und verschickt gesonderte Redraw-Meldungen (genaueres bei der Erkl„rung zu fill_window()). Auch diese beiden sollte man nicht zu grož w„hlen, mindestens 0. Beispiele siehe Demo. - alert$: nochmal die Logik: man gibt ja nen Standard-Alert$ bei init_winlib() an (oder auch nicht, as you like it). Wenn jetzt kein Handle frei ist, macht define_wind() folgendes: IF alert$<>"NO" IF alert$="" AND standard-alert$<>"" @winlib_alert(standard-alert$) ! @winlib_alert: wie ~form_alert() ELSE @winlib_alert(alert$) ENDIF ENDIF - flags%: 31 Bits fr zuknftige Erweiterungen. Das 32. Bit wird change_wind() benutzen. Mit den Bits 0-2 hat die Zukunft schon begonnen (heute ist morgen schon gestern ;-). Bit 0 wird in der Demo vom Grafikfenster nicht benutzt, da das Neuzeichnen der Musterfl„chen auch so schon schnell genug (bzw. schneller!) und es beim Scrollen via VDI-Copy-Raster zu Fehlern kommt (zum Ausprobieren: einfach Bit 0 setzen), Bit 1 wird fr das Text-Fenster benutzt, Bit 2 fr das 'Desktop'-Fenster open_wind() ”ffnet Fenster und setzt sie an neue Positionen: PROCEDURE open_wind(nr&,mod|,x%,y%,w%,h%,hor%,ver%) nr: Fensternummer (programminterne Kennung) mod: Modus; als da sind: 1 : x,y,w,h sind Angaben in einem (virtuellen) 1 Million * 1 Million - Koordinatensystem; Zweck: Fenster aufl”sungsunabh„ngig genau positionieren. Das Fenster wird im angegebenen Bereich zentriert (wenn 'n”tig'). Falls die verwendeten Koordinaten von der Funktion win_get_virt_coords() stammen, wird erkannt, ob das Fenster auf dem Bildschirm war, in diesem Fall wird es nicht ge”ffnet; dies wird vermerkt, und folgende Aufrufe in diesem Modus (zum Neupositionieren) werden ignoriert. Ein Fenster, das sich schon auf dem Bildschirm befindet, wird neu positioniert (aber nicht getoppt!). 2 : wie 1, aber: das Fenster wird in _jedem_ Fall ge”ffnet und ev. getoppt; wenn das Fenster w„hrend des aktuellen Programmlaufs schonmal auf dem Bildschirm war und dann geschlossen wurde, werden x,y,w,h,hor,ver ignoriert und das Fenster an der letzten Position ge”ffnet alle anderen: reserviert hor,ver: Horizontal-/Vertikal-Offset fr den Fensterinhalt, bestimmen Sliderpositionierung Das virtuelle Koordinatensystem ist unter define_wind() erkl„rt. Wann soll man Modus 1, wann 2 benutzen? Nun: beim automatischen ™ffnen am Programmanfang und zum Neupositionieren (zB: Fenster untereinander anordnen wie bei Tempus) sollte/muž man Modus 1 benutzen. Auf Aufforderung der Benutzerin zum ™ffnen sollte man Modus 2 benutzen. Die Demo geht wie folgt vor: am Anfang werden die Werte (x,y,w,h,hor,ver, aužerdem Rang) aus einem DATA-Feld vorbelegt. Danach werden diese mit den Werten aus der Datei mit den gespeicherten Fensterwerten, falls diese existiert, berladen. Dann werden die Fenster der Reihe nach 'ge”ffnet' im Modus 1. Bei Anforderung zum Fenster ”ffnen ber die Menleiste werden die Fenster im Modus 2 'ge”ffnet'. Fenster positionieren ber Modus 1 benutzt die Demo (noch) nicht. Wird 'Pos. speichern' aufgerufen, werden die Fensterpositionen via win_get_virt_coords() geholt und gespeichert. War ein Fenster zu diesem Zeitpunkt geschlossen, wird das mitgespeichert (automatisch, win_get_virt_coords() und open_wind() sind trickreich aufeinander abgestimmt). Beim n„chsten Programmstart werden die Fenster am Anfang natrlich wieder ber Modus 1 ge”ffnet: und hier erkennt open_wind(), daž das Fenster geschlossen war und ”ffnet es nicht. Beim Aufruf ber Modus 2 (Menleiste) wird das Fenster in jedem Fall ge”ffnet: die Benutzerin will es schliežlich so. An dieser Stelle sind ein paar Worte zur Verwaltung von offenen/ geschlossenen Fenstern durch die Winlib angebracht: die ganze Wahrheit ist, daž die Winlib dafr sorgt, daž Sie darauf nicht achten mssen. Wenn ein Fenster zu is und Sie schicken ne Redraw-Meldung dafr (ja, auch SIE k”nnen Redraws senden, dazu sp„ter mehr), ignoriert die Winlib die Meldung halt usw. Trotzdem kann man Abfragen, ob ein Fenster auf dem Bildschirm ist: die Demo braucht das fr das Iconifizieren - UND SONST FšR NICHTS. Zur Funktion dazu sp„ter, hier nur: machen Sie es genauso. In der Regel kann Ihnen egal sein, ob ein Fenster auf dem Bildschirm is oder nicht, machen Sie sich das Leben nicht mit Sicherheitsabfragen schwer, die die Winlib _eh_ schon selber macht ... ;-) hor und ver: sind immer Vielfache von cellw und cellh (siehe define_wind()). Von beiden sollte man die Finger lassen: abfragen und in open_wind() einspeisen reicht. Zum Verschieben des Inhalts is cursor_wind() da (eigentlich nicht, sondern eine der verbotenen Funktionen ... jedenfalls k”nnen _Sie_ den Inhalt ber Aufruf von cursor_wind() verschieben ;-). Es ist gut m”glich, daž ich mit change_wind() das Žndern dieser beiden _nicht_ erm”gliche: ich sehe n„mlich keinen Bedarf dazu. Und da dies eine gute Gelegenheit is, n paar Worte zur Sliderverwaltung zu verlieren: Fensterinhalte k”nnen mit der Winlib nur in Vielfachen von cellw bzw. cellh verschoben werden. Das ist 1. sinnvoll und 2. geht es nicht anders (genauer: wrde zu viele unn”tige Probleme mit sich bringen -> lohnt nicht). šbrigens machen das alle Programme, die ich kenne, so. So, und nun: fill_window() PROCEDURE fill_window(nr&,which&,x&,y&,w&,h&,xc%,yc1%,wc%,yc2%,xoff%,yoff%) wird zum Fllen von Fenstern und zur Button-Auswertung aufgerufen Unterscheidung ber which: which: beim Fllen: 0 Inhalt, 1 horizontal, 2 vertikal beim Buttonauswerten: 10 Inhalt, 11 hor., 12 vert. nr: Fensternummer beim Fllen: x: linke x-Koordinate des neu zu zeichnenden Bereiches absolut y: obere y-Koordinate des neu zu zeichnenden Bereiches absolut w: Breite des neu zu zeichnenden Bereiches absolut h: H”he des neu zu zeichnenden Bereiches absolut xc: x-Koordinate des neu zu zeichnenden Bereichs in Zellenz„hlung (0-?) yc1: obere y-Koordinate des neu zu z. Bereichs in Zellenz„hlung (0-?) wc: Breite des neu zu zeichnenden Bereichs in Zellenz„hlung (1-?) yc2: untere y-Koordinate des neu zu z. Bereichs in Zellenz„hlung (0-?) beim Buttonauswerten: x: x-Koordinate des Klicks absolut y: y-Koordinate des Klicks absolut w: gedrckte Maustaste (Bitvektor) h: Anzahl der Mausklicks xc: x-Koordinate des Klicks in Zellenz„hlung (0-?) yc1: y-Koordinate des Klicks in Zellenz„hlung (0-?) wc: immer 1 yc2: wie yc1 xoff: x-Offset der absoluten Koordinaten zum Fensterinhalt yoff: y-Offset der absoluten Koordinaten zum Fensterinhalt Das is n Monster, was? Nunja: ich h„tte auch Fllen und Buttonauswerten auf 2 Funktionen aufteilen k”nnen. Es hat aber nen Vorteil, sie zusammen zu haben: man kann die Koordinatenberechnungen fr beide 'auf einen Blick' zusammenbehalten. Tips: - es kann sehr hilfreich sein, die Anzahl der Mausklicks usw. in 'besser' benannte Variablen zu holen und w und h auf 1 zu setzen: also am Anfang IF which&>9 mk&=w& no&=h& w&=1 h&=1 ! mk& und no& LOCAL definieren! ENDIF - m”chte man eine Funktion fr beliebige Fenster haben: man _muž_ nicht auf nr& prfen. Die Winlib ruft die Funktion nur auf, wenn n eigenes Fenster betroffen ist, also immer man druff ;-) - man sollte - wenn man _nicht_ xc,yc1,wc,yc2 benutzt - die Koordinaten, die man fr einen Grafikbefahel (LINE, TEXT usw.) benutzen will, mit rect_intersect() auf Legalit„t prfen! Also zB: x1%=200+xoff% y1%=200+yoff% w1%=100 h1%=100 IF @rect_intersect(x&,y&,w&,h&,x1%,y1%,w%,h%) BOX x1%,y1%,x1%+w%-1,y1%+h%-1 ENDIF Dadurch werden illegale Werte (vor allem: zu grože) verhindert. Diese k”nnen ja durch das Aufaddieren von xoff/yoff entstehen! Also: immer benutzen. Nicht n”tig ist dieser Test, wenn Sie statt x,y,w,h die zellenbezogenen Koordinaten xc,yc1,wc,yc2 benutzen, fr diese macht die Winlib den Check selber (weil es hier _m”glich_ ist, im anderen Fall ist es _nicht_ m”glich). Diese Koordinaten wurden so gew„hlt, daž ein Ausgeben in einer Schleife m”glichst einfach ist, zB: x1%=charw& * xc% + xoff% y1%=charh& * yc1% + yoff% - (charh&-charpixh&) ' ^^^^^ dies dient zur Korrektur, is n”tig ' (da TEXT sich auf die Baseline bezieht ... Unterl„ngen!) FOR i%=yc1% TO yc2% a$=LEFT$(text$(i%)+SPACE$(wc%),wc%) ! SUCC wg 0...x TEXT x1%,ADD(y1%,charh&),a$ ADD y1%,charh& NEXT i% Weitere Beispiele in der Demo - in fill_window() natrlich. 5. Die weiteren Funktionen 5.1 Weitere, die Sie fllen OR erg„nzen OR „ndern mssen: PROCEDURE clipbrd_search Man sollte in dieser Prozedur nachschauen, ob das Clipboard ne interessante Datei enth„lt (zB per exist() nach Dateien suchen). Erstens wird diese Routine aufgerufen, wenn ein Fenster _durch Anklicken_ getoppt wird. Zweitens wird diese Routine aufgerufen, wenn das oberste Fenster der Applikation eine Redraw-Nachricht erh„lt: das is dann der Fall, wenn ein Fenster/Dialog ber diesem lag oder direkt nach dem ™ffnen. Ist kein Clipboard gesetzt, wird diese Funktion nicht aufgerufen, also: šberprfung (IF @clipbrd_path$<>"") nicht n”tig. Beispiel: IF EXIST(@clipbrd_path$+"SCRAP.TXT") clip!=TRUE ELSE clip!=FALSE ENDIF In der Demo steht in der letzten Zeile dieser Funktion noch: @redraw_programmer(0,0,FALSE,5,0,1,0) ... um das Klemmbrett-Icon im 'Desktop'-Fenster zeichnen zu lassen. PROCEDURE close_window(nr&) Eventuell von Ihnen zu erg„nzen. Hier kann man einen Programm-Ende-Aufruf beim Schliessen eines bestimmten Fensters einbauen. ZB, wenn bei Fenster 1 dies bewirkt werden soll: if nr&=1 ende ! Aufruf der Programmende-Prozedur endif Auf jeden Fall sollte (muž) hierin stehen: @delete_wind(nr&) Richtig: delete_wind(), da man beim Schliežen auch das AES-Handle freigeben sollte (damit der Anwender durch Schliežen eines Fensters die M”glichkeit erh„lt, ein anderes zu ”ffnen ...). delete_wind() erledigt das Schliežen mit. In der Demo steht in der letzten Zeile dieser Funktion noch: IF nr&>0 ! nicht 0: 0 ist das 'Desktop'-Fenster @redraw_programmer(0,0,FALSE,nr&-1,0,1,0) ENDIF ... um das Icon im 'Desktop'-Fenster zeichnen zu lassen. PROCEDURE handle_xmsg Wenn window_event eine AES-Message nicht erkennt, wird diese Prozedur aufgerufen. Hier kann man also zB Messages des AV/VA- oder des XAcc-Protokolls abhandeln In der Demo wird in dieser Prozedur das Empfangen von Tastendrcken mittels AV_SENDKEY erm”glicht. Zum Testen zB Clock (von Stefan Hintz) geeignet. Siehe Demo. PROCEDURE new_curpos(nr&) Diese Prozedur wird von der Winlib aufgerufen, wenn die Cursorposition im Fenster nr sich durch a) Aufruf von open_wind() oder b) durch Anklicken der entsprechenden Fensterelemente ge„ndert hat. In der Demo wird aus dieser Prozedur heraus zeige_position(nr&) aufgerufen, um die Cursorposition im Textfenster anzeigen zu lassen. PROCEDURE winlib_alert(alert$) Diese Prozedur kann vom Programmierer an seinen Bedarf angepažt werden, zB um alternative Alert-Routinen durch die Winlib benutzen zu lassen (zB die der MyDials) Hier sollte also zB stehen: ~FORM_ALERT(1,alert$) ! AES ODER (exklusiv) ~@my_do_alert(1,alert$) ! MyDials 5.2 Abfragefunktionen: FUNCTION clipbrd_path$ <- STRING Gibt den Klemmbrett-Pfad zurck (w„r auch so keiner drauf gekommen). Der zurckgegebene String ist entweder leer oder hat immer ein "\" am Ende. FUNCTION rect_intersect(x&,y&,w&,h&,x%,y%,w%,h%) <- BOOLEAN šberschneiden sich die Rechtecke im (eventuell) sichtbaren Bereich und liegen die LONG-Koordinaten im WORD-Bereich? ja: TRUE, nein: FALSE. Trotz namentlicher Žhnlichkeit unterscheidet sich die Funktion von RC_INTERSECT deutlich: 1. ver„ndert sie die eingegebenen Koordinaten nicht (absichtlich) 2. darf das 2. der Rechtecke aus LONG-Koordinaten 'bestehen' FUNCTION win_bottom <- WORD Gibt nr des untersten Fensters (der Applikation) zurck FUNCTION win_cellh(nr&) <- WORD Gibt Zellh”he des Fensters nr zurck FUNCTION win_cellw(nr&) <- WORD Gibt Zellbreite des Fensters nr zurck FUNCTION win_find(x&,y&,VAR nr&) <- BOOLEAN Befindet sich an Position x,y (absolut) eines meiner Fenster? ja: TRUE, nein: FALSE; in nr Rckgabe der Fensterkennung PROCEDURE win_get_cur_xy(nr&,VAR x%,y%) --- Gibt Cursorposition von Fenster nr in x,y zurck. Rechnung ab 0,0, nicht ab 1,1 ! FUNCTION win_get_virt_coords(nr&,VAR vx%,vy%,vw%,vh%) <- BOOLEAN Gibt Aužen-Koordinaten des Fensters nr im virtuellen (1-1000000) Koordinatensystem in vx,vy,vw,vh zurck. Wenn das Fenster noch nie ge”ffnet war, werden vx,vy,vw,vh nicht ver„ndert; hat man beim Aufruf diese nicht vordefiniert, sind sie nachher also weiter undefiniert -> Garbage in, Garbage out. Die Funktion liefert in diesem Fall FALSE, ansonsten TRUE. Beispiel in der Demo in der Prozedur menu_evaluation() FUNCTION win_hor(nr&) <- LONG Gibt Horizontaloffset des Inhalts von Fenster nr zurck. Siehe Anmerkungen zu open_wind(). FUNCTION win_off_screen(nr&) <- BOOLEAN Ist das Fenster nr _nicht_ auf dem Bildschirm? TRUE: es ist nicht, FALSE: es ist (doch) auf dem Bildschirm FUNCTION win_rank(rank&) <- WORD Gibt nr des Fensters mit dem 'Rang' rank zurck. Das is etwas tricky, Beispiel: 4 Fenster, nr 0-3. nr 0 liegt ganz unten und hat damit Rang 0, nr 1 liegt ganz oben und hat damit Rang 3, nr 2 liegt zweitunterst, also Rang 1, und nr 3 hat Rang 2 und liegt ... ? Also: Rang = 'Entfernung' zum untersten Fenster FUNCTION win_top <- WORD Gibt nr des obersten Fensters der Applikation zurck. FUNCTION win_topabs(nr&) <- BOOLEAN Ist das Fenster nr das (absolut) oberste? ja: TRUE, nein: FALSE FUNCTION win_ver(nr&) <- LONG Gibt Vertikaloffset des Inhalts von Fenster nr zurck. Siehe Anmerkungen zu open_wind(). FUNCTION win_workh(nr&) <- LONG Gibt H”he des _gesamten_ Arbeitsbereichs von nr in Pixeln zurck. Also: den Wert, den man bei define_wind() in h% angegeben hat. FUNCTION win_workw(nr&) <- LONG Gibt Breite des _gesamten_ Arbeitsbereichs von nr in Pixeln zurck. Also: den Wert, den man bei define_wind() in w% angegeben hat. FUNCTION win_xoff(nr&) <- WORD Gibt Breite der vertikalen nicht-scrollenden Box nr in Pixeln zurck. Also: den Wert, den man bei define_wind() in xoff& angegeben hat. FUNCTION win_yoff(nr&) <- WORD Gibt H”he der horizontalen nicht-scrollenden Box nr in Pixeln zurck. Also: den Wert, den man bei define_wind() in yoff& angegeben hat. 5.3 Andere benutzbare Funktionen: FUNCTION cursor_set(nr&,x%,y%) <- BOOLEAN nr: Fensterkennung x: neue gewnschte X-Position, Z„hlung ab 0 y: neue gewnschte Y-Position, Z„hlung ab 0 Rckgabe: TRUE, wenn sich die Cursorposition ge„ndert hat, sonst FALSE. Mit cursor_set() kann man den Cursor absolut setzen (cursor_wind() setzt nur relativ neu). Ansonsten gelten die Anmerkungen zu cursor_wind() auch hier. PROCEDURE delete_wind(nr&) L”scht Kennung von (und schliežt n”tigenfalls das) Fenster nr Mit nr<0 werden alle gel”scht (und n”tigenfalls die Fenster geschlossen). Diese Funktion funktioniert auch vor Aufruf von init_winlib(), daher: setzen Sie in die Ausgangsfunktion Ihres Programms einfach @delete_wind(-1), und am Ende werden alle offenen automatisch geschlossen. Voila! PROCEDURE ob_draw_wind(tree%,start&,depth&,x%,y%) Zeichnet Objekt per OBJC_DRAW(). Diese Funktion sollte bei Bedarf aus fill_window() heraus aufgerufen werden. In x,y bergeben Sie die dort erhaltenen xoff,yoff. Die anderen Parameter: tree: Adresse des Objektbaums start: (Start-) Objekt depth: Tiefe, mit der OBJC_DRAW() zeichnen soll Siehe fill_window() der Demo und GFA-Handbuch. PROCEDURE redraw_programmer(nr&,which&,coordtype!,x%,y%,w%,h%) nr: Fensterkennung which: 0=Inhalt, 1=hor. Box, 2=vert. Box coordtype!: TRUE: x,y,w,h sind absolute Angaben FALSE: x,y,w,h sind wie xc,yc1,wc,yc2 bei fill_window() Hiermit zeichnen Sie Teile eines Fensters neu. Sie k”nnen zwischen absoluten Koordinaten (in _ihrem_ Koordinatensystem, dem des Inhalts) und Zellenkoordinaten (ebenfalls bezogen auf den Inhalt) w„hlen. Aužerdem k”nnen Sie den Teil des Fensters, der neu gezeichnet werden soll, ber which bestimmen. PROCEDURE redraw_part(nr&,which&) nr: Fensterkennung which: 0=Inhalt, 1=hor. Box, 2=vert. Box, 3= alle (0,1,2) Auch hiermit kann man einen Redraw einleiten, der Unterschied ist: diese Prozedur zeichnet immer das komplette angegebene Teil (which) neu. Kann also furchtbar ineffizient sein, wenn man zB nur wenige Zeichen neu zeichnen wollte ... dafr simpelst in der Anwendung. PROCEDURE set_wind_line(nr&,field&,adr%) nr: Fensterkennung field: 2 (Name) oder 3 (Infozeile) adr: Adresse des (neuen) Textes Setzt neuen Text fr das Namensfeld oder die Infozeile eines Fensters. Diese muž man in der Tat noch selbst verwalten, die Winlib nimmt das nicht ab. Der Grund dafr: dann h„tte ich auch noch ne Speicherverwaltung spendieren mssen ... irgendwann is aber Schluss, woll, Sie sollen ja auch noch was tun ;-) PROCEDURE top_wind(nr&) nr: Fensterkennung Bringt das Fenster nr nach oben ('toppt' das Fenster) anl-xm: ' XRSRC-/MyDial-Routinen fr GFA-Basic, Stefan Mnch Dez.1992/Jan.93 ' ' XRSRC-Routinen-Version: 1.01 20.3.93 ' MyDial-Routinen-Version: 1.01 20.3.93 ' ' Die MyDial- und XRSRC-Routinen werden mit dem Resourceeditor ' Interface geliefert. Dabei werden auch die Files "XRSRC.OVL" und ' "MYDIAL.OVL" geliefert. ' ' Diese Routinen stellen eine Weiterentwicklung bzw. Fehlerkorrektur der ' zuerst mit den Mydials gelieferten GFA-Routinen dar. Der Autor dieser ' stellte allen Mydial-Routinen ein 'my_' im Namen voraus; das habe ' ich (weils Sinn macht) beibehalten. Auch die Parameterreihenfolgen ' wurden groženteils beibehalten, diese entsprechen den C-Routinen, ' also kann die Mydial-Anleitung hier fast 1:1 herangezogen werden. ' An einigen Stellen waren jedoch Žnderungen n”tig oder sinnvoll. ' Die Žnderung der Reihenfolge war grunds„tzlich da n”tig, wo ' auf call-by-reference-Parameter call-by-value-Parameter folgten ' (in C kann man dies mischen, in GFA-Basic nicht); hier wurde so ' umgestellt, daž wirklich nur die n”tigen Variablen zurckgegeben ' werden. Dies hat immerhin den Vorteil, daž man diese Parameter ' mit konstantem Wert aufrufen kann, ohne diesen extra einer Variablen ' zuzuweisen. Aužerdem wurden da, wo m”glich, boolesche Variablen ' verwendet; die unterschiedliche Definition (in C ist TRUE=1, aužerdem ' sind diese Variablen in C Words) wurde bercksichtigt. ' Desweiteren: ' ' Die XRSRC-Routinen machen (jeweils) einen Test, ob sie installiert sind; ' sind sie nicht, werden die Original-RSRC_xxx-Routinen aufgerufen. ' Ich habe dies beibehalten: es ist insofern sinnvoll, da man zwar ' am Beginn eines Projektes die Routinen wohl noch nicht braucht ' (kaum jemand f„ngt mit einer RSC >64 kb an ;-), wenn man aber ' irgendwann feststellt, daž die RSC doch gr”žer wird, braucht man ' nur beim init_xrsrc-Aufruf den essential!-Parameter mit TRUE ' aufrufen und ansonsten keine Ver„nderungen am Programm vornehmen. ' Die Funktionsnamen h„tten natrlich auf rsrc_xxx (statt xrsrc_xxx) ' ge„ndert werden k”nnen, da GFA-Basic dies erlaubt; die Voranstellung ' des x is insofern sinnvoll, als damit Tippfehler (vergessener Klammeraffe ' als Zeichen des Funktionsaufrufs) leichter erkannt werden k”nnen und ' weil die Bezeichnung sich inzwischen eingebrgert hat. ' ' Auch die Mydial-Routinen machten im Original jeweils einen Test, ' ob sie installiert sind. Dies ist rausgeflogen: es ist nicht ' sinnvoll. Wenn man schon testet, mžte man bei Nichtinstallation ' die Funktion nachbilden -> das w„re aber unsinnig, dann k”nnte man ' gleich auf die Routinen verzichten und eigene verwenden. ' Bei den beiden Alert-Funktionen der Mydials wurde es beibehalten: ' dies ist sinnvoll, da man so IMMER diese Funktion aufrufen kann ' (auch _vor_ Installation der Routinen !!) und ' da eine Alternative einfach bereitzustellen ist. Auch bei exit_mydial ' wurde es logischerweise beibehalten, da exit_mydial von global_exit ' aufgerufen wird ... ' Statt diesen einzelnen Tests wird von init_mydial im Mižerfolgsfall ' abgebrochen und dazu 'global_exit' aufgerufen. ' ' Auch Routinen, die nichts sinnvolles zurckgeben, ' weil sie als VOID in C definiert sind, sind als Funktionen ' definiert. Ich habe davon abgesehen, diese in Prozeduren zu „ndern; ' Funktionen sind manchmal eleganter zu benutzen. Also nicht ' wundern, wenn eine Funktion fest TRUE zurckgibt, ich habe das ' mit Absicht so gemacht. ' ' Beide Sammlungen ben”tigen einen Installationsaufruf und einen ' Deinstallationsaufruf. Diese habe ich 'init_xxx' und 'exit_xxx' ' genannt. Die NKCC-Routinen der Mydials werden dort mit abgehandelt, ' darum braucht man sich nicht mehr kmmern. Beide Routinensammlungen ' verstecken ihre globalen Variablen mittels Prozeduren 'xxx_global_var'; ' ich habe dies eingefhrt, damit nicht aus Versehen im Hauptprogramm ' wichtige Variablen der Routinen ver„ndert werden k”nnen. Dieses ' Verstecken kostet Rechenzeit, logisch; doch der Verlust ist minimal ' (im 1000stel-Sekunden-Bereich), also: keine Panik ! Die ' Deinstallationsaufrufe sollte man in global_exit t„tigen. ' ' Beide Sammlungen ben”tigen die Funktion @compiled und die ' globale Ausgangsprozedur global_exit. Letztere wird ben”tigt, um ' aus den init-Prozeduren im Mižerfolgsfall zu einem definierten Ende ' zu springen; man sollte global_exit soweit n”tig um eigene Aufr„um- ' Aktionen erg„nzen. Die Funktion @compiled wird ben”tigt, um im ' Interpreter einen Fehler des Einbindungskonzepts ' (gemeldet von Andreas Frank, thanx!) zu umschiffen: ' die Overlay-Routinen werden mittels EXEC geladen. Das bedeutet aber, ' daž der Speicher von diesen erst bei Verlassen des Interpreters freigegeben ' wird - schliežlich ist aus GEM-Sicht der Interpreter der aktive Prozež, und ' nicht das Programm im Interpreter ... die Folge daraus war eine Verkleinerung ' des Speichers bei jedem Start, die Overlays wurden ja immer wieder ' geladen. Abhilfe: im Interpreter wird nach dem ersten Laden in der ' Basepage (des Interpreters) vermerkt, daž die Routine geladen ist ' (und die zugeh”rigen Adressen werden gemerkt). Bei jedem ' Programmstart wird in der Basepage nachgesehen, ob die Routinen ' schon geladen sind, und sie werden dann nicht neu geladen. ' Wer genauer wissen will, wie's geht, schaue in die init/exit-Routinen. ' Diese Methode drfte keine Probleme mit sich bringen, und im Compilat ' wird sie eh nicht angewandt. Ansonsten ist das Einbindungskonzept ' brigens sehr sinnvoll !! ' Aužerdem wird noch eine Funktion mit einem Text fr die Fehlermeldung ' ben”tigt, fr den Fall, daž ein Overlayfile nicht gefunden wurde/ ' der Speicher nicht reichte. Diese Funktion ist ebenfalls bei den ' ben”tigten aufgefhrt. ' ' Einige Definitionen zu den Mydials habe ich unten aufgefhrt, ' zB ALI_CENTER. Weitere Definitionen sind den beigelieferten .H-Files ' zu entnehmen bzw. den Anleitungen (irgendwo stehen sie halt ;-). ' ' Zu den Kommentaren in den Funktionen: diese stammen zum gr”žten ' Teil aus den Original-GFA-Routinen. Ich habe sie dringelassen, ' da sie kaum schaden k”nnen, sie aber nicht oder kaum erg„nzt, ' wo das eigentlich wnschenswert gewesen w„re. Ich habe sie auch ' nicht auf Fehler durchgesehen, also Vorsicht ! Ich hatte schon ' genug zu tun ... und man kann ja auf die Mydial-Anleitung ' zurckgreifen !! Was ich erg„nzt habe, is die Kapitelzahl ' in der Anleitung; in den Funktionen steht jeweils ne Zeile mit ' dieser (da ich die Routinen alphabetisch sortiert habe). Aužerdem ' hab ich die Rckgabe beschrieben (zB 'Rckgabe: WORD'). ' ' Ich hoffe, daž ich alle Fužangeln der Routinen gefunden und ausgemerzt ' habe, so daž diese von Ihnen (und mir ;-) als das benutzt werden k”nnen, ' als was sie gedacht sind: als 'black boxes', als Routinen, die ' funktionieren, ohne daž man wissen muž, wie. Fr Fehlermeldungen ' und Kritik ist meine Adresse oben aufgefhrt. Von Telefonanrufen ' bitte ich abzusehen; schriftliche Anfragen werden natrlich nur ' beantwortet, wenn ein frankierter Rckumschlag beiliegt. Eine ' Haftung wird in keiner Weise fr irgendetwas bernommen; ich ' verdiene nichts an diesen Routinen, und entsprechend betrachte ' ich meine Verpflichtung als NULL. Das betrifft auch die Verpflichtung, ' diese Routinen zu pflegen und auf Anfragen zu reagieren; ich sage nicht, ' daž ich dies nicht tun werde, ich sage aber: sollte ich es nicht tun, ' braucht sich niemand wundern. ' ' Noch eine Anmerkung zur Demo: die Variablennamen fr die Objektnummern ' haben alle ein 'h_' vorangestellt. Wozu? Natrlich zur Unterscheidung ' von anderen Variablen des Hauptprogramms (man bedenke: diese Variablen ' sind ja global!). Doch WIE? Ganz einfach: ich habe in Interface die ' Ausgabe eben mit vorangestelltem 'h_' definiert (da Interface nur ne ' begrenzte Namensl„nge erlaubt und man das vorangestellte 'h_' sonst ' ev. vergižt). Zur Nachahmung empfohlen, siehe IF_DIF.RSC! ' ' Viel Spaž mit den Mydials !! ' ' Stefan Mnch im Januar 93 ' ' ************************************************************************ ' ** Einige Definitionen zu den Mydials ** ' ************************************************************************ ' ALI_CENTER, ALCENTER: chr$(1) (Pfeil hoch) ' ALI_RIGHT,ALRIGHT: chr$(2) (Pfeil runter) ' ALI_LEFT, ALLEFT: "" (Leerstring, ebend: linksbndig is default) ' ' NIL -1 ' TRUE (in C) 1 ' FALSE (in C) 0 ' ' Struktur MKINFO wird nicht ben”tigt, fllt die Routine selbst aus ' Struktur DIALINFO: wird nicht ben”tigt, fllt die Routine selbst aus ' Struktur RECT: wird nicht ben”tigt, ersetzt durch 'x&,y&,w&,h&' ' ' Erweiterte Objekttypen ' DIALMOVER 0x0011 / 17 ' DCRBUTTON 0x0012 / 18 ' UNDERLINE 0x0013 / 19 ' TITLELINE 0x0014 / 20 ' HELPBUT 0x0015 / 21 ' CIRCLEBUT 0x0016 / 22 ' UNDOBUT 0x001F / 31 ' ' Flags fr popup_select ' DO_POPUP 0 ' DO_CYCLE -2 ' DO_POPPREV -1 ' DO_POPNEXT 1 ' ' frs Verst„ndnis der Einbindung eventuell wichtige Definitionen ' aus PORTAB.H: ' #define BYTE signed char /* Signed byte ' #define UBYTE unsigned char /* Unsigned byte ' #if LATTICE_C | PCC ' #define WORD short /* Signed word (16 bits) ' #define UWORD unsigned short /* Unsigned word ' #else ' #define WORD int /* Signed word (16 bits) ' #define UWORD unsigned int /* Unsigned word ' #endif ' #define LONG long /* Signed long (32 bits) ' #define ULONG unsigned long /* Unsigned long ' #define BOOLEAN WORD /* 2 valued (true/false) ' #define FLOAT float /* Single precision float ' #define DOUBLE double /* Double precision float ' #define INT int /* A machine dependent int ' #define UINT unsigned int /* A machine dependent uint ' ' #define FALSE (BOOLEAN)0 /* Function FALSE value ' #define TRUE (BOOLEAN)1 /* Function TRUE value