Events / Hooks and Stuff

BlitzMax Forums/BlitzMax Beginners Area/Events / Hooks and Stuff

Eric(Posted 2005) [#1]
I know this is a broad question..but can someone help me in simple terms what these are used for and how they are implemented in a practical application.

I remember way back when , when I couldn't understand "TYPES" now they are second nature.

GUI based stuff is really new to me.

Thanks in advance for any help.
Eric


Space_guy(Posted 2005) [#2]
yes an event and hook tutorial would be great!


Warpy(Posted 2005) [#3]
shagwana posted some great code yesterday, but it's a bit obscure...

ah, here it is! http://www.blitzbasic.com/Community/posts.php?topic=53153


Eric(Posted 2005) [#4]
Yep I saw that and that is what prompted my question.


ImaginaryHuman(Posted 2005) [#5]
I have tried the MaxGUI demo, it's pretty nice, but I am not really using it for anything right now. However I probably can explain what events and hooks are, in general. If this doesn't totally pertain to MaxGUI, forgive me.

To start with, any GUI system that is a native part of the operating system, is largely handled by the operating system itself. The o/s deals with drawing the windows, buttons, sliders, all the rest of it. Because the o/s is handling that stuff, it also handles the user input. So when you are doing stuff with the mouse, clicking on buttons, moving sliders, etc, the o/s is handling all that, drawing the slider controls, moving windows around, etc. For the most part that can all be controlled without having to involve the underlying application whatseover. It's just a `front end` for your application which is separately managed by the operating system, not by your application. It's kind of like your application says, okay, I would like you to draw a window for me, and the o/s draws it and then the o/s manages it too. The o/s deals with any basic updating that needs to be done as a result of a window moving over the top of another, or to show that buttons are being clicked on, etc. Of course it then has to communicate with your application to tell you that something important happened. Normally your application is blind to these `events` so that's why you then need to have an `event handler`.

So you have a list of events that stream in to your application through a doorway that allows the o/s to tell you what the user is doing with the GUI. These little messages arrive and then BlitzMax will process them for you and make them available to your program in a way that you can make use of them.

Sometimes all you might want to do in your program, then, is to say "wait for an event to happen" , and when an event does happen, you then interpret the event ie figure out what type of event it is, and then act accordingly. So you might be waiting for an event, the user clicks a button, the o/s handles animating the button click, it passes an event code to your application behind the scenes, the BlitzMax event system puts it in the queue, then it feeds into the `wait event` command (i guess there is one?). So then control is in the hands of your program, you can then get the event code and decide what it means to you. Like if they clicked a certain button, you can say ok, make a new window open, or play a sound, or whatever functionality.

Waiting for events is the simplest way of getting communication from the o/s. Usually it is a little inconvenient for you, in your programming design, however, to have just one place in your `main loop` where you wait for events. You might want to be getting on with doing some other stuff and it might not be practical to wait for the events in only on point in the program. This is where hooks come in.

A hook, or a call-back routine, is a way of getting the external o/s system to call specific functions as and when an event actually occurs, as if they were wired directly into the GUI itself. In other words, rather than you waiting for an event, the o/s triggers an event, handles the GUI and calls the piece of your program that you've told it is a hook. They call it a hook because it allowing you to `hook into` the o/s's GUI management and be a more integrated part of it. These are also sometimes called call-back routines. So it's like taking a little chunk of your blitz code and `uploading it` to the separate o/s-managed GUI system, yet it still being able to inter-operate with the rest of your program. You then don't have to wait for the events to happen or to check for them, as soon as they happen the hooked function gets executed. Since it gets called right there and then, it probably interrupts whatever else is happening at the time (i guess?). There may be some multitasking involved, I don't know how they have it working in BlitzMax.

So a hook is basically a way of putting some of your code on the other side of the fence, in the o/s realm of control rather than on this side where you are blind to what's going on. The o/s can trigger specific routines in your program when they need to be called. It makes the GUI more responsive because things happen as and when they are clicked rather than when your program happens to get to it.
The GUI becomes responsive and events are handled in a more `object oriented` way. Ie, you have separate little functions that get called for each type of event, rather than one `centralized` event handling procedure. You are basically hardwiring your program into the GUI manager so that it already knows ahead of time what routine goes with what action, and can call that routine.

Normally when the program flow is in the GUI-management code, you don't have any control over what happens and you can't get access to it. With a hook in there, you can get the o/s to call a little piece of program according to your will. So maybe you have a slider bar which the o/s is handling, and the user is clicking it and sliding it around, but you don't want it to just be some dumb slider hanging around in mid air. You want it to do something WHILE the user is still controlling it, like scroll a page of text or make a value increase or a color change. So by telling it what your hook program is, you can have it `tie in` (be hooked into) your program and do something real-time responsive while the user is still controlling things. So as you slide the slider bar, your little `scroll the canvas` routine might be called, or your `cycle the colors` or whatever else you want to happen. It needs to be in there as a hook because while the user is still controlling the GUI, the CPU's program flow is locked into the GUI program, separate from your application. You want to be getting some feedback from what's going on in realtime while still allowing the o/s to handle what the user is doing, so you sort of `share` the program flow by telling it to call your hook program every time there is a change (ie user moves the mouse on a slider etc).

There are many other examples I'm sure, that's basically how I understand it. So when you are wanting the o/s to tell you what events are happening you need them to come to you in order of clicking, etc, so you have an event queue. You can read it yourself or tell the o/s what pieces of your program to execute for which events. It's kind of a way to add some multitasking to your program as well, since your regular program is probably pre-empted/interrupted while the hook program is run (AFAIK).

I hope this helps.


Eric(Posted 2005) [#6]
Angel...Wow Thanks for that answer it really helped. Now I just need to grasp the commands that make this happen.

Again Thanks.

Eric


Takuan(Posted 2005) [#7]
Very nice explanation.
Mr.S should hire you to write Docs:)


FlameDuck(Posted 2005) [#8]
Mr.S should hire you to write Docs:)
You must not have used Miranda. :o>

Although in his defense I must say he has gotten better.


ImaginaryHuman(Posted 2005) [#9]
Do you mean Mildred? I would agree those docs were somewhat shabby ;-D


REDi(Posted 2005) [#10]
Eric have a look at the "maxgui_overview" tutorial in the "doc/maxtuts" folder of your install, in there you'll find a section called "Event Hook based Rendering".

Hope that helps


Eric(Posted 2005) [#11]
Papa,

I read that I am trying to understand how

AddHook EmitEventHook,eventhook,Self


And
Function eventhook:Object (id,data:Object,context:Object)
		Local	event:TEvent
		Local	app:TApplet
		event=TEvent(data)
		app=TApplet(context)
		app.OnEvent event	
End Function


Correlate to one another but I'll figure it out. I never thought this GUI stuff would be confusing to me.


Dreamora(Posted 2005) [#12]
Most confusing thing is especially that the example in the help does not work without GUI (the addhook FlipHook, MyHook results in a FlipHook not found)


Wiebo(Posted 2005) [#13]
I don't understand one damned thing of that code example Eric just posted... There is no explaining comment in the spinningapplet demo at all!! argh.


Eric(Posted 2005) [#14]
It is confusing isn't it?

I was playing around with that code and I still don't understand.
If we can hook events to functions how do you distinguish which event hooks what function.


René(Posted 2005) [#15]
Hi there,

I don't know whether this topic is still active but maybe this example is helpfull: a slider which immediately moves a panel when the slider moves.

Global window:TGadget = CreateWindow("Main", 0,0,800,600)
Global slider:TGadget = CreateSlider(5,50,500,20, window, SLIDER_HORIZONTAL|SLIDER_SCROLLBAR)
Global panel:TGadget = CreatePanel(50,100,20,20, window, PANEL_BORDER)

SetSliderRange(slider, 0,100)
SetSliderValue(slider, 50)

AddHook EmitEventHook,myFunc


While Not KeyHit(KEY_ESCAPE)	
Wend
End


Function myFunc:Object(id, data:Object, context:Object)
	Local event:TEvent = TEvent(data)
	
	Select event.source
		Case slider
			SetGadgetShape(panel,event.data,GadgetY(panel), GadgetWidth(panel), GadgetHeight(panel))
	End Select
	
	Select event.id
		Case EVENT_WINDOWCLOSE
			End
	EndSelect
End Function



Gabriel(Posted 2005) [#16]
If we can hook events to functions how do you distinguish which event hooks what function.


Exactly what I'm wondering.


And while I appreciate the effort to assist, Rene's example just leaves me more confused. You're not using AllocHookID so it still looks to me as though MyFunc is executed on every single event, and then you just parse to see what event it was. That doesn't seem to fit the stated purpose of hooks at all. Instead of having one action tied to an event, you end up slowing things down parsing every possible event on every single occasion. In other words, with 10 events to parse and 10 possible outcomes, you end up checking 100 different possibilities.

If that's really how hooks are supposed to work, isn't it being unecessarily slow?


skidracer(Posted 2005) [#17]
Unless you are doing something advanced the only time you will want to use an event Hook is in the following example:
' standard main loop

window=CreateWindow("test",20,20,200,200)

While True
	WaitEvent()
	Select EventID()
		Case EVENT_WINDOWCLOSE
			End
	End Select
Wend
' an event handler based program

Function EventHandler:Object(id, data:Object, context:Object)
	Select EventID()
		Case EVENT_WINDOWCLOSE
			End
	End Select
End Function

window=CreateWindow("test",20,20,200,200)

AddHook EmitEventHook,EventHandler

While True
	WaitEvent()
Wend
These two programs may look the same but the fact the the system is calling the EventHandler function in the second example means that when systems such as Windows enters a "modal loop" such as during window sizing, scrollbar dragging and menu activation your application can continue to support event handling.

The first example using the traditional eventloop which will only allow you to process events once the user has released the mouse and the system exits such modal loops as mentioned.


Smokey(Posted 2005) [#18]
the code

' an event handler based program

Function EventHandler()
	Select EventID()
		Case EVENT_WINDOWCLOSE
			End
	End Select
End Function

window=CreateWindow("test",20,20,200,200)

AddHook EmitEventHook,EventHandler

While True
	WaitEvent()
Wend



does't work for me it give me an error

"Unable to convert from Int() to Object(int,Object,Object) ?


skidracer(Posted 2005) [#19]
oops.


LarsG(Posted 2005) [#20]
so:
AddHook EmitEventHook,EventHandler

means that "EmitEventHook" is like "react on everything which happens to my window/program", and it calls the given function when this event fires (ie. "EventHandler")?


René(Posted 2005) [#21]
Maybe the SetGadgetTarget command is the one you're/we're loking for. Does somebody have an example of SetGadgetTarget and this SendMessage stuff?


skidracer(Posted 2005) [#22]
I will post a tutorial tomorrow with a new implementation, the SetGadgetTarget command documented actually got ripped out just before release.


Eric(Posted 2005) [#23]
Hey Skid are you still planning a small tutorial?


degac(Posted 2005) [#24]
yes, it will help! I'm very confused at the moment...


marksibly(Posted 2005) [#25]
Hi,

My attempt at a hook example:
Strict

Function MyEventHook:Object( id,data:Object,context:Object )

	Local ev:TEvent=TEvent(data)
	
	If ev Print "Event="+ev.ToString()
	
	Return data
	
End Function

AddHook EmitEventHook,MyEventHook

window=CreateWindow( "A window!",0,0,640,480 )

While WaitEvent()<>EVENT_WINDOWCLOSE
Wend


A couple of points:

* The 'MyEventHook' function is the 'hook' and gets called *every time* an event occurs (from within WaitEvent - or more precisely, WaitSystem, which is called by WaitEvent).

* Hooks should check the 'data' param to make sure it's valid. In this example it always will be, but it's a good idea in general.

* Hooks should generally return the 'data' param they are passed - this is so other hooks can look at the data too. So if you want to 'block' other hooks, return Null.

Both polled input (KeyDown, KeyHit etc) and the event queue are built on top of hooks - check out the source code to really confuse yourselves!

Why use hooks? Why not just stick with WaitEvent? Well, hooks are mainly useful for dealing with 'modal actions' - actions which involve the user holding down the mouse and doing something, like resizing a window or dragging a scroller.

When the user is performing a modal action, the OS goes into a loop and notifies your app of events via a 'callback function'. Hooks are really just a generalization of such callback functions.

BlitzPlus got around this using a complex system of mirrors and pulleys, but I was nervous about using the same trick on multiple platforms, much to skid's disappointment.

Hope this helps a bit!


Perturbatio(Posted 2005) [#26]
Hope this helps a bit!

It certainly helped me, thanks :)

I managed to put together this test, hopefully people can get some idea from it.



Wiebo(Posted 2005) [#27]
So, that makes things a lot clearer. I also notice from Perturbatio's example that we no longer have to re-create a canvas when we want to resize it?? nice. It would be cool if we could compile a list of gadget-behaviour changes from b+


Muttley(Posted 2005) [#28]
OK, really dumb question time.

I assume you can just use the event queue stuff (along with timers triggering custom events) even if you're not using the GUI stuff?

I'm thinking along the lines of using timers this way to trigger updating animations/scrolling, etc. Rather than relying on the vblank for timing stuff.

Muttley


Perturbatio(Posted 2005) [#29]
I assume you can just use the event queue stuff (along with timers triggering custom events) even if you're not using the GUI stuff?

Yes, you can.


Muttley(Posted 2005) [#30]
Yay! :D

Muttley


Ziltch(Posted 2006) [#31]
The example that Mark posted here would be a better example to
use in the help files.


peltazoid(Posted 2007) [#32]
@Perturbatio

your example I don't get it as from reading the code I would expect it to display the window size as you are resizing it.

When run it only updates the window sizes in the canvas when you release the mouse button! If this is how it is ment to work what it the point? As thats how the resize gadget works anyhow.

I'm trying to get my head around event hooks :D

Cheers.


peltazoid(Posted 2007) [#33]
some more eventhook questions

the hook function, when it is called by an event taking place data contains the last event data.

what does context contain?

and you only return the data from the hook function if you want another hook function to work on the same event?

I don't have time at present to test this. I may have more questions as well. :)

Cheers.


assari(Posted 2007) [#34]
Have you gone thru this?
http://www.2dgamecreators.com/maxgui/T15-Eventhooks.html


peltazoid(Posted 2007) [#35]
yes I have and it was very helpful but does not answer the questions above.

plus the examples on my system do not cause a trial of windows to occour in the non event hook example.

I'm running 1.24 with latest sync.

Cheers