	La mise en oeuvre facile des Fentres de dialogue non modales.
				en Pure C, par  Jacques  Delavoix.

Mise  jour du 27/05/1996.

		Comme ce titre l'indique, ces routines, dont je viens de terminer
la mise au point, ont t tudies pour permettre une mise en oeuvre trs
faile des formulaires en fentres non bloquants, encore appels "fentres
de dialogue non modales", avec une architecture similaire (mais pas identique)
 celle employe lors de la mise en oeuvre de formulaires bloquants par
"form_do()".
		Il tait galement important d'viter une dispersion et un mlange
du code et aussi d'obtenir une bonne structuration de celui_ ci; le code
grant le fonctionnement des fentres de dialogue est ici indpendant du
code de gestion des fentres principales. Cette structuration offre en outre
l'avantage de faciliter la mise en oeuvre, la mise au point et le dboggage
des programmes.

		Il est important de noter que les routines fournies ici donnent 
une base pour la programmation des fentres de dialogue, mais que ce code 
peut tre modifi pour tre adapt aux besoins propres de chaque programmeur.
On peut galement utiliser ces routines pour la programmation d'un accessoire
ou d'un executable mixte ACC/APP.

	Quatre routines sont  la disposition des programmeurs pour la ges-
tion de ces fentres :
	- init_var() pour l'initialisation de chaque fentre.
	- open_dialog() pour ouvrir une fentre de dialogue.
	- close_dialog() pour la refermer.
	- windform_do() pour grer le dialogue actuellement actif, le coeur 
du dispositif, quivalent en gestion non bloquante  la fonction form_do().

		Pour la suite des explications, le terme de "routine utilisateur", 
servira  dsigner les fonctions ayant une action particulire dans votre
programme et qui vont utiliser les fentres de dialogue; par exemple une
fonction de Recherche et Remplacement ou tout simplement une routine affichant
la traditionnelle boite d'Informations du programme (baptise "informe()"
dans le programme d'exemple fourni).

Le principe de fonctionnement :

Voyons donc ce qui se passe dans le cas o l'on appele la boite "Informa-
tions" :

		Regardez tout d'abord dans la fonction "main()", aprs l'appel 
evnt_multi(): on commence, dans un premier temps, par dcoder l'option de
menu correspondante et on appele la routine utilisateur "informe()".
Vous remarquerez que l'on transmet un paramtre baptis "OPEN_DIAL"  cette
routine. Ce paramtre, comme son nom le laisse supposer, indique  cette
routine que l'on demande l'ouverture du dialogue. Cette routine va donc
ouvrir la fentre d'"Informations" puis va retourner dans la boucle d'attente
des vnements.

		Maintenant un problme se pose, car il est ncssaire de retourner
dans cette routine  chaque fois que l'on reoit un vnement concernant
cette fentre de dialogue, (et donc pour grer le dialogue), comment faire ?

		En fait c'est simple: Il suffit, aprs le dcodage des options de 
menus, d'effectuer un aiguillage en fonction du Handle de fentre renvoy
par la fonction "evnt_multi()" et d'appeler  nouveau la routine utilisateur
concerne (et donc la routine "informe()" dans le cas prsent) mais cette fois
en lui transmettant la variable des flags d'vnements en paramtre.
		Etant donn que le paramtre "OPEN_DIAL" emprunte le mme chemin,
sa valeur a t fixe suffisamment haute pour ne pas interfrer avec les flags
d'vnements. 

		Mais avant de faire ceci il reste quand mme un petit problme 
rgler: en effet, le handle de fentre renvoy dans le mot 3 du buffer de
message n'est valable que pour les vnements "Message"... 
		Et bien peu inporte car il suffit, au pralable, d'affecter un 
handle de fentre aux vnements qui en sont dpourvus :

	- Pour "MU_KEYBD" nous demandons le handle de la fentre qui se trouve
au premier plan.

	- Pour "MU_BUTTON" nous demandons, par "wind_find()", le handle de la
fentre qui se trouve sous la souris :

		Si le handle de Fentre est gal  zro, cela signifie que c'est le 
Bureau du programme qui se trouve concern et qu'il est possible alors,
le cas chant, d'aiguiller le programme vers un traitement des objets
ventuellements prsents sur ce bureau (non employ dans l'exemple fourni).

Les Variables :

		Pour pouvoir faire fonctionner les fentres de dialogue, un certain
nombre de variables s'avrent ncssaires: L'adresse du formulaire, le Handle
de la fentre et les coordonnes de celle-ci ainsi que deux variables
ncssaires  la gestion des champs de texte ditables.
		Ces variables, qui sont personnelles  chaque fentre, ont t 
regroupes dans une structure de type "WINDFORM_VAR".
		L'adresse de la structure concerne sera transmise par la routine
utilisateur aux fonctions de gestion du dialogue (voir le fichier "WINDFORM.H").
Il faudra donc prvoir une structure "WINDFORM_VAR" (et bien videmment une
routine utilisateur) pour chaque fentre de dialogue que l'on compte utiliser.

La Routine "Utilisateur" :

		Pour que le fonctionnement soit possible cette routine doit tre conue
selon un shmas particulier, d'une manire similaire  ce que l'on ferait pour
une gestion bloquante par "form_do()", et dont voici le principe :

Routine utilisateur (vnements)
	Si vnements == OPEN_DIAL
		/* Initialisations ventuelles (champs ditables et/ou radio_buttons) */
		Alors Ouverture du dialogue
	sinon Choix = Gestion du dialogue
		Si Choix diffrent de Zro	/* si Choix == 0 le dialogue n'est pas
										termin. */
			Alors Fermeture possible du dialogue
			Si Choix == CLOSE_DIAL  /* La case de fermeture a t clique. */
				Choix = ANNULER		/* C'est  vous de le dcider ! */
			fin Si
			Si Choix diffrent de ANNULER
				Alors action demande
			fin Si
		fin Si
	fin Si
Retour

Voyons donc ce qui se passe dans le cas de la procdure "color_window()":

		Si cette routine reoit le paramtre "OPEN_DIAL": aprs avoir vrifi
que la fentre n'est pas dj ouverte, nous initialisons l'unique champ de
texte ditable prsent dans cette boite, (notez que dans la boite "Client"
les champs de texte ne sont initialiss que lors du dmarrage du programme
(c'est suivant ce que vous voulez faire)), puis nous appellons la procdure
d'ouverture.
		Sinon le paramtre reu est un vnement, et nous appellons la fonction
de gestion du dialogue "windform_do()"; au retour de cette fonction, nous
commenons par tester si le dialogue est termin:
 
		Dans ce cas la valeur renvoye (rcupre dans la variable "choix")
est diffrente de zro et le reste du traitement est identique  celui que
l'on aurait eu dans le cas d'une gestion par "form_do()", except la prise
en compte de la valeur "CLOSE_DIAL" indiquant un Clic sur la case de fermeture
de la fentre, normalement considre comme quivalente  "ANNULER", comme
c'est le cas dans l'exemple fourni, mais vous pouvez bien entendu en dcider
autrement.
		Sinon, la valeur renvoye par "windform_do()" est gale  zro, 
et dans ce cas le dialogue doit continuer.

		Observez attentivement les routines "informe()", "fiche_client()"
et "color_window()" dans le programme et comparez les avec le modle que
je viens de dcrire.

	NOTE : Remarquez le bouton 'noir' dans la boite "Couleur Fentre" qui
a t dclar "DISABLED".


Les quatre routines principales :

		Ces quatre routines reoivent toutes l'adresse de la structure 
WINDFORM_VAR concerne en premier paramtre. Leurs prototypes se trouvent
dans le fichier "WINDFORM.H" ainsi que les diffrentes dfinitions utilises
par les routines "WINDFORM".

La routine d'initialisation :

		Cette routine doit tre appele durant la phase d'initialisation 
du programme pour chaque fentre de dialogue. Le deuxime paramtre est
l'index du formulaire dans le fichier ressource, donn par le fichier header
associ (.H). Les deux paramtres "inf_x" et "inf_y" sont prvus pour tre
utiliss en conjonction avec la lecture d'un fichier ".INF" o pourront tre
sauvegardes les coordonnes initiales X et Y de chaque fentre (sauvegarde
des prfrences). Si ces deux paramtres sont  zro, la fentre sera centre
 l'cran.
		Cette routine permet maintenant un recadrage automatique de la fentre
de dialogue, si les donnes fournies par "inf_x" et "inf_y" tendent  faire
sortir le formulaire de l'cran.

	Voir la procdure "init_prog()" dans le programme d'exemple "WINFDEMO.PRG".

La routine d'ouverture :

		Cette routine assure l'ouverture de la fentre de dialogue. Les deux
autres paramtres  passer sont un pointeur sur le titre de la fentre et
l'index de l'objet texte ditable o doit apparaitre le curseur d'dition
(ou '0' sinon).

La routine de fermeture :

	Fermeture de la fentre de dialogue concerne.

La routine de gestion du dialogue :

		Voici enfin cette fameuse routine ! Le deuxime paramtre est 
constitu des flags d'vnement retransmis par la routine utilisateur 
appelante. La valeur retourne est soit :

	- Zro : Le dialogue n'est pas termin.
	- CLOSE_DIAL  : Valeur -1, la case de fermeture de la fentre a t 
clique.
	- Une valeur Positive : Dans ce cas l'utilisateur a actionn un bouton 
de sortie et cette valeur en reprsente l'index.

La Mise en Oeuvre :

	Elle doit tre faite de la faon suivante, en vous inspirant du programme
d'exemple fourni :

	1, Dclarez une structure WINDFORM_VAR pour chaque fentre de dialogue
que vous dsirez mettre dans votre programme, et en lui donnant un nom
explicite.

	2, Si ce n'est dj fait, structurez le traitement des vnements,
effectu aussitt aprs le retour de l'appel evnt_multi(), en traitant d'abord
les options de Menu, puis en affectant un Handle de fentre aux vnements
voulus et en effectuant ensuite des aiguillages sur vos procdures
"utilisateur" en fonction de ce Handle. Je laisse  votre initiative le
traitement d'autres vnements comme par exemple l' vnement MU_TIMER, utile
si vous voulez grer un ou plusieurs phnomnes priodiques (par ex.:
sauvegarde automatique du document actif toute les n secondes et/ou un
curseur clignotant, etc...), 
mais ne l'utilisez pas, comme je l'ai dj vu faire, uniquement pour que
"l'AES rende la main", ce qui est inutile si le programme n'a rien  faire.

	3, Lors de l'initialisation du programme, effectuez un appel  init_var()
pour chaque fentre de dialogue, en passant en paramtres : L'adresse de la
structure concerne, l'Indice du formulaire concern et ventuellement les
coordonnes X et Y de dpart (pouvant provenir de la lecture d'un fichier INF).

	4,  Concevez vos fonctions "utilisateurs" conformment  ce qui a t
dcrit plus haut.

Les Formulaires :

		Ils seront dits de la mme faon que pour une mise en oeuvre
classique avec des radio_buttons, champs de texte ditables, icnes couleurs,
boutons de sortie et un bouton par dfaut ventuel. 
Libre  vous de mettre en oeuvre les menus POP_UP du FALCON , les USERDEFS
et autres...
		Notez que l'paisseur du cadre du formulaire doit tre au moins gal
 2 pour les boites en 3D, il est galement possible de lui donner une
paisseur de 3 si l'on veut que ce cadre soit visible dans la fentre.

Les extensions :

		WINDFORM_DO permet des commandes tendues, tout d'abord pour les
champs ditables, avec le positionnement du curseur en dbut ou en fin de champ
par les touches "Control" + les touches  curseur gauche et droite, sauter
un mot par la touche "Shift" + ces mme touches curseur et positionner le
curseur sur une lettre avec la souris ainsi que le fait de dplacer ce curseur
dans le champ en maintenant le bouton de la souris enfonc.

		Une possibilit nouvelle est apparue depuis le mois d'Aout 1995 :
les fentres comportent maintenant une case "FULLER" qui permet de rduire
la fentre  sa seule barre de titre, cette commande agit en bascule, c'est
 dire qu'un second clic sur la case Plein cran permet de retrouver
l'intgralit de la fentre de dialogue. 
Une fentre "Rduite" ne peut bien sur pas recevoir de commandes. 
Adjonction due  Rmi VANEL .

Les Raccourcis clavier :

		Ils sont traits pour les Boutons dont l'OB_TYPE tendu comporte la
valeur 18 (BIT '1' DE L'OB_TYPE ETENDU) et la lettre concerne doit tre
prcde du symbole "[" standard.
Dans ces conditions le dessin et le comportement de ces boutons est tout  fait
conforme aux boutons du GEM par le truchement de la routine USERDEF fournie
ici, avec l'affichage du raccourci par un soulignement.

		La documentation dveloppeur ATARI spcifie que les raccourcis clavier
pour les Menus Droulants doivent tre dclenchs par la touche "Control";
en consquence de ceci, il parait logique que la touche utilise pour le
dclenchement des raccourcis clavier dans les fentres de dialogue soit la
touche "Alternate" comme c'est le cas dans WINDFORM.
Ces dispositions permettent d'viter d'ventuels conflits dans la gestion des
raccourcis claviers entre les Menus et les Fentres de dialogue, et d'ailleurs,
depuis quelques temps, de nombreux programmes fonctionnent de cette manire.

		Les flags 3D du nouveau TOS sont galement pris en compte
(ob_flags 9 et ob_flags 10), seul l'tat SHADOWED n'est pas trait par la 
routine. J'ai cependant dot cette routine d'une possibilit supplmentaire,
accessible en donnant la valeur 22 au lieu de 18 pour l'OB_TYPE tendu, 
et qui affiche alors un "mini bouton" (dcrit un peu plus bas).

Les valeurs utilises :

		Afficher des raccourcis clavier dans des boutons transforms en
USERDEFS est une chose, en assurer la dtection dans la routine de gestion
en est une autre. On pourrait penser qu'il suffit de dtecter la valeur 18
pour dcider que le bouton puisse comporter un raccourci clavier, mais on se
retrouve alors limit  un seul type de bouton; rajouter des tests sur d'autres
valeurs est tout aussi limitatif, et de plus il faudrait encore dcider quelle
seraient les valeurs  employer.

		J'ai donc opt pour le systme suivant : La valeur 18, prconise par
INTERFACE pour les raccourcis clavier, positionne le bit Numro 1 de OB_TYPE
tendu (valeur 2), la dtection des raccourcis clavier se fera donc en testant
si ce bit est  1, ce qui nous laisse une belle brochette de valeurs pour les
routines de boutons avec raccourcis que nous pourrons implmenter.

Les "mini boutons" :

		Cette possibilit est accessible en donnant une valeur de 22  
l'OB_TYPE tendu au lieu de 18, on a alors accs  un bouton GEM de taille
rduite et dont le texte est affich avec la plus petite fonte systme
(fonte des Icnes de hauteur 4). Il sera par contre utile, dans ce cas, de
rduire la largeur du bouton lors de l'dition du ressource.

Les "boutons bistables" :

		Il ne s'agit pas d'une nouveaut, puisque cette possibilit a toujours
exist dans le GEM.
		WINDFORM permet maintenant l'affichage correct des raccourcis clavier
dans ce type de boutons.
		Un bouton de ce type est dfini lorsqu'il est dclar SELECTABLE et
ventuellement TOUCHEXIT et que les flags suivants : DEFAULT, EXIT, EDITABLE
et RBUTTON soient tous  zro.

		L'tat de ce bouton s'inverse  chaque fois que l'on clique dessus;
utile, par exemple, pour activer/dsactiver une ou plusieurs option(s)
individuellement. Si le bouton Bistable est dclar TOUCHEXIT, il provoquera
une sortie du dialogue (c'est  dire que son index sera retourn)  chaque
sollicitation de ce bouton, cette possibilit de sortie permet une action
immdiate de ce bouton Bistable.
	Voir l'exemple dans la boite 'Informations' de "WINFDEMO.PRG".

Les routines USERDEFS :

	-set_user() : Cette routine parcours le formulaire  la recherche des 
objets  transformer en USERDEFS et appelle, dans ce cas, la routine set_objc()
qui ralise cette transformation, en lui transmettant l'adresse de l'objet et
l'adresse de la routine de dessin  utiliser (under_button() ou d'autres
Routines ventuellement).
		Une particularit du TOS 4.02 fait que les flags 3D en ob_flag 9 et
ob_flag 10 ne sont pas directement utilisables avec des Ojets Userdefs;
ils sont donc automatiquement dplacs dans ob_flags 11 et ob_flags 12 si
ncssaire.
		Ces flags sont dfinis au dbut du fichier WINDFORM.C par 
USR_INDICATOR et USR_ACTIVATOR.

Les Accessoires :

		Le fichier ACC_FORM.C est un squelette pour la programmation d'un
accessoire (mixte ACC / APP) utilisant les routines WINDFORM.

		L'utilisation d'une allocation dynamique de mmoire tant dconseille
dans le cas d'un accessoire, il suffit alors de rserver un tableau de
structures USERBLK dont le nombre d'lments sera au moins gal au nombre de
boutons contenu dans le Ressource. La fonction set_objc() doit dans ce cas
tre modifie en consquence, une variable globale sera alors utilise,
comme compteur, pour indexer ce tableau d'USERBLKs et incrmnte aprs chaque
transformation en USERDEF (voir USER_ACC.TXT dans le dossier SOURCES).

Annexe :
		Le fichier "USAGE" est destin  l'utilisateur de votre programme et
est prvu pour tre incorpor dans le Manuel de celui_ci.

Les dfauts :

		Malgrs une tude approfondie, je n'ai pu viter un phnomne de
non_rapparition du curseur  d'dition dans certains cas, assez rares il est
vrai. Si cela se produit, il suffit d'activer une autre fentre puis de
ractiver la fentre de dialogue en cliquant dessus (ceci peut se produire si
une fentre  t dplace sur notre fentre de dialogue puis redplace
compltement en dehors de celle_ci, puis ferme, autant dire qu'il faut presque
le faire exprs).


Fonctions Annexes :

	int load_rsc( char *rsc_name, int wind_fail ) :

		Cette routine assure le chargement du Fichier Ressource (par 
rsrc_load() ) et la rcupration de l'adresse d'une chaine d'Alerte 
"Plus de Fentres", qui doit Obligatoirement tre place dans le Ressource,
pour la Fonction "open_dialog()". Les paramtres  passer sont :

	- Le nom du Fichier Ressource.
	- L'index de la chaine Libre d'Alerte "NO_WINDOW".
	La valeur retourne par cette fonction est celle renvoye par rsrc_load().
	Exemple :	load_rsc( "winfdemo.rsc", NO_WINDOW );

	char * rsrc_get_string( int index ) :
		Cette routine renvoie l'adresse d'une chaine libre place dans 
le ressource, et dont l'index est pass en paramtre. Cette fonction est
utilise par load_rsc().

	Ces deux fonctions ont t rajoutes de faon  faciliter la mise en 
oeuvre de chaines libres dans le fichier ressource, en vue de pouvoir 
facilement traduire son programme dans une autre Langue sans avoir 
recompiler (en mettant les chaines de caractres dans le Ressource).

	Voir les Fichiers WINFDEMO.C et ACC_FORM.C.

Double-clic sur Champ ditable :

	Il est maintenant possible de "Sortir du Dialogue" par un Double-clic sur 
un Champ ditable, il suffit que celui-ci ait galement son Flag EXIT 
positionn. Cette fonctionnalit est gnralement employe pour appeler le
Slecteur d'objets.

	A cette occasion, une nouvelle fonction a fait son apparition pour assurer
le redessin du Champ ditable actif dans lequel on vient de copier une chaine
(la fentre de dialogue tant toujours prsente  l'cran) :

	void redraw_editable(WINDFORM_VAR *ptr_var, index) ;

	- Le premier paramtre est bien sr un pointeur sur la structure
	WINDFORM_VAR concerne.
	- Le deuxime paramtre est l'index du Champ ditable  redessiner.

	Voir l'exemple dans la boite "Couleurs Fentre" et la Routine associe,
"color_window" dans le fichier WINFDEMO.C .

Nouvelle Fonctionnalits :

Les Userdefs :

	La fonction "set_user()" a t dporte dans le fichier USERDEFS.C dont 
l'inclusion dans le script de compilation est devenue Obligatoire, ceci pour
faciliter l'ajout des tests ncssaires,  chaque fois que l'on veut rajouter
un nouvel objet Userdef.
	Exemple dans la boite d'informations de WINFDEMO.C

	Deux nouveaux Userdefs ont fait leur apparition : Boutons Rond et Carrs,
voir les fichiers "USERDEFS.C" et "USERDEFS.H"  ce sujet.

Les Pop Up :

	Le fichier "POP_UP.C" contient les routines de gestion de Pop Up (origine
Claude Attard dans DEVGEM 4) adaptes  WINDFORM. 	Prototype :

	int pop_up(WINDFORM_VAR *ptr_var, int objc, int index)

	La fonction renvoie l'index de l'option de Pop Up choisie ou -1; le test
sur la valeur de retour de cette fonction doit avoir la forme suivante :

		if ((retour = pop_up(ptr_var, choix, INDEX_POP) > 0)  { /* Action */

	Le bouton d'appel doit, de Prfrence tre dclar SHADOWED, Non USERDEF,
et son champ de texte doit tre d'une longueur au moins gale  celle du champ
de texte le plus long des options Pop Up associes.
	Ce bouton pourra, avantageusement, tre dclar "TOUCHEXIT", mais la
combinaison "SELECTABLE" + "EXIT" peut galement tre utilise, bien qu'elle
soit beaucoup moins intressante dans la pratique.

	Voir l'exemple dans la boite "fiche_client" de WINFDEMO.C ainsi que le
fichier "POP_UP.C", l'usage de ce fichier reste facultatif (ne pas oublier le
Prototype de pop_up() dans votre programme.

Le Programme d'exemple :

	Ce programme est founi sous la forme de  plusieurs fichiers source :
	- WINDFORM.C : Contient les routines de gestion du dialogue ainsi 
que rc_intersect() et stdkey().
Ce fichier est  prvu pour tre incorpor directement dans un projet logiciel.
	 ATTENTION : Ce fichier utilise des variables externes dfinies dans 
le programme principal et il vous faudra mettre les noms des variables
concernes en concordance.

	- WINFDEMO.C : Le programme d'exemple proprement dit.
	ATTENTION : Vrifier dans votre fichier AES.H si la structure utilise par
votre version de PURE C se nomme _GemParBlk; Si elle se nomme _VDIParBlk ,
alors mettez en service la ligne de redfinition situe au dbut du fichier
WINDFORM.H.

	- WINDFORM.H contient les prototypes des fonctions et les dclarations
utilises pour la gestion des dialogues.

	- ACC_FORM.C : Squelette d'un accessoire utilisant les routines WINDFORM.


