A single message-handler routine is written for each control and almost all messsages for that particular control are fed into it's handler routine, eg :
-- This is a handler routine for a Window function handler_MAINWINDOW(integer id, integer msg, atom wParam, object lParam) if msg=WM_PAINT then -- paint the window elsif msg=WM_VSCROLL then -- scroll something elsif msg=WM_HSCROLL then -- scroll something elsif msg=WM_TIMER then moveFish() -- Eh? Whats going on here? end if return 0 end function -- This is a handler routine for a Button function handler_BUTTON1(integer id,integer msg, atom wParam, object lParam) if msg=WM_COMMAND then -- Button1 was clicked, do something end if return 0 end function
setHandler(MAINWINDOW,routine_id("handler_MAINWINDOW"))
setHandler({BUTTON1,BUTTON2}, routine_id("handler_BUTTONS"))
function handler_CONTROL(integer id, integer msg, atom wParam, object lParam) -- some code return 0 end function
Important Notice: Messages are sent to a control OR the control's parent (usually a Window). Notification messages are sent from a control to it's parent. The library will try to trap this type of message and redirect them to the (child) control's handler routine. Messages redirected in this way should not be (intercepted and) altered since the redirection process alters the Message format. Whoever writes the handler routines must be aware of this.
The user can intercept and alter certain messages and thus modify the default Windows processing. This is done by returning a 2-element sequence containing your values of {wParam, lParam}. This can be used to advantage when, say, implementing a password window where you do not want the actual characters shown on the screen, eg :
-- untested password capture code fragment sequence passwordstring -- holds the password entered passwordstring = "" function handler_PASSWORD_EDITBOX(integer id, integer msg, atom wParam, object lParam) if msg = WM_CHAR then -- printable key was pressed -- add new character to the string variable passwordstring &= wParam -- return new character to print, in this case it's an asterisk return {'*', lParam} elsif msg = WM_KEYUP then if wParam = '\13' then -- ENTER key pressed processPassword(passwordstring) end if end if return 0 end function
Generally speaking, the return values from handlers can be in 3 formats:
return 0 - this is the default value when you want windows to process the message
return {i} - use a 1-element sequence to tell windows to return with the enclosed value immediately
return {W, L} - intercept & modify original message for windows to process Apart from the specific messages that ARWEN traps, the user has access to all other messages but the user is advised to refer to the API for specific implementation details. In some instances the user may be able to return an atomic value other than 0 for certain messages. These cases are discussed in other sections.
If a control has been associated with a particular handler routine and you wish to replace that routine with another then simply call setHandler() again and pass the new routine id. If you wish to disassociate the control from any handler routine then call setHandler() and pass UNDEFINED as the 2nd parameter. Multiple controls may be relinked or disassociated in a single call.
The heart of an event-driven Windows program is the Message Loop. In my library this loop resides in the WinMain() routine. Usually it would be something like this:
while c_func(xGetMessage, {msg, NULL, 0, 0})<=0 do c_proc(xTranslateMessage, {msg}) c_proc(xDispatchMessage, {msg}) end while
setHandler(IDLE, routine_id("MyBackgroundRoutine"))
startIdle()
and
stopIdle()
.
Please note that
startIdle()
must pass a timing
value (in milliseconds) specifying the granularity of calls to the
runIdle()
manager. The particular timing
value is not very important since OS latency etc will mess it up
anyway. A value of, say, 50 milliseconds is probably allright.
IDLE is a global atom that ARWEN recognizes. Please note about the IDLE handler :
1) It is a procedure and NO parameters are passed to it since ARWEN does the calling not Windows.
2) The handler should spend only a short time doing any processing before returning.
3) The handler will fire when a Common Dialog box is open.
4) The handler may be relinked or disassociated in exactly the same way as other control handlers can be but with the restriction of item 1).