Une autre façon de traiter les évènements

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Une autre façon de traiter les évènements

Message par Droopy »

Voici le code

Code : Tout sélectionner

; PureBasic 3.93
; Droopy 10/05/05

;{ Constantes
#LClick=1
#RClick=2
#LDClick=4
#RDClick=8
#Focus=16
#LFocus=32
#Change=64
;}

Structure GadgetStructure
  LeftClick.l
  RightClick.l
  LeftDoubleClick.l
  RightDoubleClick.l
  Focus.l
  LostFocus.l
  Change.l
EndStructure

Procedure ManageEventInit()
  Static Flag
  Global ManageEventFlagClose,ManageEventDebugMode
  
  If Flag=0
    Flag=1
    NewList GadgetEventList.GadgetStructure()
    AddElement(GadgetEventList())
    NewList MenuEventList()
    AddElement(MenuEventList())
  Else
    ManageEventFlagClose=0
    ClearList(GadgetEventList())
    ClearList(MenuEventList())
  EndIf
EndProcedure

ProcedureDLL ManageEventDebug(Bool)
  ManageEventDebugMode=Bool
EndProcedure

Procedure ManageEventDebugText(ObjectType,Number,Text.s,ProcedurePointer)

If ManageEventDebugMode ; Mode debug actif

  If ObjectType=0 ; Gadget
    If ProcedurePointer=0 ; Pas de procedure Call définie
      Debug "Gadget "+Str(Number)+" "+Text+" No Procedure Call define"
    Else ; Procedure Call define
      Debug "Gadget "+Str(Number)+" "+Text+" Call Procedure "+Str(ProcedurePointer)
    EndIf
  
  Else ; Menu
    If ProcedurePointer=0
      Debug "Menu "+Str(Number)+" No Procedure Call define"
    Else
      Debug "Menu "+Str(Number)+" Call Procedure "+Str(ProcedurePointer)
    EndIf
  EndIf
  
EndIf
EndProcedure

ProcedureDLL ManageEventGadget(Gadget,Event,ProcedurePointer) ; #LClick #RClick #LDClick #RDClick #Focus #LFocus #Change
  ; Si pas assez d'élément on en ajoute
  Compte=CountList(GadgetEventList())
  If Compte-1<Gadget
    ElementACreer=Gadget-Compte+1
    LastElement(GadgetEventList())
    For n=1 To ElementACreer
      AddElement(GadgetEventList())
    Next
  EndIf
  
SelectElement(GadgetEventList(),Gadget)

If Event & #LClick
  GadgetEventList()\LeftClick=ProcedurePointer
EndIf
  
If Event & #RClick
  GadgetEventList()\RightClick=ProcedurePointer
EndIf
    
If Event & #LDClick
  GadgetEventList()\LeftDoubleClick=ProcedurePointer
EndIf

If Event & #RDClick
  GadgetEventList()\RightDoubleClick=ProcedurePointer
EndIf

If Event & #Focus
  GadgetEventList()\Focus=ProcedurePointer
EndIf

If Event & #LFocus
  GadgetEventList()\LostFocus=ProcedurePointer
EndIf

If Event & #Change
  GadgetEventList()\Change=ProcedurePointer
EndIf
  
EndProcedure

ProcedureDLL ManageEventMenu(Menu,ProcedurePointer)
  ; Si pas assez d'élément on en ajoute
  ElementACreer=CountList(MenuEventList())-Menu
  If ElementACreer>0
    LastElement(MenuEventList())
    For n=1 To ElementACreer
      AddElement(MenuEventList())
    Next
  EndIf
  SelectElement(MenuEventList(),Menu)
  
  MenuEventList()=ProcedurePointer
  
EndProcedure

ProcedureDLL ManageEventStart()
  Repeat
    Evenement=WaitWindowEvent()
    
    
    ;/ Gadget
    If Evenement=#PB_Event_Gadget
      GadgetID=EventGadgetID()

      SelectElement(GadgetEventList(),GadgetID)
      
      Event= EventType()
      Select Event
        
      Case  #PB_EventType_LeftClick
        temp=GadgetEventList()\LeftClick
        ManageEventDebugText(0,GadgetID,"Left Click",temp)
        If GadgetEventList()\LeftClick<>0
          CallFunctionFast(temp,"")
        EndIf
          
      
      Case #PB_EventType_RightClick
        temp=GadgetEventList()\RightClick
        ManageEventDebugText(0,GadgetID,"Right click",temp)
        If GadgetEventList()\RightClick<>0
          CallFunctionFast(temp,"")
        EndIf
        
      
      Case #PB_EventType_LeftDoubleClick
        temp=GadgetEventList()\LeftDoubleClick
        ManageEventDebugText(0,GadgetID,"LeftDoubleClick",temp)
        If GadgetEventList()\LeftDoubleClick<>0
          CallFunctionFast(temp,"")
        EndIf
      
      Case #PB_EventType_RightDoubleClick
        temp=GadgetEventList()\RightDoubleClick
        ManageEventDebugText(0,GadgetID,"RightDoubleClick",temp)
        If GadgetEventList()\RightDoubleClick<>0
          CallFunctionFast(temp,"")
        EndIf
      
      Case #PB_EventType_Focus
        temp=GadgetEventList()\Focus
        ManageEventDebugText(0,GadgetID,"Focus",temp)
        If GadgetEventList()\Focus<>0
          CallFunctionFast(temp,"")
        EndIf
        
      
      Case #PB_EventType_LostFocus
        temp=GadgetEventList()\LostFocus
        ManageEventDebugText(0,GadgetID,"LostFocus",temp)
        If GadgetEventList()\LostFocus <>0
          CallFunctionFast(temp,"")
        EndIf
        
      
      Case #PB_EventType_Change
        temp=GadgetEventList()\Change
        ManageEventDebugText(0,GadgetID,"Change",temp)
        If GadgetEventList()\Change<>0
          CallFunctionFast(temp,"")
        EndIf
      
    EndSelect
      
    EndIf
    
    ;/ Menu
    If Evenement=#PB_Event_Menu
      Menu=EventMenuID()
      SelectElement(MenuEventList(),Menu)
      CallFunctionFast(MenuEventList(),"")
    EndIf

    ;/ #PB_Event_CloseWindow
    If Evenement=#PB_Event_CloseWindow
      Select ManageEventFlagClose
        Case -1 ; Quitter la gestion des evenements
          Break 
        Case 0 ; Fin du Programme
          End
        Default ; Appel d'une procédure
          CallFunctionFast(ManageEventFlagClose,"")
      EndSelect
    EndIf
    
  ForEver

EndProcedure

ProcedureDLL ManageEventSetCloseEvent(ProcedurePointer)
  ManageEventFlagClose=ProcedurePointer
EndProcedure
    
Procedure Bip()
  beep_(3000,100)
EndProcedure

Procedure Bop()
  beep_(400,100)
EndProcedure

Procedure Tap()
  beep_(200,30)
EndProcedure

Procedure Bup()
  beep_(100,30)
  beep_(300,30)
  beep_(600,30)
EndProcedure

Enumeration ; Définition des Gadgets
  #Texte1
  #Bouton1
EndEnumeration

;/ Test de la Librairie
OpenWindow(0, 302, 150, 382, 143,  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar , "Manage Event")
CreateGadgetList(WindowID())
StringGadget(#Texte1, 10, 10, 360, 30, "")
ButtonGadget(#Bouton1, 10, 50, 360, 80, "")

ManageEventInit()
ManageEventGadget(#Texte1,#Focus,@Bip())
ManageEventGadget(#Texte1,#LFocus,@Bop())
ManageEventGadget(#Texte1,#Change,@Tap())

ManageEventGadget(#Bouton1,#LClick,@Bup())
ManageEventDebug(#True)
ManageEventStart()
à tester en mode Debug
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Tu t'es bien compliqué (mais ça démontre un grand potentiel :wink: ), tu as rajouté une couche supplémentaire de tests(if-endif) et (select-case) qui ne sert à rien, de plus il faut utiliser les constantes de Pb.

En fait c'est beaucoup plus simple que ça, regarde cette exemple:

Code : Tout sélectionner

Structure liste
  ID.l
  event.l
  *AdresseProc.l
EndStructure 

NewList message.liste()

Procedure ManageEventGadget(ID,event,AdresseProc)
  AddElement(message())
  message()\ID=ID
  message()\event=event
  message()\AdresseProc=AdresseProc
EndProcedure   
  
Procedure ManageEventStart()
  Repeat
  Evenement=WaitWindowEvent() 
  
  If  Evenement=#PB_Event_Gadget 
    ForEach message()
      If message()\ID=EventGadgetID()
        If message()\event=EventType()
          CallFunctionFast(message()\AdresseProc)
        EndIf
      EndIf
    Next 
  EndIf 
  Until Evenement=#PB_Event_CloseWindow
EndProcedure 
    
Procedure Bip() 
  beep_(3000,100) 
EndProcedure 
    
Procedure Bop() 
  beep_(400,100) 
EndProcedure 
    
Procedure Tap() 
  beep_(200,30) 
EndProcedure 

Enumeration ; Définition des Gadgets 
  #Texte1 
  #Bouton1 
EndEnumeration 

;/ Test de la Librairie 
OpenWindow(0, 302, 150, 382, 143,  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar , "Manage Event") 
CreateGadgetList(WindowID()) 
AdvancedGadgetEvents(1)
StringGadget(#Texte1, 10, 10, 360, 30, "") 
ButtonGadget(#Bouton1, 10, 50, 360, 80, "") 

ManageEventGadget(#Texte1,#PB_EventType_Focus,@Bip()) 
 
ManageEventGadget(#Bouton1,#PB_EventType_LeftClick,@Bop()) 
ManageEventGadget(#Bouton1,#PB_EventType_RightClick,@Tap()) 

ManageEventStart() 
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Merci d'avoir critiqué / simplifié mon code ( Critique bien entendu constructive :D )

Je te répond point par point pour t'expliquer le cahier des charges que je m'étais fixé )
Tu t'es bien compliqué
- C'est plein de procédures ( ex ManagementInit ) car le but de ce code est d'en faire un Librairie avec tailbite

tu as rajouté une couche supplémentaire de tests(if-endif) et (select-case) qui ne sert à rien
- Mode debogage
- Accès direct aux évènements : ( Annulation facile d'un évènement associé à un gadget ( mettre à 0 ProcedurePointer ))
de plus il faut utiliser les constantes de Pb
- Les constantes que j'ai définit permettent d'associer la même procédure à différents évènement d'un gadget.
exemple :

Code : Tout sélectionner

ManageEventGadget(#Texte1,#Change | #LClick | #RClick,@Tap())
J'ai des choses à changer dans mon code ( Debug marche pas avec Tailbite ) donc je pense ouvrir une console en mode debug / ajouter des touches de raccourcis aux gadget / menu .
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Merci d'avoir critiqué / simplifié mon code ( Critique bien entendu constructive :D )

Je te répond point par point pour t'expliquer le cahier des charges que je m'étais fixé )
Tu t'es bien compliqué
- C'est plein de procédures ( ex ManagementInit ) car le but de ce code est d'en faire un Librairie avec tailbite

tu as rajouté une couche supplémentaire de tests(if-endif) et (select-case) qui ne sert à rien
- Mode debogage
- Accès direct aux évènements : ( Annulation facile d'un évènement associé à un gadget ( mettre à 0 ProcedurePointer ))
de plus il faut utiliser les constantes de Pb
- Les constantes que j'ai définit permettent d'associer la même procédure à différents évènement d'un gadget.
exemple :

Code : Tout sélectionner

ManageEventGadget(#Texte1,#Change | #LClick | #RClick,@Tap())
J'ai des choses à changer dans mon code ( Debug marche pas avec Tailbite ) donc je pense ouvrir une console en mode debug / ajouter des touches de raccourcis aux gadget / menu .
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Je pensais que tu voulais surtout supprimer du point de vue programmeur la boucle d'évènements comme ça se fait déjà à la méthode POO.

Pure Basic utilise une gestion de traitement des messages très simplifiée des évènements reconnus de ses gadgets, on ne peut pas faire plus simple, de plus il est facile de mettre un debug à l'endroit du programme ou l'on souhaite vérifier la présence d'un de ces évènements. Il n'y a comme je te l'explique aucune raison de rajouter une couche de débogage tant il est simple de gérer la boucle d'évènement. Il est vraiment rare d'avoir des problèmes à ce niveau là.

La grande difficulté, c'est lorsque que l'on souhaite utiliser d'autres messages que Pure Basic ne gère pas et là il te faut en général un callback et une bonne dose de lecture MSDN.

:)
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Je pensais que tu voulais surtout supprimer du point de vue programmeur la boucle d'évènements comme ça se fait déjà à la méthode POO.
C'est ce que je veux faire ( Elle est gérée dans la lib )
Pure Basic utilise une gestion de traitement des messages très simplifiée des évènements reconnus de ses gadgets, on ne peut pas faire plus simple, de plus il est facile de mettre un debug à l'endroit du programme ou l'on souhaite vérifier la présence d'un de ces évènements. Il n'y a comme je te l'explique aucune raison de rajouter une couche de débogage tant il est simple de gérer la boucle d'évènement. Il est vraiment rare d'avoir des problèmes à ce niveau là.
Je pense qu'avec une lib, cette façon de gérer les évènements est plus simple pour un débutant. ( Le mode debug que j'ai rajouté me permet de voir les type d'évènements qu'un gadget peut recevoir : Je me suis apperçu comme ça que le double clic n'était pas géré par certains gadgets.

Pour un débutant ( Tout petit programme mono-fenêtre ), je pense que ça lui simplifie la vie.

Je me rend compte aussi que cette façon de gérer les évènements génère quelques limitations, par exemple elle ne permet pas de passer des paramètres à une procédure.
La grande difficulté, c'est lorsque que l'on souhaite utiliser d'autres messages que Pure Basic ne gère pas et là il te faut en général un callback et une bonne dose de lecture MSDN.
Totalement daccord ( je maitrise pas du tout les Callback )

Merci pour ta réponse
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Après réflexion, j'ai trouvé un gros gros avantage à ta méthode :D .

Elle permet d'appeler plusieurs procédures lorsque se produit un évènement. ( ma méthode ne permet l'appel que d'une seule procédure ! )

Seul bémol, la suppression d'évènement / modification d'évènement ne semble pas simple, puisque les évènement sont pilés .

bref je vais plancher dessus, merci encore.
Répondre