
Voici l'EXE mis à jour:
http://keleb.free.fr/codecorner/downloa ... bmng32.exe
et le code:
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
Protected oldiconStep.i,redrawDog.b
; On fait avancer l'animation d'un cran
oldiconStep = Int(iconStep)
iconstep + 0.15
If iconStep > #ICONNBFRAMES
iconStep = 0
EndIf
If oldiconStep <> Int(iconStep)
redrawDog = #True
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)
If redrawDog = #True
RedrawWindow_(progBar()\hAddedWnd,0,0, #RDW_INVALIDATE)
EndIf
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|#WS_EX_TRANSPARENT,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