Page 1 of 2
On_Events
Posted: Sat Mar 02, 2013 3:43 am
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
Re: WaitWindowEventCallBacks()
Posted: Sat Mar 02, 2013 10:34 pm
by Kiffi

Thanks for sharing!
Greetings ... Kiffi
Re: WaitWindowEventCallBacks()
Posted: Sun Mar 03, 2013 2:16 am
by said
Nice and very useful
thanks for sharing
Re: WaitWindowEventCallBacks()
Posted: Sun Mar 03, 2013 5:51 am
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
Re: WaitWindowEventCallBacks()
Posted: Sun Mar 03, 2013 5:39 pm
by jassing
Nice work! Thanks.
Re: WaitWindowEventCallBacks()
Posted: Sun Mar 03, 2013 11:58 pm
by idle
Version 3
[edit] removed
Re: WaitWindowEventCallBacks()
Posted: Fri Mar 08, 2013 1:55 am
by idle
Added V4
Changed to using prototypes
Re: WaitWindowEventCallBacks()
Posted: Fri Mar 08, 2013 4:58 am
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.
Re: WaitWindowEventCallBacks()
Posted: Fri Mar 08, 2013 7:58 am
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.
Re: WaitWindowEventCallBacks()
Posted: Fri Mar 08, 2013 8:12 am
by flaith
Same issue on Windows XP and PB 5.11

Re: WaitWindowEventCallBacks()
Posted: Fri Mar 08, 2013 8:15 am
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.
Re: WaitWindowEventCallBacks()
Posted: Fri Mar 08, 2013 9:47 am
by flaith
It works now, thanks idle

Re: WaitWindowEventCallBacks()
Posted: Fri Mar 08, 2013 10:03 am
by kvitaliy
Ok! It works now

Re: WaitWindowEventCallBacks()
Posted: Fri Mar 08, 2013 11:08 am
by idle
Thanks, I really should take the time to check and test code in the vm
Re: WaitWindowEventCallBacks()
Posted: Fri Mar 08, 2013 11:42 am
by Joris
Thanks for sharing.
I'm still learning PB but this might become quit useful.