Obligement - L'Amiga au maximum

Mercredi 13 décembre 2017 - 04:19  

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


Contact

David Brunet

Courriel

 


Programmation : MUI - communication, notification
(Article écrit par Mathias Parnaudeau - juillet 2004)


Chapitre 2

Ce chapitre réutilise bien sûr les bases du chapitre 1 et porte plus précisément sur l'interaction entre les composants. Toujours dans l'optique de notre lecteur de CD, nous lui attribuerons un bouton "Play" et un autre "Stop", les deux agissant sur un objet graphique Busy appartenant à une classe externe. Cet objet dynamique symbolisera la lecture d'un morceau en cours ; il se figera lors d'un clic sur Stop.

La bibliothèque Busy.mcc, et ses includes, peut être récupérée sur : mui.zerohero.se/mcc/MCC_Busy.lha.

Complément

L'organisation du programme a légèrement changé. Les bibliothèques sont cette fois-ci ouvertes et fermées dans la fonction main. Mais l'intérêt porte sur la fonction CreateGui qui nous intéresse ; elle a changé en plusieurs points :

1. Les boutons sont créés différemment, avec l'appellation KeyButton ici, qui spécifie un raccourci clavier. D'autre part, ils sont affectés à une variable de type "Object *", c'est-à-dire un pointeur sur un composant MUI (objet BOOPSI en fait) alloué dynamiquement. On trouve parfois la notation "APTR" à la place, ce qui n'est pas une faute mais se trouve moins appropriée. La variable ainsi renseignée va permettre de communiquer avec le composant associé, comme c'était déjà le cas de la fenêtre (DoMethod() sur la variable window).

2. La description de l'interface présente une autre nouveauté : l'attribut MUIA_Application_UsedClasses. Mentionné dans le fichier MUIUndoc (voir sur Aminet), il n'est utilisé qu'à partir de MUI 3.9 : chaque classe externe est indiquée dans une liste de chaînes de caractères et fera que l'application ne fournira le panel des préférences que pour ces classes référencées. Voilà donc une bonne habitude à prendre. Comme cet attribut n'est pas défini dans les includes de bases, il doit être ajouté à la main au début du source (#define MUIA_Application_UsedClasses, etc.).

3. La classe Busy a l'avantage d'être vraiment simple ! On la construit de façon à ce qu'elle soit inactive au démarrage puis on change sa vitesse de défilement :
  • 20 (valeur arbitraire, vous pouvez en tester d'autres) lorsque l'on clique sur Play.
  • 0 (avec la valeur particulière MUIV_Busy_Speed_Off) quand on stoppe.
4. Il est possible d'associer une bulle d'aide à un composant grâce au simple attribut MUIA_ShortHelp, suivi de la chaîne de caractères à afficher après quelques secondes. Pour les boutons, à cause de la notation choisie, on ne peut leur ajouter un attribut. Nous verrons par la suite un nouveau moyen pour décrire un bouton de manière plus expansée.

5. Un dernier détail concerne la mise en forme du texte : pour montrer que ça existe, on utilise les defines MUIX_U et MUIX_N dans le TextObjet au lieu des codes \33u et \33n équivalents.

6. Après la construction de l'interface, nous nous trouvons en présence de la fonction SetAttrs(). Cette dernière agit comme la fonction set du chapitre 1 mais permet de passer plusieurs paramètres, donc de modifier plusieurs attributs d'un objet, avec l'appel d'une seule fonction.

Voilà à quoi ressemble désormais notre programme :

/*
 * DisKo2.c (05/06/04)
 *
 */

#include <stdio.h>
#include <libraries/mui.h>
#include <proto/intuition.h>
#include <proto/muimaster.h>
#include <proto/exec.h>
#include <clib/alib_protos.h>

#include <mui/Busy_mcc.h>

#define MAKE_ID(a,b,c,d)  ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))

struct Library *MUIMasterBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;

#ifdef __amigaos4__
struct IntuitionIFace *IIntuition;
struct MUIMasterIFace *IMUIMaster;
#endif

#define	MUIA_Application_UsedClasses	0x8042e9a7	/* V20 STRPTR *	i..	*/

static STRPTR ClassList[] =
{
      "Busy.mcc",
      NULL
};

void CreateGui(void)
{
      Object *app = NULL;
      Object *window = NULL;
      Object *bt_play, *bt_stop;
      Object *busy;

      /* Description de l'interface et de ses propriétés */	

      app = (Object *)ApplicationObject,
            MUIA_Application_Author, "corto@guru-meditation.net",
            MUIA_Application_Base, "DISKO",
            MUIA_Application_Title, "MUI - Exemple 2",
            MUIA_Application_Version, "$VER: Exemple2 1.00 (21/01/03)",
            MUIA_Application_Copyright, "Mathias PARNAUDEAU",
            MUIA_Application_Description, "Interface MUI avec texte et boutons",
            MUIA_Application_HelpFile, NULL,
            MUIA_Application_UsedClasses, ClassList,

        SubWindow, window = WindowObject,
                        MUIA_Window_Title, "Exemple 2",
            MUIA_Window_ID, MAKE_ID('W', 'I', 'N', '1'),
            WindowContents, VGroup,

                              Child, TextObject,
                                    TextFrame,
                                    MUIA_Background, MUII_TextBack,
                                    MUIA_Text_Contents, "\33c A nouveau notre composant texte qui nous revient de l'exemple précédent\n" \
"Et ci-dessous le nouveau composant de "MUIX_U"classe Busy"MUIX_N" dont on va tester la dynamique",
                                    MUIA_ShortHelp, "Texte explicatif, montre le fonctionnement d'une bulle d'aide",
                              End,

                              /* Utilisation d'un groupe horizontal pourvu de boutons */
                              Child, HGroup,
                                    Child, bt_play = KeyButton("Play", 'p'),
                                    Child, bt_stop = KeyButton("Stop", 's'),
                              End,

                              Child, busy = BusyObject,
                                    MUIA_Busy_Speed, MUIV_Busy_Speed_Off,
                              End,
                        End,
        End,
    End;

      /* On fixe quelques valeurs et notifications */
      
      DoMethod(window,
            MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
            app, 2,
            MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);

      set(bt_stop, MUIA_Disabled, TRUE);

      DoMethod(busy, MUIM_Busy_Move, FALSE);

      DoMethod(bt_play, MUIM_Notify, MUIA_Pressed, FALSE,
         bt_stop, 3, MUIM_Set, MUIA_Disabled, FALSE);
      DoMethod(bt_play, MUIM_Notify, MUIA_Pressed, FALSE,
         bt_play, 3, MUIM_Set, MUIA_Disabled, TRUE);

      DoMethod(bt_stop, MUIM_Notify, MUIA_Pressed, FALSE,
         bt_play, 3, MUIM_Set, MUIA_Disabled, FALSE);
      DoMethod(bt_stop, MUIM_Notify, MUIA_Pressed, FALSE,
         bt_stop, 3, MUIM_Set, MUIA_Disabled, TRUE);

      /* MUIV_ représente une valeur spéciale d'un attribut, ici il annule la vitesse */

      DoMethod(bt_play, MUIM_Notify, MUIA_Pressed, FALSE,
                              busy, 3, MUIM_Set, MUIA_Busy_Speed, 20);
      DoMethod(bt_stop, MUIM_Notify, MUIA_Pressed, FALSE,
                              busy, 3, MUIM_Set, MUIA_Busy_Speed, MUIV_Busy_Speed_Off);

      SetAttrs(window, MUIA_Window_Open, TRUE, TAG_END);

      /* Boucle de gestion des événements, toujours la même */
      {
            ULONG sigs = 0;

            while (DoMethod(app,MUIM_Application_NewInput,&sigs) != MUIV_Application_ReturnID_Quit)
            {
                  if (sigs)
                  {
                        sigs = Wait(sigs | SIGBREAKF_CTRL_C);
                        if (sigs & SIGBREAKF_CTRL_C) break;
                  }
            }
      }

      set(window, MUIA_Window_Open, FALSE);

      /* Libération des ressources et fermeture */
      MUI_DisposeObject(app);
}

/*
 * Initialisation et vérification de tout ce qui est nécessaire à la bonne exécution
 * de l'application : ouverture des bibliothèques, test de présence des classes MCC, ...
 */
int Initialize(void)
{
      int res = 1;
      Object *busy = NULL;

      IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39L);
      MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN);

      if (IntuitionBase == NULL){
            printf("Impossible d'ouvrir 'intuition.library' V39\n");
            res = 0;
      }
      if (MUIMasterBase == NULL){
            printf("Impossible d'ouvrir '%s' V%d\n", MUIMASTER_NAME, MUIMASTER_VMIN);
            res = 0;
      }

#ifdef __amigaos4__
      IIntuition = (struct IntuitionIFace *)GetInterface((struct Library *)IntuitionBase, "main", 1, NULL);
      if (!IIntuition){
            printf("Impossible d'obtenir l'interface IIntuition\n");
            res = 0;
      }

      IMUIMaster = (struct MUIMasterIFace *)GetInterface(MUIMasterBase, "main", 1, NULL);
      if (!IMUIMaster){
            printf("Impossible d'obtenir l'interface IMUIMaster\n");
            res = 0;
      }
#endif

      busy = BusyObject, End;
      if (busy == NULL){
            printf("Classe Busy manquante\n");
            res = 0;
      }
      MUI_DisposeObject(busy);

      return res;
}


/*
 * Fermeture et libération de tout ce qui a été initialisé au démarrage.
 */
void DeInitialize(void)
{
#ifdef __amigaos4__
      if (IMUIMaster) {
            DropInterface((struct Interface *)IMUIMaster);
      }
      if (IIntuition) {
            DropInterface((struct Interface *)IIntuition);
      }
#endif
      CloseLibrary(MUIMasterBase);
      CloseLibrary((struct Library *)IntuitionBase);
}


int main(int argc, char **argv)
{

      if(Initialize()){
            CreateGui();
      }
      DeInitialize();

      return 0;
}

Les notifications

Une notification permet d'indiquer à un objet quoi faire quand il lui arrive quelque chose, c'est aussi simple que ça ! Par exemple, pour que l'application reçoive un événement de fin lorsque l'on clique sur le bouton de fermeture de la fenêtre, on utilise la fonction à tout faire DoMethod() comme ceci :

DoMethod(window, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
app, 2, MUIM_Application_ReturnID, UIV_Application_ReturnID_Quit);

Voici l'explication de chaque paramètre, dans l'ordre :
  • L'objet sur lequel on veut appeler une méthode, ici la fenêtre.
  • Le nom de la méthode, MUIM_Notify.
  • L'attribut qui déclenchera la notification lors du changement de sa valeur.
  • La valeur : ici on veut déclencher l'action lorsque l'attribut MUIA_Window_CloseRequest passe à TRUE, c'est-à-dire quand on clique sur le gadget de fermeture ou qu'on appuie sur la touche Escape.
  • L'objet cible sur lequel porte la notification.
  • Le nombre de paramètres qui restent à suivre.
  • La méthode que l'objet cible doit exécuter, ici l'affectation d'une valeur de retour à l'application.
  • Le paramètre passée à cette méthode.
Pour plus d'informations, réferrez-vous au fichier MUI_Notify.doc dans les autodocs de MUI. Mais le principe est là, applicable à nos composants :

DoMethod(bt_play, MUIM_Notify, MUIA_Pressed, FALSE,
bt_stop, 3, MUIM_Set, MUIA_Disabled, FALSE);

Dans ce cas, on indique au bouton Play, quand il est sélectionné (plus précisément au moment où il est relâché) de griser le bouton Stop. On remarque toute la puissance des notifications ici. Il est ensuite inutile de gérer les événements dans un boucle. Les actions sont définies ainsi et il n'y a plus rien à faire !

Notions acquises dans ce chapitre
  • Notion de notification.
  • Interactions entre composants avec set()/SetAttrs() et DoMethod().
  • Utilisation d'une classe externe, à opposer aux classes de base dites "builtin".
  • Ajout de bulles d'aide.
  • Imbrication de groupes : un horizontal dans le groupe vertical principal.
  • Raccourcis clavier avec KeyButton.
  • Attribut MUIA_Application_UsedClasses.


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