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 : icon.library
(Article écrit par Iliak et extrait de GuruMed.net - décembre 2002)
|
|
Le Workbench est le bureau de l'Amiga. Celui-ci permet de représenter simplement et graphiquement
les disques, les répertoires et les fichiers. Dans cet article, nous allons aborder deux bibliothèques,
la workbench.library et l'icon.library du Workbench 3.5. La première permet aux applications de communiquer
avec le Workbench, tandis que la deuxième permet aux applications d'afficher des icônes sur le bureau.
Dans un premier temps, nous allons étudier l'icon.library afin d'afficher des icônes,
puis nous nous intéresserons à la workbench.library.
1. Présentation de l'icon.library
Afin d'afficher des icônes, le Workbench a besoin d'un fichier se terminant par un ".info" et portant le
même nom que le fichier à afficher. Ainsi, pour afficher le fichier "toto", il faut avoir son fichier
icône nommé "toto.info" dans le même répertoire. Par défaut, le système fourni quatre types d'icônes :
- Disque : un disque dur ou une disquette.
- Répertoire : par exemple Sys:Devs/.
- Projet : un fichier de données.
- Objet : un exécutable.
Pour créer des icônes, vous devez utiliser le logiciel IconEdit fourni avec le système, ou la créer
vous-même au sein de votre programme. Vous devez absolument respecter la liste ci-dessus, sinon
vous aurez des problèmes pour faire marcher votre application si vous désirez la lancer depuis le
Workbench. Il existe un cas particulier pour nommer les icônes : les disques. Dans tous les cas, l'icône
pour un disque se nomme "disk.info", a le type "disk" et se situe à la racine du disque (disquette ou
disque dur). En plus du fait de fournir une interface graphique, l'icon.library est un pilier central
entre votre application et le Workbench. En effet, vous pouvez stocker des informations à l'intérieur
des icônes, comme la taille de la pile, des arguments, la priorité, etc.
1.1 Structure
Tout d'abord, voici à quoi ressemble la structure DiskObject (voir "include:workbench/workbench.h" dans les
RKM ou sur l'Amiga Developer CD 2.1) :
struct DiskObject
{
UWORD do_Magic;
UWORD do_Version;
struct Gadget do_Gadget;
UBYTE do_Type;
char *do_DefaultTool;
char **do_ToolTypes;
LONG do_CurrentX;
LONG do_CurrentY;
struct DrawerData *do_DrawerData;
char *do_ToolWindow;
LONG do_StackSize;
};
|
- do_Magic : numéro qui permet à la bibliothèque de savoir à coup sûr que c'est une icône.
Cette valeur est WB_DISKMAGIC.
- do_Version : permet de savoir et garder la compatibilité de l'icône.
- do_Gadget : structure Gadget qui contient les images de l'icône (voir paragraphe "1.2 Les gadgets").
- do_Type : type de l'icône :
- WBDISK : icône d'un disque.
- WBDRAWER : icône d'un répertoire.
- WBTOOL : icône d'un exécutable.
- WBPROJECT : icône d'un fichier de données.
- WBGARBAGE : icône d'une poubelle.
- WBKICK : icône d'une disquette de démarrage (Kickstart).
- WBAPPICON : icône d'une AppIcon (voir paragraphe "2.1 AppIcon").
- do_DefaultTool : utilisable seulement sur les icônes de type projet et disque.
Chemin indiquant l'action par défaut à effectuer lorsque l'on double-clique sur l'icône pour
un projet. Pour un disque, l'action par défaut est "Sys:System/diskCopy".
- do_ToolTypes : permet de passer des chaînes de caractères au programme. Ni l'icon.library,
ni le Workbench ne regarde ces chaînes. Elles servent juste à passer des arguments au programme via
l'icône (voir chapitre "1.3 Les types d'outils").
- do_CurrentX, do_CurrentY : position de l'icône dans la fenêtre. Au cas où l'icône ne
dispose pas de position prédéfinie, elle a comme valeur "NO_ICON_POSITION".
- do_DrawerData : si l'icône est du type WBDISK, WBDRAWER ou WBGARBAGE, alors ce champ est
valide. Il indique au Workbench comment ouvrir le répertoire et aussi sauvegarder vos préférences.
Cette structure à la forme suivante :
struct DrawerData
{
struct NewWindow dd_NewWindow; // voir le fichier d'inclusion intuition/intuition.h
LONG dd_CurrentX; // Position X
LONG dd_CurrentY; // Position Y
};
|
- do_ToolWindow : ne pas utiliser, pour un usage futur.
- do_StackSize : taille de la pile du programme en octets. Si cette valeur est absente,
une pile de 4 ko sera attribuée au programme.
1.2 Les gadgets
Afin de garder l'image de l'icône, le Workbench utilise une structure Gadget. Étant donné que tous
les champs de cette structure ne sont pas utilisés, ils sont laissés à 0 et ne doivent pas être modifiés.
Voici la liste des champs utilisés :
- Width : largeur de la zone réactive de l'icône.
- Height : hauteur de la zone réactive de l'icône.
- Flags : doit absolument être du type "GADIMAGE". Trois méthodes
de surbrillance existent :
- GADHCOMP : complète l'image de l'icône.
- GADHIMAGE : utilise une autre image.
- GADGBACKFILL : similaire à "GADHCOMP" mais évite "l'anneau" autour de l'image.
- Activation : soit "RELVERIFY" ou "GADGIMMEDIAT".
- Type : doit être "BOOLGADGET".
- GadgetRender : pointeur vers l'image complémentaire.
1.3 Les types d'outils
Nous avons dit que l'on pouvait utiliser l'icône afin de passer des arguments à notre programme. Cela
se fait par l'intermédiaire du champ "do_ToolTypes". Pour modifier ce champ, vous devez sélectionner
l'icône et, dans le menu du Workbench, cliquer sur "Information". Vous obtiendrez la liste des types d'outils
("ToolTypes"). Du point de vue programmation, les types d'outils sont une série de pointeurs vers des
chaînes de 128 caractères au maximum. De plus, vous ne devez utiliser que des caractères imprimables
(fortement conseillé) et la casse est sensible, ainsi "Toto" est différent de "TOTO".
Le format standard des types d'outils est "=[|...]". Bien évidement, des valeurs réservées existent :
- DONOTWAIT=n : le Workbench n'attend pas un message de retour de la part de la tâche.
- STARTPRI=n : définit l'ordre de lancement dans le répertoire WBStartup.
- TOOLPRI=n : définit la priorité de la tâche sous Exec.
Afin de lire les types d'outils, le système fournit "FindToolType()" qui permet de récupérer la valeur
d'un type d'outils et "MatchToolValue()" qui permet de savoir si un type d'outils a une certaine valeur.
Exemple d'utilisation des types d'outils : cette procédure va lire tous les types d'outils d'une icône.
Comme argument, elle prend le message que le Workbench vous envoie au démarrage.
void showToolTypes(struct WBArg *wbarg)
{
struct DiskObject *dobj;
char **toolarray;
char *s;
BOOL success = FALSE;
printf("Lock=0x%lx, Nom=%s\n", wbarg->wa_Lock, wbarg->wa_Name);
if((*wbarg->wa_Name) && (dobj=GetDiskObject(wbarg->wa_Name)))
{
printf("We have read the DiskObject (icon) for this arg\n");
toolarray = (char **)dobj->do_ToolTypes;
if(s=(char *)FindToolType(toolarray,"FILETYPE"))
{
fprintf(conwin," Found tooltype FILETYPE with value %s\n",s);
}
if(s=(char *)FindToolType(toolarray,"FLAGS"))
{
fprintf(conwin," Found tooltype FLAGS with value %s\n",s);
if(MatchToolValue(s,"BOLD"))
fprintf(conwin," BOLD flag requested\n");
if(MatchToolValue(s,"ITALICS"))
fprintf(conwin," ITALICS flag requested\n");
}
/* Free the diskobject we got */
FreeDiskObject(dobj);
success = TRUE;
}
else if(!(*wbarg->wa_Name)){
fprintf(conwin," Must be a disk or drawer icon\n");
}
else
{
fprintf(conwin," Can't find any DiskObject (icon) for this WBArg\n");
}
}
|
2. La workbench.library
La workbench.library fournit aux développeurs trois moyens de communication supplémentaires sous le Workbench :
- Les AppIcons : icône spéciale qui renvoie un signal lorsqu'une autre icône est lâchée dessus.
Le Workbench donne le nom et le répertoire de l'icône lâchée dans l'AppIcon.
- Les AppMenus : sous-menu spécial qui se rajoute dans le menu "Outils" du Workbench.
Celui-ci, en retour, nous indique dès que le menu a été sélectionné.
- Les AppWindows : fenêtre qui a la particularité de permettre d'y déposer une icône dedans.
Ainsi, on est informé dès qu'une icône est déposée dans cette fenêtre. En retour, le Workbench donne le nom
et le répertoire de l'icône lâchée dans l'AppWindow.
Ces trois fonctions permettent d'étendre les possibilités de communication avec l'interface graphique
du Workbench. En retour de chacunes d'elles, le Workbench renvoie un pointeur vers une structure "WBArg" :
struct WBArg{
BPTR wa_Lock; /* Verrou sur le répertoire */
BYTE *wa_Name; /* Nom de l'icône */
};
|
Nous allons d'ailleurs aborder ces trois facettes grâce à des exemples.
2.1 AppIcon
Dans cet exemple, nous allons mettre en place une AppIcon. Notre icône aura l'apparence d'un disque
et dès que nous lâcherons une icône dessus, nous afficherons des informations.
#include <exec/types.h>
#include <workbench/workbench.h> /* Les structures DiskObject et AppIcon */
#include <workbench/startup.h> /* Les structures WBStartup et WBArg */
#include <exec/libraries.h>
struct Library *IconBase;
struct Library *WBBase;
int main(int argc, char **argv)
{
struct DiskObject *dskobj;
struct MsgPort *mport;
struct AppIcon *appicon;
struct AppMessage *appmsg;
ULONG x;
if(IconBase = OpenLibrary("icon.library",37))
{
if (WBBase=OpenLibrary("workbench.library",37))
{
/* On obtient l'image d'une icône par défaut (ici un disque) */
dskobj=GetDefDiskObject(WBDISK);
if(dskobj!=0)
{
/* toujours NULL pour une AppIcon ! */
dskobj->do_Type=NULL;
/* Création du port de communication pour que le Workbench puisse nous répondre */
mport=CreateMsgPort();
if(mport)
{
/* On met l'icône sur le Workbench */
appicon=AddAppIconA(0,0,"AppIcon",mport,NULL,dskobj,NULL);
if(appicon)
{
/* On attend un message de la part du Workbench */
WaitPort(mport);
/* Attention, il peut y avoir plusieurs messages ! */
while(appmsg=GetMsg(mport))
{
if(appmsg->am_NumArgs==0)
/* Si NumArgs est nul, alors on a double-cliqué sur l'AppIcon */
printf("Double-clic sur l'icône !\n");
else if(appmsg->am_NumArgs>0)
{
/* Si NumArgs est >0 alors l'AppIcon a été activée avec */
/* une ou plusieurs autre(s) icônes */
printf("Il y a %ld icônes lâchées sur l'AppIcon\n", appmsg->am_NumArgs);
for(x=0;xam_NumArgs;x++)
printf("Icône #%ld, nom='%s'\n",x+1,appmsg->am_ArgList[x].wa_Name);
}
/* On répond au message */
ReplyMsg(appmsg);
}
RemoveAppIcon(appicon);
}
DeleteMsgPort(mport);
}
FreeDiskObject(dskobj);
}
CloseLibrary(WBBase);
}
CloseLibrary(IconBase);
}
return(0);
}
|
2.2 AppMenu
Dans cet exemple, nous allons rajouter un menu appellé "CLI" dans le menu "Outils" du Workbench.
Dès que celui-ci sera sélectionné, cela ouvrira une fenêtre CLI et nous quitterons notre programe.
Pour ouvrir la fenêtre CLI, nous utiliserons la commande "SystemTags()".
#include <exec/types.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <exec/libraries.h>
#include <dos/dostags.h>
#include <stdio.h>
struct Library *WBBase;
int main(int argc, char **argv)
{
struct MsgPort *msgport;
struct AppMenuItem *appitem;
struct AppMessage *appmsg;
LONG result, x;
BPTR file;
if (WBBase = OpenLibrary("workbench.library",37))
{
/* On crée notre port de communication */
if(msgport = CreateMsgPort())
{
/* On ajoute notre AppMenu aux menus du Workbench */
appitem=AddAppMenuItemA(NULL, /* Notre numéro ID */
(ULONG)"c:NewShell", /* Notre commande */
"Cli", /* Le texte à afficher */
msgport, /* Notre port de communication */
NULL); /* Pas de paramètres */
if(appitem)
{
WaitPort(msgport);
appmsg=(struct AppMessage *)GetMsg(msgport)
printf("AppMenuItem sélectionné avec %ld icônes\n",appmsg->am_NumArgs);
for(x=0;xam_NumArgs;x++)
printf("Icône #%ld nom : '%s'\n",x+1,appmsg->am_ArgList[x].wa_Name);
/* On ouvre une fenêtre pour tout message à afficher */
if( file=Open("CON:0/40/640/150/Fenêtre de sorite/auto/close/wait",MODE_OLDFILE))
{
result=SystemTags((UBYTE *)appmsg->am_UserData,SYS_Input,file,
SYS_Output,NULL,
SYS_Asynch,TRUE,
TAG_DONE);
/* La commande a échoué */
if(result == -1) Close(file);
}
ReplyMsg((struct Message *)appmsg);
RemoveAppMenuItem(appitem);
}
/* On efface tous les messages potentiellement restants dans la file d'attente */
while(appmsg=(struct AppMessage *)GetMsg(msgport))
ReplyMsg((struct Message *)appmsg);
DeleteMsgPort(msgport);
}
CloseLibrary(WBBase);
}
return(0);
}
|
2.3 AppWindow
Cet exemple montre comment créer une AppWindow. Il suffit de lâcher une ou plusieurs icônes dans cette
fenêtre pour récuperer leur nom.
#include <exec/types.h>
#include <workbench/workbench.h>
#include <workbench/startup.h>
#include <exec/libraries.h>
#include <stdio.h>
struct Library *IntuitionBase;
struct Library *WBBase;
int main(int argc, char **argv)
{
struct MsgPort *msgport;
struct Window *win;
struct AppWindow *appwin;
struct IntuiMessage *imsg;
struct AppMessage *appmsg;
struct WBArg *WBarg;
ULONG winsig,
appwinsig,
signals,
id=1,
userdata = 0;
BOOL done=FALSE;
int i;
if (IntuitionBase = OpenLibrary("intuition.library", 37))
{
if (WBBase = OpenLibrary("workbench.library", 37))
{
if (msgport = CreateMsgPort())
{
if (win = OpenWindowTags(NULL,
WA_Width, 200, /* Largeur */
WA_Height, 50, /* Hauteur */
WA_IDCMP, CLOSEWINDOW, /* Messages que l'on désire recevoir */
WA_Flags, WINDOWCLOSE | WINDOWDRAG, /* Les gadgets de la fenêtre */
WA_Title, "AppWindow", /* Nom de la fenêtre */
TAG_DONE))
{
if (appwin = AddAppWindow(id, userdata, win, msgport, NULL))
{
winsig = 1 << win->UserPort->mp_SigBit;
appwinsig = 1 << msgport->mp_SigBit;
while (!done)
{
/* On attend des signaux IDCMP ou de l'AppWindow */
signals = Wait( winsig | appwinsig );
if(signals & winsig) /* Message IDCMP*/
{
while (imsg=GetMsg(win->UserPort))
{
if (imsg->Class = CLOSEWINDOW) done=TRUE;
ReplyMsg(imsg);
}
}
if(signals & appwinsig) /* AppMessage */
{
while (appmsg =GetMsg(msgport))
{
printf("AppMessage : Type = %ld, ID = %ld, Arguments=%ld\n",
appmsg->am_Type, /* Type de message */
appmsg->am_ID, /* Numéro du message */
appmsg->am_NumArgs /* Arguments */
);
WBarg = appmsg->am_ArgList;
for (i=0; iam_NumArgs; i++)
{
printf("arg(%ld): Name='%s', Lock=%lx\n",
i, /* numéro */
WBarg->wa_Name, /* Nom de l'icône */
WBarg->wa_Lock /* Verrou sur le répertoire */
);
WBarg++;
}
ReplyMsg(appmsg);
}
}
}
RemoveAppWindow(appwin);
}
CloseWindow(win);
}
/* On efface tous les messages en attente */
while(appmsg = (struct AppMessage *)GetMsg(msgport))
{
ReplyMsg((struct Message *)appmsg);
}
DeleteMsgPort(msgport);
}
CloseLibrary(WorkbenchBase);
}
CloseLibrary(IntuitionBase);
}
return(0);
}
|
|