[R] Fonctions AdlibRegister() imbriquées

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
jpascal
Niveau 6
Niveau 6
Messages : 239
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

[R] Fonctions AdlibRegister() imbriquées

#1

Message par jpascal »

Bonjour,

J'utilise plusieurs fonctions _AnimXXX() permettant d'afficher une animation. Ces fonctions utilisent AdlibRegister() et AdlibUnRegister()
Si j'utilise ces fonctions dans une fonction lancée elle-même par un AdlibRegister(), cela ne fonctionne plus. Plus exactement, la fonction _AnimPlay() ne semble pas être exécutée.

Est-ce une limitation ? Y a-t-il une erreur dans mon code ?
Main()

Func Main()
   MsgBox(0, '', 'sans AdlibRegister() : OK')
   Test()

   ConsoleWrite('' & @CRLF)

   MsgBox(0, '', 'avec AdlibRegister() : BAD')
   AdlibRegister('Test')

   Sleep(5000)
EndFunc   ;==>Main

Func Test()
   AdlibUnRegister()
   _AnimStart()
   Sleep(2000)
   _AnimStop()
EndFunc   ;==>Test

Func _AnimStart()
   ConsoleWrite('START' & @CRLF)
   AdlibRegister("_AnimPlay", 10)
EndFunc   ;==>_AnimStart

Func _AnimStop()
   AdlibUnRegister("_AnimPlay")
   ConsoleWrite('STOP' & @CRLF)
EndFunc   ;==>_AnimStop

Func _AnimPlay()
   AdlibUnRegister()
   ConsoleWrite('PLAY' & @CRLF)
   AdlibRegister("_AnimPlay", 10)
EndFunc   ;==>_AnimPlay
Modifié en dernier par jpascal le mar. 30 juil. 2024 09:30, modifié 1 fois.
AutoIt 3.3.16.1 - AutoIt3Wrapper 21.316.1639.1
Avatar du membre
Nine
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 116
Enregistré le : ven. 17 avr. 2020 01:23
Localisation : Montréal, Québec
Status : Hors ligne

Re: [..] Fonctions AdlibRegister() imbriquées

#2

Message par Nine »

L'utilisation de AdlibUnRegister() sans paramètre est plutôt risquée si tu as plusieurs timers à la fois. Si c'est pour afficher des GIF je te suggère mon UDF (voir le site anglo)
Avatar du membre
TommyDDR
Modérateur
Modérateur
Messages : 2093
Enregistré le : mar. 22 juil. 2008 21:55
Localisation : Nantes
Status : Hors ligne

Re: [..] Fonctions AdlibRegister() imbriquées

#3

Message par TommyDDR »

AdlibRegister n'est pas fait pour être utilisé de cette façon.
La doc précise : "La fonction adlib doit être le plus simple possible car elle est exécutée souvent et que pendant son temps d'exécution le script principal est mis en pause."

Comme vous l'avez remarqué, quand une fonction appelée par un AdlibRegister, utilise elle même un AdlibRegister, celui-ci n'est pas exécuté car il me semble que la routine qui vérifie si les xxx millisecondes se sont bien écoulées pour éxécuter la fonction associée au AdlibRegister s'exécute dans "le script principal".

Essayez de supprimer la ligne 19 (_AnimStop()) vous verrez que lorsque vous sortez de votre fonction "test" et que vous revenez dans votre programme principal, le _AnimPlay est bien appelé
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
jpascal
Niveau 6
Niveau 6
Messages : 239
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

Re: [..] Fonctions AdlibRegister() imbriquées

#4

Message par jpascal »

Bonjour messieurs,

Merci pour vos réponses instructives.

J'ai découvert avec bonheur l'UDF de Nine (https://www.autoitscript.com/forum/topi ... on-cached/)

Je fais cependant face à un problème insoluble.
Comme il est recommandé de ne pas utiliser de fonctions bloquantes dans WM_NOTIFY(), j'ai pris la (mauvaise ?) habitude d'utiliser AdlibRegister().
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
...
      Case $idListview
         Switch $iCode
            Case $NM_CLICK
AdlibRegister('MaFonction')
...
EndFunc

Func MaFonction()
AdlibUnregister()
...
EndFunc

J'ai pensé que l'UDF de Nine allait fonctionner car le chargement du GIF animé, même s'il utilise AdlibRegister()
  ; if first GIF, start the timer
  If UBound($aGIF_Animation) = 1 Then AdlibRegister(__GIF_Animation_DrawTimer, 10)
  Return $idPic

EndFunc   ;==>_GUICtrlCreateAnimGIF
... est initialisé avant l'utilisation de WM_NOTIFY() et ensuite, le code est un simple :
Func Test()
   AdlibUnRegister('Test')

   GUICtrlSetState($idPic_AnimGIF, $GUI_SHOW)
   For $i = 1 To 4
      Sleep(500)
      ConsoleWrite($i & @CRLF)
   Next
   GUICtrlSetState($idPic_AnimGIF, $GUI_HIDE)
EndFunc   ;==>Testc
mais cela ne fonctionne pas.

Si je remplace AdlibRegister('Test') par Test() dans WM_NOTIFY(), cela fonctionne.

De plus, si je lance AdlibRegister('Test') après _GUICtrlCreateAnimGIF() pour tester simplement sans ajouter de contrainte supplémentaire, cela ne fonctionne pas non plus.

Du coup le problème ne vient pas seulement de l'imbrication des fonctions AdlibRegister() ?!


AVANT DE POSTER ce message, j'ai quand même préféré tester avec un code simple (celui fourni par Nine avec son UDF) et je ne rencontre pas le problème.
#include <GUIConstants.au3>
#include <Constants.au3>
#include "Cached GIF Animation.au3"
#include <WinAPISysWin.au3>

OnAutoItExitRegister(_GIF_Animation_Quit)

Global $hGUI = GUICreate("GIF Animation", 500, 500, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
GUISetBkColor(0xFFFFFF)
Global $IMG_Ctrl1 = _GUICtrlCreateAnimGIF("9.gif", 150, 0, 192, 172, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl2 = _GUICtrlCreateAnimGIF("gif-Green-UFO.gif", 0, 180, 150, 80, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl3 = _GUICtrlCreateAnimGIF("Catalog.gif", 160, 180, 320, 184, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl4 = _GUICtrlCreateAnimGIF("Kafu.gif", 30, 260, 90, 90, -1, $GUI_WS_EX_PARENTDRAG)
Local $idButton = GUICtrlCreateButton("Hide", 10, 10, 80, 30)
Local $idQuit = GUICtrlCreateButton("Quit", 10, 50, 80, 30)
Local $idAdlib = GUICtrlCreateButton("Adlib", 10, 90, 80, 30)

_WinAPI_SetLayeredWindowAttributes($hGUI, 0xFFFFFF)

GUISetState(@SW_SHOW, $hGUI)

Local $aCaption[4] = ["Show", "Delete", "Recreate", "Hide"], $iCounter = -1


While True
   Switch GUIGetMsg()
      Case $GUI_EVENT_CLOSE, $idQuit
         ExitLoop
      Case $idAdlib
         AdlibRegister('Test')
      Case $idButton
         $iCounter += 1
         $iCounter = Mod($iCounter, 4)
         GUICtrlSetData($idButton, $aCaption[$iCounter])
         Switch $iCounter
            Case 0 ; hide
               GUICtrlSetState($IMG_Ctrl2, $GUI_HIDE)
            Case 1 ; show
               GUICtrlSetState($IMG_Ctrl2, $GUI_SHOW)
            Case 2 ; delete
               _GUICtrlDeleteAnimGIF($IMG_Ctrl2)
            Case 3 ; recreate
               $IMG_Ctrl2 = _GUICtrlCreateAnimGIF("gif-Green-UFO.gif", 0, 180, 150, 80, -1, $GUI_WS_EX_PARENTDRAG)
               _WinAPI_SetLayeredWindowAttributes($hGUI, 0xFFFFFF)
         EndSwitch
   EndSwitch
WEnd

_GIF_Animation_Quit()


Func Test()
   AdlibUnRegister('Test')

   GUICtrlSetState($IMG_Ctrl2, $GUI_HIDE)
   For $i = 1 To 3
      Sleep(500)
      ConsoleWrite($i & @CRLF)
   Next
   GUICtrlSetState($IMG_Ctrl2, $GUI_SHOW)
EndFunc   ;==>Test

Je cherche...
Modifié en dernier par jpascal le lun. 29 juil. 2024 12:21, modifié 1 fois.
AutoIt 3.3.16.1 - AutoIt3Wrapper 21.316.1639.1
jpascal
Niveau 6
Niveau 6
Messages : 239
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

Re: [..] Fonctions AdlibRegister() imbriquées

#5

Message par jpascal »

Et ce n'est pas un problème lié à Opt("GUIOnEventMode", 1)

#include <ResourcesEx.au3>

#include <GUIConstants.au3>
#include <Constants.au3>
#include "Cached GIF Animation.au3"
#include <WinAPISysWin.au3>

Opt("GUIOnEventMode", 1)

;~ OnAutoItExitRegister(_GIF_Animation_Quit)

Global $hGUI = GUICreate("GIF Animation", 500, 500, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
GUISetOnEvent($GUI_EVENT_CLOSE, 'ExitApp')
GUISetBkColor(0xFFFFFF)
Global $IMG_Ctrl1 = _GUICtrlCreateAnimGIF("9.gif", 150, 0, 192, 172, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl2 = _GUICtrlCreateAnimGIF("gif-Green-UFO.gif", 0, 180, 150, 80, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl3 = _GUICtrlCreateAnimGIF("Catalog.gif", 160, 180, 320, 184, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl4 = _GUICtrlCreateAnimGIF("Kafu.gif", 30, 260, 90, 90, -1, $GUI_WS_EX_PARENTDRAG)
Global $idButton = GUICtrlCreateButton("Hide", 10, 10, 80, 30)
GUICtrlSetOnEvent(-1, 'Button')
GUICtrlCreateButton("Quit", 10, 50, 80, 30)
GUICtrlSetOnEvent(-1, 'ExitApp')
GUICtrlCreateButton("Adlib", 10, 90, 80, 30)
GUICtrlSetOnEvent(-1, 'Adlib')

_WinAPI_SetLayeredWindowAttributes($hGUI, 0xFFFFFF)

GUISetState(@SW_SHOW, $hGUI)

Global $aCaption[4] = ["Show", "Delete", "Recreate", "Hide"], $iCounter = -1

While 1
   Sleep(100)
WEnd

Func Button()
   $iCounter += 1
   $iCounter = Mod($iCounter, 4)
   GUICtrlSetData($idButton, $aCaption[$iCounter])
   Switch $iCounter
      Case 0         ; hide
         GUICtrlSetState($IMG_Ctrl2, $GUI_HIDE)
      Case 1         ; show
         GUICtrlSetState($IMG_Ctrl2, $GUI_SHOW)
      Case 2         ; delete
         _GUICtrlDeleteAnimGIF($IMG_Ctrl2)
      Case 3         ; recreate
         $IMG_Ctrl2 = _GUICtrlCreateAnimGIF("gif-Green-UFO.gif", 0, 180, 150, 80, -1, $GUI_WS_EX_PARENTDRAG)
         _WinAPI_SetLayeredWindowAttributes($hGUI, 0xFFFFFF)
   EndSwitch
EndFunc   ;==>Button

Func ExitApp()
   _GIF_Animation_Quit()
   Exit
EndFunc   ;==>ExitApp

Func Adlib()
   AdlibRegister('Test')
EndFunc   ;==>Adlib

Func Test()
   AdlibUnRegister()

   GUICtrlSetState($IMG_Ctrl2, $GUI_HIDE)
   For $i = 1 To 3
      Sleep(500)
      ConsoleWrite($i & @CRLF)
   Next
   GUICtrlSetState($IMG_Ctrl2, $GUI_SHOW)
EndFunc   ;==>Test
AutoIt 3.3.16.1 - AutoIt3Wrapper 21.316.1639.1
jpascal
Niveau 6
Niveau 6
Messages : 239
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

Re: [..] Fonctions AdlibRegister() imbriquées

#6

Message par jpascal »

Je viens de comprendre d'où venait le problème sans pour autant avoir de solution.

Dans le code ci-dessus, l'image est affichée. La fonction Test() cache l'image pendant 1500 ms puis l'affiche à nouveau.

Dans le code ci-dessous, l'image est cachée. La fonction Test() doit afficher l'image pendant 1500 ms puis la cacher à nouveau. Cela ne fonctionne pas.

Le problème vient en fait de l'utilisation de :
   For $i = 1 To 3
      Sleep(500)
   Next
ou
   Local $hTimer = TimerInit()
   While 1
      If TimerDiff($hTimer) > 1500 Then ExitLoop
   WEnd
qui "bloque" la fonction __GIF_Animation_DrawTimer()

Dans le code du dessus, nous ne voyons pas ce "blocage" car l'image est cachée.

Sachant que mon but est d'afficher l'image pendant un traitement puis de la cacher ensuite, le problème reste entier.
#include <ResourcesEx.au3>

#include <GUIConstants.au3>
#include <Constants.au3>
#include "Cached GIF Animation.au3"
#include <WinAPISysWin.au3>

Opt("GUIOnEventMode", 1)

;~ OnAutoItExitRegister(_GIF_Animation_Quit)

Global $hGUI = GUICreate("GIF Animation", 500, 500, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
GUISetOnEvent($GUI_EVENT_CLOSE, 'ExitApp')
GUISetBkColor(0xFFFFFF)
Global $IMG_Ctrl1 = _GUICtrlCreateAnimGIF("9.gif", 150, 0, 192, 172, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl2 = _GUICtrlCreateAnimGIF("gif-Green-UFO.gif", 0, 180, 150, 80, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl3 = _GUICtrlCreateAnimGIF("Catalog.gif", 160, 180, 320, 184, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl4 = _GUICtrlCreateAnimGIF("Kafu.gif", 30, 260, 90, 90, -1, $GUI_WS_EX_PARENTDRAG)
Global $idButton = GUICtrlCreateButton("Show", 10, 10, 80, 30)
GUICtrlSetOnEvent(-1, 'Button')
GUICtrlCreateButton("Quit", 10, 50, 80, 30)
GUICtrlSetOnEvent(-1, 'ExitApp')
GUICtrlCreateButton("Adlib", 10, 90, 80, 30)
GUICtrlSetOnEvent(-1, 'Adlib')

_WinAPI_SetLayeredWindowAttributes($hGUI, 0xFFFFFF)

GUISetState(@SW_SHOW, $hGUI)

GUICtrlSetState($IMG_Ctrl2, $GUI_HIDE) ; l'image est cachée au départ

Global $aCaption[4] = ["Show", "Delete", "Recreate", "Hide"], $iCounter = 0

While 1
   Sleep(100)
WEnd

Func Button()
   $iCounter += 1
   $iCounter = Mod($iCounter, 4)
   GUICtrlSetData($idButton, $aCaption[$iCounter])
   Switch $iCounter
      Case 0         ; hide
         GUICtrlSetState($IMG_Ctrl2, $GUI_HIDE)
      Case 1         ; show
         GUICtrlSetState($IMG_Ctrl2, $GUI_SHOW)
      Case 2         ; delete
         _GUICtrlDeleteAnimGIF($IMG_Ctrl2)
      Case 3         ; recreate
         $IMG_Ctrl2 = _GUICtrlCreateAnimGIF("gif-Green-UFO.gif", 0, 180, 150, 80, -1, $GUI_WS_EX_PARENTDRAG)
         _WinAPI_SetLayeredWindowAttributes($hGUI, 0xFFFFFF)
   EndSwitch
EndFunc   ;==>Button

Func ExitApp()
   _GIF_Animation_Quit()
   Exit
EndFunc   ;==>ExitApp

Func Adlib()
   AdlibRegister('Test')
EndFunc   ;==>Adlib

Func Test()
   AdlibUnRegister()

   GUICtrlSetState($IMG_Ctrl2, $GUI_SHOW)
;~    For $i = 1 To 3
;~       Sleep(500)
;~    Next
   Local $hTimer = TimerInit()
   While 1
      If TimerDiff($hTimer) > 1500 Then ExitLoop
   WEnd
   GUICtrlSetState($IMG_Ctrl2, $GUI_HIDE)
EndFunc   ;==>Test
AutoIt 3.3.16.1 - AutoIt3Wrapper 21.316.1639.1
Avatar du membre
Nine
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 116
Enregistré le : ven. 17 avr. 2020 01:23
Localisation : Montréal, Québec
Status : Hors ligne

Re: [..] Fonctions AdlibRegister() imbriquées  

#7

Message par Nine »

La solution est de vérifier le timer dans la boucle principale et non dans une boucle secondaire.

Code : Tout sélectionner

#include <GUIConstants.au3>
#include <Constants.au3>
#include "Cached GIF Animation.au3"
#include <WinAPISysWin.au3>

Global $hGUI = GUICreate("GIF Animation", 500, 500, -1, -1, $WS_POPUP, $WS_EX_LAYERED)
GUISetBkColor(0xFFFFFF)
Global $IMG_Ctrl1 = _GUICtrlCreateAnimGIF("9.gif", 150, 0, 192, 172, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl2 = _GUICtrlCreateAnimGIF("gif-Green-UFO.gif", 0, 180, 150, 80, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl3 = _GUICtrlCreateAnimGIF("Catalog.gif", 160, 180, 320, 184, -1, $GUI_WS_EX_PARENTDRAG)
Global $IMG_Ctrl4 = _GUICtrlCreateAnimGIF("Kafu.gif", 30, 260, 90, 90, -1, $GUI_WS_EX_PARENTDRAG)
Global $idButton = GUICtrlCreateButton("Show", 10, 10, 80, 30)
Global $idQuit = GUICtrlCreateButton("Quit", 10, 50, 80, 30)
Global $idAdlib = GUICtrlCreateButton("Adlib", 10, 90, 80, 30)

_WinAPI_SetLayeredWindowAttributes($hGUI, 0xFFFFFF)

GUISetState(@SW_SHOW, $hGUI)

GUICtrlSetState($IMG_Ctrl2, $GUI_HIDE) ; l'image est cachée au départ

Global $aCaption[4] = ["Show", "Delete", "Recreate", "Hide"], $iCounter = 0
Global $hTimer, $bRun = False

While True
  Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE, $idQuit
      ExitApp()
    Case $idButton
      Button()
    Case $idAdlib
      If $bRun Then ContinueLoop
      $bRun = True
      GUICtrlSetState($IMG_Ctrl2, $GUI_SHOW)
      $hTimer = TimerInit()
  EndSwitch
  If $bRun And TimerDiff($hTimer) > 1500 Then
    GUICtrlSetState($IMG_Ctrl2, $GUI_HIDE)
    $bRun = False
  EndIf
WEnd

Func Button()
  $iCounter += 1
  $iCounter = Mod($iCounter, 4)
  GUICtrlSetData($idButton, $aCaption[$iCounter])
  Switch $iCounter
    Case 0           ; hide
      GUICtrlSetState($IMG_Ctrl2, $GUI_HIDE)
    Case 1           ; show
      GUICtrlSetState($IMG_Ctrl2, $GUI_SHOW)
    Case 2           ; delete
      _GUICtrlDeleteAnimGIF($IMG_Ctrl2)
    Case 3           ; recreate
      $IMG_Ctrl2 = _GUICtrlCreateAnimGIF("gif-Green-UFO.gif", 0, 180, 150, 80, -1, $GUI_WS_EX_PARENTDRAG)
      _WinAPI_SetLayeredWindowAttributes($hGUI, 0xFFFFFF)
  EndSwitch
EndFunc   ;==>Button

Func ExitApp()
  _GIF_Animation_Quit()
  Exit
EndFunc   ;==>ExitApp
ps. j'ai converti en non-event par simplification de code
Modifié en dernier par Nine le lun. 29 juil. 2024 15:57, modifié 1 fois.
Avatar du membre
TommyDDR
Modérateur
Modérateur
Messages : 2093
Enregistré le : mar. 22 juil. 2008 21:55
Localisation : Nantes
Status : Hors ligne

Re: [..] Fonctions AdlibRegister() imbriquées

#8

Message par TommyDDR »

Je pense qu'à votre place, je créerais une variable globale que je changerai à "true" dans le WM_NOTIFY ou autre endroit où vous mettez votre AdlibRegister (à la place du AdlibRegister) et je ferais le traitement dans la boucle principale si cette variable est à True
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
jpascal
Niveau 6
Niveau 6
Messages : 239
Enregistré le : jeu. 16 oct. 2008 16:21
Status : Hors ligne

Re: [..] Fonctions AdlibRegister() imbriquées

#9

Message par jpascal »

Merci messieurs pour vos solutions parfaites et simples à mettre en place. :-)
AutoIt 3.3.16.1 - AutoIt3Wrapper 21.316.1639.1
Répondre