Obligement - L'Amiga au maximum

Samedi 27 mai 2017 - 15:47  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Hit Parade
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles in other languages


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Moteurs de recherche
 · Pages de liens
 · Constructeurs matériels
 · Matériel
 · Autres sites de matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Développeurs logiciels
 · Logiciels
 · Développeurs de jeux
 · Jeux
 · Autres sites de jeux
 · Scène démo
 · Divers
 · Informatique générale


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Soutien

N'hésitez pas à soutenir le projet Obligement



Contact

David Brunet

Courriel

 


Programmation : C - les fenêtres
(Article écrit par Laurent Faillie et extrait d'Amiga News - novembre 1998)


C reparti !

Oups, certains des listings de l'article précédent ne se compilent pas avec DICE. Son éditeur de lien affichant :

DLINK: "" L:0 C:0 Error:34 Multiply defined symbol: _SysBase (amiga/c & T:Article)

Cela m'a échappé car je les ai compilés uniquement avec GCC qui permet ce genre d'excentricités.

En fait, il faut savoir que les compilateurs ouvrent d'eux-mêmes certaines bibliothèques, simplement car elles sont utilisées avant que notre main() ne soit appelé : c'est ce qu'on appelle le code de démarrage. Entre autres, c'est lui qui gère les arguments du programme.

Dans notre cas, SysBase est déjà utilisé, donc l'éditeur de liens crie car il est à la fois défini dans notre programme et dans son code de démarrage.

Bref, inutile de refaire ce qui a déjà été fait par le compilateur, donc toute la partie initialisation de SysBase est superflue, c'est pourquoi elle n'apparaît plus dans les listings de ce mois.

Attention, ce n'est pas toujours vrai car, en cherchant bien dans la documentation de votre compilateur, vous découvrirez que certaines options empêchent l'utilisation du code de démarrage, dans le but d'obtenir un exécutable de très petite taille. Dans ce cas, il ne faudra pas oublier d'initialiser SysBase sinon...

La dos.library fait aussi partie des bibliothèques qui sont forcément ouvertes pour nous.

Dans le même genre, certains compilateurs dont DICE n'apprécient pas la ligne...

char buff[longueur + 5]; /* Buffer de travail */

...du programme de notre Guru : ils n'admettent pas que la taille du tampon à allouer soit calculée lors de l'exécution.

La solution est donc d'y mettre une longueur constante, donc la ligne devient :

char buff[1024];

Note : il est évident que si l'utilisateur passe un message de plus de 1019 caractères, il sera trop grand pour être stocké, d'où un plantage assuré. Je vous laisse le soin d'ajouter le test qui convient...

Bon passons à l'article du jour

Qui dit environnement graphique, dit inévitablement fenêtre. On a vu dans le dernier article que certains compilateurs en ouvraient une automatiquement si le programme effectuait des sorties sur le flux de sortie standard, stdout, et s'il était lancé depuis le Workbench.

Aujourd'hui, nous allons voir comment créer nous-mêmes une fenêtre.

Tous les éléments graphiques de l'Amiga sont gérés par la fameuse "intuition.library", que nous avons déjà utilisée pour créer notre Guru personnel. C'est elle qui gère les écrans, les fenêtres, les alertes mais aussi les requêtes, et les boutons de toutes sortes.

Pour définir notre fenêtre, il faut initialiser une structure nommée NewWindow qui est définie par un :

#include <intuition/intuition.h>

Et dont voici les champs :

struct NewWindow {
	WORD LeftEdge, TopEdge;     /* Origine de la fenêtre */
	WORD Width, Height;         /* Sa taille initiale */

	UBYTE DetailPen, BlockPen;  /* Crayons (couleurs) utilisés */
	ULONG IDCMPFlags;           /* Événements attendus */
	ULONG Flags;                /* Drapeaux (on verra plus loin) */
	struct Gadget *FirstGadget; /* Boutons persos */

	struct Image *CheckMark;    /* Notre propre image pour les marques des menus */

	UBYTE *Title;               /* Titre de la fenêtre */
	struct Screen *Screen;      /* Sur quel écran elle s'ouvre */
	struct BitMap *BitMap;      /* Notre propre bitmap */

	WORD MinWidth, MinHeight;   /* Taille minimale */
	UWORD MaxWidth, MaxHeight;  /* Taille maximale */

	UWORD Type;                 /* Type de la fenêtre */
};

Comme dit l'adage, un petit exemple valant mieux qu'un long discours, voici un petit listing qui crée notre première fenêtre :

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>	/* Ces 3 là ne nous servent à rien mais évitent */
#include <exec/semaphores.h>	/* des erreurs à la compilation */
#include <exec/io.h>		/* dans exec_protos.h */
#include <clib/exec_protos.h>
#include <exec/types.h>
#include <clib/intuition_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>		/* Pour le sleep() */

	/*
	 *  On n'oublie pas les bonnes vieilles habitudes :
	 *  Faut faire le ménage
	 */
struct ExecBase         *SysBase;
struct IntuitionBase    *IntuitionBase=NULL;
struct Window           *ma_fenetre=NULL;

void fini(){
	if(ma_fenetre){
		CloseWindow(ma_fenetre);
		ma_fenetre = NULL;
	}

	if(IntuitionBase){
		CloseLibrary((struct Library *)IntuitionBase);
		IntuitionBase = NULL;
	}
}

	/*
	 *  Définition de la nouvelle fenêtre
	 */
struct NewWindow nouvelle_fenetre = {
		10,  50,        /* Origine de la fenêtre */
		200, 30,        /* Taille de la fenêtre */
		-1, -1,         /* Couleurs par défaut */
		0,              /* Aucun événement attendu */
		WFLG_NOCAREREFRESH, /* Le système gérera les rafraîchissements */
		NULL,           /* Y'a pas de gadget dans la fenêtre */
		NULL,           /* On utilise l'image standard */
		"Salut",        /* Titre de la fenêtre */
		NULL,           /* Elle apparaîtra sur l'écran par defaut */
		NULL,           /* Le système gère les bitmaps */
		50,50,400,500,  /* Taille minimale et maximale de la fenêtre */
		WBENCHSCREEN    /* C'est une fenêtre pour le Workbench */
};

int main(int ac, char **av){
	SysBase = *(struct ExecBase **)4;   /* Recherche d'exec */

	if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0))){
		puts("Impossible d'ouvrir intuition.");
		exit(EXIT_FAILURE);
	}
	atexit(fini);

	if(!(ma_fenetre = OpenWindow( &nouvelle_fenetre ))){
		puts("La fenêtre ne veut pas s'ouvrir.");
		exit(EXIT_FAILURE);
	}

	sleep(10);  /* La fenêtre restera ouverte 10 secondes */

	exit(EXIT_SUCCESS);	/* On laisse fini() fermer tout ce qui doit l'être */
}

Vous aurez bien sûr remarqué que ce programme doit se lancer depuis le Shell (bon, pour la dernière fois, je rappelle qu'il utilise des "puts()" pour afficher ses erreurs).

On remarque au début du listing, tout le bla-bla habituel, c'est-à-dire les includes qui définissent les bibliothèques et les structures utilisées, les variables globales pour stocker les pointeurs de ces mêmes bibliothèques et un autre pointeur sur la structure de la nouvelle fenêtre créée.

Attention : contrairement aux ressources allouées par les bibliothèques du compilateur, comme par exemple la mémoire d'un malloc(), les éléments du système ne sont jamais détruits automatiquement. Ainsi, si vous supprimez le atexit(), la fenêtre restera ouverte après que le programme a terminé son exécution. Ce n'est pas dangereux mais ça fait un peu désordre !

Au passage, on vient de découvrir une nouvelle fonction :

void Delay( ULONG ticks );

Elle fait partie de la dos.library et ne rend la main qu'une fois le délai indiqué passé. L'unité de ce délai est le ticks qui vaut 1/50e de seconde.

Les autodocs indique cette valeur mais je me demande si le ticks ne vaut pas 1/60e de seconde sur les machines NTSC...

Ici nous souhaitons une attente de 10 secondes donc l'argument vaut 10x50 = 500.

Pour créer des attentes certains programmeurs utilisent des boucles d'attente genre...

int i; for(i=0; i<32000; i++);

C'est à proscrire :
  • Déjà, ça dépend de la vitesse d'un processeur... Imaginez ce que donnerait une boucle d'une seconde calculée sur un 68060/50 MHz sur une machine à base de 68000. L'utilisateur a intérêt d'être patient ! Dans le passé, certains simulateurs de vols célèbres utilisaient ce genre de méthode basée sur la vitesse d'un 68000 des machines de l'époque. Avec les cartes à base de 68030/50 MHz, ils devenaient difficilement jouables, je n'ose même pas imaginer ce que ça donnerait sur un 68040 ou un 68060 !
  • C'est débile : le processeur tourne en rond pour rien, alors qu'il pourrait être utilisé pour un autre programme.
Delay() utilisant le timer.device, la durée d'attente est stable quel que soit le système utilisé et n'utilise pas du tout le processeur.

M'enfin, c'est bien, nous venons de créer une fenêtre de 200 par 30 pixels qui se ferme automatiquement après 10 secondes. Génial, non ?

C

Pour le moment, on laisse tomber la majorité des champs de la structure NewWindow qui seront abordés le moment venu (toujours des promesses, hein ?), en particulier le "IDCMPFlags" car la gestion des événements nécessite un (voire plusieurs) article(s) à elle seule.

Les drapeaux

Regardons par contre de plus près les "flags" (drapeaux) utilisables. Pour le moment, aucune modification ne nous est permise sur cette fenêtre : elle est là, ne bouge pas, ne peut être renommée et aucune action sur elle-même ne nous permet de la faire passer en avant ou en arrière-plan. Ce n'est pas vraiment vivant !

Pour que ce soit possible, il suffit d'indiquer au système d'ajouter ces propriétés grâce aux drapeaux suivants :
  • WFLG_DRAGBAR - il est possible de déplacer la fenêtre ; il y a un gadget de déplacement dans la barre supérieure de la fenêtre. Sous 1.x, il se matérialise par une barre de titre hachurée. A partir du 2.0, malheureusement ça n'a plus d'impact sur la représentation de la fenêtre.
  • WFLG_DEPTHGADGET - ajout d'un gadget de profondeur pour placer la fenêtre en avant/arrière-plan.
  • WFLG_SIZEGADGET - ajout d'un gadget permettant de changer de taille la fenêtre.
  • WFLG_SIZEBRIGHT et WFLG_SIZEBBOTTOM indiquent respectivement que ce gadget est pris sur le côté droit ou le bas de la fenêtre (ce qui crée une zone sur le côté en question qui ne fait pas partie de la surface utilisable de la fenêtre). Ces deux drapeaux peuvent être utilisés simultanément.
  • WFLG_CLOSEGADGET - ajoute un gadget de fermeture. Attention : contrairement aux précédents, c'est à vous de le gérer, le système l'ignore totalement. Nous le retrouverons avec la gestion des événements...
Il existe aussi d'autres drapeaux qui peuvent être mis dans ce champ :
  • WFLG_BACKDROP - cette fenêtre est une fenêtre de fond d'écran : elle ne contient pas de bord, de barre de titre ni de gadgets. C'est typiquement la fenêtre du Workbench du 1.3 ou la fenêtre qui contient l'image de fond du 2.0 ou supérieur. Attention : ce drapeau est plus important qu'il n'y paraît car il est _interdit_ de dessiner directement sur un écran, il faut utiliser ce type de fenêtre !
  • WFLG_BORDERLESS - la fenêtre n'aura pas de bordure. A partir du 2.0, pour que ça marche correctement, il ne faut pas que la fenêtre puisse être redimensionnée sinon des fantômes de bordures sont ajoutés automatiquement et l'effet n'est pas des plus beaux !
  • WFLG_ACTIVATE - si ce drapeau est mis, la fenêtre deviendra la fenêtre active dès son ouverture (pas besoin de cliquer dessus).
  • WFLG_GIMMEZEROZERO - normalement, l'origine de toutes les opérations graphiques est le coin supérieur gauche de la fenêtre. Ainsi, si vous dessinez aux coordonnées (5,5), il y a de fortes chances que vous altériez la barre de titre. Avec ce drapeau l'origine est déplacée au coin supérieur gauche de la zone de travail, ceci au prix d'un peu de temps processeur.
Il existe aussi les drapeaux indiquant le type de rafraîchissement à utiliser mais on en reparlera lors de la gestion des événements. Ce sont les drapeaux WFLG_NOCAREREFRESH, WFLG_SIMPLE_REFRESH, WFLG_SMART_REFRESH et WFLG_SUPER_BITMAP.
  • WFLG_REPORTMOUSE et WFLG_RMBTRAP - concernent aussi la gestion des événements, et plus particulièrement ceux de la souris.
  • WFLG_NW_EXTENDED - apparu avec le Workbench 2.0 (version 36 de la bibliothèque), ce drapeau indique que c'est une structure ExtNewWindow et qu'elle contient une liste de tags, que l'on découvrira plus loin lorsque l'on parlera de la programmation spécifique au 2.0 et supérieur. Pour le moment, on reste compatible avec tous les Kickstart.
  • WFLG_NEWLOOKMENUS - celui-là n'est disponible que depuis le 3.0 (version 39) et indique que les menus doivent prendre le "nouveau look".
Bon, on va rendre notre fenêtre un peu plus sympathique, en lui permettant de passer devant ou derrière les autres, de bouger et d'être redimensionnable, le tout en ne modifiant qu'une seule ligne : celle des drapeaux !

struct NewWindow nouvelle_fenetre = {
		10,  50,        /* Origine de la fenêtre */
		200, 30,        /* Taille de la fenêtre */
		-1, -1,         /* Couleurs par défaut */
		0,              /* Aucun événement attendu */
		WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_SIZEGADGET |
		WFLG_NOCAREREFRESH, /* Le système gérera les rafraîchissements */
		NULL,           /* Y'a pas de gadget dans la fenêtre */
		NULL,           /* On utilise l'image standard */
		"Salut",        /* Titre de la fenêtre */
		NULL,           /* Elle apparaîtra sur l'écran par defaut */
		NULL,           /* Le système gère les bitmaps */
		50,50,400,500,  /* Taille minimale et maximale de la fenêtre */
		WBENCHSCREEN    /* C'est une fenêtre pour le Workbench */
};

Pour ceux qui ne maîtrisent pas entièrement le C, je ferai remarquer que les drapeaux sont associés entre eux par des "OU", ou bit à bit. Certains programmeurs utilisent de simples additions mais cette pratique est à proscrire sinon un jour ou l'autre, vous aurez de mauvaises surprises...

La fenêtre correspondante est :
C

A vous de faire des expériences avec les autres drapeaux disponibles, à l'exception bien sûr de WFLG_NW_EXTENDED sinon gare au réveil du grand "méditeur". Les drapeaux ayant trait aux rafraîchissements et à la souris n'auront aucun effet visible car concernant la gestion des événements (mais je l'ai déjà dit, non ?).

Quelques considérations sur les tailles des fenêtres : si la fenêtre peut être redimensionnée, les champs MinWidth, MinHeight et MaxWidth, MaxHeight doivent être renseignés. Ils contiennent les tailles minimales et maximales de la fenêtre. Une valeur nulle indique qu'il faut prendre la taille définie par défaut comme valeur.

Ainsi, si MinHeight et MaxHeight sont nuls, il sera impossible de changer la hauteur de la fenêtre.

Attention : l'autodoc de OpenWindow() précise bien que "s'il n'y a aucune raison de limiter la taille d'une fenêtre, il ne faut pas le faire" (Lapalisse n'aurait pas dit mieux !).

C'est pourquoi, si un champ a la valeur ~0 (ou -1), la seule limite qu'aura à subir la fenêtre sera la taille physique de l'écran sur lequel elle se trouve.

A partir du 2.0, on peut faire mieux avec les tags

Le 2.0 n'a pas fait que chambouler l'aspect graphique du système, mais a aussi amené de nombreuses améliorations pour le programmeur. En particulier, les développeurs de Commodore ont ajouté une méthode plus souple que les structures pour spécifier les paramètres.

Au lieu de définir une structure, avec toute la lourdeur que ça implique, en particulier d'initialiser correctement les champs que nous n'utilisons pas, pourquoi ne pas spécifier uniquement les valeurs qui nous intéressent. Ainsi sont apparus les fameux tags.

Reprenons notre fenêtre, mais utilisons entièrement la méthode du 2.0.

Voici le nouveau listing :

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>	/* Ces 3 là ne nous servent à rien mais évitent */
#include <exec/semaphores.h>	/* des erreurs à la compilation */
#include <exec/io.h>		/* dans exec_protos.h */
#include <clib/exec_protos.h>
#include <exec/types.h>
#include <clib/intuition_protos.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>		/* Pour le sleep() */

	/*
	 *  On n'oublie pas les bonnes vieilles habitudes :
	 *  Faut faire le ménage
	 */
struct ExecBase         *SysBase;
struct IntuitionBase    *IntuitionBase=NULL;
struct Window           *ma_fenetre=NULL;

void fini(){
	if(ma_fenetre){
		CloseWindow(ma_fenetre);
		ma_fenetre = NULL;
	}

	if(IntuitionBase){
		CloseLibrary((struct Library *)IntuitionBase);
		IntuitionBase = NULL;
	}
}

int main(int ac, char **av){
	SysBase = *(struct ExecBase **)4;   /* Recherche d'exec */

	if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",36))){
		puts("Impossible d'ouvrir intuition.");
		exit(EXIT_FAILURE);
	}
	atexit(fini);

	if(!(ma_fenetre = OpenWindowTags( NULL,
		WA_Left, (Tag)10,
		WA_Top, (Tag)50,
		WA_Width, (Tag)200,
		WA_Height, (Tag)30,
		WA_Title, (Tag)"Salut",
		WA_NoCareRefresh, TRUE,
		TAG_DONE
	))){
		puts("La fenêtre ne veut pas s'ouvrir.");
		exit(EXIT_FAILURE);
	}

	sleep(10);  /* La fenêtre restera ouverte 10 secondes */

	exit(EXIT_SUCCESS); /* On laisse fini() fermer tout ce qui doit l'être */
}

Première remarque : ce coup-ci, on indique que l'on recherche l'intuition.library de version 36 ou supérieure, c'est-à-dire qu'il faut au moins que l'on soit sous 2.0.

Pour le 3.0, la version aurait été 39, et 40 pour le 3.1. Même si les fans des univers micro$oftiens soutiennent que c'est impossible, remarquez que ceci préserve de fait une compatibilité ascendante : comme on ne peut rechercher une version spécifique, toute évolution de la bibliothèque devra faire tourner les applications prévues pour une version antérieure. Ce n'est pas une option, c'est un postulat (c'est beau, non, comme phrase, hein ?).

Le meilleur, c'est que cela fonctionne très bien et que les problèmes d'incompatibilité lorsque l'on met à jour son système sont très rares. Hormis bien sûr les jeux et les démos, dans ma vie d'amigaïste (depuis 1988 tout de même), je n'ai eu que deux problèmes :
  • Lorsque j'ai installé un 68010 sur mon 1000. Certains programmes utilisent des instructions qui sont privilégiées sur le 68010 et ne fonctionnaient plus. Le plus célèbre est le fameux " Transformer ", le premier émulateur PC sur Amiga...
  • Lors de la migration de mon 1000 du 1.3 au 2.1. Du fait du changement dans l'attribution des couleurs et l'agrandissement des bordures, certaines applications devenaient ignobles (mais fonctionnaient toujours).
De quoi faire méditer les défenseurs de Windows, où la mise à jour de Word (par exemple) entraîne la mise à jour de DLL pour les liens OLE... qui ne fonctionneront plus avec d'autres applications. Mais bon, je m'éloigne du sujet !

Revenons à nos moutons, heu, à notre fenêtre

Nous utilisons une nouvelle fonction introduite par le 2.0, OpenWindowTags(). Le premier argument devrait être une structure NewWindow comme avec le 1.3. Comme elle nous est inutile, on n'en donne pas (simple non ; j'ai essayé de faire le parallèle avec mes impôts mais mon percepteur, sans doute un fan de M$, n'a pas vraiment apprécié !). Jetez un oeil dans le fichier intuition/intuition.h des includes système et vous y découvrirez que chaque champ de NewWindows a son équivalent sous forme de tag mais d'autres permettent aussi d'ajouter de nouvelles caractéristiques. En voici quelques-uns :
  • WA_ScreenTitle - lorsque la fenêtre est active, c'est la chaîne associée à ce tag qui est affichée dans la barre de titre de l'écran.
  • WA_AutoAdjust - à "TRUE", si la taille initiale de la fenêtre est supérieure à celle de l'écran, elle prendra la taille de ce dernier (si Minxxxx le permettent). Dans le cas contraire, elle ne s'ouvrira pas et provoquera une erreur.
  • WA_InnerWidth et WA_InnerHeight - au lieu de spécifier la taille de la fenêtre comme avec WA_Width et WA_Height, ces tags permettent d'indiquer la taille de la partie utile de la fenêtre.
  • WA_PubScreenName, WA_PubScreen et WA_PubScreenFallBack concernent les écrans publics et nous en reparlerons dans un article qui leur sera consacré.
  • WA_Zoom - en argument, on trouve un pointeur sur un tableau de 4 "WORD" qui contiennent la position et la taille de la fenêtre une fois zoomée, ce qui provoque l'ajout d'un bouton de zoom dans la barre de titre.
Il y en a d'autres (beaucoup d'autres) qui permettent de changer la représentation de la touche Amiga des menus, différentes formes de pointeurs et tout ce qui concerne l'implémentation de l'aide en ligne.

Et la portabilité ?

Problème, avec notre listing précédent, notre programme ne fonctionne plus sur les Amiga sous 1.3 ! Heureusement, à nouveau les concepteurs d'AmigaOS ont bien fait les choses puisqu'il existe une méthode permettant de générer un programme qui fonctionnera sous 1.x, mais qui en présence du 2.0 gagnera de nouvelles possibilités.

Voici le dernier listing :

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>	/* Ces 3 là ne nous servent à rien mais évitent */
#include <exec/semaphores.h>	/* des erreurs à la compilation */
#include <exec/io.h>		/* dans exec_protos.h */
#include <clib/exec_protos.h>
#include <exec/types.h>
#include <clib/intuition_protos.h>
#include <stdlib.h>
#include <stdio.h>

#ifndef __DCC__
#include  /* Pour le sleep() */
#endif

	/*
	 *  On n'oublie pas les bonnes vieilles habitudes :
	 *  Faut faire le ménage
	 */
struct ExecBase         *SysBase;
struct IntuitionBase    *IntuitionBase=NULL;
struct Window           *ma_fenetre=NULL;

	/*
	 *  Définition de la nouvelle fenêtre
	 */
WORD stockage_zoom[4] = { 20, 30, 50, 10 };

struct TagItem tags[] = {
	{ WA_Zoom, (Tag)&stockage_zoom },
	{ WA_ScreenTitle, (Tag) "Hô, c'est ma fenêtre qui est active !" },
	{ TAG_DONE, NULL }
};

struct ExtNewWindow nouvelle_fenetre = {
		10,  50,        /* Origine de la fenêtre */
		200, 30,        /* Taille de la fenêtre */
		-1, -1,         /* Couleurs par défaut */
		0,              /* Aucun événement attendu */
		WFLG_NW_EXTENDED |	/* C'est une structure étendue */
		WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_SIZEGADGET |
		WFLG_NOCAREREFRESH, /* Le système gérera les rafraîchissements */
		NULL,           /* Y'a pas de gadget dans la fenêtre */
		NULL,           /* On utilise l'image standard */
		"Salut",        /* Titre de la fenêtre */
		NULL,           /* Elle apparaîtra sur l'écran par defaut */
		NULL,           /* Le système gère les bitmaps */
		50,50,400,500,  /* Taille minimale et maximale de la fenêtre */
		WBENCHSCREEN,	/* C'est une fenêtre pour le Workbench */
	tags
};

void fini(){
	if(ma_fenetre){
		CloseWindow(ma_fenetre);
		ma_fenetre = NULL;
	}

	if(IntuitionBase){
		CloseLibrary((struct Library *)IntuitionBase);
		IntuitionBase = NULL;
	}
}

int main(int ac, char **av){
	SysBase = *(struct ExecBase **)4;   /* Recherche d'exec */

	if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0))){
		puts("Impossible d'ouvrir intuition.");
		exit(EXIT_FAILURE);
	}
	atexit(fini);

	if(!(ma_fenetre = OpenWindow( (struct NewWindow *)&nouvelle_fenetre ))){
		puts("La fenêtre ne veut pas s'ouvrir.");
		exit(EXIT_FAILURE);
	}

	sleep(30);  /* La fenêtre restera ouverte 10 secondes */

	exit(EXIT_SUCCESS); /* On laisse fini() fermer tout ce qui doit l'être */
}

Remarquez qu'à nouveau, nous ouvrons n'importe quelle version d'Intuition : ça marchera donc quel que soit la version du système, délire !
  • Sous 1.x, aucun changement, le système ne connaissant pas WFLG_NW_EXTENDED.
  • A partir du 2.0, c'est l'extase, la méga teuf, le must, le nec plus ultra : avec le même exécutable, la fenêtre a gagné un nouveau gadget, de zoom, qui permet de la réduire au maximum. Notez que la position et la taille de la fenêtre sont spécifiées par le contenu du tableau "stockage_zoom". Pour une application réelle, l'idéal aurait été de dimensionner cette fenêtre zoomée pour que n'apparaissent plus que le titre et le gadget permettant de la restaurer à sa taille originelle (on le fera sans doute un jour). En plus, dès que la fenêtre est active, le titre de l'écran change.
La portabilité : le mot de la fin

Il ne faut pas non plus être plus royaliste que le roi : la compatibilité ne doit être conservée que lorsque cela ne bride pas trop le programme. Par exemple, inutile de continuer à développer pour le 1.x des programmes de gestion du système (par exemple, lorsque l'on gère les éléments du DOS comme les assignations), car on perdrait tout l'intérêt du 2.0 qui nous facilite beaucoup les choses. C'est d'ailleurs la politique d'Amiga International qui ne soutient plus le 1.x. Par contre, sauf si des spécificités propres au 3.0 sont nécessaires comme les datatypes, la cible du développement devrait être le 2.0, avec les extensions nécessaires pour les nouveautés des 3.0 et 3.1.

L'utilisation de tags rend ce travail très trivial... C'est généralement la voie prise par les développeurs de DP Amiga (moi y compris).

Voilà, voilà, c'est tout pour aujourd'hui, la prochaine fois on attaque les choses sérieuses en parlant, enfin, de la gestion des évènements... à nous les boutons, gadgets et autres joyeusetés (eh ! allez chercher une serpillière, vous bavez !).

A nouveau, remercions mes correcteurs (Alain Liverneaux et Alexandre Stotzer) qui ont fait un travail éreintant pour sortir cet article de la nullité orthographique affligeante dans laquelle il était !


[Retour en haut] / [Retour aux articles] [Article précédent] / [Article suivant]