
@++
ha ? plus simple que de redimensionner en verticale la barre de progression ?graph100 a écrit :c'est pas plus simple de mettre une sticky window sur la barre, de la faire suivre la position de la fenetre, et de dessiner dessus ?
en tout cas ça fonctionnerais sur tout les windows et ca ne scintillerais pas ^^
Code : Tout sélectionner
#PBM_GETRANGE = #WM_USER + 7
#PBM_GETSTEP = $040D ; Vista
#ICONSIZEX = 32
#ICONSIZEY = 32
#ICONNBFRAMES = 6 ; nombre de frames dans l'animation du curseur de progression
Structure addedWin_struct
hParentWnd.l
hProgressWnd.l
hAddedWnd.l
EndStructure
Global NewList addedWin.addedWin_struct()
EnableExplicit
Global numimage.i,hBitmap.i,hBrush.i,hIcon.i,iconStep.f
Procedure redrawProgressBar(hParentWnd.l,hwnd.l)
Protected rc.RECT,rcinv.RECT
Protected chaine.s
Protected lo.l,hi.l,valeur.l
Protected posX.f
Protected wndInfo.WINDOWINFO, refx.i, refy.i
Protected hDC.l,x.i,y.i
Protected iconX.i,iconY.i
Protected found.b
GetWindowInfo_(hParentWnd,wndInfo)
refX = wndInfo\rcClient\left
refY = wndInfo\rcClient\top
; récupérer les coordonnées de la barre
GetWindowRect_(hwnd,@rc)
valeur = SendMessage_(hwnd,#PBM_DELTAPOS,0,0)
chaine=Space(255)
; GetWindowText_(hParentWnd,@chaine,255)
; Debug " Progress bar trouvée : "
; Debug " Fenêtre : " + chaine
; Debug " Position: " + Str(rc\left)+","+Str(rc\top)
; Debug " Taille : " + Str(rc\right - rc\left)+","+Str(rc\bottom - rc\top)
; Debug " Valeur : " + Str(valeur)
; Valeurs minimum/maximum de la barre (ce n'est pas forcément 0 / 100)
lo = SendMessage_(hwnd,#PBM_GETRANGE,#True,0)
hi = SendMessage_(hwnd,#PBM_GETRANGE,#False,0)
; Calcul de la limite entre "fait" et "reste à faire"
posX = ((valeur - lo) / (hi - lo)) ; Pourcentage de progression
posX * (rc\right - rc\left) ; Avancement dans la barre (en pixels)
; Est-ce que l'on redessine déjà cette barre ?
ForEach addedWin()
If addedWin()\hProgressWnd = hwnd
found = #True
Break
EndIf
Next addedWin()
; Si ce n'est pas le cas, on le fait
If found = #False
AddElement(addedWin())
addedWin()\hParentWnd = hParentWnd
addedWin()\hProgressWnd = hwnd
addedWin()\hAddedWnd = CreateWindowEx_(0,"static","",#WS_CHILD|#WS_VISIBLE|#WS_CLIPCHILDREN,0,0,#ICONSIZEX,#ICONSIZEY,addedWin()\hParentWnd,0,GetModuleHandle_(0),0)
EndIf
; On récupère le DC de la fenêtre parente.
hDC = GetDC_( hParentWnd )
; On remplit la zone "faite" avec l'image chargée au démarrage du programme
SetRect_( @rcinv, (rc\left - refx),(rc\top - refy)+1,(rc\left - refx) + Int(posX), (rc\top - refy) + (rc\bottom - rc\top) - 2)
FillRect_(hDC, @rcinv, hBrush)
; On remplit la zone "reste à faire" avec du blanc
Rectangle_(hDC,(rc\left - refx) + Int(posX) + 1, (rc\top - refy) + 1,rc\right - refx - 1,rc\bottom - refy - 1)
; Et on relâche le contexte
ReleaseDC_(hParentWnd,hDC)
; On centre le curseur animé sur la progression
iconX = (rc\left - refx) + Int(posX) - 10
If iconX < rc\left - refx
iconX = rc\left - refx
ElseIf iconX > rc\right - refx - #ICONSIZEX + 1
iconX = rc\right - refx - #ICONSIZEX + 1
EndIf
iconY = (rc\top - refy) + ((rc\bottom - rc\top) - #ICONSIZEY) / 2 - 1
; Puis on bouge la fenêtre "static" au bon endroit et on dessine le cruseur dedans
SetWindowPos_(addedWin()\hAddedWnd,addedWin()\hProgressWnd,iconX,iconY,32,32,#SWP_NOSIZE)
hDC = GetDC_( addedWin()\hAddedWnd)
DrawIconEx_(hDC,0,0,hIcon,0,0,Int(iconStep),0,#DI_NORMAL)
ReleaseDC_(addedWin()\hAddedWnd,hDC)
RedrawWindow_(addedWin()\hAddedWnd,0,0, #RDW_INVALIDATE)
EndProcedure
; Enumère les fenêtres filles
Procedure.l EnumChildWindowProc(hwnd.l, hParentWnd.l)
Protected classe.s
; Tester si on se trouve sur une progress bar
If GetParent_(hWnd) = hParentWnd
classe=Space(100)
GetClassName_(hwnd, @classe, 100)
If classe = "msctls_progress32"
; Si oui, on la redessine
redrawProgressBar(hParentWnd,hwnd)
EndIf
ProcedureReturn 1
EndIf
EndProcedure
; Parcourt toutes les fenêtre visibles
Procedure listWindows()
Protected hwnd.l
hWnd = FindWindow_( 0, 0 )
While hWnd <> 0
If GetWindowLong_(hWnd, #GWL_STYLE) & #WS_VISIBLE = #WS_VISIBLE
If GetWindowLong_(hWnd, #GWL_EXSTYLE) & #WS_EX_TOOLWINDOW <> #WS_EX_TOOLWINDOW
EnumChildWindows_(hWnd, @EnumChildWindowProc(),hWnd)
EndIf
EndIf
hWnd = GetWindow_(hWnd, #GW_HWNDNEXT)
Wend
EndProcedure
;- ************* Main *************
; Créer une fenêtre avec une barre de progression, pour le test
DisableExplicit
OpenWindow(0,0,0,320,200,"test progress bar");,#PB_Window_Invisible|#PB_Window_NoGadgets)
numimage = CatchImage(#PB_Any,?progressPattern)
hBitmap = ImageID(numImage)
hBrush = CreatePatternBrush_(hBitmap)
; Est-ce possible de le charger à partir de la DataSection plutôt qu'à partir d'un fichier ?
iconname.s = "dog.ani"
hIcon = LoadImage_(0,@iconname,#IMAGE_ICON,0,0,#LR_LOADFROMFILE)
; Dessiner une barre de progression aux caractéristiques aléatoires
RandomSeed(ElapsedMilliseconds())
minvalue.i = Random(50)
maxvalue.i = minvalue + 50 + Random(200)
ProgressBarGadget(1,30,60,150 + Random(150),16,minvalue,maxvalue)
targetPos.i = maxvalue
currentPos.f = 20
Repeat
While WindowEvent()
Delay(2)
Wend
; je fais bouger la progress bar
If Int(currentPos) = targetPos
targetPos = minvalue + Random(maxvalue - minvalue)
Else
If currentPos < targetPos
currentPos + 0.1
Else
currentPos - 0.1
EndIf
EndIf
SetGadgetState(1,Int(currentPos))
; Et là, je pars à sa recherche dans les fenêtres de Windows pour la trouver et la redessiner
listWindows()
; On fait avancer l'animation d'un cran
iconstep + 0.25
If iconStep > #ICONNBFRAMES
iconStep = 0
EndIf
; Nettoyage de la liste des fenêtres ajoutées
ForEach addedWin()
If IsWindow_(addedWin()\hProgressWnd) = #False
; Pas forcément nécessaire (les fenêtre filles sont détruites avec la mère)
If IsWindow_(addedWin()\hAddedWnd) = #True
DestroyWindow_(addedWin()\hAddedWnd)
EndIf
DeleteElement(addedWin())
EndIf
Next addedWin()
Delay(25)
Until quit = 1
DestroyIcon_(hIcon)
DataSection
progressPattern:
IncludeBinary "dog.bmp"
EndDataSection
c'est peut etre a toi d'adapter la taille du chien ...kelebrindae a écrit :@Dobro:
Oui, redimensionner, c'est une idée.![]()
...Mais ça ne marche pas avec les barres de progression des autres applis (genre "copie dans l'explorateur").
Code : Tout sélectionner
dogani RCDATA "D:\\Programmation\\PureBasic\\projects\\Astuces\\dog.ani"
Code : Tout sélectionner
; But: Remplacer les barres de progression (toutes, pas seulement celles de ce programme)
; par une petite animation rigolote
; Version: PB 4.51
; Date: 01 août 2011
; Auteur: Kelebrindae
; Note: Ne fonctionne qu'avec Windows XP 32bits, car seul le contrôle "msctls_progress32"
; est géré.
;- Constantes, structures, globales
#PBM_GETRANGE = #WM_USER + 7
#ICONSIZEX = 32 ; Taille X du curseur de progression
#ICONSIZEY = 32 ; Taille Y du curseur de progression
#ICONNBFRAMES = 6 ; Nombre de frames dans l'animation du curseur de progression
#TESTMODE = #True ; Passez cette constante à #False pour que le programme fonctionne en "invisible"
; Liste des barres de progression redessinées
Structure progBar_struct
hParentWnd.i
hProgressWnd.i
hAddedWnd.i
EndStructure
Global NewList progBar.progBar_struct()
EnableExplicit
Global numimage.i,hBitmap.i,hBrush.i,hIcon.i ; Image de fond pour la barre, handles pour l'API
Global iconStep.f ; phase de l'animation
;- ********* Procedures *********
; Chargement d'un icone depuis les ressources. Merci au Dr Dri pour cette technique !
Procedure.i loadIconFromResources(iconName.s)
Protected ResourceID.i, iconData.i, iconSize.i
; Localiser les infos voulues dans les ressources et les charger
ResourceID = FindResource_(GetModuleHandle_(0), @iconName, #RT_RCDATA)
iconData = LoadResource_(GetModuleHandle_(0), ResourceID)
iconSize = SizeofResource_(GetModuleHandle_(0), ResourceID)
; Créer l'icône à partir de ces infos et retourner le handle
ProcedureReturn CreateIconFromResourceEx_(IconData, IconSize, #True, $00030000, 32, 32, #LR_DEFAULTCOLOR)
EndProcedure
; On redessine toutes les barres de progression répertoriées
; (ou plutôt, on dessine par-dessus)
Procedure redrawProgressBars()
Protected wndInfo.WINDOWINFO, refx.i, refy.i
Protected rc.RECT,rcinv.RECT
Protected lo.i,hi.i,valeur.i
Protected posX.f
Protected hDC.i,iconX.i,iconY.i
; On fait avancer l'animation d'un cran
iconstep + 0.25
If iconStep > #ICONNBFRAMES
iconStep = 0
EndIf
; Pour toutes les barres de la liste:
ForEach progBar()
; Si la barre n'existe plus, on la vire de la liste
If IsWindow_(progBar()\hProgressWnd) = #False
; Pas forcément nécessaire (les fenêtre filles sont détruites avec la mère)
If IsWindow_(progBar()\hAddedWnd) = #True
DestroyWindow_(progBar()\hAddedWnd)
EndIf
DeleteElement(progBar())
Break ; et on passe à la suivante
EndIf
; Coordonnées de la fenêtre parente
GetWindowInfo_(progBar()\hParentWnd,wndInfo)
refX = wndInfo\rcClient\left
refY = wndInfo\rcClient\top
; Coordonnées de la barre
GetWindowRect_(progBar()\hProgressWnd,@rc)
; Valeur actuelle de la progression
valeur = SendMessage_(progBar()\hProgressWnd,#PBM_DELTAPOS,0,0)
; Valeurs minimum/maximum de la barre (ce n'est pas forcément 0 / 100)
lo = SendMessage_(progBar()\hProgressWnd,#PBM_GETRANGE,#True,0)
hi = SendMessage_(progBar()\hProgressWnd,#PBM_GETRANGE,#False,0)
; Calcul de la limite entre "fait" et "reste à faire"
posX = ((valeur - lo) / (hi - lo)) ; Pourcentage de progression
posX * (rc\right - rc\left) ; Avancement dans la barre (en pixels)
; On récupère le DC de la fenêtre parente.
hDC = GetDC_( progBar()\hProgressWnd )
; On remplit la zone "faite" avec l'image chargée au démarrage du programme
SetRect_( @rcinv, 0,1,Int(posX),(rc\bottom - rc\top))
FillRect_(hDC, @rcinv, hBrush)
; On remplit la zone "reste à faire" avec du blanc
Rectangle_(hDC,Int(posX) + 1,0,(rc\right - rc\left),(rc\bottom - rc\top))
; Et on relâche le contexte
ReleaseDC_(progBar()\hProgressWnd,hDC)
; On centre le curseur animé sur la progression
iconX = (rc\left - refx) + Int(posX) - 10
If iconX < rc\left - refx
iconX = rc\left - refx
ElseIf iconX > rc\right - refx - #ICONSIZEX + 1
iconX = rc\right - refx - #ICONSIZEX + 1
EndIf
iconY = (rc\top - refy) + ((rc\bottom - rc\top) - #ICONSIZEY) / 2 - 1
; Puis on bouge la fenêtre "static" au bon endroit et on dessine le cruseur dedans
SetWindowPos_(progBar()\hAddedWnd,progBar()\hProgressWnd,iconX,iconY,32,32,#SWP_NOSIZE)
hDC = GetDC_( progBar()\hAddedWnd)
DrawIconEx_(hDC,0,0,hIcon,0,0,Int(iconStep),0,#DI_NORMAL)
ReleaseDC_(progBar()\hAddedWnd,hDC)
RedrawWindow_(progBar()\hAddedWnd,0,0, #RDW_INVALIDATE)
Next progBar()
EndProcedure
; Enumère les fenêtres filles
Procedure.i enumChildWindowProc(hwnd.i, hParentWnd.i)
Protected classe.s, found.b
; Tester si on se trouve sur une progress bar
If GetParent_(hWnd) = hParentWnd
classe=Space(100)
GetClassName_(hwnd, @classe, 100)
If classe = "msctls_progress32"
; Est-ce que l'on redessine déjà cette barre ?
ForEach progBar()
If progBar()\hProgressWnd = hwnd
found = #True
Break
EndIf
Next progBar()
; Si ce n'est pas le cas, on l'ajoute à la liste et on crée la fenêtre pour le curseur animé
If found = #False
AddElement(progBar())
progBar()\hParentWnd = hParentWnd
progBar()\hProgressWnd = hwnd
progBar()\hAddedWnd = CreateWindowEx_(0,"static","",#WS_CHILD|#WS_VISIBLE|#WS_CLIPCHILDREN,0,0,#ICONSIZEX,#ICONSIZEY,progBar()\hParentWnd,0,GetModuleHandle_(0),0)
EndIf
EndIf
ProcedureReturn 1
EndIf
EndProcedure
; Parcourt toutes les fenêtre visibles
Procedure findProgressBars()
Protected hwnd.i
hWnd = FindWindow_( 0, 0 )
While hWnd <> 0
If GetWindowLong_(hWnd, #GWL_STYLE) & #WS_VISIBLE = #WS_VISIBLE
If GetWindowLong_(hWnd, #GWL_EXSTYLE) & #WS_EX_TOOLWINDOW <> #WS_EX_TOOLWINDOW
EnumChildWindows_(hWnd, @EnumChildWindowProc(),hWnd)
EndIf
EndIf
hWnd = GetWindow_(hWnd, #GW_HWNDNEXT)
Wend
EndProcedure
;- ************* Main *************
; Créer une fenêtre avec une barre de progression, pour le test
DisableExplicit
CompilerIf #TESTMODE = #True
OpenWindow(0,0,0,320,200,"Détournement des barres de progression")
CompilerElse
OpenWindow(0,0,0,100,100,"",#PB_Window_Invisible)
CompilerEndIf
; Chargement de l'image qui sert de fond à la barre de progression
numimage = CatchImage(#PB_Any,?progressPattern)
hBitmap = ImageID(numImage)
hBrush = CreatePatternBrush_(hBitmap)
DeleteObject_(hBitmap)
FreeImage(numimage)
; Chargement du curseur animé
hIcon = loadIconFromResources("dogani")
; On aurait aussi pu charger l'icone depuis un fichier
; hIcon = LoadImage_(0,@"dog.ani",#IMAGE_ICON,0,0,#LR_LOADFROMFILE)
; Si on est en mode "Test", on dessine une barre de progression aux caractéristiques aléatoires
CompilerIf #TESTMODE = #True
RandomSeed(ElapsedMilliseconds())
minvalue.i = Random(50)
maxvalue.i = minvalue + 50 + Random(200)
ProgressBarGadget(1,30,20,150 + Random(150),13,minvalue,maxvalue)
targetPos.i = maxvalue
currentPos.f = minvalue
CompilerEndIf
; Boucle principale
Repeat
While WindowEvent()
Delay(2)
Wend
CompilerIf #TESTMODE = #True
; je fais bouger la progress bar
If Int(currentPos) = targetPos
targetPos = minvalue + Random(maxvalue - minvalue)
Else
If currentPos < targetPos
currentPos + 0.1
Else
currentPos - 0.1
EndIf
EndIf
SetGadgetState(1,Int(currentPos))
CompilerEndIf
; On parcourt les fenêtres de Windows pour trouver les barres de progression
findProgressBars()
; S'il y en a, on les redessine
If ListSize(progBar()) > 0
redrawProgressBars()
EndIf
; Laisser du temps, pour économiser le CPU
Delay(20)
ForEver
DeleteObject_(hBrush)
DestroyIcon_(hIcon)
;- Datas
DataSection
progressPattern:
IncludeBinary "dog.bmp"
EndDataSection
pourtant j'ai testé sous seven x64 avec winrar x64 cela fonctionne bienkelebrindae a écrit :@Graph100:
Merci, mais... 1080 Ko ? Ici, il ne prend que 508 Ko; bizarre.![]()
Et si tu testes sur Win7 64bits, c'est "normal" que ça ne trouve pas les barres de progression: je ne surveille que les contrôles "msctls_progress32", qui sont utilisés par XP.
au lieu de#TESTMODE = #True ; Passez cette constante à #False pour que le programme fonctionne en "invisible"
#TESTMODE = #True ; Passez cette constante à #Truepour que le programme fonctionne en "invisible"