You can create custom functions to handle mouse events in a graphics WINDOW or a WIDGET_WINDOW. These functions must use the syntax described below.
Each function 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.
Tip: Instead of creating a separate function for each event handler, you may find it convenient to use a custom event handling class along with the EVENT_HANDLER property. See Creating an Event Handler Class to Control Events for details on how to write this object class.
Syntax
The syntax of the various event handler functions are similar, as the following list shows.
Handler Type |
Syntax |
Mouse_Down |
Result = FUNCTION_NAME(Window, X, Y, Button, KeyMods, Clicks)
|
Mouse_Motion |
Result = FUNCTION_NAME(Window, X, Y, KeyMods)
|
Mouse_Up |
Result = FUNCTION_NAME(Window, X, Y, Button)
|
Mouse_Wheel |
Result = FUNCTION_NAME(Window, X, Y, Delta, KeyMods)
|
Where FUNCTION_NAME is a unique name for the function, which will be called from one of the mouse event handling keywords of WINDOW or WIDGET_WINDOW. Avoid using generic names such as "MouseDownHandler" or "MouseUpHandler" to prevent name collisions with other applications using event handlers.
Arguments
Window
The object reference of the window in which the mouse 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 |
Example Using WINDOW
In the following example code, the RBBoxMouseDown function creates a polygon and caches the start point of a drag operation. In the RBBoxMouseMotion function the polygon is updated with the current location of the cursor. In the RBBoxMouseUp function, 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 RBBoxMouseDown, oWin, $
x, y, iButton, KeyMods, nClicks
state = oWin.UVALUE
state.x0 = x
state.y0 = y
state.buttonDown = 1
state.poly.HIDE = 0
state.poly.SetData, [0,0,0], [0,0,0]
state.poly.LINESTYLE='--'
oWin.UVALUE=state
RETURN, 0
END
FUNCTION RBBoxMouseMotion, oWin, x, y, KeyMods
state = oWin.uvalue
IF state.buttonDown then begin
x0 = state.x0
y0 = state.y0
xVector=[x0,x0,x,x,x0]
yVector=[y0,y,y,y0,y0]
xy = state.poly.ConvertCoord(xVector, yVector, /DEVICE, /TO_NORMAL)
state.poly.SetData, REFORM(xy[0,*]), REFORM(xy[1,*])
ENDIF
RETURN, 0
END
FUNCTION RBBoxMouseUp, oWin, x, y, iButton
state = oWin.uvalue
IF (~state.buttonDown) THEN RETURN, 0
x0 = state.x0
y0 = state.y0
xVector=[x0,x0,x,x,x0]
yVector=[y0,y,y,y0,y0]
xy = state.poly.ConvertCoord(xVector, yVector, /DEVICE, /TO_NORMAL)
state.poly.SetData, REFORM(xy[0,*]), REFORM(xy[1,*])
state.poly.LINESTYLE='-'
state.buttonDown=0
oWin.uvalue=state
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 state.poly then vis.Select, /ADD
ENDFOREACH
RETURN, 0
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')
poly = POLYGON([0,0,0],[0,0,0], /DEVICE, $
LINESTYLE='--', /HIDE, $
FILL_TRANSPARENCY=90, FILL_BACKGROUND = 1, FILL_COLOR='red')
p.window.UVALUE={x0:0, y0:0, buttonDown:0L, $
poly: poly}
p.window.MOUSE_DOWN_HANDLER='RBBoxMouseDown'
p.window.MOUSE_UP_HANDLER='RBBoxMouseUp'
p.window.MOUSE_MOTION_HANDLER='RBBoxMouseMotion'
END
Example Using WIDGET_WINDOW
In this example, only the MOUSE_MOTION_HANDLER event handler 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.
Mouse Event Handler Function
FUNCTION ExWidWinMouseMotionHandler, oWin, x, y, KeyMods
state = oWin.uValue
IF (~ISA(state.plot)) then return, 1
xy = state.plot.ConvertCoord(x, y, /DEVICE, /TO_DATA)
xy = state.plot.GetValueAtLocation(xy[0])
state.crosshair.LOCATION = xy
probe = STRING(xy[0:1], FORMAT='(2F9.2)')
WIDGET_CONTROL, state.label, SET_VALUE=probe
return, 1
END
Mouse Motion Procedure
Run the following code example to test the event handling functions defined in the previous code example.
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', $
MOUSE_MOTION_HANDLER='ExWidWinMouseMotionHandler', $
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 = '-'
win.uValue = {plot:p, label:w1, crosshair: c}
WIDGET_CONTROL, wBase, /MAP
XMANAGER, 'ExWidgetWindowEvents', wBase, /NO_BLOCK
END