# ...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