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