[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

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

Message par kelebrindae »

Bonjour,

Pour faire une farce à un collègue, j'ai eu une idée mais je ne sais pas si c'est réalisable.
Voilà l'idée:
1 - Pendant qu'il est absent, je lui mets dans son groupe de démarrage un petit programme PB qui tourne en mode "invisible".
2 - Ce programme scanne régulièrement toutes les fenêtres ouvertes dans Windows à la recherche d'un type de gadget particulier (les barres de progressions, en l'occurrence).
3 - Si le programme trouve un gadget de ce type, j'affiche par dessus une petite image rigolote, qui se déplace en même temps que la barre progresse.
4 - Moultes LoLeries

Voilà où j'en suis (une grosse partie de ce code a été trouvé dans ce forums, donc merci aux auteurs).
Qui pourra me dire comment récupérer la valeur d'une progress bar dans l'API Windows ?

Code : Tout sélectionner

EnableExplicit

; Enumère les fenêtres filles
Procedure.l EnumChildWindowProc(hwnd.l, hParentWnd.l)
  Protected classe.s, chaine.s, rc.RECT
  Protected windowX.w,windowY.w,windowWIDTH.w,windowHEIGHT.w
  Protected chaine_coords.s
  
  If GetParent_(hWnd) = hParentWnd
    classe=Space(100)
    chaine=Space(255)
    GetClassName_(hwnd, @classe, 100)
    GetWindowText_(hwnd,@chaine,255)
    GetWindowRect_(hwnd,@rc)  

    windowX = rc\left
    windowY = rc\top
    windowWIDTH = rc\right-rc\left
    windowHEIGHT = rc\bottom-rc\top
    chaine_coords = Str(windowX)+","+Str(windowY)+","+Str(windowWIDTH)+","+Str(windowHEIGHT)
    
    If classe = "msctls_progress32"
      GetWindowText_(hParentWnd,@chaine,255)
      Debug "   Progress bar trouvée : "
      Debug "      Fenêtre : " + chaine
      Debug "      Position: " + Str(windowX)+","+Str(windowY)
      Debug "      Taille  : " + Str(windowWIDTH)+","+Str(windowHEIGHT)     
      Debug " J'ai trouvé la Progress Bar, mais comment je récupère sa valeur ?"
    EndIf
  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

; Créer une fenêtre avec une barre de progression, pour le test
OpenWindow(0,0,0,320,200,"test progress bar")
ProgressBarGadget(1,5,5,200,20,0,100)
SetGadgetState(1,53) ; je la positionne arbitrairement à 53, juste pour le test

; Et là, je pars à sa recherche dans les fenêtres de Windows
listWindows()
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Avatar de l’utilisateur
Ar-S
Messages : 9539
Inscription : dim. 09/oct./2005 16:51
Contact :

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

Message par Ar-S »

ça peu être drôle, je ne suis pas assez connaisseur en API pour t'aider sur ce coup mais je vais suivre ce sujet.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
zaphod
Messages : 135
Inscription : dim. 07/déc./2008 9:32

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

Message par zaphod »

...
Dernière modification par zaphod le dim. 27/mai/2012 7:52, modifié 1 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 »

C'est tout-à-fait ça, Zaphod. Merci ! :D

Voilà un second code pour tester le principe.
Pour l'instant, ça ne fonctionne qu'avec la barre qui se trouve dans PB (puisque je fais le dessin avec un startdrawing de base), mais le résultat est là: je peux retrouver la barre de progression, récupérer sa valeur, et calculer où je dois dessiner.

Bon, maintenant, je n'ai plus qu'à trouver comment afficher une image dans (ou par-dessus) une autre fenêtre...
Je vais fouiller un peu dans les forums, mais si vous avez des pistes, je suis preneur ! :P

Code : Tout sélectionner

EnableExplicit

Procedure redrawProgressBar(hParentWnd.l,hwnd.l)
  Protected rc.RECT
  Protected chaine.s
  Protected oldrange.q,lo.l,hi.l,valeur.l
  Protected posX.f
  
  ; 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)
  
  ; Pour connaitre la position du bout de la barre, il faut avoir les valeurs 
  ; minimum/maximum de la barre (ce n'est pas forcément 0 / 100)
  ; Problème: je ne sais pas comment la récupérer sans la modifier (sendMessage_ renvoie la valeur avant modif')
  ;           => je dois donc repositionner les valeurs récupérées après
  oldrange = SendMessage_(hwnd,#PBM_SETRANGE32,0,valeur+1)
  lo = oldrange & %00000000000000001111111111111111
  hi  = (oldrange & %11111111111111110000000000000000) >> 16
  SendMessage_(hwnd,#PBM_SETRANGE32,lo,hi)
;   Debug "      Low     : " + Str(lo)
;   Debug "      Hi      : " + Str(hi)
  
  posX = ((valeur - lo) / (hi - lo)) ; Pourcentage de progression
  posX * (rc\right - rc\left) ; Avancement dans la barre (en pixels)
      
  ; Temporaire pour le test: ne fonctionne qu'avec la progress bar de la fenêtre PB en cours
  StartDrawing(WindowOutput(0))
    Box(rc\left,rc\bottom + 5,(rc\right - rc\left),10,$FFFFFF)
    Circle(rc\left + posX,rc\bottom + 9,4,$0000FF)
  StopDrawing()
  
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
  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")

; Dessiner une barre de progression aux caractéristiques aléatoires
RandomSeed(ElapsedMilliseconds())
minvalue.i = Random(50)
maxvalue.i = minvalue + Random(250)
ProgressBarGadget(1,30,60,100 + Random(150),Random(50),minvalue,maxvalue)

targetPos.i = 0
currentPos.f = 0
Repeat
  While WindowEvent()
  Wend
  
  ; je fais bouger la progress bar
  If Int(currentPos) = targetPos
    targetPos = minvalue + Random(maxvalue - minvalue)
    Delay(1000)
  Else
    
    If currentPos < targetPos
      currentPos + 0.01
    Else
      currentPos - 0.01
    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()
  
Until quit = 1
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
kwandjeen
Messages : 204
Inscription : dim. 16/juil./2006 21:44

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

Message par kwandjeen »

J'avais vu un code sur les fofos ou un type redessinait des boutons sur la calculatrice window.

J'essai de voir si je retrouve ça.

Edit : ce n'est pas le code que j'avais vu mais Dobro à un truc un peu similaire dans sa besace :wink:

Code : Tout sélectionner

; lire un pixel dans une autre application
FenExt = FindWindow_(#Null,"Calculatrice") ; Cherche la calculatrice.
FenExtDC = GetDC_( FenExt ) ; DC de la fenêtre.
x=10
y=10
couleur = GetPixel_( FenExtDC,x, y ) ; Lecture du pixel.


; ecrire un pixel dans une autre application
couleur=RGB(255,0,255)
;CallDebugger
FenExt = FindWindow_(#Null,"Calculatrice") ; Cherche la calculatrice.
FenExtDC = GetDC_( FenExt ) ; DC de la fenêtre.
For y=1 To 10
      For x=1 To 10
            SetPixel_( FenExtDC,x+i, y,RGB(255,0,255) ) ; Lecture du pixel.
      Next x
Next y

; ecrire un text dans une autre application..
LoadFont(1, "Comic Sans MS", 20)

Texte.s = "Dobro" ; le texte à afficher
SetBkMode_(FenExtDC, #TRANSPARENT) ; fond transparent
SetTextColor_(FenExtDC, RGB(0,200,0)) ; texte en vert
TextOut_(FenExtDC, 20, 5, Texte, Len(Texte)) ; affichage dans la calculatrice
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

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

Message par Backup »

....................
Dernière modification par Backup le ven. 30/sept./2011 19:51, modifié 1 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 »

@Kwandjeen & Dobro:
Ah oui, ça a l'air intéressant; je vais étudier ça de plus près.

De mon côté, j'ai fait quelques progrès: je peux créer un gadget (ici, pour le test, un bouton) dans une autre fenêtre et à l'endroit voulu.
Problème: pour l'instant, il s'affiche derrière la barre de progression et non par-dessus... :(

voici le code:

Code : Tout sélectionner

EnableExplicit

Structure addedWin_struct
  hParentWnd.l
  hProgressWnd.l
  hAddedWnd.l
EndStructure
Global NewList addedWin.addedWin_struct()


Procedure redrawProgressBar(hParentWnd.l,hwnd.l)
  Protected rc.RECT
  Protected chaine.s
  Protected oldrange.q,lo.l,hi.l,valeur.l
  Protected posX.f
  Protected found.b
  Protected wndInfo.WINDOWINFO, h.i
  
  GetWindowInfo_(hParentWnd,wndInfo)
  h = 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)
  
  ; Pour connaitre la position du bout de la barre, il faut avoir les valeurs 
  ; minimum/maximum de la barre (ce n'est pas forcément 0 / 100)
  ; Problème: je ne sais pas comment la récupérer sans la modifier (sendMessage_ renvoie la valeur avant modif')
  ;           => je dois donc repositionner les valeurs récupérées après
  oldrange = SendMessage_(hwnd,#PBM_SETRANGE32,0,valeur+1)
  lo = oldrange & %00000000000000001111111111111111
  hi  = (oldrange & %11111111111111110000000000000000) >> 16
  SendMessage_(hwnd,#PBM_SETRANGE32,lo,hi)
;   Debug "      Low     : " + Str(lo)
;   Debug "      Hi      : " + Str(hi)
  
  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,"button","X",#WS_CHILD|#WS_VISIBLE,rc\left + Int(posX),rc\top - h - 3,20,(rc\bottom - rc\top) + 6,hParentWnd,0,GetModuleHandle_(0),0)
  EndIf
  
  ; Repositionnement
  SetWindowPos_(addedWin()\hAddedWnd,addedWin()\hProgressWnd,rc\left + Int(posX),rc\top - h - 3,0,0,#SWP_NOSIZE|#SWP_FRAMECHANGED)
  
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
  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")

; Dessiner une barre de progression aux caractéristiques aléatoires
RandomSeed(ElapsedMilliseconds())
minvalue.i = Random(50)
maxvalue.i = minvalue + Random(250)
ProgressBarGadget(1,30,60,100 + Random(150),Random(50),minvalue,maxvalue)

targetPos.i = 0
currentPos.f = 0

currentPos = minvalue + Random(maxvalue - minvalue)
SetGadgetState(1,Int(currentPos))
  
  ; Et là, je pars à sa recherche dans les fenêtres de Windows pour la trouver et la redessiner
  listWindows()
  
Repeat
  While WindowEvent()
  Wend
  
  ; je fais bouger la progress bar
  If Int(currentPos) = targetPos
    targetPos = minvalue + Random(maxvalue - minvalue)
    Delay(1000)
  Else
    
    If currentPos < targetPos
      currentPos + 0.01
    Else
      currentPos - 0.01
    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()
   
   ; 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()
Until quit = 1
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Avatar de l’utilisateur
Progi1984
Messages : 2659
Inscription : mar. 14/déc./2004 13:56
Localisation : France > Rennes
Contact :

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

Message par Progi1984 »

#PBM_SETRANGE/#PBM_SETRANGE32 étant pour définir les valeurs minimale et maximale, #PBM_GETRANGE est donc pour les récupérer.

#PBM_GETRANGE : http://msdn.microsoft.com/en-us/library ... 85%29.aspx
#PBM_SETRANGE : http://msdn.microsoft.com/en-us/library ... 85%29.aspx
#PBM_SETRANGE32 : http://msdn.microsoft.com/en-us/library ... 85%29.aspx
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

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

Message par kelebrindae »

@Progi1984
Certes, mais "#PBM_GETRANGE" n'est pas définie dans PureBasic. Comment connaître sa valeur ? :?
[EDIT]: Je crois avoir trouvé et ça a l'air de marcher:

Code : Tout sélectionner

#PBM_GETRANGE = #WM_USER + 7
lo =  SendMessage_(hwnd,#PBM_GETRANGE,#TRUE,0)
hi =  SendMessage_(hwnd,#PBM_GETRANGE,#FALSE,0)
Sinon, voici une version prenant en compte les indications de Dobro.
Ce qui est marrant, c'est que si vous lancez en parallèle une copie d'un gros fichier dans l'explorateur (ou n'importe quoi qui affiche une barre de progression), le programme le prend en compte et en bidouille l'affichage. Normal, me direz-vous, mais ça fait quand même plaisir à voir... :wink:

[EDIT 18h40]: Petite modif' de l'affichage + effet "feu d'artifice" rudimentaire :roll:

Code : Tout sélectionner

#PBM_GETRANGE = #WM_USER + 7
#PBM_GETSTEP = $040D ; Vista

EnableExplicit

Structure addedWin_struct
  hParentWnd.l
  hProgressWnd.l
  hAddedWnd.l
  lo.i
  hi.i
EndStructure
Global NewList addedWin.addedWin_struct()

Structure sparkle_struct
  hWnd.l
  x.f
  y.f
  oldX.i
  oldY.i
  xd.f
  yd.f
  maxY.i
EndStructure
Global NewList sparkle.sparkle_struct()


Procedure redrawProgressBar(hParentWnd.l,hwnd.l)
  Protected rc.RECT,rcinv.RECT
  Protected chaine.s
  Protected oldrange.q,lo.l,hi.l,valeur.l
  Protected posX.f
  Protected found.b
  Protected wndInfo.WINDOWINFO, refx.i, refy.i
  Protected hDC.l,x.i,y.i,maxy.i

  GetWindowInfo_(hParentWnd,wndInfo)
  refx = wndInfo\rcClient\left
  refy = wndInfo\rcClient\top
  maxy = wndInfo\rcWindow\bottom - refy 
  
  ; 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)
  
  
  ; 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()\lo = 0
    addedWin()\hi = 100
    ;addedWin()\hAddedWnd = CreateWindowEx_(0,"button","X",#WS_CHILD|#WS_VISIBLE,rc\left- refX + Int(posX),rc\top - refY - 3,20,(rc\bottom - rc\top) + 6,hParentWnd,0,GetModuleHandle_(0),0)
  EndIf
  
  ; Valeurs minimum/maximum de la barre (ce n'est pas forcément 0 / 100)
  addedWin()\lo =  SendMessage_(hwnd,#PBM_GETRANGE,#True,0)
  addedWin()\hi =  SendMessage_(hwnd,#PBM_GETRANGE,#False,0)
  lo = addedWin()\lo
  hi = addedWin()\hi

  posX = ((valeur - lo) / (hi - lo)) ; Pourcentage de progression
  posX * (rc\right - rc\left) ; Avancement dans la barre (en pixels)
  
  ; Repositionnement
  ;SetWindowPos_(addedWin()\hAddedWnd,addedWin()\hProgressWnd,rc\left - refX + Int(posX),rc\top - refY - 3,0,0,#SWP_NOSIZE|#SWP_FRAMECHANGED)

  hDC = GetDC_( hParentWnd  ) ; DC de la fenêtre.
  For y=1 To (rc\bottom - rc\top) - 2
    For x=1 To Int(posX)
      SetPixel_(hDc,(rc\left - refx) + x, (rc\top - refy) + y,RGB((x * 3 + y * 7) % 255,(x * 11 - y * 3) % 255,(x * y) % 255) ) 
    Next x
  Next y
  Rectangle_(hDc,(rc\left - refx) + Int(posX) + 1, (rc\top - refy) + 1,rc\right - refx - 1,rc\bottom - refy - 1)
  
  If (valeur - lo) > 0 And Random(10000) > 6600
    AddElement(sparkle())
    sparkle()\hWnd = hParentWnd
    sparkle()\x = (rc\left) + Int(posX)
    sparkle()\y = (rc\top ) + (rc\bottom - rc\top)/2
    sparkle()\xd = (20 - Random(40)) / 10.0
    sparkle()\yd = Random(20) / -10.0
    sparkle()\maxY = maxy
    sparkle()\oldX = Int(sparkle()\x)
    sparkle()\oldY = Int(sparkle()\y)
  EndIf
  
  ForEach sparkle()
    If sparkle()\hWnd = hParentWnd
      sparkle()\x + sparkle()\xd 
      sparkle()\y + sparkle()\yd 
      If sparkle()\oldX <> Int(sparkle()\x) Or sparkle()\oldY <> Int(sparkle()\y)
        If sparkle()\y > sparkle()\maxY + refy
          DeleteElement(sparkle())
        Else          
          sparkle()\oldX = Int(sparkle()\x)
          sparkle()\oldY = Int(sparkle()\y)
          rcinv\left = sparkle()\oldX - refx
          rcinv\right = sparkle()\oldX - refx + 3
          rcinv\top = sparkle()\oldY - refy
          rcinv\bottom = sparkle()\oldY - refy + 3
          Rectangle_(hDC,rcinv\left,rcinv\top,rcinv\right,rcinv\bottom)
          InvalidateRect_(sparkle()\hWnd,@rcinv,1)
          sparkle()\yd + 0.1
        EndIf
      EndIf
    EndIf
  Next sparkle()
  ReleaseDC_(hParentWnd,hDC)
  
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)

; 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),50,minvalue,maxvalue)

targetPos.i = 0
currentPos.f = 0

  
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()
  
  ; 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
    
Dernière modification par kelebrindae le ven. 29/juil./2011 17:42, modifié 1 fois.
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 »

lorsque tu fais :

Code : Tout sélectionner

Repeat
  While WindowEvent()
 
fais toujours quivbre par un delay()

Code : Tout sélectionner

Repeat
  While WindowEvent()
  delay(2)
  Wend
sinon bonjour le temp machine bouffé par l'application ;)
kelebrindae
Messages : 579
Inscription : ven. 11/mai/2007 15:21

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

Message par kelebrindae »

Oups! C'est exact, je l'oublie trop souvent...
Merci.
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 »

sur mon win7 64b ça ne modifie pas les autre barres hors de la fenêtre.
mais sinon ca modifie celle de la fenetre. D'ailleurs elle n'a pas la meme taille lorsque le prog est lancé pendant qu'il y a une autre barre, c'est bizarre
_________________________________________________
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 »

graph100 a écrit :elle n'a pas la meme taille lorsque le prog est lancé pendant qu'il y a une autre barre, c'est bizarre
La barre de progression "test" a une taille aléatoire, de façon à vérifier que ça marche dans tous les cas; ce ne serait pas pour ça ?

Je n'ai testé que sur WinXP (32bits); ça demandera sans doute quelques adaptations pour le autres versions...
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 »

oui ca doit etre ça, (ca marche toujours pas sur 7 ^^)
_________________________________________________
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 »

Voici une version nettoyée et un peu moins coûteuse en CPU.
Vous aurez besoin des deux fichiers suivants, à placer dans le même répertoire de le programme:
http://keleb.free.fr/codecorner/downloa ... ic/dog.bmp
http://keleb.free.fr/codecorner/downloa ... ic/dog.ani

Mais j'ai un souci: l'image laisse des traces sur la fenêtre (le fond n'est pas restauré). Et si j'essaie d'y remédier avec des "invalidateRect_", ça clignote et ce n'est pas beau.
Auriez-vous des suggestions ?

Le code:

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

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

  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)
    
  
  ; 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)
  
  ; 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 
  
  DrawIconEx_(hDC,iconX,iconY,hIcon,0,0,Int(iconStep),0,#DI_NORMAL)

  ; Et on relâche le contexte
  ReleaseDC_(hParentWnd,hDC)
  
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 = 0
  
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
  
  Delay(25)
Until quit = 1

DestroyIcon_(hIcon)

DataSection
  progressPattern:
  IncludeBinary "dog.bmp"
  progressIcon:
  IncludeBinary "dog.ani"
EndDataSection
Les idées sont le souvenir de choses qui ne se sont pas encore produites.
Répondre