Gestion des objets (+ exemple)

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Gestion des objets (+ exemple)

Message par Dr. Dri »

Je vous propose un code sympa (je l'ai commencé hier soir par hasard) qui permet de gérer des objets purebasic. Ces objets statiques ou dynamiques (#PB_Any) qu'on retrouve dans beaucoup de lib (image, gadget, window, sprite...)

L'usage, c'est principalement pour ceux qui font des userlib, donc j'en ai fait un fichier simple à inclure, compatible EnableExplicit et compatible avec ou sans l'assembleur en ligne.

En gros c'est une série de fonction qui vous permettra d'ajouter, supprimer, énumérer des objets. Tous les objets que vous créez seront supprimés à la fermeture du programme (c'est magique =) parce qu'il faut fournir une fonction de suppression d'objet. J'ai aussi recodé en PB les structures et prototypes qu'on n'utilise en théorie pas.

Pour résumer si vous faite une lib pour gérer des fichiers rar, vous pourrez faire facilement ce genre de fonctions :
CreateRAR(5, "fichier.rar", ...)
Index = CreateRAR(#PB_Any, "archive.rar", ...)
CloseRAR(Index)

Code : Tout sélectionner

Prototype   ThreadFunction(Param)

Prototype.l ObjectEnumerateAllCallback(Object.l, *Element, *VoidData)
Prototype   ObjectFreeFunction(Object.l)

Structure PB_SimpleList
  *Next    .PB_SimpleList
  *Previous.PB_SimpleList
EndStructure

Structure PB_Object
  StructureSize.l
  IncrementStep.l
  ObjectsNumber.l
  *ListFirstElement.PB_SimpleList

  FreeObject.ObjectFreeFunction

  Current.l
  *CurrentElement.PB_SimpleList

CompilerIf #PB_Compiler_Thread
  IncrementShift.l
  *FirstObjectsArea.PB_SimpleList
  *LastObjectsArea .PB_SimpleList
  ObjectMutex.Critical_Section
CompilerElse
  *ObjectsArea
CompilerEndIf
  
EndStructure

Prototype   PB_Object_GetOrAllocate   (*Object.PB_Object, Object.l)
Prototype   PB_Object_GetObject       (*Object.PB_Object, Object.l)
Prototype   PB_Object_IsObject        (*Object.PB_Object, Object.l)
Prototype   PB_Object_EnumerateAll    (*Object.PB_Object, Callback.ObjectEnumerateAllCallback, *VoidData)
Prototype   PB_Object_EnumerateStart  (*Object.PB_Object)
Prototype   PB_Object_EnumerateNext   (*Object.PB_Object, *ID.Long)
Prototype   PB_Object_EnumerateAbort  (*Object.PB_Object)
Prototype   PB_Object_Free            (*Object.PB_Object, Object.l)
Prototype.l PB_Object_Init            (StructureSize.l, IncrementStep.l, FreeObject.ObjectFreeFunction)
Prototype   PB_Object_GetThreadMemory (MemoryID.l)
Prototype.l PB_Object_InitThreadMemory(Size.l, InitFunction.ThreadFunction, EndFunction.ThreadFunction)

Global Object_GetOrAllocate   .PB_Object_GetOrAllocate
Global Object_GetObject       .PB_Object_GetObject
Global Object_IsObject        .PB_Object_IsObject
Global Object_EnumerateAll    .PB_Object_EnumerateAll
Global Object_EnumerateStart  .PB_Object_EnumerateStart
Global Object_EnumerateNext   .PB_Object_EnumerateNext
Global Object_EnumerateAbort  .PB_Object_EnumerateAbort
Global Object_Free            .PB_Object_Free
Global Object_Init            .PB_Object_Init
Global Object_GetThreadMemory .PB_Object_GetThreadMemory
Global Object_InitThreadMemory.PB_Object_InitThreadMemory

!extrn _PB_Object_GetOrAllocateID@8
!extrn _PB_Object_GetObject@8
!extrn _PB_Object_IsObject@8
!extrn _PB_Object_EnumerateAll@12
!extrn _PB_Object_EnumerateStart@4
!extrn _PB_Object_EnumerateNext@8
!extrn _PB_Object_EnumerateAbort@4
!extrn _PB_Object_FreeID@8
!extrn _PB_Object_Init@12
!extrn _PB_Object_GetThreadMemory@4
!extrn _PB_Object_InitThreadMemory@12

!MOV [v_Object_GetOrAllocate]   , _PB_Object_GetOrAllocateID@8
!MOV [v_Object_GetObject]       , _PB_Object_GetObject@8
!MOV [v_Object_IsObject]        , _PB_Object_IsObject@8
!MOV [v_Object_EnumerateAll]    , _PB_Object_EnumerateAll@12
!MOV [v_Object_EnumerateStart]  , _PB_Object_EnumerateStart@4
!MOV [v_Object_EnumerateNext]   , _PB_Object_EnumerateNext@8
!MOV [v_Object_EnumerateAbort]  , _PB_Object_EnumerateAbort@4
!MOV [v_Object_Free]            , _PB_Object_FreeID@8
!MOV [v_Object_Init]            , _PB_Object_Init@12
!MOV [v_Object_GetThreadMemory] , _PB_Object_GetThreadMemory@4
!MOV [v_Object_InitThreadMemory], _PB_Object_InitThreadMemory@12
J'ai codé un petit exemple avec des timers, en espérant que ca vous parle

Code : Tout sélectionner

IncludeFile "Object.pbi"

;la structure qui contient les
;informations sur les timers
Structure Timer
  Event.l
  Window.l
  Elapse.l
EndStructure

;il faut que ce soit global ^^
;ou alors shared dans chaque fonction
Global TimerObjects

;la fonction la plus importante, sans elle
;pas d'objets statiques/dynamiques
Procedure.l FreeTimer(Timer.l)
  Protected Free.l = #False, *Timer.Timer
  
  If Timer <> #PB_Any And Object_IsObject(TimerObjects, Timer)
    *Timer = Object_GetObject(TimerObjects, Timer)
  EndIf
  
  If *Timer And IsWindow(*Timer\Window)
    Free = KillTimer_(WindowID(*Timer\Window), *Timer\Event)
    Object_Free(TimerObjects, Timer)
  EndIf
  
  ProcedureReturn Free
EndProcedure

;Retourne "non-zero" si le timer a été créé
;Retourne l'index du timer si Timer = #PB_Any
Procedure.l CreateTimer(Timer.l, Window.l, Event.l, Elapse.l)
  Protected Create.l = #Null, *Timer.Timer
  
  If IsWindow(Window) And Event
    FreeTimer(Timer)
    *Timer = Object_GetOrAllocate(TimerObjects, Timer)
  EndIf
  
  If *Timer
    SetTimer_(WindowID(Window), Event, Elapse, #Null)
    *Timer\Event  = Event
    *Timer\Window = Window
    *Timer\Elapse = Elapse
  EndIf
  
  If Timer = #PB_Any
    Create = *Timer
  ElseIf *Timer
    Create = *Timer\Event
  EndIf
  
  ProcedureReturn Create
EndProcedure

;trois fonctions pour meubler
Procedure.l GetTimerEvent(Timer.l)
  Protected Event.l = #PB_Any, *Timer.Timer
  
  *Timer = Object_GetObject(TimerObjects, Timer)
   
  If *Timer And IsWindow(*Timer\Window)
    Event = *Timer\Event
  EndIf
  
  ProcedureReturn Event
EndProcedure

Procedure.l GetTimerWindow(Timer.l)
  Protected Window.l = #PB_Any, *Timer.Timer
  
  *Timer = Object_GetObject(TimerObjects, Timer)
   
  If *Timer And IsWindow(*Timer\Window)
    Window = *Timer\Window
  EndIf
  
  ProcedureReturn Window
EndProcedure

Procedure.l GetTimerElapse(Timer.l)
  Protected Elapse.l = #PB_Any, *Timer.Timer
  
  *Timer = Object_GetObject(TimerObjects, Timer)
   
  If *Timer And IsWindow(*Timer\Window)
    Elapse = *Timer\Elapse
  EndIf
  
  ProcedureReturn Elapse
EndProcedure

;si on fait une lib autant
;créer les évennements qui vont avec ^^
#PB_Event_Timer = #WM_TIMER

;retourne le numéro de timer (#PB_Any s'il n'existe pas)
Procedure.l EventTimer()
  Protected Window.l, Event.l, Temp.l
  Protected Timer.l = #PB_Any, *Timer.Timer
  
  Window = EventWindow()
  Event  = EventwParam()
  
  Object_EnumerateStart(TimerObjects)
  
  While Object_EnumerateNext(TimerObjects, @Temp)
    *Timer = Object_GetObject(TimerObjects, Temp)
    
    If *Timer\Window = Window And *Timer\Event = Event
      Object_EnumerateAbort(TimerObjects)
      Timer = Temp
    EndIf
  Wend
  
  ProcedureReturn Timer
EndProcedure

;crée la liste d'objets des timers,
;je ne sais pas à quoi correspond le 2e argument
TimerObjects = Object_Init(SizeOf(Timer), 1, @FreeTimer())

;fin de la "lib"

;-------------------------------------------------------------------------------

;début du programme

Enumeration
  #Timer_A
  #Timer_C
EndEnumeration

If OpenWindow(0, 0, 0, 222, 50, "Timer", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CreateGadgetList(WindowID(0))
  
  ButtonGadget(0, 10, 10, 200, 30, "Timer", #PB_Button_Toggle)
  
  CreateTimer(#Timer_A, 0, 6, 2000)
  CreateTimer(#Timer_C, 0, 2, 1500)
  
  Repeat
    
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Gadget
      
      If GetGadgetState(0)
        Timer = CreateTimer(#PB_Any, 0, 1, 1000)
      Else
        FreeTimer(Timer)
      EndIf
      
    ElseIf Event = #PB_Event_Timer
      
      Select EventTimer()
        Case #Timer_A
          Debug "#Timer_A"
          
        Case #Timer_C
          Debug "#Timer_C"
          
        Case Timer
          Debug "Timer"
          
      EndSelect
      
    EndIf
    
  Until Event = #PB_Event_CloseWindow
EndIf
Dri :D