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

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

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

Message 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
Dernière modification par kelebrindae le jeu. 04/août/2011 7:02, modifié 1 fois.
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

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

Message par graph100 »

effectivement ^^ c'est beaucoup mieux ! Beau Travail ;)
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

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

Message par Backup »

#TESTMODE = #True ; Passez cette constante à #true pour que le programme fonctionne en "invisible"
Hum !! :roll:
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

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

Message 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:
Dernière modification par Backup le jeu. 04/août/2011 7:14, modifié 2 fois.
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

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

Message 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... :?
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

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

Message 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:
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

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

Message 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é :!
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

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

Message 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" ?
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

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

Message 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 ? :)
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

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

Message 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
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

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

Message 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..).
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

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

Message par Backup »

ok! Merci :)
Répondre