VAR_EDIT (C)

Warum viele Dialogboxen für verschiedene Zwecke konstruieren, wenn eine einzige denselben Zweck erfüllt? Edit-Felder variabler Länge machen es möglich. Dabei benötigt man weniger Speicherplatz und muss sich mit weniger Feldnamen und Adressen belasten.

Stellen Sie sich ein Programm vor, in dem Sie dem Benutzer die Möglichkeit bieten wollen, über die Breite und Art der Edit-Felder einer Dialogbox frei zu entscheiden (z.B. Adimens Init). Denken Sie an ein Programm, in dem der Benutzer in unterschiedlichen Dialogboxen verschiedene Einträge ganz bestimmter Länge und Art machen soll; oder wollen Sie ein Programm erstellen, das Edit-Felder mit mehr als 40 Buchstaben benötigt - und nur so groß kann man sie mit dem Megamax RCS konstruieren dann kann Ihnen das folgende Listing bestimmt einige Anregungen bieten. Wir wollen das Problem durch Konstruktion eines einzigen Objektbaumes lösen, den man durch Modifikation während des Programmablaufs den jeweiligen Bedürfnissen anpaßt.

Vorarbeiten

Zum Studium der Objekt- und Tedinfostruktur verweise ich auf die in ST Computer bereits erschienenen Artikel sowie auf das Handbuch Ihres C-Compilers. Das hier gezeigte Programm wurde mit Megamax Laser C für hohe Auflösung erstellt.

Ich möchte hier nur die wichtigsten Punkte herausgreifen und kurz erläutern:

Zeilen 24-40: 14 Zeichenketten der Länge 80 einrichten und teilweise mit Text füllen.

Zeilen 42-48: In den letzten beiden Spalten des TEDINFO stehen te_txtlen und te_tmplen für die Längen der Textzeichenkette (z.B.: „Variable“) und des Maskentextes (z.B.: “Zeile 1:„). Diese Längen können natürlich nicht den Wert -2 annehmen. Da zur Initialisierung aber ein Eintrag benötigt wird, habe ich überall dort den sonst nicht benötigten Wert -2 als Platzhalter verwendet, wo während des Programmablaufs passende Werte einzuschreiben sind.

Zeilen 50-62: Hier wird der Objektbaum erstellt. Das Vaterobjekt, die Box also, soll ebenso wie die drei Edit-Felder von variabler Länge sein, weshalb vorerst für die Objektbreite in ob_width eine -2 steht. Alle in der Box liegenden Objekte sollen zentriert bzw. symmetrisch angeordnet werden, was veränderbare ob_x zur Folge haben kann (-2 in der viertletzten Spalte). Vergessen Sie nicht, das letzte Objekt mit LASTOB zu versehen. Bei der Steuerung des Schreib-Cursors für die Edit-Felder mittels der Pfeiltasten kommt es sonst zu einem Totalabsturz.

Das Rahmenprogramm

Zeile 73: Es werden Boxen unterschiedlicher Größe erzeugt.

Zeile 75: Soll das größte Kindobjekt n Buchstaben enthalten, benötigt man dazu 8*n Bildpunkte. Links und rechts lassen wir einen Rand von je 30 Punkten.

Zeilen 77-79: Die Buttons werden mit einem Abstand von je 10 Bildpunkten von der Mittelachse angeordnet.

Zeile 82: Der Boxtitel wird zusammengesetzt.

Zeilen 83-86: Zur Einrichtung des Boxtitels und der Edit-Felder wird die Funktion var_edit() aufgerufen, die auch die Adresse des später eventuell auszulesenden Eintrags zurückgibt. Zu übergeben sind dabei:

Zeilen 90-91: Aufruf der Dialogbox und Sprung zum Programmende, falls der Knopf mit Eintrag Ende selektiert wurde.

Zeilen 92-96: Cursor auf Home-Position bringen, Zeile jeweils vor dem Auslesen des Textes säubern.

Die Hauptsache

Zeilen 102-120:* Die Adresse des entsprechenden Objekts wird ermittelt und die Objektbreite bestimmt. Nach der Zentrierung und der Bestimmung der Tedinfoadresse des Objekts wird die Länge te_tmplen der Textmaske (nicht des Maskentextes) wegen des abschließenden Null-Bytes mit n+1 festgesetzt. Nach Bestimmung dieser Größenverhältnisse werden der Maskentext nach te_ptmplt kopiert und die restlichen Stellen mit aufgefüllt.

Zeilen 122-127: Für jedes '_'-Zeichen, das im Maskentext vorkommt, wird nun ein Validitätszeichen ab te_pvalid eingetragen und die Zeichenkette mit einem Null-Byte abgeschlossen. Die um 1 vergrößerte Länge des Strings wird in te_txtlen gespeichert.

Zeile 128: Schließlich kann ein vorläufiger Text (z.B.: „Variable“ oder „“) bei te_ptext eingeschrieben werden. Da strcpy() auf te_ptext zeigt, wird diese Adresse mit return zurückgegeben.

Zeilen 145 ff: Die vielfach verwendete Routine hndl_dial() ruft nach dem Zeichnen mittels form_dial() die Dialogbox auf, wobei der Cursor auf ein Edit-Feld Ihrer Wahl gesetzt werden kann (z.B: TXT_1). Ist kein Edit-Feld in der Box , muß stattdessen eine 0 übergeben werden.

Anregung

In ähnlicher Form lassen sich alle Arten von Objekten verändern, verschieben, verstecken oder mehrfach nutzen. Versuchen Sie doch zur Übung, eine Box mit einem Titel- und einem einzigen Edit-Feld zu entwerfen, in das Sie nacheinander bei jedem Aufruf etwas anderes eingeben können. Versuchen Sie es vielleicht mit einem Paßwort vorgegebener Länge, Ihrer Konto-Nummer und Ihrer Telefonnummer.

Achten Sie dabei auf den Maskentext und die Anzahl der einzugebenden Zeichen sowie auf Ihre Validität. Mit ein wenig Übung können Sie bald kompliziertere Dialogboxen zusammensetzen.

/*****************************************************************/ 
/* Var_edit erzeugt Dialogboxen mit Editfeldern variabler Laenge */
/* Erstellt mit Megamax LaserC                                   */
/* Wolfgang Heine, 8111 Urfeld                                   */
/* Juli 1990                                                     */
/*****************************************************************/ 
#include <obdefs.h> 
#include <gemdefs.h> 
#include <stdio.h>
#include <string.h>
#define TITEL   1
#define TXT_1   2
#define TXT_2   3
#define TXT_3   4
#define AUS     5
#define OK      6

int contrl[12], intin[128], intout[128], ptsin[128], ptsout[128];

char *var_edit();               /* Vorausdeklaration */

typedef char STRING[80];

STRING s[] =
    {
        "",     /* s[ 0] */
        "",     /* s[ 1] */
        "",     /* s[ 2] */
        "",     /* s[ 3] */
        "",     /* s[ 4] */
        "",     /* s[ 5] */
        "",     /* s[ 6] */
        "",     /* s[ 7] */
        "",     /* s[ 8] */
        "",     /* s[ 9] */
        "",     /* s[10] */
        "",     /* s[11] */
        "Ende", /* s[12] */
        "OK"    /* s[13] */
    };

TEDINFO ted[] =
    {
        s[ 0], s[ 1], s[ 2], 3, 6, 2, 0x1180, 0x0,-4, -2, -2,
        s[ 3], s[ 4], s[ 5], 3, 6, 0, 0x1180, 0x0,-1, -2, -2, 
        s[ 6], s[ 7], s[ 8], 3, 6, 0, 0x1180, 0x0,-1, -2, -2, 
        s[ 9], s[10], s[11], 3, 6, 0, 0x1180, 0x0,-1, -2, -2
    };

OBJECT baum[] -
    {
        -1, 1, 6, G_BOX, NONE, OUTLINED, 0x21100L, 0, 0, -2, 200,
        2, -1,-1, G_BOXTEXT, NONE, OUTLINED|SHADOWED,&ted[0], -2, 20, -2, 18,
        3, -1,-1, G_FTEXT, EDITABLE, NORMAL, &ted[1],-2, 60, -2, 18,
        4, -1,-1, G_FTEXT, EDITABLE, NORMAL, &ted[2],-2, 80, -2, 18,
        5, -1,-1, G_FTEXT, EDITABLE, NORMAL, &ted[3],-2, 100, -2, 18,
        6, -1,-1, G_BUTTON, SELECTABLE|EXIT|OUTLINED, NORMAL, s[12], -2, 130, 70, 20,
        0,-1,-1, G_BUTTON, SELECTABLE|EXIT|DEFAULT|LASTOB,
        NORMAL, s[13] , -2, 130, 70, 20
    };

/**********************************************/

main ()
{
char help[80];
    int n;              /* Buchstaben im Editfeldfeld */
    char *txtl_adr, *txt2_adr, *txt3_adr;
                        /* Adressen der Texte */

    appl_init();        /* Applikation anmelden */
    for ( n = 25; n< 85 ; n+= 10)
                        /* Verschiedene n probieren */
    {
        baum[0].ob_width = n*8+60; /* Breite des Vaterobjekts */

        baum[AUS].ob_x=baum[0].ob_width/2   /* Ende-Button und OK-Button */
            - 10-baum[AUS].ob_width;        /* symmetrisch zur Mitte */
        baum[OK].ob_x=baum[0].ob_width/2 + 10;  /* anordnen */

        /* 3 Editfelder der Laenge n einrichten und Texte eintragen */
        sprintf(help, " %s %d %s"," Editfelder mit",n, "Buchstaben "); 
        var_edit(baum, TITEL, strlen(help),"",help, "X");
        txt1_adr = var_edit(baum, TXT_1, 18, "Datum:__.___.19_","310790","9");
        txt2_adr = var_edit(baum, TXT_2, n,"Zeile 1: ","Edit-","X"); 
        txt3_adr = var_edit[baum, TXT_3, n,"Zeile 2: ","felder","X");

        /* Dialogfeld aufrufen, Prog. beenden, falls Ende-Button gedrueckt ist*/

        if ( hndl_dial(baum, TXT_1, 0,0,0,0) == AUS) break;
        printf("\033Y "); /* od. "\033Y%c%c",y+' ',x+' ' */
        printf("\033K%s\n",txt1_adr); /* Zeilen freimachen und aus- */
        printf("\033K%s\n",txt2_adr); /* gelesene Texte anschreiben */ 
        printf("\033K%s\n",txt3_adr); 
        puts("          Taste druecken!");
    }
    appl_exit();                        /* Programm beenden */
}

/*********************************************/ 
char *var_edit(tree, index, n, pt, tx, val)
OBJECT tree[);                      /* uebergebenes Objekt */
int index;                          /* Objektindex */
int n;                              /* Laenge des Editfeldes */
char *pt, *tx, *val;                /* Zeiger auf Maskentext u.Text */
{                                   /* und Validitätszeichen */
    register OBJECT *obj; 
    register TEDINFO *ted; 
    register char *s, *t;
    obj = (OBJECT*) &tree[index]; /* Adresse des Objekts im Baum */ 
    obj->ob_width = 8*n; /* Obj.breite = 8 * Buchst.zahl */ 
    obj->ob_x = (tree[0].ob_width
            /* Objekt zentrieren */ 
            - obj->ob_width)/2; 
    ted = (TEDINFO*) (obj->ob_spec);    /* Tedinfoadresse ermitteln */ 
    ted->te_tmplen = n + 1;
                                    /* Laenge der Textmaske */
                                    /* Nullbyte nicht vergessen */ 
    strcpy (s = ted->te_ptmplt, pt);
                                    /* Maskentext eintragen */ 
    while( strlen(ted->te_ptmplt) < n )
                                    /* Rest mit "_" auffuellen */
        strcat(ted->te_ptmplt, "_") ;

    t = ted->te_pvalid; /* Fuer jedes im "_" Maskentext */ 
    while(*s)           /* wird im Validitaetsstring das*/
        if (*s++ == '_')
                        /* in val uebergebene Zeichen */ 
            *t++ = *val;            /* eingetragen */
    *t= '\0';                       /* Mit Nullbyte abschliePen */
    ted->te_txtlen-strlen(ted->te_pvalid)+1;
                /* Textlaenge=Validlaenge+Nullb.*/ 
    return strcpy (ted->te_ptext, tx) ; /* Text eintragen und Adresse */ 
                /* zurueckmelden */
}

/**********************************************/

int hndl_dial (tree, cur, x, y, w, h)
                /* Dialogfeld aufrufen */ 
OBJECT tree[];         /* Baumadresse */
int cur; /* Wo soll der Cursor sitzen? */
int x, y, w, h;

{
    int xd, yd, wd, hd;
    int exit_objc;  /* Nummer d. Exit-Buttons */
    form_center (tree, &xd, &yd, &wd, &hd); /* Formular zentrieren */
    form_dial(FMD_START, x,y,w,h, xd,yd,wd,hd); /* Bildschirmbereich res. */ 
    form_dial(FMD_GROW, x,y,w,h, xd,yd,wd,hd);  /* Growbox */
    objc_draw(tree,ROOT,MAX_DEPTH, xd,yd,wd,hd); /* Dialogbox zeichnen */
    exit_objc = form_do(tree, cur ) & 0x7FFF;   /* Dialog abhandeln */
    form_dial(FMD_SHRINK, x,y,w,h, xd,yd,wd,hd);/* Shrinkbox */
    form_dial(FMD_FINISH, x,y,w,h, xd,yd,wd,hd);
                        /* Bildschirmbereich frei-*/ 
                        /* geben und Hintergrund */ 
                        /* herstellen */    
    objc_change(tree,exit_objc, 0, 0,0,639,399, NORMAL, 0);
    /* selektierten Knopf wiedr normal darstellen */ 
    return (exit_objc); /* Exitbutton melden */
}

Wolfgang Heine
Aus: ST-Computer 05 / 1991, Seite 89

Links

Copyright-Bestimmungen: siehe Über diese Seite