Page 3 sur 3

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : mer. 03/août/2011 7:45
par kelebrindae
Une petite mise à jour, qui réduit le scintillement du clébard: je ne le redessine que lorsque qu'il change de frame dans son animation (et non plus à chaque tour de boucle) => il ne clignote plus que 7 ou 8 fois par seconde, au lieu de 50 précédemment. 8)

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

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : mer. 03/août/2011 9:54
par graph100
effectivement ^^ c'est beaucoup mieux ! Beau Travail ;)

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : mer. 03/août/2011 20:21
par Backup
#TESTMODE = #True ; Passez cette constante à #true pour que le programme fonctionne en "invisible"
Hum !! :roll:

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : jeu. 04/août/2011 7:03
par Backup
du reste pour une raison que j'ignore ce dernier listing plante chez moi !

"Acces memoire invalide en ligne 44"

il semble que ce dernier listing n'arrive pas a charger l'animation du chien par le ressource
la ligne :

Code : Tout sélectionner

 ResourceID = FindResource_(GetModuleHandle_(0), @iconname, #RT_RCDATA)
me revoie ResourceID=0 , ce qui prouverai que ça deconne au ressource...
(le meme ressource fonctionnait avec l'autre version.. 8O )



(ça fonctionne par le chargement en fichier ..)

note que l'ancienne version , elle , fonctionnait ! ..avec le ressource "chien.rc"

j'ai fait une rapide comparaison , et franchement,.... je vois pas d'ou ça peut venir . :roll:

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : jeu. 04/août/2011 7:10
par kelebrindae
@Graph100: Merci ! :)

@Dobro:
Dobro a écrit :Hum !! :roll:
Arrrh! C'est revenu, ça? Mais d'où ça sort ?! :x
Enfin bon, c'est re-corrigé. Merci, Dobro.

Sinon, pour l'erreur ligne 44, je dois dire que je ne comprends pas trop: je ne crois pas avoir changé quoi que ce soit dans cette partie du code... :?

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : jeu. 04/août/2011 8:09
par Backup
je suis un âne !
j'avais oublié de declarer le fichier *.rc dans les option du projet de Jabpe :oops:

:lol: je prefere ça ! :)

ptain ! ça fait 2 jours que je cherche ! :lol:

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : jeu. 04/août/2011 10:43
par graph100
au fait, j'avais oublié ton programme, et je l'avais laissé fonctionner sur mon pc pendant un moment, jusqu'à ce qu'il plante soudainement avec la fenêtre de window sur les erreurs ;)
Donc il a peut etre fonctionné 45 min tout seul, mais il y a l'air d'avoir un problème de stabilité :!

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : jeu. 04/août/2011 15:11
par kelebrindae
Ah bon? Ici, il tourne sur un PC depuis deux jours non-stop (celui du collègue, justement) sans causer le moindre problème... Mais, encore une fois, je n'y connais rien en API Windows; j'oublie peut-être de libérer certains composants utilisés. :?

Tu as eu le souci en mode "Test" ou en mode "Invisible" ?

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : jeu. 04/août/2011 17:53
par Backup
perso en mode invisible, il tourne depuis ce matin , il est 18:53 pas de plantage ..
(xp SP3) ;)

dans le genre il faudrait un icone animé d'un petit bonhome qui tire a la corde
et nous le verrions alors, tirer sur la progression .. ça pourrai etre sympath :)

ps: les icones animé , c'est un format special , j'imagine ...
existe t'il un site specialisé la dedans ? :)

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : jeu. 04/août/2011 18:55
par GallyHC
je vais peu etre dire une betise mais pendant pas mal de temps les choses animer chez microsoft c'ete de simple avi.

Cordialement,
GallyHC

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : ven. 05/août/2011 7:29
par kelebrindae
Il faut plutôt chercher "curseur animé". Il y en a quelques uns ici :http://60gp.ovh.net/~toutla/graph/curseur.html et là: http://www.favorisxp.com/curseur-souris ... suite.html

Pour ce programme, j'ai utilisé un curseur animé trouvé dans un vieux jeu de Monopoly pour Windows 3.1, que j'ai modifié avec un freeware nommé "RealWorld Cursor Editor". Et il me semble avoir vu des utilitaires permettant de convertir un GIF animé en .ANI (mais il faudra alors bien respecter une taille Windows standard: 32x32, 48x48, 64x64, etc..).

Re: [API Windows] Lire la valeur d'une barre de progression

Publié : ven. 05/août/2011 10:55
par Backup
ok! Merci :)