Code: Alles auswählen
;======================================================================
; Library:         EM_EventManager.pbi
;
; Author:          Thomas (ts-soft) Schulz
; Date:            March 30, 2013
; Version:         1.5
; Target Compiler: PureBasic 5.1+
; Target OS:       Windows, Linux, MacOS
; License:         Free, unrestricted, no warranty whatsoever
;                  Use at your own risk
;======================================================================
; Description:
;   All parts of the normal event loop can be used without restriction or
;   replaced by eventhandlers. Integration into existing projects should no problem
;
;   EM_SetEventHandler(ID, ObjectType, *function, EventType = -1)
;     ID = ID of Object (Window, Gadget, MenuItem, Timer, SysTray icon or EventNumber like #PB_Event_CloseWindow, #PB_Event_SizeWindow, #PB_Event_FirstCustomValue ...
;     ObjectType = see ObjectType Enumeration
;     *function = Address of Procedure to handle event, should only have one parameter: Procedure Foo(*ev.EM_Events)
;     EventType = the #PB_EventType for Type #EM_Window, #EM_Gadget, and #EM_SysTray
;
; EM_RemoveEventHandler(ID, ObjectType, EventType = -1)
;     ID = ID of Object (Window, Gadget, MenuItem, Timer, SysTray icon or EventNumber like #PB_Event_CloseWindow, #PB_Event_SizeWindow, #PB_Event_FirstCustomValue ...
;     EventType = the #PB_EventType for Type #EM_Window, #EM_Gadget, and #EM_SysTray
;
; History:
; Version 1.5 (March 30, 2013) - by Danilo
; added #EM_Window for window events
; added #PB_Event_GadgetDrop to gadget event system
;
; Version 1.4 (March 30, 2013) - by Danilo
; added #EM_SysTray for SysTrayIcon events
;
; Version 1.3 (March 05, 2013)
; fixed a memoryleak with maps, comes with Version 1.2
;
; Version 1.2 (March 04, 2013)
; Codeoptimization (removed map events(), some FindMapElement ...
;
; Version 1.1
; changed from CallFunctionFast to Prototype, thx to netmaestro!
;
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
Enumeration ; ObjectType
  #EM_Window
  #EM_Gadget
  #EM_Menu
  #EM_SysTray
  #EM_Timer
  #EM_Special
EndEnumeration
Structure EM_Events
  Event.i
  EventType.i
  EventWindow.i
  EventGadget.i
  EventMenu.i
  EventSysTray.i
  EventTimer.i
  EventData.i
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    EventwParam.i
    EventlParam.i
  CompilerEndIf
EndStructure
Structure __EM_Maps__
  Map WindowEvents.i()
  Map GadgetEvents.i()
  Map MenuEvents.i()
  Map SysTrayEvents.i()
  Map TimerEvents.i()
  Map SpecialEvents.i()
EndStructure
Prototype __EM_ProcessEvent__(*Event.EM_Events)
Global __EM_Map__.__EM_Maps__
Procedure EM_SetEventHandler(ID, ObjectType, *function.__EM_ProcessEvent__, EventType = -1)
  If *function <> 0
    Select ObjectType
      Case #EM_Window
        If IsWindow(ID)
          __EM_Map__\WindowEvents(Str(ID) + ":" + Str(EventType)) = *function
        EndIf
        
      Case #EM_Gadget
        If IsGadget(ID)
          __EM_Map__\GadgetEvents(Str(ID) + ":" + Str(EventType)) = *function
        EndIf
        
      Case #EM_SysTray
        If IsSysTrayIcon(ID)
          __EM_Map__\SysTrayEvents(Str(ID) + ":" + Str(EventType)) = *function
        EndIf
        
      Case #EM_Menu
        __EM_Map__\MenuEvents(Str(ID)) = *function
        
      Case #EM_Timer
        __EM_Map__\TimerEvents(Str(ID)) = *function
        
      Case #EM_Special
        __EM_Map__\SpecialEvents(Str(ID)) = *function
        
    EndSelect
  EndIf
EndProcedure
Procedure EM_RemoveEventHandler(ID, ObjectType, EventType = -1)
  Select ObjectType
    Case #EM_Window
      DeleteMapElement(__EM_Map__\WindowEvents(), Str(ID) + ":" + Str(EventType))
      
    Case #EM_Gadget
      DeleteMapElement(__EM_Map__\GadgetEvents(), Str(ID) + ":" + Str(EventType))
      
    Case #EM_SysTray
      DeleteMapElement(__EM_Map__\SysTrayEvents(), Str(ID) + ":" + Str(EventType))
      
    Case #EM_Menu
      DeleteMapElement(__EM_Map__\MenuEvents(), Str(ID))
      
    Case #EM_Timer
      DeleteMapElement(__EM_Map__\TimerEvents(), Str(ID))
      
    Case #EM_Special
      DeleteMapElement(__EM_Map__\SpecialEvents(), Str(ID))
  EndSelect
EndProcedure
Procedure __EM_WaitWindowEvent__(timeout.i = -1)
  Protected Event.EM_Events, ProcessThisEvent.__EM_ProcessEvent__
  
  With Event 
    \Event = WaitWindowEvent(timeout)
    \EventType    = EventType()
    \EventWindow  = EventWindow()
    \EventGadget  = EventGadget()
    \EventMenu    = EventMenu()
    \EventTimer   = EventTimer()
    \EventData    = EventData()
    CompilerIf #PB_Compiler_OS = #PB_OS_Windows
      \EventwParam  = EventwParam()
      \EventlParam  = EventlParam()
    CompilerEndIf
    
    Select \Event
        
      Case #PB_Event_Gadget, #PB_Event_GadgetDrop
        If \Event = #PB_Event_GadgetDrop
          \EventType = \Event
        EndIf
        If FindMapElement(__EM_Map__\GadgetEvents(), Str(\EventGadget) + ":" + Str(\EventType))
          If __EM_Map__\GadgetEvents()
            ProcessThisEvent = __EM_Map__\GadgetEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf
        ElseIf FindMapElement(__EM_Map__\GadgetEvents(), Str(\EventGadget) + ":-1")
          If __EM_Map__\GadgetEvents()
            ProcessThisEvent = __EM_Map__\GadgetEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf
          ; for compatibility with special events:
        ElseIf \Event = #PB_Event_GadgetDrop And FindMapElement(__EM_Map__\SpecialEvents(), Str(\Event))
          If __EM_Map__\SpecialEvents()
            ProcessThisEvent = __EM_Map__\SpecialEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf
        EndIf
      Case #PB_Event_SysTray
        \EventSysTray = \EventGadget
        If FindMapElement(__EM_Map__\SysTrayEvents(), Str(\EventSysTray) + ":" + Str(\EventType))
          If __EM_Map__\SysTrayEvents()
            ProcessThisEvent = __EM_Map__\SysTrayEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf
        ElseIf FindMapElement(__EM_Map__\SysTrayEvents(), Str(\EventSysTray) + ":-1")
          If __EM_Map__\GadgetEvents()
            ProcessThisEvent = __EM_Map__\SysTrayEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf       
        EndIf
      Case #PB_Event_Menu
        If FindMapElement(__EM_Map__\MenuEvents(), Str(\EventMenu))
          If __EM_Map__\MenuEvents()
            ProcessThisEvent = __EM_Map__\MenuEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf
        EndIf
      Case #PB_Event_Timer
        If FindMapElement(__EM_Map__\TimerEvents(), Str(\EventTimer))
          If __EM_Map__\TimerEvents()
            ProcessThisEvent = __EM_Map__\TimerEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf
        EndIf
      Case #PB_Event_CloseWindow,
           #PB_Event_Repaint,
           #PB_Event_SizeWindow,
           #PB_Event_MoveWindow,
           #PB_Event_MinimizeWindow,
           #PB_Event_MaximizeWindow,
           #PB_Event_RestoreWindow,
           #PB_Event_ActivateWindow,
           #PB_Event_DeactivateWindow,
           #PB_Event_WindowDrop,
           #PB_Event_RightClick,
           #PB_Event_LeftClick,
           #PB_Event_LeftDoubleClick
        \EventType = \Event
        If FindMapElement(__EM_Map__\WindowEvents(), Str(\EventWindow) + ":" + Str(\Event))
          If __EM_Map__\WindowEvents()
            ProcessThisEvent = __EM_Map__\WindowEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf
        ElseIf FindMapElement(__EM_Map__\WindowEvents(), Str(\EventWindow) + ":-1")
          If __EM_Map__\WindowEvents()
            ProcessThisEvent = __EM_Map__\WindowEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf
          ; for compatibility with special events:
        ElseIf FindMapElement(__EM_Map__\SpecialEvents(), Str(\Event))
          If __EM_Map__\SpecialEvents()
            ProcessThisEvent = __EM_Map__\SpecialEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf
        EndIf
        
      Default
        If FindMapElement(__EM_Map__\SpecialEvents(), Str(\Event))
          If __EM_Map__\SpecialEvents()
            ProcessThisEvent = __EM_Map__\SpecialEvents()
            If ProcessThisEvent
              ProcessThisEvent(Event)
            EndIf
          EndIf
        EndIf
    EndSelect
    
    ProcedureReturn Event\Event
  EndWith
EndProcedure
Macro WaitWindowEvent(timeout = -1)
  __EM_WaitWindowEvent__(timeout)
EndMacro
Macro WindowEvent()
  __EM_WaitWindowEvent__(0)
EndMacro
CompilerIf #PB_Compiler_IsMainFile
  ; small example
  Procedure Event_CloseWindow(*ev.EM_Events)
    End
  EndProcedure
  
  Procedure Event_btnOkay_Clicked(*ev.EM_Events)
    Debug "Okay clicked"
  EndProcedure
  
  Procedure Event_btnCancel_Clicked(*ev.EM_Events)
    Debug "Cancel clicked"
  EndProcedure
  
  Procedure Event_btnQuit_Clicked(*ev.EM_Events)
    PostEvent(#PB_Event_CloseWindow, *ev\EventWindow, -1)
    ;Event_CloseWindow(*ev)
    ;End
  EndProcedure
  
  Procedure Event_SysTray_Clicked(*ev.EM_Events)
    MessageRequester("INFO","SysTray Icon clicked: "+Str(*ev\EventSysTray))
  EndProcedure
  
  Procedure Event_SysTray1_RightClick(*ev.EM_Events)
    Protected menu = CreatePopupMenu(#PB_Any)
    If menu
      MenuItem(1, "Item 1")
      MenuItem(2, "Item 2")
      MenuItem(3, "Item 3")
      MenuItem(4, "Item 4")
      
      DisplayPopupMenu(menu,WindowID(*ev\EventWindow))
    EndIf
  EndProcedure
  
  
  OpenWindow(0, #PB_Ignore, #PB_Ignore, 340, 45, "EM_EventManager - Example")
  EM_SetEventHandler(0, #EM_Window, @Event_CloseWindow(), #PB_Event_CloseWindow)
  ;EM_SetEventHandler(#PB_Event_CloseWindow, #EM_Special, @Event_CloseWindow())
  
  ButtonGadget(0, 10, 10, 100, 25, "Okay")
  EM_SetEventHandler(0, #EM_Gadget, @Event_btnOkay_Clicked(), #PB_EventType_LeftClick)
  
  Define btnCancel = ButtonGadget(#PB_Any, 120, 10, 100, 25, "Cancel")
  EM_SetEventHandler(btnCancel, #EM_Gadget, @Event_btnCancel_Clicked(), #PB_EventType_LeftClick)
  
  ButtonGadget(1, 230, 10, 100, 25, "Quit")
  EM_SetEventHandler(1, #EM_Gadget, @Event_btnQuit_Clicked(), #PB_EventType_LeftClick)
  
  If CreateImage(1,16,16)
    
    AddSysTrayIcon(1, WindowID(0), ImageID(1))
    EM_SetEventHandler(1, #EM_SysTray, @Event_SysTray_Clicked(), #PB_EventType_LeftClick)
    EM_SetEventHandler(1, #EM_SysTray, @Event_SysTray1_RightClick(), #PB_EventType_RightClick)
    
    AddSysTrayIcon(2, WindowID(0), ImageID(1))
    EM_SetEventHandler(2, #EM_SysTray, @Event_SysTray_Clicked(), #PB_EventType_LeftClick)
  EndIf
  
  Repeat
    WaitWindowEvent()
  ForEver
CompilerEndIf
Gruß
Thomas
