### Handling Mouse Events

Pointer devices give users the ability to perform actions directly. The Open Class Library offers classes to handle the mouse pointer.

You can use IMouseHandler to process a variety of mouse events. These events include button presses and releases, double-clicks, multiple button presses, and mouse moves. You can also query keyboard state information at the time a mouse event is generated.

Begin by creating an IMouseHandler object and then attach it to any kind of window (for example, IMultiLineEdit or ISetCanvas). Although the window that the mouse is over receives a mouse event first, events are sometimes passed on for additional processing to their owner windows. A mouse event continues to travel up the owner window chain until either a handler stops it or the event is processed by the window itself. The mouse handler must return true to stop any additional processing of a mouse event.

When an IMouseHandler object receives a mouse event, it creates either an IMouseEvent, an IMouseClickEvent, or an IMousePointerEvent and routes it to a mouse handler virtual function. The mouse handler virtual functions are as follows:

Function
  Purpose
mouseClicked
  Processes a mouse click event.
mouseMoved
  Processes a mouse move event.
changeMousePointer
  Changes the pointer when the mouse is over the handled window. If you need to change the mouse pointer for a frame window and all its children, use IFrameWindow::setMousePointer.

Whenever a mouse button's state changes, the IMouseHandler calls its mouseClicked function. The IMouseClickEvent object identifies the button, its current keyboard state, and the mouse pointer position. The IMouseClickEvent defines the following virtual functions:

Function
  Purpose
mouseButton
  Returns the clicked mouse button (button1, button2, button3).
mouseAction
  Returns the mouse action (clicked, double-clicked).
mouseNumber
  Returns the mouse button that changed state (button1, button2).
windowUnderPointer
  Returns the handle of the window that the mouse pointer is over.

Note: | On a two-button mouse, button1 is the left mouse button on a right-handed mouse and the right button on a left-handed mouse. Button2 is the right mouse button on a right-handed mouse and the left button on a left-handed mouse.

The IMouseEvent defines the following virtual functions:

Function
  Purpose
windowUnderPointer
  Returns the handle of the window that is under the mouse pointer.
isAltKeyDown
  Returns true if the Alt or menu key is down when the mouse is moved.
isCtrlKeyDown
  Returns true if the Ctrl key is down when the mouse is moved.
isShiftKeyDown
  Returns true if the Shift key is down when the mouse is moved.

You initiate a mouse pointer event when you enter and exit a window with a mouse handler attached. The IMousePointerEvent defines the following virtual functions:

Function
  Purpose
defaultMousePointer
  Returns the default mouse pointer for the window that is under the mouse.
setMousePointer
  Sets the pointer to use for the window that is under the mouse.
windowId
  Returns the window ID of the control that the event applies to.

#### Mouse Handler Example

The following code creates a multicell canvas as a client window with a view port control, and two bitmaps as its children. A mouse handler is attached to the client canvas, the view port and the bitmaps. Code, in the overloaded changeMousePointer member function, changes the mouse pointer when the mouse is over the view port. The information area at the bottom of the frame is updated to indicate when the mouse is over the view port and when it leaves the view port. When the mouse is over the bitmaps, the program invokes the mouseClicked member function. The code in the .hpp file is as follows:

    /*************************************************************/
    /* Define the Mouse Handler                                  */
    /*************************************************************/
    class AMouseHandler : public IMouseHandler  { public:
       AMouseHandler(MainWindow *aFrame);

    protected:
       virtual bool mouseClicked           (IMouseClickEvent & event);
       virtual bool mousePointerChange     (IMousePointerEvent& event);

    private:
       MainWindow * frame;
    };

    /*************************************************************/
    /* Define the Main Window                                    */
    /*************************************************************/
    class MainWindow : public IFrameWindow {
    public:
      MainWindow( unsigned long windowId);
      bool handleClickEvent(unsigned long id);
      bool handleChangeEvent(IMousePointerEvent& event);

    private:

       IMultiCellCanvas    clientCanvas;
       IViewPort           aviewport;
       IStaticText         viewText;
       IStaticText         bmpText;
       IStaticText         infoText;
       IBitmapControl      bmp1;
       IBitmapControl      bmp2;
       IPointerHandle      ptr_bmp;
       AMouseHandler       mouseHandler;
      };

The code in the .cpp file is as follows:

    /*************************************************************/
    /* Create the Main Window                                    */
    /*************************************************************/
    MainWindow::MainWindow( unsigned long windowId)
              : IFrameWindow("Mouse Handler Example", windowId),
                         clientCanvas(REMOTECANVASID, this, this),
                         aviewport(VPID, &clientCanvas, &clientCanvas),
                         viewText(VTXT, &aviewport, &aviewport, IRectangle(),
                           IStaticText::defaultStyle() | IStaticText::center),
                         bmpText(BMPTXT, &clientCanvas, &clientCanvas, IRectangle(),
                           IStaticText::defaultStyle() | IStaticText::center
                            | IStaticText::top),
                         infoText(INFOID, this, this, IRectangle(), IStaticText::defaultStyle()
                            | IStaticText::top
                            | IStaticText::left
                            | IStaticText::wordBreak ),
                         bmp1(BMP1ID,&clientCanvas,&clientCanvas,
                                   ISystemBitmapHandle::minimizeButton),
                         bmp2(BMP2ID,&clientCanvas,&clientCanvas,
                                   ISystemBitmapHandle::maximizeButton),
                         mouseHandler(this)

     {
         addExtension(&infoText, IFrameWindow::belowClient,
             IFont(&infoText).maxCharHeight(),
             IFrameWindow::thickLine);
         infoText.setText(ID_TEXT);
         bmpText.setText("<==click on bitmaps"); viewtext.settext(vtxt); viewtext.setforegroundcolor(icolor::kwhite); setclient(&clientcanvas); aviewport.setbackgroundcolor(icolor::kpalegray); clientcanvas.addtocell(&aviewport, 2, 6, 40, 1); clientcanvas.addtocell(&bmp1, 2, 2, 4, 2); clientcanvas.addtocell(&bmp2, 8, 2, 4, 2); clientcanvas.addtocell(&bmptext, 12, 2, 5, 2); isize size="clientCanvas.minimumSize();" ipoint point="position();" movesizetoclient(irectangle(point.x(), point.y(), point.x() + size.width(), point.y() + size.height())); /********************************************************/ /* add the mouse handler */ /********************************************************/ mousehandler.handleeventsfor(&aviewport); mousehandler.handleeventsfor(&bmp1); mousehandler.handleeventsfor(&bmp2); mousehandler.handleeventsfor(&clientcanvas); iresourcelibrary reslib; ptr_bmp="reslib.loadPointer(PTR_BITMAP);" show(); setfocus(); } /*************************************************************/ /* change the mouse pointer and update the info area */ /*************************************************************/ bool mainwindow::handlechangeevent(imousepointerevent& event) { if (event.windowid()="=" ic_viewport_viewrectangle) { event.setmousepointer(ptr_bmp); infotext.settext("mouse is on top of the viewport"); return true; } else { infotext.settext("mouse is not on top of the viewport"); return false; } } /*************************************************************/ /* change the button bitmaps and update the info area. */ /*************************************************************/ bool mainwindow::handleclickevent(unsigned long id) { switch (id) { case bmp1id: bmp1.setbitmap(bmpcd); infotext.settext("minimize button pushed"); break; case bmp2id: bmp2.setbitmap(bmpmidi); infotext.settext("maximize button pushed"); break; } return true; } amousehandler :: amousehandler(mainwindow *aframe) { frame="aFrame;" } /*************************************************************/ /* hande the mouse click event */ /*************************************************************/ bool amousehandler :: mouseclicked (imouseclickevent & event) { iwindow * pwindow="IWindow::windowWithHandle(event.windowUnderPointer());" unsigned long int winid="pWindow-">id();
       frame->handleClickEvent(winId);
       return true;
    }

    /*************************************************************/
    /* Hande the mouse pointer change event                      */
    /*************************************************************/
    bool AMouseHandler :: mousePointerChange (IMousePointerEvent& event)
    {

      return (frame->handleChangeEvent(event));
    }

The following graphics show the results of using the mouse handler.

Events and Event Handlers

Adding Events and Event Handlers

IEvent
IMouseHandler
IMouseClickEvent
IMousePointerEvent