Windows unter GEM: Von Rollbalken und Ähnlichem...

Der Titel sagt es bereits, in dieser vorläufig letzten Folge beschäftigen wir uns mit den Bestandteilen eines Fensters, die es uns ermöglichen, mehr Informationen in einem Fenster darzustellen, als eigentlich auf den Bildschirm passen würden. Der “Trick" dabei ist es, nicht alles auf einmal ausgeben, sondern den Benutzer “blättern" zu lassen.

Als erfahrene GEM-Benutzer ist Ihnen dies bestimmt mehr als geläufig: um z.B. in First-Word den Text zu scrollen, greifen Sie zur Maus und klicken einen der Rollpfeile an, verschieben die Rollbox an eine andere Position oder klicken das graue Feld des Rollbalkens an (Vergleichen Sie auch mit Bild 1 aus dem ersten Artikel dieser Folge, dort sehen Sie die Elemente eines Fensters beschrieben). Was geschieht? Wenn Sie ein Rollpfeil anklicken, bewegt sich der Text um eine Zeile nach oben oder unten, bzw. einen Buchstaben nach rechts oder nach links, je nachdem, welchen der vier Rollpfeile Sie angeklickt haben. Wenn Sie den grauen Bereich eines Rollbalkens anklicken, verschiebt sich der Fensterinhalt um eine Seite vorwärts oder rückwärts, bzw. nach links oder rechts, wobei die oberste bzw. unterste Zeile der vorherigen Seite sichtbar bleibt. Ganz anders aber, wenn Sie die Rollbox mit der Maus verschieben. Dann springt der Text an die entsprechende Stelle. Es ist so, daß die ganze Länge des Rollbalkens die Länge des Dokumentes, das sich hinter dem Fenster versteckt, darstellt. Die weiße Rollbox steht für den sichtbaren Ausschnitt des Fensters und daher der grau schraffierte Teil für den momentan unsichtbaren Abschnitt des Fensters. D.h., das Fenster stellt eine Art von Sichtfenster dar, durch das Sie einen Ausschnitt des größeren Dokumentes sehen können, je nachdem, über welchem Teil sie es mit den Rollbalken plaziert haben.

Die Realisierung in C

Soweit, so gut. Das Ganze sieht ziemlich einfach aus, jedenfalls für den Benutzer, für den Programmierer stellen sich jedoch einige Schwierigkeiten. Im folgenden werde ich Ihnen also beschreiben, wie ich die Verwaltung der Rollbalken in unsere Windowbibliothek eingebunden habe. Um die zusätzlichen Daten zu verwalten, erfuhr unsere Window-Struktur einige Erweiterungen, außerdem wurde sie in die Headerdatei verlegt. Neu hinzu kamen:

GRECT work; enthält die aktuellen Koordinaten des Arbeitsbereiches (die Fläche innerhalb der Titelzeile(evtl. Infozeile) und den Rollbalken)

WORD scroll_x: Scrollwert für X-Richtung, um diesen Betrag wird der Fensterinhalt bei Betätigung der horizontalen Schieber gerollt. Bei Textausgabe normalerweise 8 (entspricht den Pixeln auf dem Bildschirm)

WORD scroll_y: Scrollwert für Y-Richtung, um diesen Betrag wird der Fensterinhalt bei Betätigung der vertikalen Schieber gerollt. Bei Textausgabe normalerweise 16.

WORD doc_x; Horizontale Position der linken oberen Ecke des Fensters im Dokument (Nicht mit Bildschirmkoordinaten zu verwechseln). Zeigt die linke Spalte z.B. den dritten Buchstaben eines Textes mit X-Scrollweite 8 an, dann beträgt doc_x 16.

WORD doc_y; Vertikale Position der linken oberen Ecke des Fensters im Dokument. Zeigt die oberste Zeile des Fensters z.B. die dritte Zeile eines Textes mit Y-Scrollweite 16 an, dann beträgt doc_y 32.

WORD doc_length; Länge des Dokumentes, das das Fenster darzustellen hat. Angabe in Pixeln. Ein Text von 100 Zeilen ist so z.B. bei einer Zeilenhöhe von 16 Pixeln 1600 Pixel lang.

WORD doc_width; Breite des Dokumentes. Ein Text mit der Breite von 65 Buchstaben und 8 Pixeln pro Buchstabe ist daher 520 Pixel breit.

Zu wissen, was für eine Aktion der Benutzer getätigt hat, ist kein Problem. Wenn Sie die Funktion handle_window() betrachten, fallen Ihnen drei bisher stiefmütterlich behandelte case-statements auf: WM_ARROWED, WM_HSLID und WM_VSLID. Eine dieser drei Meldungen erhalten wir, wenn wir unser Fenster mit den entsprechenden Elementen beim Öffnen ausgestattet haben und der Benutzer eines davon angeklickt hat. WM_ARROWED bedeutet dabei, daß einer der Rollpfeile oder einer der grauen Bereiche angeklickt wurde und der Benutzer entweder eine Zeile odereine Seite weiter- bzw. zurückblättern, oder nach rechts oder links blättern möchte. WM_HSLID meldet GEM bei Verschieben der horizontalen Rollbox, analog WM_VSLID bei Verschieben der vertikalen Rollbox.

Um diese Meldungen handzuhaben, schrieb ich entsprechende Funktionen, die die notwendigen Schritte durchführen: Mittels scroll_wind() verwalten wir eine WM_ARROWED-Message. Der Funktion übergeben wir das handle des Windows (buffer[3]) und den Inhalt von buffer[4], der die vom Benutzer getätigte Aktion genauer spezifiziert. Vergleichen Sie hierzu das switch-statement in scroll_wind. Je nachdem wird dann die Dokumentsposition um den Scrollwert vermindert oder erhöht. Beispiel:

case W_UPLINE : 
windows[w_handle].doc_y -= windows[w_handle].scroll_y.

Um aber zu verhindern, daß der neue Wert größer als die Dokumentslänge, bzw. kleiner als Null wird, muß eine zusätzliche Überprüfung durchgeführt werden:

if(windows[w_handle].doc_y < 0) 
    windows[w_handle].doc_y = 0

bzw.

if(windows[w_handle].doc_y > windows[w_handle].doc_length) 
    windows[w_handle].doc_y 
    windows[w_handle].doc_length

Diese Methode funktioniert bei zeilenweisem Rollen, bei seitenweisem Verschieben kommt aber noch etwas hinzu: es wäre sinnvoll, jeweils die letzte Zeile der vorherigen Seite mit anzuzeigen. Eine Seite entspricht hier immer der aktuellen Größe des Arbeitsbereiches. Wir müssen die Dokumentsposition also um die Größe des Arbeitsbereiches plus/minus der X- bzw. Y-Scrollweite vermindern/erhöhen. Beispiel:

case W_DNPAGE : 
windows[w_handle].doc_y += windows[w_handle].work.g_h - windows[w_handle].scroll_y

Die Überprüfung auf Über- oder Unterlauf der maximalen bzw. minimalen Größe bleibt gleich. Nachdem die Dokumentsposition nun so verändert wurde, müssen die Slider (=Rollboxen) neu positioniert werden, da sie ja die Größe und die relative Position des sichtbaren Fensterinhalts zum ganzen Dokument wiedergeben sollen. Hierzu dient set_slider_pos(), der wir das Handle des entsprechenden Fensters übergeben. Um die Position der Slider setzen zu können, muß man wissen, daß die GEM-Entwickler die Länge des Rollbalkens auf 1000 festgesetzt haben. Wir müssen also die Dokumentsposition entsprechend umrechnen. Hier die verwendete Formel: Schieberposition = Dokumentsposition * 1000/(Dokumentsgröße - Arbeitsbereichgröße)

Ein spezieller Fall muß aber berücksichtigt werden: ist die Arbeitsbereichgröße größer als die Dokumentsgröße, dann würde die Schieberposition ungewollterweise negativ, wir müssen diesen Fall also durch eine if-Abfrage abfangen. Nach der Berechnung der neuen Position können wir diesen Wert GEM mittels wind_set() mitteilen. Die Implementation sehen Sie in Listing 1.

Für WM_HSLID und WM_VSLID existieren zwei eigene Funktionen: wind_hslide() und wind_vslide(). Beide berechnen im Prinzip dasselbe, nur entweder horizontal oder vertikal, nämlich die neue Dokumentsposition. Dies ist der umgekehrte Fall von vorhin, bei set_slider_pos() war die Dokumentsposition bekannt, und die neue Sliderposition mußte berechnet werden. Jetzt ist die Sliderposition (buffer[4]) bekannt, und wir müssen die neue Dokumentspositon ermitteln. Aus der oben genannten Formel läßt sich dies leicht ableiten: Dokumentsposition = Schieberpositon * (Dokumentsgröße - Arbeitsbereichsgröße)/1000. Schließlich darf man nicht vergessen, die neue Sliderposition mittels wind_set() zu setzten, da dies GEM nicht selbstständig macht. Zu allerletzt, jetzt wieder in handle_window(), wird das ganze Fenster neu gezeichnet, da sich ja der Inhalt verschoben hat. Dazu rufen wir full_redraw() auf, das nichts anderes tut, als den Fensterinhalt mittels clear_window() zu löschen und je nach Fenster die entsprechende Redraw-Routine aufzurufen.

Sehr schön, aber...

... das ist noch nicht alles. Einerseits müssen wir open_window() anpassen, andererseits darf man keinesfalls vergessen, daß, wenn das Fenster in der Größe verändert wird, sich die Schiebergrößen ändern, da die Rollbalkenlänge verändert wird. Zunächst aber zu der nochmals erweiterten open_window()-Funktion. Notwendigerweise müssen wir ihr die X- und Y-Scrollwerte und die Dokumentslänge und Dokumentsbreite mitteilen. Sie trägt dann diese Werte in die Struktur ein. Außerdem setzt sie die horizontale und vertikale Dokumentsposition auf Null und berechnet die aktuellen Arbeitsbereichkoordinaten durch einen direkten Aufruf von wind_calc(). Jetzt zur Änderung der Schieber bei einer Größenänderung des Fensters: am Ende der Anweisungen, die in handle_window() bei WM_MOVED aufgerufen werden (d.h. wenn das Fenster in der Größe verändert wurde) fügen wir einen Aufruf von wind_calc_work() und set_slider_size() ein. *Wind_calc_work() berechnet aus den Koordinaten des gesamten Fensters diejenigen des Arbeitsbereiches (wie dies schon open_window() tat) und trägt die neuen Daten in die Struktur ein. Set_slider_size() berechnet, wie der Name schon sagt, die neue Größe der Slider und teilt diese Werte GEM mit, das dann die Slider neu zeichnet. Desweiteren müssen wir auch daran denken, daß bei einer Betätigung des Volle-Größen-Ecks die Fenstergröße verändert wird. Daher ergänzen wir handle_full() durch einen wind_calc_work() Aufruf und fügen in handle_window() nach dem Aufruf von handle_full() einen Aufruf von set_slider_size() ein.

Endlich

Damit möchte ich diese Folge vorläufig beenden. Sie haben nun eine praktische Windowbibliothek in den Händen, die es Ihnen ermöglicht, Fenster in GEM einfach handzuhaben. Natürlich steht es Ihnen frei, diese Ihren Wünschen anzupassen und zu erweitern - Möglichkeiten gäbe es noch genug...


/* HEADERDATEI, DIE WICHTIGE KONSTANTEN FÜR DIE WINDOW-ROUTINEN ENTHÄLT (vgl. Gem-Bibliothek ihres C-Compilers !) */ /* Definitionen für wind_create() */ #define NAME 0x0001 #define CLOSER 0x0002 #define FULLER 0x0004 #define MOVER 0x0008 #define INFO 0x0010 #define SIZER 0x0020 #define UPARROW 0x0040 #define DNARROW 0x0080 #define VSLIDE 0x0100 #define LFARROW 0x0200 #define RTARROW 0x0400 #define HSLIDE 0x0800 /* Definitionen für wind_get() bzw. wind_set() */ #define WF_KIND 1 #define WF_NAME 2 #define WF_INFO 3 #define WF_WORKXYWH 4 #define WF_CURRXYWH 5 #define WF_PREVXYWH 6 #define WF_FULLXYWH 7 #define WF_HSLIDE 8 #define WF_VSLIDE 9 #define WF_TOP 10 #define WF_FIRSTXYWH 11 #define WF_NEXTXYWH 12 #define WF_RESVD 13 #define WF_NEWDESK 14 #define WF_HSLSIZE 15 #define WF_VSLSIZE 16 #define WF_SCREEN 17 /* Definitionen für wind_update() */ #define END_UPDATE 0 #define BEG_UPDATE 1 #define END_MCTRL 2 #define BEG_MCTRL 3 /* Definitionen für wind_scroll () */ #define W_UPPAGE 0 #define W_DNPAGE 1 #define W_UPLINE 2 #define W_DNLINE 3 #define W_LFPAGE 4 #define W_RTPAGE 5 #define W_LFLINE 6 #define W_RTLINE 7 /* Definitionen für wind_calc() */ #define WC_BORDER 0 #define WC_WORK 1 /* Definitionen für evnt_mesag() */ #define MU_KEYBD 0x0001 #define MU_BUTTON 0x0002 #define MU_M1 0x0004 #define MU_M2 0x0008 #define MU_MESAG 0x0010 #define MU_TIMER 0x0020 /* von evnt_mesag() gemeldete Aktionen */ #define MN_SELECTED 10 #define WM_REDRAW 20 #define WM_TOPPED 21 #define WM_CLOSED 22 #define WM_FULLED 23 #define WM_ARROWED 24 #define WM_HSLID 25 #define WM_VSLID 26 #define WM_SIZED 27 #define WM_MOVED 28 #define WM_NEWTOP 29 #define AC_OPEN 40 #define AC_CLOSE 41 /* Definitionen für graf_growbox() bzw. für graf_shrinkbox() */ #define FMD_START 0 #define FMD_GROW 1 #define FMD_SHRINK 2 #define FMD_FINISH 3 /* Strukturdefinition für Rechteckslisten */ typedef struct grect { short g_x; short g_y; short g_w; short g_h; } GRECT; typedef struct wind_data /*Struktur, die Wissenswertes */ { /*ueber unsere Fenster enthaelt */ char name[80]; /* Fenstername */ GRECT max; /* Maximalgroesse */ GRECT work; /* Arbeitsbereichgroesse */ WORD elements; /* Bestandteile des Fensters */ WORD align; /* Faktor zur hör. Ausrichtung */ WORD snap; /* Fenster snappen (TRUE/FALSE) */ WORD full; /* Full-Flag (TRUE/FALSE) */ WORD scroll_x; /* Scrollwert fuer X-Achse */ WORD scroll_y; /* Scrollwert fuer Y-Achse */ WORD doc_x; /* X-Position des Dokumentes */ WORD doc_y; /* Y-Position des Dokumentes */ long doc_length; /* Dokumentslaenge */ WORD doc_width; /* Dokumentsbreite */ void (*w_redraw)(); /* Pointer auf Redraw-Funk.*/ } WIND_DATA; /* Ein Makro, das einen 32 Bit Pointer-Wert als zwei 16 Bit Werte zurückgibt. Wird in wind_set() gebraucht, um die Adresse des Fensternamens zu übergeben */ #define ADDR(a) ((long)(a) >> 16), ((long)(a) & 0xFFFF) /* Makros, die zwei Zahlen vergleichen und den groesseren bzw. kleineren zurueckgeben */ #define _max(a,b) ((a)>(b)?(a):(b)) #define _min(a,b) ((a)<=(b)?(a):(b))

/* Window-Bibliothek-Erweiterung */ /* Andreas Loetscher 1988 */ /* verwendeter Compiler : Lattice C 3.04 */ /*****************************************/ #include <a:\headers\portab.h> #include <c:\listing1.h> WORD ap_id, handle, work_in[12], work_out[57]; WIND_DATA windows[8]; void gem_init() { } void gem_exit() { } void clear_window(w_hndl) { } rc_intersect(p1, p2) { } void /* Setzen der Groesse der Slider */ set_slider_size (w_handle) WORD w_handle; { long h_size, v_size; h_size = windows[w_handle].work.g_w * 1000 / windows[w_handle].doc_width; v_size = windows[w_handle].work.g_h * 1000 / windows[w_handle].doc_length; wind_set(w_handle,WF_HSLSIZE,h_size,0,0,0); wind_set(w_handle,WF_VSLSIZE,v_size,0,0,0); } void /* Setzen der Position der Slider */ set_slider_pos(w_handle) WORD w_handle; { long x_pos, y_pos; if(windows[w_handle].doc_width <= windows[w_handle].work.g_w) x_pos = 0; else x_pos = windows[w_handle].doc_x * 1000 / ( windows[w_handle].doc_width - windows[w_handle].work.g_w ); if(windows[w_handle].doc_length <= windows[w_handle].work.g_h) y_pos = 0; else y_pos = windows[w_handle].doc_y * 1000 / ( windows[w_handle].doc_length - windows[w_handle].work.g_h ); wind_set(w_handle,WF_HSLIDE,x_pos,0,0,0); wind_set(w_handle,WF_VSLIDE,y_pos,0,0,0); } /* erweiterte open_window()-Funktion ... */ WORD open_window(w_name,redraw,was,algn,snp, s_x,s_y,doc_l,doc_w, x1,y1,w1,h1, mx,my,mw,mh) char *w_name; /* Ptr auf Namensstring */ void (*redraw)(); /* Ptr auf Redraw-Funktion */ WORD was, /* Liste der Elemente */ algn,snp, /* align-Wert, snap j/n */ s_x, s_y, /* Scrollwerte X/Y */ doc_l,doc_w, /* Dokumentslaenge/breite */ x1,y1,w1,h1, /* Startkoordinaten */ mx,my,mw,mh; /* Maximalkoordinaten */ /* falls mw==0 gleich */ /* Desktop */ { WORD w_handle; if(mw==0) /* ermittelt die Grösse des Desktop: */ wind_get (0,4, &mx, &my, &mw, &mh); /* und meldet ein Fenster an */ w_handle=wind_create(was,mx,my,mw,mh); /* traegt wichtige Daten in Struktur ein : */ windows[w_handle].max.g_x = mx; windows[w_handle].max.g_y = my; windows[w_handle].max.g_w = mw; windows[w_handle].max.g_h = mh; windows[w_handle].elements = was; windows[w_handlej.align = algn; windows[w_handle].snap = snp; windows[w_handle).w_redraw = redraw; windows[w_handle].scroll_x = s_x; windows[w_handle].scroll_y = s_y; windows[w_handle].doc_length = doc_l; windows[w_handle].doc_width = doc_w; windows[w_handle].doc_x = windows[w_handle].doc_y = 0; strcpy(windows[w_handle].name,w_name); windows[w_handle].full = (x1==mx && y1==my && w1==mw && h1==mh); wind_calc(WC_WORK,was,x1,y1,w1,h1, &windows[w_handle].work.g_x, &windows[w_handle].work.g_y, &windows[w_handle].work.g_w, &windows[w_handle].work.g_h); /* setzen des Fensternamens : */ wind_set(w_handle,2,ADDR(windows[w_handle].name),0,0); /* zeichnet öffnende Box: */ graf_growbox(0,0,0,0,x1,y1,w1,h1); wind_open(w_handle,x1,y1,w1,h1); clear_window(w_handle); set_slider_size(w_handle); set_slider_pos(w_handle); /* schliesslich geben wir dem rufenden Programm die Identifikationsnummer des Fensters zurück: */ return(w_handle); } void /* Berechnung der Arbeitsflaeche eines */ wind_calc_work(w_handle,x,y,w,h) /* Fensters */ WORD w_handle,x,y,w,h; { wind_calc(WC_WORK,windows[w_handle].elements, x,y,w,h,&windows[w_handle].work.g_x, &windows[w_handle].work.g_y, &windows[w_handle].work.g_w, &windows[w_handle].work.g_h); } WORD rc_equal(p1,p2) { } void handle_full(w_hndl) { ... if (rc_equal(&curr, &full)) { ... wind_set(w_hndl,WF_CURRXYWH,prev.g_x,prev.g_y,prev.g_w,prev.g_h); windows[w_hndl].full = FALSE; wind_calc_work(w_hndl,prev.g_x,prev.g_y,prev.g_w,prev.g_h); } else { ... wind_set(w_hndl,WF_CURRXYWH,full.g_x,full.g_y,full.g_w,full.g_h); windows[w_hndl].full = TRUE; wind_calc_work(w_hndl,full.g_x,full.g_y,full.g_w,full.g_h); } } void snap(w1,w2) { } WORD align(k,n) { } void /* zeichnet ganzes Fenster neu */ full_redraw(w_handle) WORD w_handle; { clear_window(w_handle); (*windows[w_handle].w_redraw)(); } do_redraw(buffer) { } void /* Berechnen der Dokumentsposition */ wind_hslide(w_handle, newpos) /* -> horizontal */ WORD w_handle,newpos; { windows[w_handle].doc_x = newpos * (windows[w_handle].doc_width - windows[w_handle].work.g_w) / 1000; wind_set(w_handle,WF_HSLIDE,newpos,0,0,0); } void wind vslide(w_handle,newpos) /* -> vertikal */ WORD w_handle,newpos; { windows[w_handle].doc_y = newpos * (windows[w_handle].doc_length - windows[w_handle].work.g_h) / 1000; wind_set(w_handle,WF_VSLIDE,newpos,0,0,0); } void /* Slidermanager */ scroll_wind(w_handle,what) WORD w_handle, what; { switch(what) { case W_UPPAGE : windows[w_handle].doc_y — windows[w_handle].work.g_h + windows[w_handle].scroll_y; if(windows[w_handle].doc_y<0) windows[w_handle].doc_y =0; break; case W_DNPAGE : windows[w_handle].doc_y += windows[w_handle].work.g_h - windows[w_handle].scroll_y; if(windows[w_handle].doc_y > windows[w_handle].doc_length) windows[w_handle].doc_y = windows[w_handle).doc_length; break; case W_UPLINE : windows[w_handle].doc_y -= windows[w_handle].scroll_y; if(windows[w_handle].doc_y<0) windows[w_handle].doc_y = 0; break; case W_DNLINE : windows[w_handle].doc_y += windows[w_handle].scroll_y; if(windows[w_handle].doc_y > windows[w_handle].doc_length) windows[w_handle].doc_y = windows [w_handle].doc_length; break; case W_LFPAGE : windows[w_handle].doc_x -= windows[w_handle].work.g_w + windows[w_handle].scroll_x; if(windows[w_handle].doc_x<0) windows[w_handle].doc_x = 0; break; case W_RTPAGE : windows[w_handle].doc_x += windows[w_handle].work.g_w - windows[w_handle].scroll_x; if(windows[w_handle].doc_x > windows[w_handle].doc_width) windows[w_handle].doc_x - windows[w_handle],doc_width; break; case W_LFLINE : windows[w_handle].doc_x -= windows[w_handle].scroll_x; if(windows[w_handle].doc_x<0) windows[w_handle].doc_x =0; break; case W_RTLINE : windows[w_handle].doc_x += windows[w_handle].scroll_x; if(windows[w_handle].doc_x > windows[w_handle].doc_width) windows [w_handle].doc_x = windows[w_handle].doc_width; break; } set_slider_pos(w_handle); } void /* allg. Fensterverwaltung */ handle_window(buffer) { switch(buffer[0]) { ... case WM_FULLED : handle_full(buffer[3]); set_slider_size(buffer[3]); break; case WM_ARROWED : scroll_wind(buffer[3],buffer[4]); full_redraw(buffer[3]); break; case WM_HSLID : wind_hslide(buffer[3],buffer[4]); full_redraw(buffer[3]); break; case WM_VSLID : wind_vslide(buffer[3],buffer[4]); full_redraw(buffer[3]); break; case WM_SIZED : case WM_MOVED : ... wind_calc_work(buffer[3],buffer[4],buffer[5],buffer[6],buffer[7]); set_slider_size(buffer[3]); break; ... } }

/* Demonstrationsprogramm zum Snappen */ /* von Windows */ /* Andreas Loetscher 1988 */ /* Compiler Lattice-C 3.04 */ /**************************************/ #include <a:\headers\portab.h> #include <c:\listing1.h> extern WORD handle; extern WIND_DATA windows[]; WORD w_handle; char *text[] = {"Dies soll ein Beispieltext sein", "der die Funktion der Slder,", "und der Rollpfeile demonstrieren", "soll.", "", "Sie koennen ihn beliebig umherschieben...", "", "Die Geschwindigkeit der Textausgabe ist", "nicht gerade grossartig, aber das ganze", "ist auch noch nicht optimiert..." }; void output() { WORD x,y,i; x = windows[w_handle].doc_x + windows[w_handle].work.g_x; y = windows[w_handle].doc_y + windows[w_handle].work.g_y+16; for (i=0; i<10; i++,y += 16) v_justified(handle,x,y,text[i],200,0,0); } void main() { WORD buffer[8]; gem_init(); graf_mouse(0,0); w_handle= open_window("Demofenster", output, NAME+CLOSER+MOVER+ SIZER+FULLER+ UPARROW+DNARROW+ VSLIDE+HSLIDE+ LFARROW+RTARROW, 8,TRUE, 8,16, 800,640, 40,30,220,290, 16,35,608,349); do { evnt_mesag(buffer); handle_window(buffer); }while(buffer[0] != WM_CLOSED); wind_delete(w_handle); gem_exit(); }

Andreas Lötscher
Links

Copyright-Bestimmungen: siehe Über diese Seite
Classic Computer Magazines
[ Join Now | Ring Hub | Random | << Prev | Next >> ]