...introducing Win32Lib's setHandler()

Since it's been rumoured that all the original onXXX() event handling syntax in Win32lib will become obsolete with Win32lib version 1.00, and a new event handling syntax will will be required, I thought I'd introduce it here.

Future Win32lib code will require a new setHandler() syntax, that will allow win32lib code to pass additional parameters to the routine that handles the event.

This, of course means that your event handling routines will now require three additional input parameters, as follows:
( atom self, atom event, sequence parms ),
which usually, was not required at all, in the old syntax style.

The cute little ellipse drawing demo below will give you a good idea of what this new syntax looks like.

Note that the onResize_Win() procedure has two 'events' in it's setHandler() code, in the form of a sequence.

Resizing this little demo will always re-draw the ellipse so that it fills the window's client area, with every WM_SIZE, and WM_SETFOCUS message the window receives.

-- ellipse2.exw

-- originally Euman's code, with C.K. Lester's patch, 
-- and some re-arrangement.

without warning
include win32lib.ew

-- set up calls to two gdi graphics functions
constant 
  zSetViewportExtEx = registerw32Function( gdi32, "SetViewportExtEx", 
                                           {C_LONG, C_INT, C_INT, C_INT}, C_INT ),
  zSetWindowExtEx = registerw32Function( gdi32, "SetWindowExtEx", 
                                           {C_LONG, C_INT, C_INT, C_POINTER}, C_INT )

constant
  Win = create( Window, "Mapping Mode Scaling Demo", NULL, 25, 25, 300, 200, 0 )

atom WinDC, void

constant  
  zMM_ANISOTROPIC = 8

-- onOpen[Win]
procedure onOpen_Win( atom self, atom event, sequence parms )
  atom oldMapMode
  sequence InitExt
    WinDC = getDC( Win )
    InitExt = getClientRect( Win )
    oldMapMode = w32Func( xSetMapMode, {WinDC, zMM_ANISOTROPIC} )
    void = w32Func( zSetWindowExtEx, {WinDC, InitExt[3]-InitExt[1], InitExt[4]-InitExt[2], 0} )
    setPenColor( Win, BrightRed )
end procedure
setHandler( Win, w32HOpen, routine_id( "onOpen_Win" ) )

-- onResize[Win], -- onGotFocus[Win]
procedure onResize_Win( atom self, atom event, sequence parms )
  sequence CurExt
    CurExt = getClientRect( Win )
    repaintRect( Win, CurExt[1], CurExt[2], CurExt[3], CurExt[4] )
    if w32Func( zSetViewportExtEx, {WinDC, CurExt[3]-CurExt[1], CurExt[4]-CurExt[2], 0} ) then
      drawEllipse( Win, True, CurExt[1], CurExt[2], CurExt[3], CurExt[4] )
    end if
end procedure
setHandler( Win, {w32HResize, w32HGotFocus}, routine_id( "onResize_Win" ) )

-- onClose[Win]
procedure onClose_Win( atom self, atom event, sequence parms )
  releaseDC( Win )
end procedure
setHandler( Win, w32HClose, routine_id( "onClose_Win" ) )

WinMain( Win, Normal )

More about the new setHandler

At its simplest, the new setHandler() type of instruction appears to be no more than a rearrangement of the old onClick[], but there are significant differences. Consider a simple event handler in the new form:

procedure MyButton_onClick( integer self, integer event, sequence params )
--                          ^^ this parameter list is invariant and must always be present

    FetchMyFile() --  do some action or call a procedure or function:

end procedure
setHandler( MyButton, w32HClick, routine_id( “MyButton_onClick” ) )
--          ^^ control ^^ event  ^^ id of procedure to be called

In this example the parameter list of procedure MyButton_onClick will contain:

  1. self : the identity of the invoking control, namely MyButton;

  2. event : the identity of the event that triggered MyButton_onClick, namely w32HClick;

  3. params : in the example params will be a null sequence, { }. The w32HClick event puts no arguments into params.

Now for a more complicated version of this handler:

procedure Buttons_onClick( integer self, integer event, sequence params )
--                          ^^ this parameter list is invariant and must  be present

    --  make choices:
    if self = MyButton then
        FetchMyFile()
    elsif self = ExitButton then
        closeApp()
    end if
    
end procedure
setHandler( { MyButton, ExitButton },  w32HClick, routine_id( “Buttons_onClick” ) )
--            ^^ control list          ^^ event  ^^ id of procedure to be called

We can put a list of controls, { MyButton, ExitButton }, into the setHandler statement and the handler will fire off whenever one of them is clicked. In (renamed) Buttons_onClick the self parameter, if we want, can be used to determine which of the buttons was clicked. So we have an ability to make choices in Buttons_onClick. As a matter of interest you can also replace the w32HClick atom in the SetHandler statement with a list of events, such as say { w32HClick, w32HKeyDown }, which gives even more choices (but might make the handling routine confusingly complicated).

Depending on the event atom (or list) in the setHandler statement, the params sequence may or may not contain arguments. For instance, w32HMouse places some into params:

procedure MyBitmap_onMouse( integer self, integer event, sequence params )
--                           ^^ this parameter list is invariant and must  be present

-- some of the arguments in params:
integer mouse_event = params[1]
integer mouse_x = params[2]
integer mouse_y = params[3]

    if mouse_event = MouseMove then
        DisplayMousePosition( x, y ) -- show where mouse is on the bitmap
    elsif mouse_event = LeftDown then
        FireGun()                    -- do something else
    end if
    
end procedure
setHandler( MyBitmap,  w32HMouse, routine_id( “MyBitmap_onMouse” ) )
--          ^^ control  ^^ event   ^^ id of procedure to be called

Things can get even more complex than this, but that's enough for now.

..end of lesson Extra_00.

CONTENTS