Page 1 sur 2
[RESOLU] Indicateur animé durant traitement
Publié : mar. 07/nov./2017 21:57
par omega
Bonsoir,
La plupart des traitements nécessitant un indicateur utilisent un
ProgressBarGadget mais il y a des cas où il faudrait utiliser un indicateur spécial qui travaille en même temps que le traitement. Exemple:
Copie d'un dossier volumineux qui risque de prendre quelques minutes...
Je souhaiterais que, durant cette copie, un indicateur (animé ou progressif) sera utilisé comme par exemple les points utilisés par Microsoft durant le chargement de Windows, ou une minuscule image qui se déplace en alternance ou autre astuce de ce genre ...
Pour l'instant, j'utilise un message ("Copie en cours. Patientez...)
Quelqu'un a une idée?
Merci
Re: Indicateur animé durant traitement
Publié : mar. 07/nov./2017 22:38
par Ar-S
Un timer devrait faire l'affaire.. Toutes les 1sec il afficherait une image par ex l'image 1/5 si ton anim fait 5 images. puis 2/5 etc.. et à 5 tu réinitialises ton compteur.
Re: Indicateur animé durant traitement
Publié : mar. 07/nov./2017 22:51
par omega
Bonsoir Ar_s
Je comprends le principe, mais je ne sais pas où exactement faut-il mettre le timer par rapport à copydirectory()?
Merci
Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 1:18
par Ar-S
Tu crées un FLAG Marche Arret (#marche = 1 : #arret=0)
Allez, en gros un truc comme ça devrait marcher. J'ai pas testé.
Lorsque ta copie se termine, tu repasses ton
GO = #ARRET
Je ne sais pas si ça bloquerai le timer de lancer une copie de fichier je n'ai pas testé. Mais ça devrait le faire. De toute façon une grosse opération de copie devrait être gérée dans un
Thread afin de ne pas bloquer la fenêtre mère.
Code : Tout sélectionner
Enumeration
#win
#TXT
#BT_COPY
#AFFICHE
#T
EndEnumeration
Declare Fermer()
#MARCHE = 1
#ARRET = 0
Global.b GO,Compteur
Compteur = 1
;// FENETRE
If OpenWindow(#win, #PB_Ignore, #PB_Ignore, 250, 100, "Exemple timer", #PB_Window_SystemMenu)
TextGadget(#TXT,0,0,250,20,"Entrer le prénom désiré",#PB_Text_Center|#PB_Text_Border)
StringGadget(#AFFICHE,10,30,230,25,"",#PB_String_LowerCase)
ButtonGadget (#BT_COPY, 10, 60, 230, 30, "COPIER")
AddWindowTimer(#Win, #T, 1000)
BindEvent(#PB_Event_CloseWindow,@Fermer())
Repeat
Event = WindowEvent()
Select Event
; LA PARTIE TIMER
Case #PB_Event_Timer
If GO = #MARCHE
SetGadgetText(#affiche, "Affiche l'image " + Compteur)
Compteur + 1
If compteur = 5
Compteur = 1
EndIf
EndIf
; LA GESTION DES GADGETS
Case #PB_Event_Gadget
Select EventGadget()
Case #BT_COPY
SetWindowTitle(#win,"Copie en cours")
GO = #MARCHE
; TU LANCES TA COPIE ICI
EndSelect
EndSelect
Until quite = 1
End
EndIf
Procedure Fermer()
quite = 1
End
EndProcedure
Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 9:45
par Marc56
omega a écrit :
La plupart des traitements nécessitant un indicateur utilisent un ProgressBarGadget mais il y a des cas où il faudrait utiliser un indicateur spécial qui travaille en même temps que le traitement. Exemple:
Copie d'un dossier volumineux qui risque de prendre quelques minutes...
À la sortie de Windows 95, la petite animation de copie/déplacement de fichier/dossier (feuille qui passe d'un dossier à l'autre) était un simple fichier AVI. Je n'ai pas essayé, mais la lib movie devrait pourvoir l'afficher
Autre solution simple: Quand tu ne connais pas le nombre de fichier estimé tu peux quand même te servir de la progressbar en lui faisant faire
plusieurs tours complets (0, 25, 50, 75, 100%) à intervalle d'une seconde avec un timer. C'est comme ça que procèdent certains programmes.
PS. Ne pas oublier que la progressbar peut aussi être affichée dans la barre d'état, ça fait gagner de la place.
Autre solution: afficher puis effacer une image (un simple carré, généré au début du programme). Pareil, on peut le mettre en barre d'état.

Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 11:07
par Ar-S
Le même ex avec la progresse barre qui boucle. J'ai accéléré le timer.
Code : Tout sélectionner
Enumeration
#win
#TXT
#BT_COPY
#AFFICHE
#T
EndEnumeration
Declare Fermer()
#MARCHE = 1
#ARRET = 0
Global.b GO,Compteur
Compteur = 0
;// FENETRE
If OpenWindow(#win, #PB_Ignore, #PB_Ignore, 250, 100, "Exemple timer", #PB_Window_SystemMenu)
TextGadget(#TXT,0,0,250,20,"Entrer le prénom désiré",#PB_Text_Center|#PB_Text_Border)
StringGadget(#AFFICHE,10,30,230,25,"",#PB_String_LowerCase)
ProgressBarGadget(#AFFICHE, 10, 30, 230, 25, 0, 100,#PB_ProgressBar_Smooth)
SetGadgetState (#AFFICHE, 0)
ButtonGadget (#BT_COPY, 10, 60, 230, 30, "COPIER")
AddWindowTimer(#Win, #T, 70)
BindEvent(#PB_Event_CloseWindow,@Fermer())
Repeat
Event = WindowEvent()
Select Event
; LA PARTIE TIMER
Case #PB_Event_Timer
If GO = #MARCHE
SetWindowTitle(#win, "Copie en cours ...")
SetGadgetState (#AFFICHE, Compteur)
Compteur + 25
If compteur > 100
Compteur = 0
EndIf
EndIf
; LA GESTION DES GADGETS
Case #PB_Event_Gadget
Select EventGadget()
Case #BT_COPY
SetWindowTitle(#win,"Copie en cours")
GO = #MARCHE
; TU LANCES TA COPIE ICI
EndSelect
EndSelect
Until quite = 1
End
EndIf
Procedure Fermer()
quite = 1
End
EndProcedure
Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 11:16
par Zorro
Depuis des lustres, j'aime utiliser le principe suivant
faire afficher (dans la boucle de traitement par exemple ) ceci
Print "/" puis
Print "-" puis
Print "\" puis
Print"|"
ce qui donne l'impression d'un petit baton qui tourne sur lui meme (Old School Power )

c'est ce que je fais dans EPB lorsqu'on effectue une recherche d'un terme dans les fichiers ....
dans le meme esprit on peut aussi faire
Print "|o---|"
Print "|-o--|"
Print "|--o-|"
Print "|---o|"
Print "|--o-|"
Print "|-o--|"
ce qui en code Purebasic donne ceci : (Cliquez sur le bouton pour simuler un traitement )
Code : Tout sélectionner
Enumeration
#win
#bouton
#Gadget_Text
EndEnumeration
Restore Sign:
If OpenWindow(#win, 0, 0, 230, 90, "Signe d'attente.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget (#bouton, 10, 10, 200, 20, "Cliquez moi")
TextGadget(#Gadget_Text, 100, 50, 100, 35, "")
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
Select EventGadget()
Case #bouton
; boucle de traitement
For i=1 to 50000
compteur_sign=compteur_sign+1
if compteur_sign=5:compteur_sign=1:Restore Sign :Endif
Read.s sig.s
SetGadgetText(#Gadget_Text, sig.s)
Delay(60)
Next i
SetGadgetText(#Gadget_Text, "")
EndSelect
EndSelect
Until Event = #PB_Event_CloseWindow
EndIf
DataSection
sign:
Data.s "|o---|"
Data.s "|-o--|"
Data.s "|--o-|"
Data.s "|---o|"
Data.s "|--o-|"
EndDataSection
Exemple double :
Code : Tout sélectionner
Enumeration
#win
#bouton
#Gadget_Text
#Gadget_Text2
EndEnumeration
If OpenWindow(#win, 0, 0, 230, 290, "Signe d'attente.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget (#bouton, 10, 10, 200, 20, "Cliquez moi")
TextGadget(#Gadget_Text, 100, 50, 100, 35, "")
TextGadget(#Gadget_Text2, 100, 150, 100, 35, "")
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Gadget
Select EventGadget()
Case #bouton
; boucle de traitement
For i=1 to 50
Restore Sign:
compteur_sign=compteur_sign+1
if compteur_sign=5:compteur_sign=1:Restore Sign :Endif
For uu=1 to compteur_sign
Read.s sign.s
Next uu
SetGadgetText(#Gadget_Text, sign.s)
Delay(60)
Restore Sign2:
compteur_sign2=compteur_sign2+1
if compteur_sign2=4:compteur_sign2=1:Restore Sign2: :Endif
For uu=1 to compteur_sign2
Read.s sign2.s
Next uu
SetGadgetText(#Gadget_Text2, sign2.s)
Delay(60)
Next i
SetGadgetText(#Gadget_Text, "")
SetGadgetText(#Gadget_Text2, "")
EndSelect
EndSelect
Until Event = #PB_Event_CloseWindow
EndIf
DataSection
sign:
Data.s "|o---|"
Data.s "|-o--|"
Data.s "|--o-|"
Data.s "|---o|"
Data.s "|--o-|"
;
Sign2:
Data.s "/"
Data.s "-"
Data.s "\"
Data.s "|"
EndDataSection
Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 13:24
par Ar-S
Je ne suis pas du tout fan de tes 2 "delay", surtout pour faire une copie en tâche de fond. Cette même version avec un timer serait préférable non ?
Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 13:29
par Zorro
le delay(60) est là pour simuler une occupation
sans, l'affichage clignote fortement ....
la boucle est un simulateur qui est la pour remplacer "simuler" un traitement, ça montre le principe
utilisé pour afficher au fur et a mesure d'un traitement (ici une boucle avec Delay)
Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 14:23
par omega
Merci à vous tous
C'est bien beau tout ça, mais mon problème ne se situe pas à faire apparaître un indicateur qui bouge ou qui change de couleur etc...
Le problème c'est de le faire PENDANT LA COPIE DE DOSSIER ! Pendant la copie de mon dossier (CopyDirectory), je voudrais que l'indicateur (n'importe lequel) soit activé (il bouge, change de couleur, image qui se déplace aucune importance, l'essentiel c'est que cet indicateur est activé au moment de la copie et il s'arrête à la fin de la copie, je ne sais pas si je suis clair. Je n'ai pas encore testé le code de Ar_s (utilisation d'un timer) mais je crois que cette méthode pourrait répondre à mon attente..
En attendant, je vais la tester
[WIndows] Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 14:35
par Mesa
Windows a une boîte de dialogue fait pour:
Code : Tout sélectionner
; Tested on Windows XP Pro SP1
Procedure Ansi2Uni(st$)
blen = (Len(st$)*2)+2
wbuf = AllocateMemory(blen)
MultiByteToWideChar_(#CP_ACP, 0, st$, -1, wbuf, blen)
ProcedureReturn wbuf
EndProcedure
#CLSCTX_INPROC_SERVER = 1
#PROGDLG_NORMAL = 0
#PROGDLG_AUTOTIME = 2
#PDTIMER_RESET = 1
#IDA_COPY_ANIMATION = 160 ; AVI file resource ID (I use an arbitrary constant name)
; This one is from shell32.dll.
; You can use any AVI file resource as long as it's
; uncompressed or RLE8 compressed, silent and
; smaller or equal to 272 by 60 pixels in size.
CoInitialize_(0)
hr = CoCreateInstance_(?CLSID_ProgressDialog, #Null, #CLSCTX_INPROC_SERVER, ?IID_IProgressDialog, @ppv.IProgressDialog)
If hr=#S_OK
*Title = Ansi2Uni("System progress dialog box")
ppv\SetTitle(*Title)
hShell = OpenLibrary(0, "shell32.dll")
If hShell
ppv\SetAnimation(hShell, #IDA_COPY_ANIMATION)
EndIf
*Cancel = Ansi2Uni("Cancel")
ppv\SetCancelMsg(*Cancel, 0)
*Line1 = Ansi2Uni("System progress dialog test in PureBasic")
ppv\SetLine(1, *Line1, #True, 0)
ppv\StartProgressDialog(#Null, 0, #PROGDLG_AUTOTIME|#PROGDLG_NORMAL, 0)
ppv\Timer(#PDTIMER_RESET, 0)
Repeat
If ppv\HasUserCancelled()
MessageRequester("Messsage", "Progress cancelled")
Break
Else
ppv\SetProgress(dwCompleted, 100)
If dwCompleted>=100
MessageRequester("Messsage", "Progress completed")
Break
Else
dwCompleted+1
*Line2 = Ansi2Uni("We are at progress point number "+Str(dwCompleted))
ppv\SetLine(2, *Line2, #True, 0)
FreeMemory(*Line2)
EndIf
EndIf
Delay(100)
ForEver
ppv\StopProgressDialog()
ppv\Release()
FreeMemory(*Title)
FreeMemory(*Cancel)
FreeMemory(*Line1)
If hShell:CloseLibrary(0):EndIf
Else
Debug Hex(hr)
EndIf
CoUninitialize_()
DataSection
CLSID_ProgressDialog:
Data.l $F8383852
Data.w $FCD3, $11D1
Data.b $A6, $B9, 0, $60, $97, $DF, $5B, $D4
IID_IProgressDialog:
Data.l $EBBC7C04
Data.w $315E, $11D2
Data.b $B6, $2F, 0, $60, $97, $DF, $5B, $D4
EndDataSection
M.
Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 14:45
par omega
@Mesa
J'ai testé ton code et ça marche, la boite de dialogue est affichée mais ... il y a un mais:
1. Est ce que la vitesse et le nombre de déplacements de l'indicateur a une relation avec la copie? si oui comment ?
2. Où dois-je placer ce code? et où dois-je placer la copie?
Merci de m'éclairer
Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 14:56
par falsam
Je te propose ce code qui ne copie pas de fichiers. Il s'agit d'une lecture récursive d'un dossier et ses sous-dossiers.
J'ai limité la lecture des fichiers à 5000 fichiers.
Clique sur le bouton OnOff pour activer ou désactiver la lecture.
A compiler avec l'option de compilation Thread activé. Si tu ne le fais pas, tu auras un message te demandant de le faire.
Code : Tout sélectionner
Enumeration Window
#mf
EndEnumeration
Enumeration Gadget
#mfOnOff
#mfListFolder
#mfCountFiles
#mfProgress
EndEnumeration
;Déclaration des variables
Global OnOff.b ;Interupteur OnOff (#True, #False)
Global CountFiles.i ;Compteur de fichiers
Global Thread
;Plan application
Declare Start()
Declare OnOff()
Declare StartThread(*Value)
Declare.s ParseDirectory(folder.s, id.l = 0)
Declare Resize()
Declare Exit()
CompilerIf Not #PB_Compiler_Thread
CompilerError "L'option activer la gestion des thread doit etre activer!"
CompilerEndIf
;Appel de la procédure Start
Start()
;Affichage de l'application
Procedure Start()
OpenWindow(#mf, 0, 0, 400, 320,"Lecture d'un dossier(Thread)",#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget)
WindowBounds(#mf, 300, 320, #PB_Ignore, #PB_Ignore)
TextGadget(#PB_Any, 5, 10, 120, 20, "Nombre de fichiers lus")
TextGadget(#mfCountFiles, 130, 10, 80, 20, "0", #PB_Text_Right)
ListIconGadget(#mfListFolder, 5, 30, 390,250, "Dossier", 200)
AddGadgetColumn(#mfListFolder, 1, "Fichiers",200)
ProgressBarGadget(#mfProgress, 5, 290, 200, 24, 0, 100)
HideGadget(#mfProgress, #True)
ButtonGadget(#mfOnOff, 325, 290, 70, 24, "On/Off")
;Gestion des evenements
BindGadgetEvent(#mfOnOff, @OnOff()) ;Si clique sur le bouton OnOff, appel de la procedure OnOff
BindEvent(#PB_Event_SizeWindow, @Resize()) ;Redimentionner les gadgets de la fenêtre
BindEvent(#PB_Event_CloseWindow, @Exit()) ;Si fermeture alors appel à la procedure Exit()
Repeat : WaitWindowEvent(10) : ForEver
EndProcedure
;Procédure appelée quand on clique sur le bouton OnOff
Procedure OnOff()
If OnOff = #False
ClearGadgetItems(#mfListFolder)
CountFiles=0
OnOff = #True
HideGadget(#mfProgress, #False)
Thread = CreateThread(@StartThread(), 0)
Else
OnOff = #False
HideGadget(#mfProgress, #True)
EndIf
EndProcedure
Procedure StartThread(*Value)
;On lance la lecture des fichiers
ParseDirectory(GetEnvironmentVariable("USERPROFILE"))
;Une boucle d'attente quand que la variable OnOff reste à #True
While OnOff = #True : Wend
EndProcedure
;Parcourir un dossier (Fonction recurssive by Flype il me semble)
Procedure.s ParseDirectory(folder.s, id.l = 0)
Static Progress
If Right(folder, 1) <> "\"
folder + "\"
EndIf
If ExamineDirectory(id, folder, "*.*")
While NextDirectoryEntry(id) And OnOff = #True
If DirectoryEntryName(id) <> "." And DirectoryEntryName(id) <> ".."
AddGadgetItem(#mfListFolder,-1, folder + Chr(10) + DirectoryEntryName(id))
;Affichage du coompteur de fichiers
CountFiles + 1
SetGadgetText(#mfCountFiles, Str(CountFiles))
;Mettre à jour le ProgressBar (Inutile de le créer à nouveau)
If CountFiles >= 5000
OnOff()
EndIf
;Mettre à jour le ProgressBar
Progress + 1
If Progress = 1001
Progress = 0
EndIf
SetGadgetState(#mfProgress, Progress/10)
If DirectoryEntryType(id) = #PB_DirectoryEntry_Directory
ParseDirectory(folder + DirectoryEntryName(id), id + 1)
EndIf
EndIf
Wend
FinishDirectory(id)
EndIf
EndProcedure
Procedure Resize()
Protected WWidth=WindowWidth(#mf)
Protected Wheight=WindowHeight(#mf)
ResizeGadget(#mfListFolder, #PB_Ignore, #PB_Ignore , WWidth-10, Wheight-75)
ResizeGadget(#mfProgress, #PB_Ignore, Wheight-30 , #PB_Ignore, #PB_Ignore)
ResizeGadget(#mfOnOff, WWidth - 75, Wheight-30 , #PB_Ignore, #PB_Ignore)
EndProcedure
Procedure Exit()
If IsThread(Thread)
KillThread(Thread)
EndIf
End
EndProcedure
Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 15:02
par omega
@Falsam
Merci quand même pour ton aide mais, encore une fois, je répète que mon problème réside UNIQUEMENT quand il s'agit de faire une copie. C'est différent. Quand il s'agit de lire des fichiers un par un, là le problème ne se pose pas, je peux manipuler facilement un ProgressBarGadget (d'ailleurs il est fait pour ça).
Merci encore
Re: Indicateur animé durant traitement
Publié : mer. 08/nov./2017 15:06
par falsam
je répète que mon problème réside UNIQUEMENT quand il s'agit de faire une copie.
Quand tu copie un fichier tu le lis obligatoirement avant de faire cette copie. Je ne vois pas ou est le souci.
Montre nous un code dans ce cas.