[RESOLU] Indicateur animé durant traitement

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
Mindphazer
Messages : 695
Inscription : mer. 24/août/2005 10:42

Re: Indicateur animé durant traitement

Message par Mindphazer »

falsam a écrit :
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.
Si j'ai bien compris il utilise la commande CopyDirectory()
Il voudrait que son indicateur s'anime pendant l'exécution de cette commande
Bureau : Win10 64bits
Maison : Macbook Pro M3 16" SSD 512 Go / Ram 24 Go - iPad Pro 32 Go (pour madame) - iPhone 15 Pro Max 256 Go
Mesa
Messages : 1126
Inscription : mer. 14/sept./2011 16:59

Re: Indicateur animé durant traitement

Message par Mesa »

A l'arache:

Code : Tout sélectionner

; Tested on Windows XP Pro SP1

;**************************LA CHOSE A FAIRE******************************************
Global ProgressLimit = 100 ; nombre total de fichier à copier
Global dwCompleted = 1
Global compteur =0
Procedure copiedefichier(ProgressLimit)
  ;je simule ici la chose à faire, comme copier des fichiers par exemple
  
  ; ici code pour copier des fichiers
  ; je mets un delay pour simuler une copie de fichier
  Delay(100)
  
  compteur=compteur+1 ; le nombre de fichiers déjà copiés
  ProcedureReturn compteur
EndProcedure
;*********************************************************************


Procedure Ansi2Uni(st$)
  CompilerIf #PB_Compiler_Unicode ; Already in correct format, just copy it
    blen = (Len(st$)+1)*SizeOf(Character)
    wbuf = AllocateMemory(blen)
    CopyMemory(@st$, wbuf, blen)
  CompilerElse
    blen = (Len(st$)*2)+2
    wbuf = AllocateMemory(blen)
    MultiByteToWideChar_(#CP_ACP, 0, st$, -1, wbuf, blen)
  CompilerEndIf
  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.

; ProgressLimit = 1000

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, ProgressLimit)
      If dwCompleted>=ProgressLimit
        MessageRequester("Messsage", "Progress completed")
        Break
      Else
        ;*********************************************
        dwCompleted=copiedefichier(ProgressLimit); <== la chose à faire ici
                                                 ;**********************************************
        *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
Avatar de l’utilisateur
Zorro
Messages : 2186
Inscription : mar. 31/mai/2016 9:06

Re: Indicateur animé durant traitement

Message par Zorro »

le probleme c'est que CopyDirectory est tiré directement de l'API windows du meme nom

hors cette APi ne propose pas un retour d'activité
https://msdn.microsoft.com/fr-fr/librar ... .110).aspx

donc, si windows ne le propose pas, tu n'as pas d'autre choix que de passer par le systeme proposé par les autres membres
c'est a dire la copie du contenue d'une arborescence File par file !! (code Proposé par Falsam par exemple )
seulement là, tu peux gerer un affichage d'activité !!

:)

autre solution ,

juste avant la copy , tu lances une animation (un Gif Animé par exemple )
tu ajoutes un flag juste apres ton copydirectory
et tant que ce flag n'est pas positionné tu laisses l'animation
tu l' arretes seulement lorsque le Flag est positionné (donc apres la ligne copydirectory)

[reedit] je crois que c'est ce que Mesa propose .....
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: Indicateur animé durant traitement

Message par G-Rom »

Exactement le faire fichier par fichier, et même encore mieux, et c'est de cette façon que je procède pour les chargements volumineux tout en gardant la main sur le thread principal , et ce sans sous thread, je réimplemente la façon de lire un fichier, c'est à dire que je ne lis que des morceaux de fichiers d'une taille définie ( 4096 byte par exemple )
je continue de loadé tant que j'ai pas fini la lecture du fichier , ca me permet aussi de connaitre la progression par fichier , dès qu'un fichier est chargé , je "tir" un event qui me signale que le fichier est fini, si il en reste , je procède de la même manière avec le fichier suivant , etc... ca me permet de faire des jolis load screen, c'est aussi valable pour la copie de fichier, tu lis un morceau, tu copie un morceau , etc... & tu gardes la main sur ton programme , pas besoin de thread.
Avatar de l’utilisateur
omega
Messages : 633
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Indicateur animé durant traitement

Message par omega »

@Falsam
Quand tu copie un fichier tu le lis obligatoirement avant de faire cette copie. Je ne vois pas ou est le souci.
Ah bon? Pourquoi dois-je le lire? Je peux très bien le copier sans savoir ce qu'il contient !

Code : Tout sélectionner

;Copie de fichier sans le lire et sans savoir son contenu (il peut être vide d'ailleurs)
CopyFile(FichierSource$,FichierDestination$) 
;Copie d'un dossier sans savoir ce qu'il contient
CopyDirectory("D:\projet1\", "D:\projet2\", "")
Mon code (réel) existe plus haut sur mon topic

Je ne sais pas si tu me comprends Falsam, quand j'utilise une des copies ci-dessus, si le fichier est volumineux, cela pourrait prendre plusieurs minutes, pendant ce temps, j'aimerais bien qu'un indicateur soit affiché montrant que la copie est en train de s'effectuer...
J'ai une petite idée mais je n'ai pas trouvé sur google ce qu je cherche: il s'agit d'une image qui clignote (ou animée) que je place quelque part jusqu'à la fin de copie je la supprime. Une image comme des points ......, ou un petit carré coloré qui bouge en alternatif etc...
Win7 (x64) 64 bits Pb 5.72
Avatar de l’utilisateur
omega
Messages : 633
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Indicateur animé durant traitement

Message par omega »

Enfin vous m'avez compris !

Comme l'a dit Zorro, CopyDirectory ne permet pas d'effectuer un traitement en parallèle. La seule solution étant d'afficher une image animée par exemple comme je l'ai dit précédemment. Même cette image, enfin celle qui convient n'a pas été trouvée sur google mais je vais continuer à chercher surtout si je trouve des points qui s'affichent (comme durant le démarrage de windows) ça serait extra !
N'empêche que si quelqu'un trouve mieux, je suis preneur...

Merci à tous de m'avoir aidé, certains codes ici sont très intéressants...

Merci beaucoup
Win7 (x64) 64 bits Pb 5.72
Avatar de l’utilisateur
Zorro
Messages : 2186
Inscription : mar. 31/mai/2016 9:06

Re: Indicateur animé durant traitement

Message par Zorro »

va ici , il y a un max d'animation dans le style

https://icons8.com/preloaders/en/rectangular
ou ici:
https://icons8.com/preloaders/en/free

et bien voilaaaa !!
Image Image

ou bien :
Image Image

ça aussi c'est cool :

Image Image

:)

peut meme faire en 3d
Image Image

du texte:
Image


Image Image



Image

Image



exemple de mise en application (sans toucher au format Gif )
pour le codes suivant,il suffit de cliquer sur le bouton et attendre un peut
dans un premier temps , au début d'un traitement, les images s'affichent .....
puis lorsque c'est fini (le traitement virtuel) ; ça disparait :)

je me suis aidé d'un code de JHPJHP
http://forums.purebasic.com/english/vie ... 922d1f0b4d

voici comment utiliser les images de Purebasic avec un Gif Animé (et un Thread )
Version avec image en ligne (sur le Net)

Code : Tout sélectionner



UseGIFImageDecoder()



Enumeration
		#win
		#bouton
		#Gadget_Text    
		#gadget_g
		#image
EndEnumeration
Restore Sign:
Declare playanimation(*hgif)


; on precharge le Gif se trouvant sur le Net


AnimatedGIF.s = GetTemporaryDirectory() + "_test.gif"

If Not FileSize(AnimatedGIF) > 0
		InitNetwork()
		ReceiveHTTPFile("https://icons8.com/preloaders/preloaders/301/Windows8%20loader.gif", AnimatedGIF)
EndIf

If AnimatedGIF
		UseGIFImageDecoder()
		hGIF = LoadImage(#PB_Any, AnimatedGIF)
		
		If IsImage(hGIF)
				nWidth = ImageWidth(hGIF) : nHeight = ImageHeight(hGIF)
		ENdif
Endif
Global Thread



If OpenWindow(#win, 0, 0, 200, 300, "Signe d'attente.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
		ButtonGadget  (#bouton, 10, 10, 200, 20, "Cliquez moi")
		TextGadget(#Gadget_Text, 100, 50, 100, 35, "")
		
		ImageGadget(#Gadget_g, 50, 150, nWidth, nHeight, #Null)
		Thread=CreateThread(@PlayAnimation(), hGIF)
		HideGadget(#Gadget_g, #True) ; cache le gadget
		
		
		Repeat
				Event = WaitWindowEvent()
				Select Event
						Case #PB_Event_Gadget
						Select EventGadget()
								Case #bouton
								HideGadget(#Gadget_g, #False); montre le gadget
								
								; 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)   
										WindowEvent()
								Next i
								SetGadgetText(#Gadget_Text, "")   
								HideGadget(#Gadget_g, #True) ; cache le gadget
						EndSelect
				EndSelect
		Until Event = #PB_Event_CloseWindow
		If  IsThread(Thread)
				KillThread(Thread)
		Endif
		
		FreeImage(hGIF)
		
EndIf

; ********* Zone Procedures *******************
Procedure PlayAnimation(*hGIF)
		FrameCount = ImageFrameCount(*hGIF)
		
		Repeat
				For rtnCount = 0 To FrameCount - 1
						SetImageFrame(*hGIF, rtnCount)
						SetGadgetState(#Gadget_g, ImageID(*hGIF)) : Delay(40)
				Next
		ForEver
EndProcedure

DataSection
		sign:
		Data.s "|o---|"
		Data.s "|-o--|"
		Data.s "|--o-|"
		Data.s "|---o|"
		Data.s "|--o-|"
EndDataSection





mais si tu telecharges les images Gif, tu les met dans un dossiers "Images_loader"
alors, plus besoin de les telecharger , le code deviens celui-ci

Version avec images sur ton disque dur :

Code : Tout sélectionner



UseGIFImageDecoder()



Enumeration
		#win
		#bouton
		#Gadget_Text    
		#gadget_g
		#image
EndEnumeration
Restore Sign:
Declare playanimation(*hgif)

;{ si on veux charger a partir du Net
; on precharge le Gif se trouvant sur le Net


;AnimatedGIF.s = GetTemporaryDirectory() + "_test.gif"

; If Not FileSize(AnimatedGIF) > 0
; 		InitNetwork()
; 	;;	ReceiveHTTPFile("https://icons8.com/preloaders/preloaders/301/Windows8%20loader.gif", AnimatedGIF)
; EndIf
;}

;If AnimatedGIF
		UseGIFImageDecoder()
		hGIF = LoadImage(#PB_Any,GetCurrentDirectory()+"Images_loader/Windows8 loader.gif")
		
		If IsImage(hGIF)
				nWidth = ImageWidth(hGIF) : nHeight = ImageHeight(hGIF)
		ENdif
;Endif
Global Thread



If OpenWindow(#win, 0, 0, 200, 300, "Signe d'attente.", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
		ButtonGadget  (#bouton, 10, 10, 150, 20, "Cliquez moi")
		TextGadget(#Gadget_Text, 100, 50, 100, 35, "")
		
		ImageGadget(#Gadget_g, 50, 150, nWidth, nHeight, #Null)
		Thread=CreateThread(@PlayAnimation(), hGIF)
		HideGadget(#Gadget_g, #True) ; cache le gadget
		
		
		Repeat
				Event = WaitWindowEvent()
				Select Event
						Case #PB_Event_Gadget
						Select EventGadget()
								Case #bouton
								HideGadget(#Gadget_g, #False); montre le gadget
								
								; 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)   
										WindowEvent()
								Next i
								SetGadgetText(#Gadget_Text, "")   
								HideGadget(#Gadget_g, #True) ; cache le gadget
						EndSelect
				EndSelect
		Until Event = #PB_Event_CloseWindow
		If  IsThread(Thread)
				KillThread(Thread)
		Endif
		
		FreeImage(hGIF)
		
EndIf

; ********* Zone Procedures *******************
Procedure PlayAnimation(*hGIF)
		FrameCount = ImageFrameCount(*hGIF)
		
		Repeat
				For rtnCount = 0 To FrameCount - 1
						SetImageFrame(*hGIF, rtnCount)
						SetGadgetState(#Gadget_g, ImageID(*hGIF)) : Delay(40)
				Next
		ForEver
EndProcedure

DataSection
		sign:
		Data.s "|o---|"
		Data.s "|-o--|"
		Data.s "|--o-|"
		Data.s "|---o|"
		Data.s "|--o-|"
EndDataSection


Avatar de l’utilisateur
falsam
Messages : 7324
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Indicateur animé durant traitement

Message par falsam »

Nouveau code avec l'utilisation de CopyDirectory(). L'inconvénient de cette fonction est de ne pas pouvoir faire un log des dossiers et fichiers sauvegardés.

Durant le processus de sauvegarde, un progressbar sera animé.

Code : Tout sélectionner

EnableExplicit 

Enumeration Window
  #mf
EndEnumeration

Enumeration Gadget
  #mfStart
  #mfSelectSource
  #mfSelectTarget
  #mfLog
  #mfProgress
EndEnumeration

Global Token.b, Thread, Source.s, Target.s

;Plan application
Declare   Start()
Declare   SaveCreate()
Declare   StartThread(*Value)    
Declare   SaveRun()
Declare   SelectSource()
Declare   SelectTarget()
Declare   ProgressUpdate()
Declare   Exit()

;Option compilation  : [x] Thread
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,"Sauvegarde",#PB_Window_ScreenCentered | #PB_Window_SystemMenu)  
  
  AddWindowTimer(#mf, 0, 1)
  
  ButtonGadget(#mfSelectSource, 5, 5, 100, 22, "Dossier Source")
  ButtonGadget(#mfSelectTarget, 110, 5, 100, 22, "Unité Cible")
  
  ListViewGadget(#mfLog, 5, 30, 390,250)
  ProgressBarGadget(#mfProgress, 5, 290, 200, 24, 0, 100) 
  HideGadget(#mfProgress, #True)
  ButtonGadget(#mfStart, 325, 290, 70, 24, "Start") 
  
  ;Gestion des evenements 
  BindGadgetEvent(#mfSelectSource, @SelectSource())
  BindGadgetEvent(#mfSelectTarget, @SelectTarget())
  BindGadgetEvent(#mfStart, @SaveCreate())
  BindEvent(#PB_Event_CloseWindow, @Exit())
  
  Repeat : WaitWindowEvent(10) : ForEver
EndProcedure

Procedure SaveCreate()
  If Source <> "" And Target <> ""
    Thread = CreateThread(@StartThread(), 0)
  Else
    MessageRequester("Information", "Le dossier source ou cible n'est pas renseigné") 
  EndIf
EndProcedure

Procedure StartThread(*Value)   
  DisableGadget(#mfStart, #True)
  AddGadgetItem(#mfLog, -1, "Copie en cours .....")
  HideGadget(#mfProgress, #False)
  BindEvent(#PB_Event_Timer, @ProgressUpdate(), #mf, 0)
  
  SaveRun()
  
  UnbindEvent(#PB_Event_Timer, @ProgressUpdate())
  HideGadget(#mfProgress, #True)
  DisableGadget(#mfStart, #False)
  
  If Token 
    AddGadgetItem(#mfLog, -1, "Copie terminée .....")
  Else
    AddGadgetItem(#mfLog, -1, "Une erreur c'est produite durant la sauvegarde")
  EndIf
EndProcedure

Procedure SaveRun()  
  If CopyDirectory(Source, Target, "*.*", #PB_FileSystem_Recursive | #PB_FileSystem_Force)
    Token = #True
  Else
    Token = #False
  EndIf 
EndProcedure

Procedure SelectSource()
  Protected Selector.S = PathRequester("Sélectionner un dossier à copier", "")
  If Selector
    Source = Selector
    AddGadgetItem(#mfLog, -1, "Source : " + Source)
  EndIf  
EndProcedure

Procedure SelectTarget()
  Protected Selector.s = PathRequester("Sélectionner l'unité cible", "") 
  If Selector
    Target = Selector
    AddGadgetItem(#mfLog, -1, "Destination : " + Target)
  EndIf  
EndProcedure

Procedure ProgressUpdate()
  Static i
  i+1
  If i = 100
    i=0
  EndIf
  SetGadgetState(#mfProgress, i)
EndProcedure

Procedure Exit()  
  End  
EndProcedure
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
omega
Messages : 633
Inscription : sam. 26/nov./2011 13:04
Localisation : Alger

Re: Indicateur animé durant traitement

Message par omega »

Merci beaucoup pour ces deux codes que je trouve intéressants (celui de Zorro et celui de Falsam) les 2 me conviennent, il va falloir maintenant choisir entre les deux. Franchement, je trouve que les animations de Zorro sont super ! Merci pour ces deux liens Zorro, c'est exactement ce que je veux comme image (surtout les points formant un cercle, c'est super).

Merci à vous tous de m'avoir aidé et bonne continuation !
Win7 (x64) 64 bits Pb 5.72
Répondre