BEGIN EVENTS ... END EVENTS statements

Purpose: In a GUI program, code that is responsible for monitoring and responding to messages and commands like mouse clicks, button presses, radio controls and so on, is placed in the BEGIN EVENTS ... END EVENTS block.

It is important to remember that this block is a callback routine which can be called several times before any specific task contained in the block is completed. For this reason, it is best that any variables which must be dimensioned in the BEGIN EVENTS ... END EVENTS block, should be dimensioned as STATIC or DIM RAW. When DIM or LOCAL are used, BCX emits code to automatically clear the variable to zero and so if a callback occurs before a task is completed the DIM or LOCAL variables will be cleared to zero and the task will fail.


 Syntax :

 BEGIN EVENTS [ProcedureName]
   ' Messages and Commands
 END EVENTS [MAIN]

 Parameters:

  • ProcedureName [OPTIONAL] parameter specifying a name for this instance of an events loop. This allows you to create more than one form with its own WNDPROC. If a ProcedureName is not specified then the BEGIN EVENTS ... END EVENTS loop can be used only once in a program.
  • MAIN [OPTIONAL] parameter which is used, when there is more than one event loop in the program, to indicate that this instance of the END EVENTS statement is the end of the main program.

Remarks:

This BCX code,


 BEGIN EVENTS
 SELECT CASE CBMSG
  CASE WM_LBUTTONDOWN
  SetWindowText(Stat1,"left mouse button down :-(")

  CASE WM_LBUTTONUP
  SetWindowText(Stat1,"LEFT MOUSE BUTTON UP   :-)")
 END SELECT
 END EVENTS

which does not use a procedure name, translates to


  LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
 for(;;)
 {
 if(Msg==WM_LBUTTONDOWN)
   {
     SetWindowText(Stat1,"left mouse button down :-(");
     break;
   }
 if(Msg==WM_LBUTTONUP)
   {
     SetWindowText(Stat1,"LEFT MOUSE BUTTON UP   :-)");
   }
 break;
 }
 if(Msg==WM_DESTROY) PostQuitMessage(0);
 return DefWindowProc(hWnd,Msg,wParam,lParam);
 }

This BCX code,


 BEGIN EVENTS ProcedureName
   SELECT CASE CBMSG
   CASE WM_LBUTTONDOWN
     SetWindowText(Stat1,"left mouse button down :-(")
 
   CASE WM_LBUTTONUP
     SetWindowText(Stat1,"LEFT MOUSE BUTTON UP   :-)")
   END SELECT
 END EVENTS

which uses a procedure name, translates to


 LRESULT CALLBACK ProcedureName(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
   while(1)
   {
     if(Msg==WM_LBUTTONDOWN)
       {
         SetWindowText(Stat1,"left mouse button down :-(");
         break;
       }
     if(Msg==WM_LBUTTONUP)
       {
         SetWindowText(Stat1,"LEFT MOUSE BUTTON UP   :-)");
       }
     break;
   }
  return DefWindowProc(hWnd,Msg,wParam,lParam);
 }

This BCX code


 BEGIN EVENTS ProcedureName
   SELECT CASE CBMSG
   CASE WM_LBUTTONDOWN
     SetWindowText(Stat1,"left mouse button down :-(")
 
   CASE WM_LBUTTONUP
     SetWindowText(Stat1,"LEFT MOUSE BUTTON UP   :-)")
   END SELECT
 END EVENTS MAIN

which uses a procedure name and the MAIN statement appended to END EVENTS, translates to


 LRESULT CALLBACK ProcedureName(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 {
   while(1)
   {
     if(Msg==WM_LBUTTONDOWN)
       {
         SetWindowText(Stat1,"left mouse button down :-(");
         break;
       }
     if(Msg==WM_LBUTTONUP)
       {
         SetWindowText(Stat1,"LEFT MOUSE BUTTON UP   :-)");
       }
     break;
   }
   if(Msg==WM_DESTROY)
     {
        PostQuitMessage(0);
        return 0;
     }
  return DefWindowProc(hWnd,Msg,wParam,lParam);
 }

This WM_DESTROY handler,


 if(Msg==WM_DESTROY)
   {
    PostQuitMessage(0);
   }

is automatically generated by the BEGIN EVENTS ... END EVENTS statements when the ProcedureName is not specified and, as well, when a ProcedureName is specified and the MAIN statement is appended to the END EVENTS statement.

Therefore, in these instances, it is redundant to include


 CASE WM_DESTROY
 PostQuitMessage(0)

in the BCX code of the events loop.