You can create a custom event handler to handle events in a graphics              WINDOW or a WIDGET_WINDOW. The event handler class must be a subclass of GraphicsEventAdapter. Your subclass can then override any of the following methods: ::MouseDown, ::MouseUp, ::MouseMotion, ::MouseWheel, ::KeyHandler, and ::SelectChange. You can also override the ::Init or ::Cleanup methods, although you should be careful to call the superclass methods and pass in any arguments or keywords.
            Each function method must return a value of 0 to turn off default event handling or 1 to perform default event handling.
            See the WINDOW example and WIDGET_WINDOW example, below.
            Syntax
            The syntax of the various event handler methods are similar, as the following list shows. 
            Result = obj.MouseDown(Window, X, Y, Button, KeyMods,  Clicks)
            Result = obj.MouseMotion(Window, X, Y, KeyMods)
            Result = obj.MouseUp(Window, X, Y, Button)
            Result = obj.MouseWheel(Window, X, Y, Delta, KeyMods)
            Result = obj.KeyHandler(Window, IsASCII, Character, KeyValue, X, Y, Press, Release, KeyMods)
            Result = obj.SelectChange(Window, Graphic, Mode, WasSelected)
            Arguments
            Window
            The object reference of the window in which the event occurred.
            X
            The x-coordinate location of the mouse cursor (in device coordinates) at the time of the event.
            Y
            The y-coordinate of the mouse cursor (in device coordinates) at the time of the event.
            Button
            The value of the clicked button. Possible values are:
            
                
                                 
                    
                        | Value | Mouse Button | 
                                  
                    
                        | 1 | Left  | 
                     
                        | 2 | Middle | 
                     
                        | 4 | Right  | 
                              
            Clicks
            The value indicating how many button clicks occurred. The value is 1 for a single click and 2 for a double click.
            Delta
            The value indicating the direction and number of movements of the mouse wheel. 
            Pushing the wheel generates positive values, pulling the wheel generates negative values. The magnitude of the value depends on the device setting for the individual mouse, but is usually limited to small integer values such as +1, -1, +2, -2, etc.
            KeyMods
            The value containing a bitwise mask indicating which modifier keys are active at the time the mouse event happens. Possible values are: 
            
                
                                 
                    
                        | Value | Modifier Key | 
                                  
                    
                        | 1 | Shift | 
                     
                        | 2 | Control | 
                     
                        | 4 | Caps lock | 
                     
                        | 8 | Alt | 
                              
            IsASCII
            A scalar byte value that indicates whether the keyboard event corresponds to an ASCII character. If IsASCII is non-zero, the Character argument will be set to a byte value corresponding to the character of the pressed key. If IsASCII is zero, the KeySymbol argument will be set to a numeric value indicating the key that was pressed.
            Character
            If IsASCII is non-zero, this argument is set to a byte value corresponding to the ASCII character of the key that was pressed. Otherwise, this argument is set to zero.
            KeyValue
            If IsASCII is zero, this argument is set to a value that indicates the key that was pressed. Otherwise, this argument is set to zero. Possible values are:
            
                
                                 
                    
                        | Value | Key | 
                                  
                    
                        | 1 | Shift | 
                     
                        | 2 | Control | 
                     
                        | 3 | Caps lock | 
                     
                        | 4  | Alt | 
                     
                        | 5 | Left | 
                     
                        | 6 | Right | 
                     
                        | 7 | Up | 
                     
                        | 8 | Down | 
                     
                        | 9 | Page up | 
                     
                        | 10 | Page down | 
                     
                        | 11 | Home | 
                     
                        | 12 | End | 
                              
            Note: On East Asian (Chinese, Japanese, Korean) localized Windows operating systems with an Asian language pack installed, characters entered in the Windows Input Method Manager (IMM)composition window are returned in the   the KeyValue argument as  unsigned integers representing a Wide character (Unicode value). The  I18N_WIDECHARTOMULTIBYTE routine can  convert these  characters to multibyte strings. For more information, see Internationalizing Code.
            Press
            The value indicating that this event represents a key press. This argument is non-zero if the event is the result of pressing the key.
            Release
            The value indicating that this event represents a key release. This argument is non-zero if the event is the result of releasing the key.
            Graphic
            The graphic to be selected or unselected.
            Mode
            A value representing the mode that was used for the current selection. Possible values are:
            
                
                                 
                    
                        | Value | Selection Type | 
                                  
                    
                        | 0 | Unselect | 
                     
                        | 1 | Select | 
                     
                        | 2 | Toggled selection | 
                    
                        | 3 | Additive  | 
                              
            WasSelected
            A value indicating if the graphic item was already selected prior to this event. A value of 1 indicates an item was previously selected; 0 if not selected.
            GraphicsEventAdapter Class
            The GraphicsEventAdapter class provides a default implementation for all of the event handler methods. The default implementation returns a value of 1 for each of the methods. For convenience, you should create your event handler as a subclass of GraphicsEventAdapter and only override the methods that you need.
            The GraphicsEventAdapter class is written in the IDL language. Its source code can be found in the file graphicseventadapter__define.pro in the lib/graphics subdirectory of the IDL distribution.
            Example Using WINDOW
            In the following example code, the RBBox class create a "rubber-band" box. The RBBox::MouseDown method creates a polygon and caches the start point of a drag operation. In the RBBox::MouseMotion method the polygon is updated with the current location of the cursor. In the RBBox::MouseUp method, the polygon is again updated and the color of the polygon is modified. Copy this code into a new IDL file and run it. To test the code, drag and drop the mouse to draw a box in the graphic window.
            FUNCTION RBBox::MouseDown, oWin, $
              x, y, iButton, KeyMods, nClicks
              if (~ISA(self.poly)) then begin
              
              self.poly = POLYGON([0,0,0],[0,0,0], /DEVICE, $
              LINESTYLE='--', /HIDE, $
              FILL_TRANSPARENCY=90, FILL_BACKGROUND = 1, FILL_COLOR='red')
              endif
              self.x0 = x
              self.y0 = y
              self.buttonDown = 1
              self.poly.HIDE = 0
              self.poly.SetData, [0,0,0], [0,0,0]
              self.poly.LINESTYLE='--'
              RETURN, 0 
            END
             
            FUNCTION RBBox::MouseMotion, oWin, x, y, KeyMods
              IF self.buttonDown then begin
                 x0 = self.x0
                 y0 = self.y0
                 xVector=[x0,x0,x,x,x0]
                 yVector=[y0,y,y,y0,y0]
                 xy = self.poly.ConvertCoord(xVector, yVector, /DEVICE, /TO_NORMAL)
                 self.poly.SetData, REFORM(xy[0,*]), REFORM(xy[1,*])
              ENDIF
              RETURN, 0 
            END
             
            FUNCTION RBBox::MouseUp, oWin, x, y, iButton
              IF (~self.buttonDown) THEN RETURN, 0
              x0 = self.x0
              y0 = self.y0
              xVector=[x0,x0,x,x,x0]
              yVector=[y0,y,y,y0,y0]
              xy = self.poly.ConvertCoord(xVector, yVector, /DEVICE, /TO_NORMAL)
              self.poly.SetData, REFORM(xy[0,*]), REFORM(xy[1,*])
              self.poly.LINESTYLE='-'
              self.buttonDown=0
              
              oSelect = oWin.GetSelect()
              FOREACH oVis, oSelect do oVis.Select, /UNSELECT
              
              oVisList = oWin.HitTest(x0+(x-x0)/2, y0+(y-y0)/2, $
                 DIMENSIONS=ABS([x-x0, y-y0]) > 10)
              FOREACH vis, oVisList do begin
                 if vis ne self.poly then vis.Select, /ADD
              ENDFOREACH
              RETURN, 0 
            END
             
            PRO RBBox__define
              
              void = {RBBox, inherits GraphicsEventAdapter, $
              X0: 0, Y0:0, BUTTONDOWN:0, POLY:OBJ_NEW()}
            END
             
            PRO RBBoxEventsTest
              x = Findgen(200)
              y = Sin(x*2*!PI/25.0)*Exp(-0.01*x)
              p = PLOT(x, y, TITLE='Click, hold mouse down and drag, release to draw box')
              p.window.EVENT_HANDLER=Obj_New('RBBox')
            END
            Example Using WIDGET_WINDOW
            In this example, only the MouseMotion event method is used. The event coordinates (in device coordinates) are converted to data coordinates and displayed in a label widget below the draw widget. A crosshair is also drawn at the nearest plot data point. Save all of the code in a file, exwidgetwindowevents.pro, and then run the ExWidgetWindowEvents procedure.
             
            FUNCTION ExWidWin::Init, plot, label, crosshair
              self.plot = plot
              self.label = label
              self.crosshair = crosshair
              return, 1
            END
             
            FUNCTION ExWidWin::MouseMotion, oWin, x, y, KeyMods
              
              xy = self.plot.ConvertCoord(x, y, /DEVICE, /TO_DATA)
              
              xy = self.plot.GetValueAtLocation(xy[0])
              
              self.crosshair.LOCATION = xy
              probe = STRING(xy[0:1], FORMAT='(2F9.2)')
              WIDGET_CONTROL, self.label, SET_VALUE=probe
              return, 1 
            END
             
            PRO ExWidWin__define
              void = {ExWidWin, inherits GraphicsEventAdapter, $
              plot: OBJ_NEW(), label: 0L, crosshair: OBJ_NEW()}
            END
             
            PRO ExWidgetWindowEvents_event, event
              
              
              w = WIDGET_EVENT(/NOWAIT)
               
              CASE TAG_NAMES(event, /STRUCTURE_NAME) of
                 'WIDGET_BASE': BEGIN
               
                 
                 
                 WIDGET_CONTROL, event.id, GET_UVALUE=pad, TLB_GET_SIZE=newSize
                 wDraw = WIDGET_INFO(event.top, FIND_BY_UNAME='ex_widwin_window')
               
                 
                 xy = newSize - pad
               
                 WIDGET_CONTROL, wDraw, $
                    DRAW_XSIZE=xy[0], DRAW_YSIZE=xy[1], $
                    SCR_XSIZE=xy[0], SCR_YSIZE=xy[1]
                 END
                 ELSE: 
              ENDCASE
               
            END
               
               
            PRO ExWidgetWindowEvents
               
              
              wBase = WIDGET_BASE(/COLUMN, /TLB_SIZE_EVENTS, MAP=0)
               
              wDraw = WIDGET_WINDOW(wBase, $
                 UNAME='ex_widwin_window', $
                 X_SCROLL_SIZE=640, Y_SCROLL_SIZE=512)
               
              w1 = WIDGET_LABEL(wBase, /ALIGN_LEFT, /DYNAMIC)
               
              WIDGET_CONTROL, wBase, /REALIZE
               
              
              WIDGET_CONTROL, wBase, TLB_GET_SIZE=basesize
              padding = basesize - [640, 512]
              WIDGET_CONTROL, wBase, SET_UVALUE=padding
               
              
              WIDGET_CONTROL, wDraw, GET_VALUE=win
               
              
              win.Select
               
              p = PLOT(/TEST, /CURRENT)
               
              
              c = p.CROSSHAIR
              c.STYLE = 'Manual'
              c.COLOR = 'Red'
              c.LINESTYLE = '-'
               
              
              handler = OBJ_NEW('ExWidWin', p, w1, c)
              win.EVENT_HANDLER = handler
               
              
              WIDGET_CONTROL, wBase, /MAP
              XMANAGER, 'ExWidgetWindowEvents', wBase, /NO_BLOCK
            END