Events and Event Handlers

The graphical user interfaces that the Open Class Library supports are event-driven. A window can process a wide variety of events from many sources. Events can include the following:

You can change the behavior of a window by changing how it processes an event. With the Open Class Library, you do this by adding an event handler to the window.

Event Handlers
The Open Class Library represents events with objects derived from  IEvent. You process events routed to a window with event handler objects. Therefore, you can add customized behavior for a window by attaching your own event handler to it. You attach an event handler to a window by passing the window to the handler's handleEventsFor function.

In addition, you can reuse your handler for other windows. For example, you can reuse a handler that verifies telephone numbers wherever an entry field accepts telephone numbers. You can also attach different handlers to a window.

The following table describes various event handler classes you can use to customize the behavior of your windows:

Class

Description

ICommandHandler Processes command events, such as displaying a file dialog window when a user selects Open from a menu bar.
IKeyboardHandler Processes the individual keystrokes from a user, such as verifying a telephone number entered into an entry field. You would not use this class for keys that relate to command processing, such as accelerator keys, or keys that the operating system itself uses, such as the F1 key to request help.
IMouseHandler Adds additional mouse functionality that the operating system does not provide.
IPaintHandler Specializes the processing of a paint event, such as painting your client window with simple 2D graphics.
IResizeHandler Customizes the behavior of your window when you resize your window. For example, you can reposition and resize the components of a window when it is resized, or change the size of the font it uses.

Processing Events
Each handler class has one or more virtual functions that process events. To use an event handler, you create a class derived from a handler class, then override the virtual functions to implement the behavior you want.

Your virtual function should either return a value of false to indicate that it has not processed the event, or true to indicate that no additional processing needs to occur for the event. Returning false allows other handlers attached to the window to be called to process the event. Handlers are called in the reverse order in which they are attached. Therefore the order in which you attach handlers can cause a handler to not receive events.

If none of the handlers attached to the window process the event, the window passes the event on for default processing by either Open Class Library or the presentation system. This could cause the event to be passed to the owner window for it to process.

All handler classes contain a dispatchHandlerEvent function to determine whether the handler needs to process an event, or return it unprocessed. If an event needs processing, the dispatchHandlerEvent function creates the appropriate event object and calls the appropriate virtual function to process the event.

The IEvent class acts as the base class for more specialized event classes. It provides general member functions to extract the message ID and message parameters. The IEvent derived classes, such as ICommandEvent, generally add more specialized functions for extracting information specific to that type of event. The IEvent class also provides a member function, setResult, for those events that require a value to be returned.

The following diagram describes how the Hello World version 5 sample handles the event that occurs when a user selects the Center command from the menu bar:

ng9us008.gif (24898 bytes)

The main window class, mainWindow, handles two kinds of events:

A class derived from ICommandHandler called ACommandHandler handles the command events. A class derived from IHelpHandler called AHelpHandler handles the help events. The following describes the above diagram in further detail:

  1. The mainWindow constructor creates an ACommandHandler object called commandHandler. The mainWindow constructor attaches this command handler by calling the handleEventsFor function:
      commandHandler.handleEventsFor(this);
  2. The mainWindow constructor creates and attaches an AHelpHandler object called helpHandler:
      helpHandler.handleEventsFor(this);
  3. The user selects the Center menu item. The ID of this command is MI_CENTER. This ID has been defined in the ahellow5.h header file:
    #define MI_ALIGNMENT     0x1500     
    #define MI_CENTER        0x1501     
    #define MI_LEFT          0x1502     
    #define MI_RIGHT         0x1503     
    #define MI_EDIT          0x1504     
    #define MI_TEXT          0x1505     
    #define MI_HELP          0x1510

    The ahellow5.rc file resource script file maps this ID onto the menu as follows:

    WND_MAIN  MENUEX
      BEGIN
        POPUP     "&Edit"                ,  MI_EDIT
          BEGIN
            POPUP     "&Alignment"       ,  MI_ALIGNMENT
              BEGIN
                MENUITEM  "&Left\tF7"    ,  MI_LEFT
                MENUITEM  "&Center\tF8"  ,  MI_CENTER
                MENUITEM  "&Right\tF9"   ,  MI_RIGHT
              END
            MENUITEM  "&Text..."         ,  MI_TEXT
          END
        POPUP     "&Help"                ,  MI_HELP  ,  MFT_RIGHTJUSTIFY
          BEGIN
            MENUITEM  "&General help..." ,  SC_HELPEXTENDED  /*MIS_SYSCOMMAND*/
            MENUITEM  "&Keys help..."    ,  SC_HELPKEYS  /*MIS_SYSCOMMAND*/
            MENUITEM  "Help &index..."   ,  SC_HELPINDEX  /*MIS_SYSCOMMAND*/
          END
      END

    ngwin.gif (1069 bytes)This extract is from a Windows resource script file.

    The IBM Open Class creates an IEvent object to represent this event.

  4. The IBM Open Class calls the IWindow::dispatch command so that the event handlers attached to mainWindow can process the event.

  5. Since helpHandler was attached last, it gets to process the event first. The help handler processes the event object by calling its dispatchHandlerEvent function. Since the event is a command event and not a help event, the dispatchHandlerEvent function returns false. A false value indicates that it did not process the event and the next event handler should process the event.

  6. The command handler commandHandler processes the event object by calling its dispatchHandlerEvent function. Since the event object is a command event, the dispatchHandlerEvent creates an ICommandEvent object from the event object. The processes this ICommandEvent object by calling its command virtual function ACommandHandler::command.

  7. The Hello World version 5 sample overrides the command virtual function as follows:
    bool
      ACommandHandler :: command(ICommandEvent & cmdEvent)
    {
      bool eventProcessed(true);
    
      switch (cmdEvent.commandId()) {
        case MI_CENTER:
          frame->setTextAlignment(AHelloWindow::center);
          break;
        case MI_LEFT:
          frame->setTextAlignment(AHelloWindow::left);
          break;
        case MI_RIGHT:
          frame->setTextAlignment(AHelloWindow::right);
          break;
        case MI_TEXT:
          frame->editText();
          break;
        default:
          eventProcessed=false;
      }
      return(eventProcessed);
    }

    To obtain the ID of the command event you call the ICommandEvent::commandId function. The command virtual function indicates that it has processed the event by returning true. If the command virtual function returns true, no other processing occurs for the event.

  8. If a handler's dispatchEventsFor function or its associated virtual function (such as ICommandHandler::command) returns false, the event object is passed to the dispatchHandlerEvent function of the next handler attached to the window. If no handlers process the event, the event object is passed to the window's defaultProcedure function for processing.

ngrelc.gif
Windows
Event and Event Handler Mechanism

ngrelt.gif (466 bytes)
Create a Frame Window
Write an Event Handler
Task and Samples Cross-Reference Table