FORM Objects + EVENTS
Updated: Apr 21, 2005

The system may report a number of events with a simple mouse click.
Therefore, internal variable nCode (notify code) may be examined in event
subroutines to filter desired events (HBguidef.inc).  For example, COMBOBOX
and LISTBOX events may be filtered as shown in hotwin.bas source code.

Note: Based on available information, a HotBasic application will most often
set hWnd to the handle of the message sender upon calling event subroutines.

All event procedures have up to five useful arguments, in HotBasic internal
variables hWnd, uMsg, wParam, lParam and nCode.  An event procedure cannot 
assume that these values will not be overwritten by startup of other event
procedures, since even a single GUI application may have multiple threads
running.  Thus, if one or more of the event arguments are needed, they 
should be saved immediately upon entry into your procedure:

  DEFINT vKey
  MyKeyDownProc:
  vKey = wParam  'save wParam

As above, event procedures may start with a LABEL and end with RETURN.  Or

  DECLARE SUB MyKeyDownProc  'no arguments listed here
  'code
  MyForm.OnKeyDown = MyKeyDownProc
  'code
  SUB MyKeyDownProc
  vKey = wParam  'save wParam
  'code
  END SUB


EVENTS     Defines subroutine called on event
~~~~~~     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OnClick    MyButton.OnClick = RunMyCode

  .OnClick is a generic user-select event, which might be called ".OnSelect"
  instead.  For example, a user LISTBOX selection occurs with doubleclick.
  Keyboard inputs may also cause a user-select event.  If you want mouse only,
  try .OnMouseDown.

  Most .OnClick events arise from WM_COMMAND (uMsg = &H111) messages.  nCode
  is the "notify code" -- the HIWORD of wParam.  The LOWORD of wParam is the
  .ID of the object originating the message.  MyID = LOWORD(wParam)

  lParam is the handle of the object which is most often that of the main form,
  since child objects send messages through the parent.  For SCROLLBAR and
  TRACKBAR, lParam is .Position for appropriate nCodes.

  Some .OnClick events arise from WM_NOTIFY (uMsg = &4E) messages where lParam
  is not a handle, but rather a pointer to a NMHDR structure. 


OnClose   

  For FORMS, the close button in the title bar normally terminates the
  application.  If you prefer that additional FORMs are "closed" without
  program exit, try using .OnClose:

  form2.OnClose = form2_close
  'code
  form2_close:
  form2.visible=0  'hide form2 instead of exiting application
  return

OnDblClick  wParam and lParam as in .OnMouseDown

OnKeyDown 

OnKeyUp 

  .OnKeyDown and .OnKeyUp trap WM_KEYDOWN (uMsg = &H100) and WM_KEYUP
  (uMsg = &H101) messages where wParam = the virtual-key code of the non-
  system key (alt not pressed) and lParam contains details:

  Bits  Description
  0-15  repeat count = LOWORD(lParam)
  16-23 scan code = HIWORD(lParam) AND &HFF
  24    1 if the key is an extended key else 0
  30    previous key state:
           1 if the key is down before the message is sent for WM_KEYDOWN
           1 for WM_KEYUP
  31    transition state: 0 for WM_KEYDOWN, 1 for WM_KEYUP

OnMessage 

  Traps Windows messages not processed by other HotBasic .On... events.
  This powerful event allows coders to process such messages to customize
  and expand HotBasic coding capabilities.  Used with main FORM.

  =====onmsg.bas
  $APPTYPE GUI: $TYPECHECK ON
  SHOWCONSOLE
  DIM form As FORM
  form.onmessage = PrintThis
  form.ShowModal
  END

  PrintThis:
  'normally you select your message here
  PRINT HEX$(hWnd);space;HEX$(uMsg);space;HEX$(wParam);space;HEX$(lParam)
  RETVAL zero  'Default Windows Procedure called as usual
  RETURN
  =====onmsg.bas

  To use .OnMessage, "RETVAL zero" or "RETVAL one" are essential to control
  whether the Default Windows Procedure is or is not called.  With 
  "RETVAL zero", window object behavior might remain the same, because
  its Default procedure is called as normal (without .OnMessage).
  With "RETVAL one", you have essentially bypassed the Default procedure
  and "replaced" it with yours, which in effect is a sort of "sub-classing"
  done in the HotBasic way -- simple and clean.
  
  In sum, your .OnMessage procedure (1) does what it wants for particular
  messages (uMsg) and (2) decides whether the Default Windows Procedure
  for the object and message is also run (RETVAL zero) or not (RETVAL one).

OnMouseDown 

OnMouseMove

OnMouseUp 

  .OnMouseDown, .OnMouseMove and .OnMouseUp trap button events. 

  wParam key flags are:

  $DEFINE MK_LBUTTON  &H1 'left mouse button
  $DEFINE MK_RBUTTON  &H2 'right mouse button
  $DEFINE MK_SHIFT    &H4 'SHIFT key is down
  $DEFINE MK_CONTROL  &H8 'CTRL key is down
  $DEFINE MK_MBUTTON &H10 'middle mouse button

  LOWORD(lParam) is mouse x and HIWORD(lParam) is mouse y position.

OnPaint    No message parameters.

  MyForm.OnPaint = form_paint
  'code
  form_paint:
  MyForm.Circle 40,40,30,&HFFFFFF 'white
  return

OnReSize 

  wParam = SIZE_ value with client width = LOWORD(lParam) and client height =
  HIWORD(lParam).

OnShow     wParam = 1 (show) or = 0 (hide)

  To run GUI programs from the command-line or from a .bat file, there may
  be not user key or mouse inputs.  Thus, the main form .OnShow procedure
  will be called with FORM .Show (not .ShowModal):

  (1) Parse the command-line and set up your job, by setting EDIT text,
  CHECKBOX states, etc, anything a real-time user might otherwise do with
  key and mouse inputs in a "regular" run of the program.

  (2) Call the procedure that starts the job.  For example, this may be an
  .OnClick procedure that would be called if a user had clicked a button. 

  (3) Exit the program.

  If you watch the program run, it will "magically" appear with all the
  "right" settings, start running and close itself when the job is done.

  You never get out of the .OnShow procedure, unless it detects that certain
  command-line parameters are absent.  If so, the .OnShow procedure is done
  and the next main program statement may be FORM .ShowModal for a regular
  user-controlled run.


~~~~~~~~~~~
Note:  The ZERO keyword may be used to "turn off" any of the above events:

  MyObject.OnClick = zero

At run-time, an application can change the procedure that handles an event:

  MyObject.OnClick = MyObjProc2  'was MyObjProc1 at startup


+ Penthouse (registered) version

Copyright 2003-2005 James J Keene PhD
Original Publication: Nov 18, 2003
