Inhaltsverzeichnis:

1. Einfhrung
2. Beschreibung der Routinen
3. Tips fr die Programmierung
4. Bugs
5. Kontakte

1. Einfhrung

Die Routinen von WINDDIAL dienen zur Verwaltung von Dialogboxen in
normalen GEM-Fenstern. Jede Menge Leute werden jetzt schon wissen,
wozu das gut ist. Diese brauchen dann erst den nchsten Abschnitt
lesen. Warum also Dialoge in Fenstern? Die Darstellung irgendwelcher
Informationen (wie z.B. der Dialogbox) ist unter GEM nur in Fenstern
mglich, wenn man nicht alle anderen Aktivitten des Rechners
lahmlegen will oder mit dem berschreiben seiner Infos rechnen will.
Die normale form_do()-Routine mu daher mit einem wind_update()
geschtzt werden, die dem AES Schreiboperationen auf dem Bildschirm
untersagt. Dadurch geht die Kontrolle ber den Rechner sozusagen auf
die Dialogbox ber, andere Programme (oder Accessorys) knnen whrend
der Zeit der Dialogabarbeitung nichts unternehmen. Lt man das
wind_update() weg, mu man bei der erstbesten Gelegenheit damit
rechnen, da die Dialogbox bermalt wird. Auf einem normalen Atari
mag es durchaus akzeptabel sein, da erst die Dialogbox fertig
bearbeitet wird, unter MULTITOS, wenn mehrere Programme sichtbar
sind, ist das jedoch uerst unpraktisch.

Legt man nun den Dialog in ein Fenster, wird man vom AES informiert,
wenn die Informationen aufgefrischt werden mssen. Man kann also
getrost vorbergehend die Kontrolle abgeben und die Dialogbox kann
gnadenlos bermalt werden: wenn sie dann wieder gebraucht wird,
bekommt man ja die Nachricht, alles neu zu zeichnen.

Im XCONTROL.ACC von Atari wird es bereits so gemacht. Mit dem hier
vorgestellten Routinen kann jeder Programmierer fr seine Programme
Dialogboxen in Fenster legen und verwalten lassen.


2. Beschreibung der Routinen

WINDDIAL wurde so entwickelt, da mglichst wenig Aufwand bei der
Umgestaltung eigener Programme mit normalen Dialogboxen entsteht. Ich
glaube dennoch nicht, das dadurch unntig ineffektiv programmiert
wurde.

Es werden 3 Routinen angeboten, die 3 AES-Funktionsaufrufe ersetzen:

-   form_wind(...) kommt fr form_dial(FMD_START,...)
-   wind_do(...) kommt fr form_do(...)
-   form_wclose(...) kommt fr form_dial(FMD_FINISH,...)

Die Prototypen sind "winddial.h" angegeben. Eine wesentliche Rolle
spielt die Datenstruktur "wi_data", in der alle ntigen Informationen
ber das Fenster und den Objektbaum enthalten sind. Ein Zeiger auf
diese Struktur ersetzt bzw. erweitert den Zeiger auf den Objektbaum
bei den obigen Funktionsaufrufen.

/* struct zum Verwalten der Windows */

typedef struct
{
    unsigned drawed:    1;   /* Flag fr erstes Redraw */
    unsigned auto_top:  1;   /* andere Fenster toppen */
    unsigned ltmf:      1;   /* let 'em fly nutzen */
}
wi_flags;

drawed verhindert das doppelte Zeichnen der Dialogbox beim ersten
Aufruf (einmal durch den Nutzer und dann nach Eintreffen der Redraw-
Meldung), auto_top sorgt darr, da auch andere Fenster als das der
Dialogbox getopt werden (d.h. wenn eine WM_TOPPED-Message kommt, wird
im True-Fall das gemeldete Fenster als oberstes Fenster gesetzt. Das kann
Arbeit sparen, aber auch unerwnscht sein). ltmf schlielich steuert
die Nutzung von Let 'em fly.

typedef struct{
   int wi_handle; /* Window-Handle */
   OBJECT *obj;   /* Zugehriger Object-Baum */
   int *m,*n,*o,*p;  /* Clipping-Koordinaten */
   wi_flags flags;   /* Flags fr Fenster*/
}wi_data;


Kommen wir zur Beschreibung der Routinen:

/********************************************************
*             form_wind()                               *
*   initialisieren und zeichnen des Fensterrahmens      *
*   erste 5 Parameter: wie form_center                  *
*   wind :   Zeiger auf zu bearbeitende Window-Struktur *
*   title:  Titel des Fensters                          *
*   return:  im Fehlerfall !=0 , sonst 0                *
********************************************************/

int form_wind(OBJECT *ptr,int *center_x,int *center_y,
           int *center_w,int *center_h,
           wi_data *wind,char *title);

Die ersten 5 Parameter sollten direkt aus form_center bernommen
werden. Als nchstes folgt die Adresse einer wi_data-Struktur, die in
dieser Funktion ausgefllt wird. Und schlielich wird ein Zeiger auf
einen String bergeben, der als Titelzeile des Fensters dient. Kann
kein Fenster geffnet werden, wird eine normale Dialogbox geffnet,
die von wind_update() geklammert wird. Es wird hierzu form_do()
aufgerufen.

/************************************
*        form_wclose()              *
* Dialog beenden, Fenster schlieen *
* Parameter:                        *
* wind: Zeiger auf Fensterstruktur  *
************************************/

int form_wclose(wi_data *wind);

Ganz einfach schlieen des Fenstes mit der Dialogbox.

/*****************************************************************
*           form_do() in Fenstern: wind_do()                     *
*   Parameter:                                                   *
*   wind       : von form_wind() bearbeitetes wind-Objekt        *
*   start_field: Objektnummer, in dem sich der Textcursor zuerst *
*                 befinden soll                                  *
*   buf[8]      : Messagepuffer                                  *
*   return      : Nummer des angesprochenen Objektes oder        *
*                 -1 Nach Eintreffen einer Message               *
*****************************************************************/

/* aus dem Profibuch (form_do()), erweitert um Message-Handling */

int wind_do(wi_data *wind,int start_field,int *buf);

Hier war das meiste zu tun. wind_do() bernimmt die komplette
Verwaltung der Dialogbox einschlielich aller Redraws. Nach Rckkehr
aus dieser Routine, wenn ein Exit-Object angesprochen wurde, kann man
sicher sein, das die Box so aussieht, wie sie es soll. Der dritte
Parameter buf dient zur Abspeicherung der eingetroffenen Nachrichten.
Alle eingegangenen Nachrichten werden weitergemeldet, auch Redraws,
die schon abgearbeitet wurden. Ein Redraw innerhalb von wind_do()
bezieht sich immer nur auf den angegebenen Objektbaum (analog zu
CPX-Modulen). Die Nachricht WM_TOPPED fhrt in Abhngigkeit vom Flag
auto_top zum Toppen des angegeben Fensters. Der entsprechende
wind_set()-Aufruf braucht also vom Hauptprogramm nicht gettigt werden.
Wird wind_do() in Accessorys verwendet und das Dialogfenster ist gerade
nicht sichtbar, fhrt ein Anklicken des Accessory-Menintrages zu einem
Sichtbarmachen des Fensters.
Von T34 (Thomas Baade) wurde ein weiteres Feature eingebaut: In den Edit-
Feldern kann der Cursor mittels der Maus positioniert werden.

3. Tips fr die Programmierung

Ein Beispielprogramm sieht z.B. so aus

{
    ....
    int x,y,w,h,mesg_buf[8];
    int form;
    wi_data wind;
    form_center(tree,&x,&y,&w,&h);
    form_wind(tree,&x,&y,&w,&h,&wind," Titel ");
/*  war: form_dial(FMD_START,...) */
    form_dial(FMD_GROW,0,0,0,0,x,y,w,h);
    objc_draw(tree,0,8,x,y,w,h);
    form=wind_do(&wind,0,mesg_buf[8]);
    switch(form)
    {
        case -1: HandleMesg();
                 break;
                 ....
    }
    form_dial(FMD_SHRINK,0,0,0,0,x,y,w,h);
    form_wclose(&wind);
/*  war: form_dial(FMD_FINISH,...) */
    ...
}

Die Unterschiede sind sind also zunchst nicht umwerfend. Sie liegen
aber im Detail. Insbesondere mssen die Ergebnisse von wind_do()
erweitert betrachtet werden:
- darauf achten, da bei return: -1 (Message) kein Objekt versucht
  zu zeichnen (tree[-1] macht wohl kaum einen Sinn)
- wie auch bei form_do() wird ein Doppelklick durch setzen des
  obersten Bits im Returnwert gekennzeichnet. Also bei Bedarf ausmas-
  kieren (form&0x7fff). Dadurch wird natrlich die Messagekennung auch
  zu 0x7fff (statt -1).
- Es knnen natrlich auch Mens, andere Fenster ... angewhlt werden.
  Das sollte beachtet werden.
- Es knnen mehrere Dialoge parallel bearbeitet werden. (wenn vom Programm
  untersttzt)
- Die Fenster und damit die Dialoge knnen verschoben werden.
- Das Fenster hat einen Schlieknopf. Die Meldung WM_CLOSED sollte
  also ausgewertet werden.
- Bei Einsatz in Accessorys mu die Meldung AC_CLOSE unbedingt zum
  Schlieen des Fensters fhren.
- Fr die Behandlung der beiden obigen Meldungen schlage ich gleiche
  Behandlung wie bei CPX-Modulen vor: WM_CLOSED als Abbruch und
  AC_CLOSE als OK. (sofern es in dieser Art einen Sinn macht)

Ach so, wenn Let 'em fly installiert ist, wird dieses zur Auswertung
von Tastaturshortcuts genutzt (in Abhngigkeit vom Flag ltmf).

4. Bugs

Viele Fehler sind uns noch nicht aufgefallen. Aber in Zusammenarbeit mit
Let 'em fly gibt es einige (zwei) Probleme:

- Aus ungeklrten Grnden strzt der Rechner ab, wenn zwei wind_dials()
  aktiv sind und ein
    - Programm die Dialogbox schliet,
    - wind_update(BEG_MCTRL) macht,
    - dann die Fileselectbox aufruft,
    - ein wind_update(END_MCTRL) macht.

Wahrscheinlich im zweiten wind_update passiert der Absturz. Zum Probieren
am besten zweimal RENUMBER als Accessory laden und aus einem eine Datei
auswhlen.

- Wird der Dialog teilweise aus dem Bildschirm geschoben, werden die Unter-
  stricht von Let 'em fly mitten auf dem Schirm plaziert. Das liegt wahr-
  scheinlich daran, das in Let 'em fly kein VDI-Clipping gemacht wird.

Bei der Erstellung der winddials stand mir Let 'em fly Version 1.14 zur
Verfgung.

5. Kontakte

Fr Kommentare, Anfeindungen, Danksagungen, Tips e.t.c. bin ich im Mausnetz
unter

Jan Starzynski @ HRO

zu erreichen.

PS: Im Programm "RENUMBER.PRG" wird von diesen Dialogen Gebrauch gemacht.

