On_Events

Share your advanced PureBasic knowledge/code with the community.
User avatar
idle
Always Here
Always Here
Posts: 5089
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

On_Events

Post by idle »

OnEvents.pbi
Implements a cross platform event callbacks framework
note where an event says it's valid for all gadgets it's only true for windows and linux

version 4.31a
Adapted for PB 6.02

version 4.3
changed to object

Version 4.2
Fixed bugs so it handles multiple windows properly
added ScreenCallback

Version 4.1
Added support for EventType_X prototypes to support any gadget, where noted as valid for any gadget
note this addition has no effect on OSX
Prototype EventType_Focus(*userdata=0) ;valid for any gadget
Prototype EventType_LostFocus(*userdata=0) ;valid for any gadget
Prototype EventType_SizeItem(*userdata=0) ;valid for any gadget
Prototype EventType_KeyDown(key.s="",*userdata=0) ;valid for any gadget
Prototype EventType_KeyUP(key.s="",*userdata=0) ;valid for any gadget
Prototype EventType_LeftButtonDown(*userdata=0) ;valid for any gadget
Prototype EventType_LeftButtonUp(*userdata=0) ;valid for any gadget
Prototype EventType_LeftClick(*userdata=0) ;valid for any gadget
Prototype EventType_leftDoubleClick(*userdata=0) ;valid for any gadget
Prototype EventType_MiddleButtonUp(*userdata=0) ;valid for any gadget
Prototype EventType_MiddleButtonDown(*userdata=0) ;valid for any gadget
Prototype EventType_MiddleButtonClick(*userdata=0) ;valid for any gadget
Prototype EventType_MiddleButtonDoubleClick(*userdata=0) ;valid for any gadget
Prototype EventType_MouseEnter(*userdata=0) ;valid for any gadget
Prototype EventType_MouseLeave(*userdata=0) ;valid for any gadget
Prototype EventType_MouseMove(x,y,*userdata=0) ;valid for any gadget
Prototype EventType_MouseWheel(direction,*userdata=0) ;valid for any gadget
Prototype EventType_RightButtonDown(*userdata=0) ;valid for any gadget
Prototype EventType_RightButtonUP(*userdata=0) ;valid for any gadget
Prototype EventType_RightClick(*userdata=0) ;valid for any gadget
Prototype EventType_RightDoubleClick(*userdata=0) ;valid for any gadget
Source

https://dnscope.io/idlefiles/On_Events.pbi
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Kiffi
Addict
Addict
Posts: 1357
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: WaitWindowEventCallBacks()

Post by Kiffi »

Image Thanks for sharing!

Greetings ... Kiffi
Hygge
said
Enthusiast
Enthusiast
Posts: 342
Joined: Thu Apr 14, 2011 6:07 pm

Re: WaitWindowEventCallBacks()

Post by said »

Nice and very useful :D

thanks for sharing
User avatar
idle
Always Here
Always Here
Posts: 5089
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: WaitWindowEventCallBacks()

Post by idle »

noticed I had a bug in SetEventWindowCallBack i V1
was adding an additional element to the list

I've made another version eliminating the foreach on the event list
It uses SetGadgetData so there is a potential a user of your code could overwrite a callback
You can only set one callback per gadget or window with this method

Could someone on OSX add the methods SetWindowData GetWindowData
Linux sometimes reports eventwindow() as -1 which seems a little odd

V2

Code: Select all

;WaitWindowEventCallBacks.pbi
;Implements a Cross platform Event CallBack Chain  
;for setting callbacks required to Impliment a custom user control where it needs to do some processing 
;Set Callbacks for gadgets and windows  
;Author Idle 2/3/13 PB 5.11 
;Version 2.0
;notes uses setgadgetdata to store the pointer to an eventcallback in a gadget 
;so it could get over written by a user of your code. 

Prototype protoEventCallBackGadget(EventType,*userdata=0)
Prototype protoEventCallBackWindow(Event,*userdata=0)

Structure PB_EventsCallbackFunction
   item.i
   *userdata
   EventType.i
   *cbGadget.protoEventCallBackGadget
   *cbWindow.protoEventCallBackWindow 
EndStructure 

Structure PB_EventsCallbacks
   List callbacks.PB_EventsCallbackFunction()
EndStructure 

Global gEventCallbacks.PB_EventsCallbacks

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
   #GWLP_USERDATA =-21
 CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux 
   ImportC  "-gtk"
     gtk_widget_get_parent_(*widget) As " gtk_widget_get_parent"
     g_object_set_data_(*Widget.GtkWidget,strData.p-ascii,*userdata) As "g_object_set_data"
     g_object_get_data_(*Widget.GtkWidget,strData.p-ascii) As "g_object_get_data"
  EndImport  
   
CompilerEndIf 

Procedure SetWindowData(window,value) 
   Protected win 
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
        SetWindowLongPtr_(WindowID(window),#GWLP_USERDATA,Value)
   CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux 
       win = WindowID(window)
       g_object_set_data_(win,"wev",value)
   CompilerElse 
       ;for osx
   CompilerEndIf 
         
EndProcedure   

Procedure GetWindowData(window) 
   Protected win  
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
       ProcedureReturn  GetWindowLongPtr_(WindowID(window),#GWLP_USERDATA)
   CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux 
     If window =-1 
        win = GetActiveWindow() 
        If IsWindow(win) 
           win = WindowID(win)
           ProcedureReturn  g_object_get_data_(win,"wev")
        EndIf   
     Else 
        Win = WindowID(window)
        ProcedureReturn g_object_get_data_(win,"wev")
    EndIf
   
   CompilerElse 
       ;osx
    CompilerEndIf 
     
EndProcedure    

;=============================================================================
; SetEventCallBackGadget(Gadget,*Function.protoEventCallBackGadget,*UserData=0) 
; Set a Gadgets Event Callback 
; Parameters 
; Gadget : Gadget Number 
; *Function : Address of the Callback Function in the form of MyEventCallBackGadget(EventType,*userdata=0)
; *UserData=0 : optional : A pointer to data you want to pass to the callback procedure eg a *this pointer for an Interface call 
; Returns 
;  Returns a EventCallback pointer or 0 if function fails 
; Notes 
;  The CallBack only Processes PB Events it doesn't process platform events  
;=============================================================================

Procedure SetEventCallBackGadget(Gadget,*Function.protoEventCallBackGadget,*UserData=0) 
   Protected CallBack 
   CallBack = AddElement(gEventCallbacks\callbacks())
   If  CallBack 
      gEventCallbacks\callbacks()\item = Gadget 
      gEventCallbacks\callbacks()\userdata = *userdata 
      gEventCallbacks\callbacks()\cbGadget = *function
      SetGadgetData(Gadget,CallBack) 
      ProcedureReturn CallBack  
  EndIf     
EndProcedure 

;=============================================================================
; ChangeEventCallBackGadget(EventCallBack,*Function.protoEventCallBackGadget,*UserData=0) 
; Change an existing EventCallback   
; Parameters 
; EventCallback : An Existing EventCallBack set from SetEventCallBackGadget 
; *Function : Address of the Callback Function in the form of MyEventCallBackGadget(EventType,*userdata=0)
; *UserData=0 : optional : A pointer to data you want to pass to the callback procedure eg a *this pointer for an Interface call 
; Returns 
;  Returns #True if sucessful  
;=============================================================================

Procedure ChangeEventCallBackGadget(EventCallback,*Function.protoEventCallBackGadget,*UserData=0) 
   Protected *EventCallBack.PB_EventsCallbackFunction
   If EventCallback
       *EventCallBack = EventCallback 
       *EventCallBack\cbGadget = *Function 
       *EventCallBack\userdata = *UserData 
       ProcedureReturn #True    
    EndIf    
 EndProcedure 

;=============================================================================
; SetEventCallBackWindow(Window,*Function.protoEventCallBackWindow,*UserData=0)
; Set a Windows Event Callback 
; Parameters 
; Window  : Window  Number 
; *Function : Address of the Callback Function in the form of MyEventCallBackWindow(Event,*userdata=0)
; *UserData=0 : optional : A pointer to data you want to pass to the callback procedure eg a *this pointer for an Interface call 
; Returns 
;  Returns a EventCallBack pointer or 0 if function fails 
; Notes 
;  The CallBack only Processes PB Events it doesn't process platform events  
;=============================================================================

Procedure SetEventCallBackWindow(Window,*Function.protoEventCallBackWindow,*UserData=0) 
   Protected CallBack 
   CallBack = AddElement(gEventCallbacks\callbacks())
   If  CallBack 
       gEventCallbacks\callbacks()\item = Window 
      gEventCallbacks\callbacks()\userdata = *UserData 
      gEventCallbacks\callbacks()\cbWindow = *Function
      SetWindowData(Window,CallBack) 
      ProcedureReturn CallBack  
  EndIf     
   
EndProcedure 

;=============================================================================
; ChangeEventCallBackWindow(EventCallBack,*Function.protoEventCallBackWindow,*UserData=0) 
; Change an existing EventCallback   
; Parameters 
; EventCallback : An Existing EventCallBack set from SetEventCallBackWindow 
; *Function : Address of the Callback Function in the form of MyEventCallBackWindow(Event,*userdata=0)
; *UserData=0 : optional : A pointer to data you want to pass to the callback procedure eg a *this pointer for an Interface call 
; Returns 
;  Returns #True if sucessful  
;=============================================================================

Procedure ChangeEventCallBackWindow(EventCallback,*Function.protoEventCallBackGadget,*UserData=0) 
   Protected *EventCallBack.PB_EventsCallbackFunction
   If EventCallback
       *EventCallBack = EventCallback 
       *EventCallBack\cbWindow = *Function 
       *EventCallBack\userdata = *UserData 
        ProcedureReturn #True    
    EndIf    
 EndProcedure 

;============================================================================
;RemoveEventCallBack(EventCallBack) 
;Removes an EventCallBack from the EventsCallBack Chain
;Parameters 
; EventCallBack the pointer to an EventCallback recieved from calling a SetEventCallBackGadget or  SetEventCallBackWindow
;==============================================================================

Procedure RemoveEventCallBack(EventCallBack) 
   Protected *EventCallBack.PB_EventsCallbackFunction
   If EventCallBack 
     ChangeCurrentElement( gEventCallbacks\callbacks(),EventCallBack) 
     *EventCallBack = @gEventCallbacks\callbacks()
     If *EventCallBack\cbGadget 
        SetGadgetData(*EventCallBack\item,0)
     Else 
        SetWindowData(*EventCallBack\item,0)
     EndIf    
     DeleteElement(gEventCallbacks\callbacks()) 
   EndIf   
EndProcedure 
 
  
;===============================================================================
;WaitWindowEventCallBacks(timeout=-1)
;Same as WaitWindowEvent()but additionally processes EventCallBack requests for Gadgets or Windows 
;set by SetEventCallBackGadget() or SetEventCallBackWindow() 
;note it uses setgadgetdata so it's only posible to trap all events to a gadget or window
;=============================================================================== 
  
  Procedure WaitWindowEventCallBacks(timeout=-1)
   Protected Event,EventType,window,*EventCallBack.PB_EventsCallbackFunction
   Event = WaitWindowEvent(timeout)
   If Event 
      If Event = #PB_Event_Gadget
         *EventCallBack = GetGadgetData(EventGadget())
         If *EventCallBack
            If *EventCallBack\cbGadget 
               *EventCallBack\cbGadget(EventType(),*EventCallBack\userdata) 
            EndIf
          EndIf   
       Else     
         *EventCallBack = GetWindowData(EventWindow())
         If *EventCallBack
            If *EventCallBack\cbWindow 
               *EventCallBack\cbWindow(Event,*EventCallBack\userdata) 
            EndIf
        EndIf   
      EndIf 
   EndIf     
   ProcedureReturn Event 
   
EndProcedure 
  

;================================================================= 


;=================================================================
;Test WaitWindowEventCallBack()

Procedure Gadget1_Events(EventType,*userdata) 
   
   If EventType = #PB_EventType_LeftClick
         Debug "Button 1 Clicked" 
   EndIf
           
EndProcedure 

Procedure Gadget2_OnRightClick(EventType,*userdata)  
    If EventType = #PB_EventType_RightClick 
       Debug "Right Button Clicked" 
    EndIf    
 EndProcedure       
  
 Procedure Window1_Events(Event,*userdata) 
    If event = #PB_Event_Repaint
       Debug "Event Repaint "
    EndIf   
  EndProcedure   
  
  
 
OpenWindow(1,0,0,200,100,"1") 
ButtonGadget(1,5,5,60,30,"click me") 
CanvasGadget(2,70,5,110,30)
ButtonGadget(3,5,40,60,30,"Click me") 
;Set a callback for the gadget to trap it's events 
Callback1 = SetEventCallBackGadget(1,@Gadget1_Events())
;Set a callback to trap a specific event 
Callback2 = SetEventCallBackGadget(2,@Gadget2_OnRightClick())
;set a callback to the PB events for the window
Callback3 = SetEventCallBackWindow(1,@Window1_Events()) 
StartDrawing(CanvasOutput(2))
DrawText(5,5,"Right click me") 
StopDrawing() 


Repeat
  
   Select WaitWindowEventCallBacks() 
      Case #PB_Event_CloseWindow 
         RemoveEventCallBack(CallBack1)
         RemoveEventCallBack(CallBack2) 
         RemoveEventCallBack(CallBack3) 
         End 
      Case #PB_Event_Gadget 
         If EventGadget() = 3 
            If EventType() = #PB_EventType_LeftClick 
               Debug "Not in Call Back Chain" 
            EndIf 
         EndIf    
   EndSelect 
ForEver 

Windows 11, Manjaro, Raspberry Pi OS
Image
jassing
Addict
Addict
Posts: 1768
Joined: Wed Feb 17, 2010 12:00 am

Re: WaitWindowEventCallBacks()

Post by jassing »

Nice work! Thanks.
User avatar
idle
Always Here
Always Here
Posts: 5089
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: WaitWindowEventCallBacks()

Post by idle »

Version 3
[edit] removed
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
idle
Always Here
Always Here
Posts: 5089
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: WaitWindowEventCallBacks()

Post by idle »

Added V4
Changed to using prototypes
Windows 11, Manjaro, Raspberry Pi OS
Image
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Re: WaitWindowEventCallBacks()

Post by kvitaliy »

idle wrote:Added V3
Line 212
Error - Invalid memory access
idle wrote:Added V4
Line 640

Code: Select all

   If (*EventCallBack\cbGadget And Result = 1)
Error - Pointer is null.
User avatar
idle
Always Here
Always Here
Posts: 5089
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: WaitWindowEventCallBacks()

Post by idle »

what OS and PB version are you using kvitaliy?

Ok fixed was missing the *userdata pointer in the callbacks, Linux didn't seem to mind
windows didn't like it.
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: WaitWindowEventCallBacks()

Post by flaith »

Same issue on Windows XP and PB 5.11 :?
“Fear is a reaction. Courage is a decision.” - WC
User avatar
idle
Always Here
Always Here
Posts: 5089
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: WaitWindowEventCallBacks()

Post by idle »

yes I was missing the *userdata pointer in the callback functions in the example
Linux didn't mind the omission of.

I removed V3 Thanks for letting me know.
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
flaith
Enthusiast
Enthusiast
Posts: 704
Joined: Mon Apr 25, 2005 9:28 pm
Location: $300:20 58 FC 60 - Rennes
Contact:

Re: WaitWindowEventCallBacks()

Post by flaith »

It works now, thanks idle :D
“Fear is a reaction. Courage is a decision.” - WC
kvitaliy
Enthusiast
Enthusiast
Posts: 162
Joined: Mon May 10, 2010 4:02 pm

Re: WaitWindowEventCallBacks()

Post by kvitaliy »

Ok! It works now :D
User avatar
idle
Always Here
Always Here
Posts: 5089
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: WaitWindowEventCallBacks()

Post by idle »

Thanks, I really should take the time to check and test code in the vm
Windows 11, Manjaro, Raspberry Pi OS
Image
Joris
Addict
Addict
Posts: 885
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: WaitWindowEventCallBacks()

Post by Joris »

Thanks for sharing.
I'm still learning PB but this might become quit useful.
Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Post Reply