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
Aus: ST-Computer 10 / 1989, Seite 143

Links

Copyright-Bestimmungen: siehe Über diese Seite