Events, Hooks etc
BlitzMax Forums/BlitzMax Beginners Area/Events, Hooks etc
| ||
I am not using MaxGUI but would like to understand Events and Hooks but find the documentation VERY poor. As a test I would like to create a timer which, when ticked, issues a MY_EVENT. However, I have no idea how to use CreateEvent. The parms (id,source:Object=Null,data=0,mods=0,x=0,y=0,extra:Object=Null ) are not exactly self-explanatory. Leaving the defaults and specifying CreateEvent(MY_EVENT) fails with 'ID MY_EVENT not found'. I can get past this by creating a function called MY_EVENT but I'm now off into the unknown. Anybody able to help? <edit> Blimey, got the first bit to work... SuperStrict Graphics 800,600 Local MY_EVENT:TEvent=CreateEvent(69) Local myTimer:TTImer = CreateTimer(3,MY_EVENT) While EventID() <> EVENT_KEYDOWN WaitEvent If EventID() = 69 Print "Timer has ticked " + TimerTicks(myTimer) + " times" EndIf EndWhile but from trial+error. |
| ||
Have you checked out the The MaxGUI Beginner Tutorial Series?. Events are explained starting from Tutorial 2 and eventhooks in Tutorial 15 |
| ||
Hi Assari, I've read those and they help to some degree but still don't explain how to use these functions outside your tutorial (which is understandable). e.g. Function AddHook( id,func:Object( id,data:Object,context:Object ),context:Object=Null,priority=0 ) What is id, data:object, context:object etc)? It's even possible what I'm hoping to do is not possible BUT, without knowing what *CAN* be done it's hard to know. The idea is to CreateTimer specifying an event_id then, when that event occurs to hook into other code. E.g. When EVENT_TIMER occurs for that TTimer to run a specific function automatically. Even if that is NOT possible I still want to understand how to use events/hooks outside MaxGui whether I need them, can use them or end up hating them (I know which is favourite at the moment). Thanks for your help so far and excellent tutorials. |
| ||
that function looks alien, and the manual is poor. yes! Use this template, I use it always, and forget about the meaning of that function or the poor'ish manual :P Type MyType Field NewEvent:TEvent=New TEvent ' if you need to emit events Function eventhook:Object(id:Int,data:Object,context:Object) If MyType(context) MyType(context).ev TEvent(data);Return data EndFunction Method New() AddHook EmitEventHook,eventhook,Self End Method Method Free() RemoveHook EmitEventHook,eventhook GCCollect() End Method Method ev(event:TEvent) If Event.id EndIf If Event.source EndIf If Event.x NewEvent.source=Self EmitEvent NewEvent EndIf If Event.y EndIf ' etc. End Method End type (don't forget to change the MyType names in that eventhook-function!) |
| ||
Hmmm. so I've managed to emit event 69 each time my CreateTimer ticks. How would I use that template (or any other method) to add a hook which checked for my event 69 and output "Hello World!" when 69 occurs? <edit> So, I now have a hook using fliphook and a user-event... Function MyHook:Object( id,data:Object,context:Object ) Print "Hello World!" End Function Local MY_EVENT:TEvent=CreateEvent(69) Local myTimer:TTImer = CreateTimer(3,MY_EVENT) 'Add our hook to the system AddHook FlipHook,MyHook Graphics 800,600 While EventID() <> EVENT_KEYDOWN WaitEvent If EventID() = 69 Print "Timer has ticked " + TimerTicks(myTimer) + " times" EndIf flip EndWhile How would I link the2 together so "Hello World!" is displayed when the timer ticks? I tried with EmitEventHook but I'm then back into the realms of confusion. |
| ||
try this (in debugmode, watch the log).., it only uses the GUI because I'm used to it :PSuperStrict Type MyType Field timer:TTimer Field NewEvent:TEvent=New TEvent Function eventhook:Object(id:Int,data:Object,context:Object) If MyType(context) MyType(context).ev TEvent(data);Return data EndFunction Method New() AddHook EmitEventHook,eventhook,Self timer=CreateTimer(3) End Method Method Free() RemoveHook EmitEventHook,eventhook GCCollect() End Method Method ev(event:TEvent) If Event.id=EVENT_TIMERTICK NewEvent.source=Self NewEvent.id=69 DebugLog "hooked timertick!" EmitEvent NewEvent EndIf End Method End Type Local window:TGadget=CreateWindow("O_O",200,200,640,480) Local mooh:MyType=New MyType Repeat WaitEvent() If EventID()=EVENT_WINDOWCLOSE End If EventID()=69 If EventSource()=mooh DebugLog "mooooh!" EndIf Forever btw: drag the window around to see the difference between 'hooks' vs 'no hooks' |
| ||
Thanks, think I've got it...SuperStrict Const TICK_EVENT:Int=69 Function MyHook:Object( id:Int,data:Object,context:Object ) Local ev:TEvent=TEvent(data) Select ev.id Case TICK_EVENT Print "Hello World!" Default Print "Not interested!" End Select End Function Local MY_EVENT:TEvent=CreateEvent(TICK_EVENT) Local myTimer:TTImer = CreateTimer(3,MY_EVENT) 'Add our hook to the system AddHook EmitEventHook,MyHook Graphics 800,600 While EventID() <> EVENT_KEYDOWN WaitEvent Flip EndWhile <edit> How would I get an Event_ID without supplying a random number myself? |
| ||
Strange ... why does this work with own defined Event constants but not if you would use EVENT_TIMERTICK and check if TEvent(data).source = timer ... Haven't been able to find a usefull reason why it should not work with source check but event id check ... But a good small example, but both are good examples (think especially the timer one might be interesting for "pseudo threaded" networking :-) Note: the good thing is that these event stuff even works when no event commands are used at all. This is a really usefull thing. Thank you :-) On the question: This is not possible at the moment. You need to specify the event with a number. But for the sake of all the other events that can be fired by the OS, it would be great if we had a command that returned the next free event number because I don't think we all are gods and know all the possible event numbers over all 3 OSes ;-) |
| ||
Think there should be an event_id equivalent of AllocHookID Possibly a better example... SuperStrict Const TICK_EVENT:Int=69 Function MyHook:Object( id:Int,data:Object,context:Object ) Local ev:TEvent=TEvent(data) Select ev.id Case TICK_EVENT Print "Hello World!" End Select End Function Local MY_EVENT:TEvent=CreateEvent(TICK_EVENT) Local myTimer:TTImer = CreateTimer(4,MY_EVENT) 'Add our hook to the system AddHook EmitEventHook,MyHook Graphics 800,600 Local time:Int=MilliSecs()+500 While EventID() <> EVENT_KEYDOWN If MilliSecs()>=time Print "1/2 second" time=MilliSecs()+500 EndIf PollEvent EndWhile I was probably lucky as event_id 69 was on the tip of my tongue. If you replace TICK_EVENT with EVENT_TIMERTICK it works the same way but I was hoping for a way to only call MY_HOOK automatically when TICK_EVENT occurred. |
| ||
All things non-event, dunno, scare me :P Since B+ I really ditched all polled stuff orso. I don't exactly see what you're coding atm, and whether there're full-event solutions, with no polling whatsoever.. back to the pollingmasters with the question :P |
| ||
I'm just trying to find out how to use these things rather than have an end in mind. In this case I could use the standard EVENT_TIMERTICK with the same hook but was just trying things out. I still want to understand all the gubbings about 'context:object' and 'mods' etc but I REALLY want this documented both out of principle and to save what little hair I have left. |
| ||
Mods etc are internal values that you can send with an event. For example the mouse sends with its x,y (position), other events send mods (modifier key values) or even extra (which is great if you want to have an object fired on event ... for example if we could do a collision event this would be extremely handy to specify the other colided object) tonyg: Yes it works if I ask for the ID. The problem is that I have more than one timer in and that I need a specific one and if I check for TEvent(data).source = timer. But for some reason tevent(data).source is null which makes totally no sense. It seems like starting an eventhook within a method or creating a type global timer, which emits the event just don't work ... have to find out which part it is (or if it is somehow related to private). The timer is created, that part is already checked ... stupid inconsistent behavior of BM is really making me angry and frustrates me |
| ||
It's stunning that this is 2 years ago already! I suppose the screaming wasn't loud enough, haha! Timers, as far as I can tell, are the nightmare of beginners for sure. The Event handling is only understandable up until the point when you introduce timers. The moment a timer is running, all bets are off, Eventsources become exterminated and replaced by timers, other queues overwritten and ignored and systems get bellyflopped until the timer has enough of a hickup to inject a little "escape" for closing the window, haha. Let me add again that I can only speak for beginners, since I'm one of them, but it somehow feels as though it ain't getting too much better after knowing more. I sure hope I'm wrong, though. I like to believe that very much! |