Share via


Handling Events in WFC

The Control base class and classes that extend it, such as buttons and edit boxes, expose standard Windows events such as click, keyPress, mouseMove, dragDrop, and others. You can work with an event in your application using delegates. You do not have to understand delegates in great detail to write event handlers in an application. However, understanding how to create and use delegates is useful if you are building controls, working with other applications that trigger events, or are using threads with WFC components. It is also interesting if you want to understand the details of the Java code created by the Forms Designer. This section provides some background on delegates and then addresses the practical aspects of handling events.

What is a delegate? A delegate declaration defines a class that extends com.ms.lang.Delegate. The JVC compiler also recognizes as a keyword, providing a shortcut for creating a delegate-based class. A delegate instance can call a method on an object and pass data to that method. Most importantly, the delegate is isolated from the object it refers to and needs to know nothing about it. Therefore, it is ideal for "anonymous invocation." In other languages, this functionality is implemented as a function pointer. However, unlike function pointers, delegates are object-oriented, type-safe, and secure.

In WFC, delegates are most often used to bind events to handler methods, such as a click event on a button control to a handler method in your class. When the event occurs, the control invokes the delegate, passing it any event information. The delegate, in turn, calls the registered handler method and passes the event data. You can also use delegates to bind one event to more than one method (called multicasting); when the event occurs, each delegate in the list is called in the order in which they were added. Conversely, delegates from different events can be assigned the same handler method (for example, a toolbar button and a menu item can both call the same handler).

To work with events in your application, you use a delegate to register for notification when that event occurs for a specific control. To register, call the addOn*<event>* method of a control, where <event> is the name of the event you want to handle. For example, to register for the click event of a button, you call the button object's addOnClick method.

The addOn*<event>* method takes as a parameter an instance of a delegate, typically an existing WFC delegate that is associated with specific event data. In the addOn<event> call, the delegate instance is created with a reference to the method you want to bind the event to. The following example shows how you would bind the event handler "btnOK_Click" (in the current class) to the click event of a button called btnOK.

   Button btnOK = new Button();
   btnOk.addOnMouseClick( new EventHandler( this.btnOK_Click ));

For most events, you can create and pass an instance of the generic delegate, which passes a generic object. However, some events use special event handler classes when they include extra, event-specific information. For example, mouse movement events typically include information such as the mouse cursor location. To get this type of information, you create and pass an instance of the class, which passes a MouseEvent object to the handler. Keyboard events require the KeyEventHandler to get information about the status of SHIFT keys, and so on (this handler passes a KeyEvent object).

All WFC event handler delegate classes extend com.ms.lang.Delegate. Most of them are in the com.ms.wfc.ui package with names that end in EventHandler. All WFC events extend com.ms.wfc.core.Event, have names that end in Event, and can be found in the com.ms.wfc.ui package.

Tip In the Forms Designer, you can use Events view in the Properties window to bind an event to a specific method. The Forms Designer then creates the appropriate addOn*<event>* method and the skeleton handler for you.

When the delegate calls your handler, it passes two parameters. The first parameter is a reference to the object that originated the event. The second is an event object that can contain information about the event. A handler for the delegate from the preceding example might look like this:

   private void btnOK_Click(Object source, Event e)  {
      if (source instanceof Button) {
         String buttonName = ((Button)source).getText();
         MessageBox.show("You clicked button " + buttonName);
      }
}

If you used the generic EventHandler class to bind to your method, the Event object in your handler will not contain any interesting information. But if extra information is available for the event, you can extract it from the specific event object. The following is what the delegate and handler might look like for a mouse movement event. The MouseEvent object exposes properties that allow you to get the mouse position.

   // This is the request for notification
   Button btnTest = new Button();
   // Note that the addOn<event> method uses the MouseEventHandler class
   btnTest.addOnMouseMove( new MouseEventHandler(this.btnTestMouseMove));


   // This is the handler for the mouse movement event
   private void btnTestMouseMove(Object source, MouseEvent e){
      edit1.setText( e.x + ", " + e.y);
   }

If you want to handle events for multiple controls or multiple events for the same control, you request a separate notification for each control/event combination. Multiple notifications can specify the same handler; for example, all the buttons on a toolbar might call the same handler for their click event. You can use the source object passed to the event handler to get details about which button was clicked. (Typically, you cast the object passed to the handler into the appropriate class to be able to invoke methods from the appropriate class.)

The following example shows code that defines buttons for a toolbar and requests notification for their click events, along with the method used to handle them.

   private void initEventHandlers() {
      Button buttonNew = new Button();
      Button buttonSave = new Button();
      Button buttonExit = new Button();
      // All events are routed to the same handler
      buttonNew.addOnClick( new MouseEventHandler( this.toolbarClick) );
      buttonSave.addOnClick( new MouseEventHandler( this.toolbarClick) );
      buttonExit.addOnClick( new MouseEventHandler( this.toolbarClick) );
   }
   // common event handler
   private void toolbarClick( Object source, Event e){
      String buttonName;
      if (source instanceof Button) {
         buttonName = new String((Button)source).getText());
         MessageBox.show("You clicked button " + buttonName);
      }
   }