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 : Assembleur - workbench.library et AppIcon
(Article écrit par Frédéric Delacroix et extrait d'Amiga News - juillet 1994)
|
|
Le Workbench a fait beaucoup de progrès depuis l'avènement des systèmes 2.x et 3.x.
Outre les (nombreux) bogues corrigés, il existe maintenant un moyen tout à fait légal
d'utiliser les capacités du Workbench.
La workbench.library vous permettra d'ajouter des AppIcons, des AppMenuItems
et des AppWindows à volonté, discipline dans laquelle l'excellent ToolManager
s'est rendu maître. A réserver aux Kickstart 2.0 et plus.
Présentation des AppObjets
Le préfixe "App" signifie ici "application". Une AppIcon est ainsi une icône
qui se comporte exactement comme une icône normale (elle peut être déplacée et cliquée)
mais qui n'est pas associée à un fichier, mais à un programme actuellement résident.
Petite différence toutefois : le menu "Information..." ne marche pas sur les AppIcons.
De la même façon, les AppMenuItems sont les menus du menu "Outils" du Workbench. Il
n'est pour l'instant pas possible d'y associer des sous-menus (c'est dommage, ce sera
peut-être pour la version 41...).
Les AppWindows sont (à peine) plus difficiles à mettre en oeuvre :
il faut d'abord ouvrir une fenêtre Intuition grâce à OpenWindow
[TagList]() et la déclarer auprès de la workbench.library.
Mais quel intérêt ?
Eh bien grâce à ces AppIcons, AppMenus et AppWindows, vous avez un
moyen de communication avec le Workbench ! Le Workbench enverra un message à
l'application qui a déclaré un objet lorsqu'un évènement concernant l'objet
en question surviendra.
Pour une AppIcon, cela signifie qu'on lui a déposé une autre icône dessus, ou
qu'elle a subi un double-clic : un AppMenu se manifeste lorsqu'il a été choisi
dans le menu "Outils", et une AppWindow signalera qu'on a déplacé une icône dans
la fenêtre (un peu à la manière des fenêtres "tiroirs" du Workbench).
Communication avec le Workbench
Le Workbench est une tâche (ou plutôt un processus). La communication avec lui
passe donc, on peut s'en douter, par l'échange de messages. Il faut donc créer un port
message, tout à fait standard, qui recevra les messages du Workbench (ce qui peut
se faire pur CreateMsgPort() d'exec.library). Le Workbench emploie des
messages étendus, connus sous le nom d'AppMessage, définie en C par :
Cette structure est bien sûr utilisable en assembleur, mais le C est un peu plus concis
pour la description. Comme on peut le voir ci-dessus, le système utilisé par le Workbench
pour passer ses arguments est le même que celui du message WBStartup : am_ArgList
pointe sur un tableau de structures WBArg (gui contiennent Lock sur le répertoire
et nom des objets sélectionnés) et am_NumArgs contient le nombre de ces arguments.
Deux champs sont à notre entière disposition : atm_ID et am_UserData contiendront
les valeurs données en paramètres aux fonctions AddAppXXXX().
Voyons maintenant le contenu des messages reçus.
- Cas d'une AppIcon : si celle-ci été double-cliquée, alors am_NumArgs vaut 0.
Si on y a déposé une ou plusieurs icônes (grâce à la multisélection), am_ArgList
est la liste des structures WBArg correspondantes, et le type du message
est MTYPE_APPICON. Pour l'instant, il est impossible de déposer l'AppIcon elle-même
sur une autre icône, ou d'utiliser la multisélection avec des AppIcon (en "Shift-cliquant"
une AppIcon). Sélectionner une AppIcon et choisir le menu "Ouvrir" est équivalent
à un double-clic.
- Cas d'un AppMenu : am_ArgList est la liste des icônes qui étaient sélectionnées au
moment où l'utilisateur a choisi le menu. am_NumArgs est leur nombre, 0 si aucune
icône n'était sélectionnée, le type du message est MTYPE_APPMENUITEM.
- Cas d'une AppWindow : la liste des icônes qui ont été déposées dans la
fenêtre est contenue dans am_ArgList. Ici, il y a toujours au moins un argument.
Le champ am_Type vaudra alors MTYPE_APPWINDOW.
Gérer de nouveaux AppObjets
Tout se fait par l'intermédiaire de la workbench.library, une condition
supplémentaire va de soi : le Workbench doit avoir été lancé (ce qui est
normalement fait par la commande "LoadWB" dans la startup-sequence).
Voyons d'abord les Applcons.
Il faut d'abord initialiser une structure DiskObject (reportez-vous à
cet article pour plus d'informations
sUr cette structure). Le meilleur moyen d'en avoir une à sa disposition est
de charger l'icône du programme grâce à GetDiskObject()
de l'icon.library, ou d'en créer une en passant 0 en paramètre à cette fonction.
Seuls les champs suivants sont pris en compte :
- do_Gadget : gg_Width, gg_Height, gg_Flags (contient 0 ou GFLG_GADGHIMAGE
si l'icône a deux images), gg_GadgetRender (image non sélectionnée), gg_SelectRender
(image sélectionnée si elle existe).
- do_CurrentX et do_CurrentY : NO_ICON_POSITION est conseillé, mais
d'autres valeurs sont possibles. On utilise ensuite la fonction AddAppIconA()
de la workbench.library. Les valeurs passées en D0 et D1 sont ignorées par la
workbench.library, on les retrouve telles quelles respectivement dans les champs
am_ID et am_UserData des structures AppMessages futures. En A0, la fonction prend
un pointeur sur la chaîne de caractères qui sera affichée sous l'icône ;
A1 pointe sur le MsgPort qui sera utilisé pour communiquer avec le Workbench ;
A2 doit être à 0, A3 pointe sur la structure DiskObject précédemment initialisée,
et A4 pointe sur une liste de marqueurs. Aucun marqueur n'est défini pour l'instant, on
peut mettre A4 à 0. En retour, D0 contient un pointeur sur une structure AppIcon,
ou 0 si la fonction a échoué. Cette valeur n'a qu'une signification booléenne pour nous.
- Pour retirer une AppIcon, c'est plus simple : on utilise la fonction
RemoveAppIcon() à laquelle on passe en A0 la valeur renvoyée par AddAppIconA(),
et on libère la structure DiskObject si nécessaire.
- En ce qui concerne les AppMenus, moins d'initialisations sont nécessaires, on peut
directement utiliser la fonction AddAppMenuItemA() avec les paramètres suivants :
D0 et D1 contiennent les valeurs respectives de am_1D et am_UserData des AppMessages
à venir, A0 pointe sur le texte qui apparaîtra dans le menu, A1 pointe sur le MsgPort
pour la communication avec le Workbench, A2 sur une liste de marqueurs (aucun marqueur n'est
défini pour l'instant). En retour, D0 pointe sur une structure AppMenuItem (privée,
tout comme les structures AppIcon et AppWindow), ou vaut 0 si une erreur est survenue.
- Pour retirer un AppMenu, on utilise naturellement RemoveAppMenuItem(),
qui prend en A0 la valeur renvoyée par AddAppMenuItemA().
- Pour les AppWindows, on passe les mêmes paramètres à AddAppWindowA()
qu'à AddAppMenuItemA(), sauf pour le texte (en A0), qui est remplacé par un pointeur
sur une fenêtre Intuition (structure Window) déjà ouverte. La fenêtre du CLI
(si elle n'est pas en mode AUTO) est un exemple tout à fait acceptable (encore faut-il
savoir récupérer un pointeur sur cette fenêtre de façon "propre", en dialoguant
avec le processus de console). En retour, on obtient un pointeur sur une structure
AppWindow, on en a l'habitude. Naturellement, la fenêtre ne doit pas se fermer
avant d'avoir été retirée de la liste des AppWindows du Workbench, grâce à la
fonction RemoveAppWindow(), qui prend en paramètre le pointeur sur la
structure AppWindow obtenu précédemment.
Un exemple
Le programme d'exemple que je vous propose est un lecteur de fichiers (très)
rudimentaire (312 octets, qui dit mieux ?). Il ne peut être utilisé qu'à
partir du CLI, pour pouvoir bénéficier de la console du CLI. Il
affiche une AppIcon sur l'écran du Workbench et affiche tous les fichiers dont
les icônes y sont déposées dans la fenêtre du CLI. Pour quitter le programme,
un double-clic sur l'icône fait l'affaire. L'AppIcon est l'icône par défaut,
libre à vous d'améliorer le programme en choisissant une icône plus belle,
en gérant le démarrage à partir du Workbench (il faudra dans ce cas ouvrir une
console). Vous pourriez aussi par exemple envoyer toutes les données vers l'imprimante
(device PRT:) et ajouter un SegList-split (voir
cet article) pour avoir un petit spooler d'imprimante...
|