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 - copie d'icône
(Article écrit par Frédéric Delacroix et extrait d'Amiga News - octobre 1996)
|
|
Lorsqu'on veut doter un fichier d'une icône, deux solutions sont offertes. La première réside en le lourd programme IconEdit,
et la seconde consiste à copier le fichier ".info" correspondant à l'icône voulue. Voici une troisième solution.
Pourquoi ?
Pourquoi ne pas se contenter, en effet, de bêtement copier le fichier "Source.info" en "Destination.info" ? Plusieurs raisons à
cela. La principale tient au fait que toutes les données sont copiées, y compris - et cela peut être gênant - le type (projet,
outil...) de l'icône, les types d'outil, la position... Lorsqu'on veut juste l'image d'une autre icône, il faut utiliser
IconEdit.
Quoi ?
Le programme que je vous décris ici n'a en fait pas grand-chose d'original dans sa fonctionnalité, mais il a le mérite de montrer
le fonctionnement de plusieurs aspects du système. Il ouvre une fenêtre avec deux gadgets texte et un bouton. Il attend ensuite
que l'on dépose une icône sur l'un des deux gadgets textes (source et destination). Le nom de l'icône apparaît alors dans le
gadget. Une fois les deux icônes choisies, vous pourrez cliquer sur le bouton "Copy" pour copier l'image de l'icône source dans
l'icône destination. Fermez la fenêtre pour quitter le programme.
Comment ?
L'interfaçage entre le programme et le Workbench pour déposer les icônes se fait par la workbench.library et ses AppWindows,
dont j'ai déjà parlé dans un article précédent. La copie d'icônes se fait par l'intermédiaire des fonctions GetDiskObjectNew()
et PutDiskObject() de l'icon.library, dont l'usage est détaillé dans le listage ci-dessous. Dans la structure DiskObject de
destination, on remplace toute la structure Gadget par celle du DiskObject source. Il ne suffit pas de remplacer les images,
car les autres champs de la structure Gadget ont leur importance (je soupçonne Kamel d'avoir modifié les GetDiskObject()s de
l'icon.library dans son programme NoDraw pour avoir une taille de 0). Un simple CopyMem() fait l'affaire.
Pour ce qui est de la pseudo-interface graphique, elle utilise la gadtools.library. Libre à vous de l'améliorer en utilisant les
articles déjà publiés à ce sujet ici même, la place me manquant.
Bogues ?
Un programme si court ne saurait être parfait. Ses défauts sont de ne pas afficher le nom des répertoires dans les gadgets
textes, de ne pas pouvoir affecter les icônes sorties sur l'écran du Workbench ou les disques (je vous laisse deviner pourquoi,
j'interroge le mois prochain), et bien sûr l'interface graphique assez minable. Vous y remédierez facilement, pour peu que vous
vous penchiez de suffisamment près sur le fonctionnement du programme. Pour un assemblage correct, ce programme nécessite les
macro-instructions de Hisoft Devpac 3.50, distribué par ADFI.
; IconCopy.s, version 1.0
; nécessite les fichiers de macros de Hisoft Devpac 3.50
IMPORT exec,exec
IMPORT workbench,icon
IMPORT workbench,workbench
IMPORT workbench,startup
IMPORT intuition,intuition
IMPORT libraries,gadtools
IMPORT dos,dos
include HISOFT_DEVPAC:Macro/defines.i
include HISOFT_DEVPAC:Macro/exec.i
move.l 4.w,a6
moveq #20,d7 ; code de retour
move.l a6,Exec.Base
OPENLIB Intuition,37 ; ouvre les bibliothèques
move.l d0,Intuition.Base ; nécessaires (Kickstart 2.04+)
beq NoIntuition
OPENLIB Icon,37
move.l d0,Icon.Base
beq.s NoIcon
OPENLIB Workbench,37
move.l d0,Workbench.Base
beq.s NoWB
OPENLIB GadTools,37
move.l d0,GadTools.Base
beq.s NoGadTools
OPENLIB DOS,37
move.l d0,DOS.Base
beq.s NoDOS
bsr.s OpenWindow ; initialisation
beq.s Exit
bsr MainLoop ; traitement
bsr CloseWindow ; libération
moveq #0,d7
Exit move.l DOS.Base(pc),a1
CALL CloseLibrary,Exec.Base
NoDOS move.l GadTools.Base(pc),a1
CALL CloseLibrary
NoGadTools
move.l Workbench.Base(pc),a1
CALL CloseLibrary
NoWB move.l Icon.Base(pc),a1
CALL CloseLibrary
NoIcon move.l Intuition.Base(pc),a1
CALL CloseLibrary
NoIntuition
move.l d7,d0
rts
OpenWindow ; (Z=0)Success=OpenWindow()
PUSH d0-d2/a0-a1/a6,OpenWindow
lea Workbench.Name(pc),a0
CALL LockPubScreen,Intuition.Base(pc)
move.l d0,a0
suba.l a1,a1
CALL GetVisualInfoA,GadTools.Base(pc)
move.l d0,Screen.VI
beq .Fail
lea Window.GList(pc),a0
CALL CreateContext ; création du contexte GadTools
move.l d0,d2
beq .Fail
moveq #TEXT_KIND,d0 ; gadget texte Source
move.l d2,a0
lea Source.NewGad(pc),a1
move.l Screen.VI(pc),gng_VisualInfo(a1)
lea Source.Tags(pc),a2
CALL CreateGadgetA
move.l d0,d2
move.l d0,Source.Gad
beq .Fail
moveq #TEXT_KIND,d0 ; gadget texte Destination
move.l d2,a0
lea Dest.NewGad(pc),a1
move.l Screen.VI(pc),gng_VisualInfo(a1)
lea Dest.Tags(pc),a2
CALL CreateGadgetA
move.l d0,d2
move.l d0,Dest.Gad
beq.s .Fail
moveq #BUTTON_KIND,d0 ; bouton de copie
move.l d2,a0
lea Copy.NewGad(pc),a1
move.l Screen.VI(pc),gng_VisualInfo(a1)
suba.l a2,a2
CALL CreateGadgetA
move.l d0,d2
move.l d0,Copy.Gad
beq.s .Fail
suba.l a0,a0 ; ouverture de la fenêtre
lea Window.Tags(pc),a1
CALL OpenWindowTagList,Intuition.Base(pc)
move.l d0,Window.Window
beq.s .Fail
CALL CreateMsgPort,Exec.Base(pc)
move.l d0,AppWindow.Port ; port de communication avec WB
beq.s .Fail
move.l Window.Window(pc),a0 ; déclare que notre fenêtre
move.l AppWindow.Port(pc),a1 ; est une AppWindow
suba.l a2,a2
CALL AddAppWindowA,Workbench.Base(pc)
move.l d0,Window.AppWindow
beq.s .Fail
moveq #-1,d0 ; succes
bra.s .Ret
.Fail bsr.s CleanUpWindow ; en cas d'erreur: tout libérer
moveq #0,d0 ; erreur
.Ret POP OpenWindow
rts
CleanUpWindow
PUSH d0-d1/a0-a1/a6,CleanUpWindow
move.l AppWindow.Port(pc),a0 ; peut être nul
CALL DeleteMsgPort,Exec.Base(pc)
move.l Window.Window(pc),d0
beq.s .NoWin
move.l d0,a0
CALL CloseWindow,Intuition.Base(pc)
.NoWin move.l Window.GList(pc),a0
CALL FreeGadgets,GadTools.Base(pc) ; idem
move.l Screen.VI(pc),a0
CALL FreeVisualInfo ; idem
lea Workbench.Name(pc),a0
CALL UnlockPubScreen,Intuition.Base(pc) ; idem
POP CleanUpWindow
rts
CloseWindow
PUSH d0-d1/a0-a2/a6,CloseWindow
move.l Window.AppWindow(pc),a0
CALL RemoveAppWindow,Workbench.Base(pc)
move.l AppWindow.Port(pc),a2
move.l Exec.Base(pc),a6
.Empty move.l a2,a0 ; vide le port de communication avec
CALL GetMsg ; le Workbench avant de fermer la fenêtre
move.l d0,a1
move.l a1,d0
beq.s .End
CALL ReplyMsg
bra.s .Empty
.End bsr CleanUpWindow
lea Source.Gad(pc),a2
bsr FreeArg ; libère les ressources éventuellement
lea Dest.Gad(pc),a2 ; allouées pour les icônes
bsr FreeArg
POP CloseWindow
rts
MainLoop
move.l Window.Window(pc),a3
move.l wd_UserPort(a3),a2
move.l AppWindow.Port(pc),a4
.MainLoop
moveq #0,d0
move.b MP_SIGBIT(a2),d1 ; signal de la fenêtre
bset d1,d0
move.b MP_SIGBIT(a4),d1 ; du Workbench
bset d1,d0
CALL Wait,Exec.Base(pc)
move.l d0,d7
move.b MP_SIGBIT(a2),d1
bclr d1,d7
beq.s .TestWB
.WndLoop
move.l a2,a0
CALL GT_GetIMsg,GadTools.Base(pc) ; message de la fenêtre?
move.l d0,a1
move.l a1,d0
beq.s .TestWB
move.l im_Class(a1),d6
CALL GT_ReplyIMsg
cmp.l #IDCMP_REFRESHWINDOW,d6
bne.s .NoRefresh
move.l a3,a0 ; demande de rafraîchissement
CALL GT_BeginRefresh ; laisse GadTools bosser
move.l a3,a0
moveq #1,d0
CALL GT_EndRefresh
bra.s .WndLoop
.NoRefresh
cmp.l #IDCMP_GADGETUP,d6 ; "Copy" actionné?
bne.s .NoGadgetUp
bsr Copy
bra.s .WndLoop
.NoGadgetUp
cmp.l #IDCMP_CLOSEWINDOW,d6 ; fermer la fenêtre?
bne.s .WndLoop
rts ; fin
.TestWB move.b MP_SIGBIT(a4),d1
bclr d1,d7
beq MainLoop
.WBLoop move.l a4,a0
CALL GetMsg,Exec.Base(pc) ; message du WB?
move.l d0,a5
move.l a5,d0
beq .MainLoop
cmp.w #AMTYPE_APPWINDOW,am_Type(a5)
bne.s .ReplyWB
cmp.l #1,am_NumArgs(a5)
blo.s .ReplyWB
move.w am_MouseY(a5),d0 ; ordonnée du pointeur
cmp.w #YLIMIT,d0
blo.s .SourceGad
lea Dest.Gad(pc),a0 ; sur gadget "Destination"
bsr.s CopyWBArg
bsr UpdateTextGad
bra.s .ReplyWB
.SourceGad
lea Source.Gad(pc),a0 ; sur gadget "Source"
bsr.s CopyWBArg ; copie de l'argument
bsr UpdateTextGad ; (répertoire et nom)
.ReplyWB
move.l a5,a1
CALL ReplyMsg,Exec.Base(pc)
bra.s .WBLoop
CopyWBArg ; CopyWBArg(Storage,AppMessage)(A0,A5)
PUSH d0-d1/a0-a3/a6,CopyWBArg
move.l a0,a2
bsr.s FreeArg ; libère le précédent
move.l am_ArgList(a5),a3
move.l wa_Lock(a3),d1
CALL DupLock,DOS.Base(pc) ; copie le Lock du répertoire
move.l d0,4(a2)
beq.s .Fail
move.l wa_Name(a3),d0
move.l d0,a0
.Len tst.b (a0)+ ; et le nom (en allouant de la mem)
bne.s .Len
sub.l a0,d0
neg.l d0 ; longueur du nom +1
move.l #MEMF_PUBLIC!MEMF_CLEAR,d1
CALL AllocVec,Exec.Base(pc)
move.l d0,8(a2)
bne.s .CopyName
bsr.s FreeArg
bra.s .Fail
.CopyName
move.l wa_Name(a3),a0
move.l 8(a2),a1
.Cpy move.b (a0)+,(a1)+
bne.s .Cpy
.Fail POP CopyWBArg
rts
FreeArg ; FreeArg(Arg)(A2)
PUSH d0-d1/a0-a2/a6,FreeArg
move.l 8(a2),d0 ; name
beq.s .NoMem
move.l d0,a1
CALL FreeVec,Exec.Base(pc)
clr.l 8(a2)
.NoMem move.l 4(a2),d1 ; lock
beq.s .NoLock
CALL UnLock,DOS.Base(pc)
clr.l 4(a2)
.NoLock POP FreeArg
rts
UpdateTextGad ; UpdateTextGad(Storage)(A0)
PUSH d0-d1/a0-a4/a6,UpdateTextGad
move.l a0,a4 ; mise à jour du gadget Texte
move.l (a4),a0
move.l Window.Window(pc),a1
suba.l a2,a2
clr.l -(sp) ; TAG_DONE
move.l 8(a4),-(sp)
pea GTTX_Text
move.l sp,a3
CALL GT_SetGadgetAttrsA,GadTools.Base(pc)
add.l #12,sp
POP UpdateTextGad
rts
Copy PUSH d0-d1/d7/a0-a1/a4-a6,Copy
tst.l Source.Gad+8 ; source sélectionnée?
beq.s .Error
tst.l Dest.Gad+8 ; dest sélectionnée?
beq.s .Error
move.l Source.Gad+4(pc),d1 ; rep source
CALL CurrentDir,DOS.Base(pc)
move.l d0,d7 ; ancien rep
move.l Source.Gad+8(pc),a0
CALL GetDiskObjectNew,Icon.Base(pc)
move.l d0,a4 ; icône source
move.l a4,d0
beq.s .DirBack
move.l Dest.Gad+4(pc),d1 ; rep destination
CALL CurrentDir,DOS.Base(pc)
move.l Dest.Gad+8(pc),a0
CALL GetDiskObjectNew,Icon.Base(pc)
move.l d0,a5 ; icône destination
move.l a5,d0
beq.s .FreeSource
lea do_Gadget(a4),a0 ; Gadget Source
lea do_Gadget(a5),a1 ; Gadget Destination
move.l #gg_SIZEOF,d0 ; taille de la zone à copier
CALL CopyMem,Exec.Base(pc)
move.l Dest.Gad+8(pc),a0
move.l a5,a1
CALL PutDiskObject,Icon.Base(pc) ; écrit la nouvelle icône
move.l a5,a0 ; libère la destination
CALL FreeDiskObject
.FreeSource
move.l a4,a0 ; libère la source
CALL FreeDiskObject
.DirBack
move.l d7,d1 ; revient au répertoire précédent
CALL CurrentDir,DOS.Base(pc)
.Error POP Copy
rts
Exec.Base Aptr 0
Intuition.Base Aptr 0
Workbench.Base Aptr 0
Icon.Base Aptr 0
GadTools.Base Aptr 0
DOS.Base Aptr 0
Screen.VI Aptr 0
Window.Window Aptr 0
AppWindow.Port Aptr 0
Window.AppWindow Aptr 0
Source.Gad Aptr 0 ; petite structure pour CopyArg()
Bptr 0 ; lock
Aptr 0 ; nom, alloué par AllocVec()
Dest.Gad Aptr 0 ; idem
Bptr 0
Aptr 0
Copy.Gad Aptr 0
Source.NewGad
dc.w 10,20,200,10
dc.l Source.Name,Topaz.Font
dc.w 0
dc.l PLACETEXT_BELOW,0,0
Dest.NewGad
dc.w 10,60,200,10
dc.l Dest.Name,Topaz.Font
dc.w 0
dc.l PLACETEXT_BELOW,0,0
YLIMIT EQU 59
Copy.NewGad
dc.w 70,100,80,10
dc.l Copy.Name,Topaz.Font
dc.w 0
dc.l PLACETEXT_IN,0,0
Source.Tags
Dest.Tags
dc.l GTTX_Border,1
dc.l TAG_DONE
Topaz.Font
Aptr Topaz.Name
Uword 8
Ubyte 0
Ubyte 0
INTNAME
WORKBENCH_NAME
ICONNAME
GADTOOLSNAME
DOSNAME
Window.Tags
dc.l WA_Width,220
dc.l WA_Height,120
IDCMP=BUTTONIDCMP!TEXTIDCMP!IDCMP_REFRESHWINDOW!IDCMP_CLOSEWINDOW
dc.l WA_IDCMP,IDCMP
dc.l WA_Flags,WFLG_DRAGBAR!WFLG_DEPTHGADGET!WFLG_CLOSEGADGET
dc.l WA_Gadgets
Window.GList Aptr 0
dc.l WA_Title,Window.Title
dc.l WA_ScreenTitle,Window.Title
dc.l WA_PubScreenName,Workbench.Name
dc.l TAG_DONE
Workbench.Name dc.b "Workbench",0
Source.Name dc.b "Source",0
Dest.Name dc.b "Destination",0
Copy.Name dc.b "Copy",0
Topaz.Name dc.b "topaz.font",0
Window.Title dc.b "IconCopy",0
|
|