Obligement - L'Amiga au maximum

Mardi 23 mai 2017 - 16:40  

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 - programmation d'une interface MUI : interaction avec les objets / notifications
(Article écrit par Eric Totel et extrait d'Amiga News - décembre 1995)


Dans cet article, nous allons explorer la notion de notification, c'est-à-dire de lien événementiel entre deux objets. Le but de ces liens est de connecter l'arrivée d'un événement provoqué par l'utilisateur à une action. Cette action peut alors être de plusieurs types :
  • Modification d'un attribut d'un autre objet.
  • Interaction avec votre programme qui peut pendre deux formes :
    • Appel d'une fonction.
    • Envoi d'un identificateur à la boucle IDCMP.
La construction d'une notification s'effectue en appliquant une méthode Notify sur l'objet origine de l'évènement, suivant le schéma suivant :

DoMethod(Objet_Origine, MUIM_Notify,    /* Méthode = Notification */
    Attribut_responsable_de_l'évènement, Valeur_attribut, 
                                 /* Description évènement */
    Objet_Destination,           /* Objet cible sur lequel s'exécutera l'action */

    Nombre_de_paramètres_utilisés_pour_décrire_l'action,
    Paramètre1, Par2, Par3 ...);            /* Description de l'action */

La valeur de l'attribut peut soit être une valeur précise, soit MUIV_EveryTime qui signifie "pour tout changement de la valeur de cet attribut". De même, si on veut donner à un attribut de notre objet destination la valeur de l'attribut ayant provoqué l'évènement, il suffit de lui affecter MUIV_TriggerValue.

La notification directe sur un objet consiste souvent à appliquer une méthode "MUIM_Set" sur un attribut de l'objet destination. Voici quelques exemples de notifications fort utiles qui illustreront ce propos :

1. Lorsque l'on appuie sur le gadget de fermeture d'une fenêtre, elle se ferme :

    DoMethod(MyWindow, MUIM_Notify,        /* objet origine = fenêtre */
        MUIA_Window_CloseRequest, TRUE,    /* demande de fermeture */
        MyWindow,                          /* action sur la fenêtre */
        3, MUIM_Set,                       /* Méthode = positionner un attribut */
        MUIA_Window_Open, FALSE );         /* fermeture de la fenêtre */

2. Lorsque l'on change la valeur d'un gadget radio, cela modifie la valeur d'un cycle, en le forçant à la même position :

    DoMethod(RA_radio, MUIM_Notify,
        MUIA_Radio_Active, MUIV_EveryTime,
        CY_cycle,
        3, 
        MUIM_Set, MUIA_Cycle_Active, MUIV_TriggerValue);

3. Lorsque l'on valide une entrée dans un gadget chaîne, on met cette entrée dans un gadget texte :

    DoMethod(STR_string, MUIM_Notify,
        MUIA_String_Acknowledge, MUIV_EveryTime,
        TX_text,
        3,
        MUIM_Set, MUIA_Text_Contents, MUIV_TriggerValue);

L'envoi d'un identificateur à la boucle IDCMP de votre programme s'effectue en prenant votre objet application comme destination. Ainsi, supposons que vous vouliez envoyer la valeur ID_Constante (que vous avez préalablement déclarée comme une macro) à votre programme. La notification se construira de la manière suivante :

    DoMethod(Objet_Source, MUIM_Notify,
        Attribut, Valeur,
        App,                                /* Votre objet application */
        3,
        MUIM_Application_ReturnID, ID_Constante );

Et dans votre boucle, vous devrez insérer :

    switch(DoMethod(App, MUIM_Application_Input, &signal))
    {
    ...
    case ID_Constante:              /* A insérer dans le 'switch' */
        ...                         /* Traitement de l'évènement */
        break;
    ...
    }

Dans votre code, vous aurez souvent besoin de récupérer l'état d'un ou plusieurs attributs d'objets, ainsi que de les positionner. Ces deux opérations s'effectuent en utilisant les deux macros présentes dans "mui.h": 'get(objet, attribut, adresse_ou_stocker_le_résultat)' et 'set(objet, attribut, valeur)'. Ainsi :

    ULONG WindowState;
    /* Ouverture d'une fenêtre */
    set(MyWindow, MUIA_Window_Open, TRUE);
    /* Récupération de l'état (ouverte/fermée) de la fenêtre */
    get(MyWindow, MUIA_Window_Open, &WindowState);

Le troisième cas que nous traiterons ici est l'appel d'une fonction. Tout d'abord, nous devons définir ce qu'est un "Hook" (crochet en français) : il s'agit d'une structure particulière qui permet de référencer une fonction (voir exemple ci-dessous). L'appel d'une fonction par un objet MUI s'effectue en passant les paramètres suivants :

    DoMethod(MyObject, MUIM_Notify,
        Attribut, Valeur,
        MyObject,
        Nombre_des_paramètres_qui_suivent,
        MUIM_CallHook, struct Hook * hook, ULONG param1, ...);

La fonction appelée reçoit alors en paramètre :

dans A0: un pointeur sur la structure Hook
dans A1: un pointeur sur le premier paramètre
dans A2: un pointeur sur l'objet appelant

Il faut remarquer que cet ordre naturel des registres n'est pas respecté par les conventions du C lors de l'appel d'une fonction, puisque les paramètres reçus sont, dans l'ordre, A0, A2, A1. Pour les compilateurs permettant de préciser les registres utilisés pour les paramètres, on aura (pour SAS-C) ULONG __saveds __asm HookFunc(register __a0 struct Hook *hook, register __a2 APTR object, register __a1 APTR message). Le source qui accompagne cet article comprend également la manière qui doit être utilisée pour DICE.

Exemple :

    /* Fonction Appelée */
    ULONG __saveds __asm HookFunc(register __a0 struct Hook *hook
         , register __a2 APTR object, register __a1 APTR message)
    {
    ... /* votre fonction */
    }
    ...
    /* Création du Hook */
    struct Hook * hook = { {NULL, NULL}, (void *)HookFunc, NULL, NULL};
    ...
    /* Création de la notification */
    /* Lorsque le bouton est relaché, la fonction HookFunc est exécutée */
    DoMethod(BT_button, MUIM_Notify, MUIA_Pressed, FALSE, BT_But
                ton, 2, MUIM_CallHook, &hook);

Cette présentation des notifications clôt cette série d'articles sur MUI. J'espère qu'ils vous auront été utiles, et qu'ils vous amèneront à utiliser cet outil sensationnel.

/*********************************
 * Exemple  d'interface MUI      *
 *********************************/
/* Compatibilité avec DICE et SAS-C */
#ifdef  _DCC
#define     REG(x) __ ## x
#define     ASM
#define     SAVEDS __geta4
#endif

#ifdef  __SASC
#define     REG(x) register __ ## x
#define     ASM    __asm
#define     SAVEDS __saveds
#endif

/* Includes nécessaires à la compilation */
#include    <clib/muimaster_protos.h>
#include    <clib/alib_protos.h>
#include    <clib/exec_protos.h>

#include    <libraries/mui.h>
#include    <pragmas/muimaster_pragmas.h>

#include    <stdio.h>

/* Structure pour l'ouverture de la bibliothèque MUI */
struct Library * MUIMasterBase = NULL;

/* Arguments en réception de la fonction ListFunction */
struct args
{
    APTR    TX_Text;
    APTR    STR_String;
};

/*******************************************************
    Fonction appelée lors de la sélection dans une liste
    But : Mettre à jour les gadgets texte et chaine
********************************************************/
ULONG SAVEDS ASM ListFunction(REG(a0) struct Hook *hook, REG(a2)
                                             APTR object, REG(a1) struct args *arguments)
{
    char *string;
    static char buffer[50];

    /* Lecture de l'élément sélectionné */
    DoMethod(object, MUIM_List_GetEntry, MUIV_List_GetEntry_Active
                                            , &string);
    /* Construction du contenu du gadget texte */
    sprintf(buffer, "\033cVous avez choisi un \0338\033b%s", string);
    /* Mise à jour des contenus des gadgets texte et chaine */
    set(arguments->STR_String, MUIA_String_Contents, string);
    set(arguments->TX_Text, MUIA_Text_Contents, buffer);
    return((ULONG)0);
}

int main(void)
{
    BOOL running = TRUE;
    ULONG signal;
    /* Declaration des objets */
    APTR App, WI_MyWindow, LV_List, TX_Text, RA_Radio, STR_String;

    /* Hook */
    static const struct Hook ListHook = {{NULL,NULL},(void*)ListFunction
                                                ,NULL,NULL};

    /* Contenu de la liste et de l'objet RadioButton */
    const char *Entries[] =
        {
            "Amiga 1000",
            "Amiga 500",
            "Amiga 2000",
            "Amiga 3000",
            "Amiga 1200",
            "Amiga 4000",
            NULL
        };

    /* Ouverture de la bibliothèque MUI */
    if (!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME
                                                ,MUIMASTER_VMIN)))
        {
            printf("Impossible d'ouvrir la muimaster.library V%d\n"
                                                , MUIMASTER_VMIN);
            return(20);
        }
    
    /* Création de l'interface */
    App = ApplicationObject,
        MUIA_Application_Title, "Essai",
        MUIA_Application_Author, "Amiga News",
        MUIA_Application_Base, "ESSAI",
        MUIA_Application_Copyright, "Amiga News",
        MUIA_Application_Description, "Un exemple d'application MUI",
        MUIA_Application_Version, "$VER: Exemple 2.0 (24/06/95)",  
            SubWindow, WI_MyWindow = WindowObject,
                MUIA_Window_Title, "AmigaNews Exemple 2",
                WindowContents, VGroup,
                    Child, TX_Text = TextObject, TextFrame, End,
                    Child, HGroup,
                        Child, VGroup,
                            Child, LV_List = ListviewObject,
                                InputListFrame,
                                MUIA_Listview_List, ListObject,
                                    MUIA_List_Title, "\033c\0338Ordinateurs",
                                    MUIA_List_SourceArray, Entries,
                                End, /* ListObject */
                            End, /* ListviewObject */
                            Child, STR_String = StringObject,
                                StringFrame,
                                MUIA_String_MaxLen, 80,
                            End, /* StringObject */
                        End, /* VGroup */
                        Child, RA_Radio = Radio("Choix", Entries),
                    End, /* HGroup */
                End, /* VGroup */
            End, /* Window */
        End; /* Application */
    
    /* Tout s'est bien passé à la création de l'interface ? */
    if (!App)
        {
            printf("Impossible de créer l'application\n");
            CloseLibrary(MUIMasterBase);
            return(20);
        }
    
    /* Création de la chaine de validation des objets */
    DoMethod(WI_MyWindow, MUIM_Window_SetCycleChain, LV_List
            , RA_Radio, STR_String, NULL);
    
    /* Demande de fermeture de la fenêtre => quitter application */
    DoMethod(WI_MyWindow, MUIM_Notify, MUIA_Window_CloseRequest
            , TRUE, App, 2, MUIM_Application_ReturnID
            , MUIV_Application_ReturnID_Quit);

    /* Sélection d'un élément de la liste => mise à jour des boutons radio */
    DoMethod(LV_List, MUIM_Notify, MUIA_List_Active, MUIV_EveryTime
            , RA_Radio, 3, MUIM_Set, MUIA_Radio_Active, MUIV_TriggerValue); 

    /* Sélection de la liste => Appel de la fonction ListFunction */
    DoMethod(LV_List, MUIM_Notify, MUIA_List_Active, MUIV_EveryTime
            , LV_List, 4, MUIM_CallHook, &ListHook, TX_Text, STR_String);

    /* Sélection d'un bouton radio => mise à jour de la position dans la liste */
    DoMethod(RA_Radio, MUIM_Notify, MUIA_Radio_Active
            , MUIV_EveryTime, LV_List, 3, MUIM_Set, MUIA_List_Active
            , MUIV_TriggerValue);

    /* On attache le gadget chaine et la liste */
    set(STR_String, MUIA_String_AttachedList, LV_List);

    /* Ouverture de la fenetre */
    set(WI_MyWindow, MUIA_Window_Open, TRUE);

    /* Boucle IDCMP                                            */
    /* On récupère les évènements en provenance de l'interface */
    while(running)
        {
            switch (DoMethod(App,MUIM_Application_Input,&signal))
                {
                case MUIV_Application_ReturnID_Quit:
                    running = FALSE; /* On sort de la boucle : fin de l'application */
                    break;
                }
            if (running && signal) Wait(signal);
        }
    
    /* Libération de la mémoire */
    MUI_DisposeObject(App);
    /* Fermeture de la bibliothèque */
    CloseLibrary(MUIMasterBase);
    return(0);
}


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