Suivez-nous sur X
|
|
|
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,
ALL
|
|
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
|
|
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
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
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 arrête.
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.
|