Keyboard and mouse
An indicator reacts to the mouse and the keyboard by overriding these methods:
- ProcessMouseClick(e), ProcessMouseDoubleClick(e);
- ProcessMouseDown(e), ProcessMouseUp(e), ProcessMouseMove(e);
- ProcessMouseWheel(delta):
deltais the wheel delta; - ProcessKeyDown(e), ProcessKeyUp(e).
The mouse methods receive a RenderControlMouseEventArgs
(namespace OFT.Rendering.Control) with the button and the position. The keyboard methods take
System.Windows.Input.KeyEventArgs in the classic ATAS; ATAS X declares them with its own cross-platform key event
type and converts a classic build at load time (see Project setup).
Every method returns true when the indicator has handled the event: the event is then not passed to the following
indicators of the chart, so that only one of several indicators reacts to it. A hidden indicator (Visible is
false) or a locked one (Locked is true) receives no events.
GetCursor(e) changes the mouse cursor depending on the position:
return a StdCursor value (namespace OFT.Rendering), or StdCursor.NULL to keep the
default cursor.
Example
A rectangle that is selected and deselected with a click, dragged while selected, and shows the hand cursor when the mouse is over it; the keyboard and wheel events are written to the log.
using System;
using System.Drawing;
using System.Windows.Input;
using ATAS.Indicators;
using OFT.Rendering;
using OFT.Rendering.Context;
using OFT.Rendering.Control;
using OFT.Rendering.Tools;
using Utils.Common.Logging;
namespace ATAS.Docs.Samples.ChartIndicators;
public class KeyboardMouseIndicator : Indicator
{
private readonly RenderPen _selectionPen = new(Color.Blue, 3);
private readonly RenderFont _font = new("Arial", 20);
private readonly RenderStringFormat _stringFormat = new() { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center };
private bool _selected;
private Rectangle _rectangle = new(30, 30, 150, 50);
private Point _pressedPoint;
private Point _lastPoint;
private bool _pressed;
public KeyboardMouseIndicator()
: base(true)
{
EnableCustomDrawing = true;
DenyToChangePanel = true;
DataSeries[0].IsHidden = true;
SubscribeToDrawingEvents(DrawingLayouts.Final);
}
protected override void OnCalculate(int bar, decimal value)
{
}
protected override void OnRender(RenderContext context, DrawingLayouts layout)
{
context.FillRectangle(Color.Coral, _rectangle);
if (_selected)
context.DrawRectangle(_selectionPen, _rectangle);
context.DrawString(DateTime.Now.ToString("T"), _font, Color.AliceBlue, _rectangle, _stringFormat);
}
public override bool ProcessMouseClick(RenderControlMouseEventArgs e)
{
this.LogInfo("Mouse click");
return false;
}
public override bool ProcessMouseDown(RenderControlMouseEventArgs e)
{
this.LogInfo("Mouse down");
if (e.Button == RenderControlMouseButtons.Left && IsPointInsideRectangle(_rectangle, e.Location))
{
_pressedPoint = _lastPoint = e.Location;
_pressed = true;
return true;
}
return false;
}
public override bool ProcessMouseUp(RenderControlMouseEventArgs e)
{
this.LogInfo("Mouse up");
if (Math.Abs(e.Location.X - _pressedPoint.X) < 4 && Math.Abs(e.Location.Y - _pressedPoint.Y) < 4 && e.Button == RenderControlMouseButtons.Left && IsPointInsideRectangle(_rectangle, e.Location))
{
_selected = !_selected;
_pressed = false;
return true;
}
if (_pressed)
{
_pressed = false;
return true;
}
return false;
}
public override bool ProcessMouseMove(RenderControlMouseEventArgs e)
{
if (_pressed && _selected)
{
var dX = e.Location.X - _lastPoint.X;
var dY = e.Location.Y - _lastPoint.Y;
_lastPoint = e.Location;
_rectangle.X += dX;
_rectangle.Y += dY;
return true;
}
return false;
}
public override bool ProcessMouseDoubleClick(RenderControlMouseEventArgs e)
{
this.LogInfo("Mouse double click");
return false;
}
public override bool ProcessMouseWheel(int delta)
{
this.LogInfo("Mouse wheel {0}", delta);
return false;
}
public override bool ProcessKeyDown(KeyEventArgs e)
{
this.LogInfo("Key down {0}", e.Key);
return false;
}
public override bool ProcessKeyUp(KeyEventArgs e)
{
this.LogInfo("Key up {0}", e.Key);
return false;
}
public override StdCursor GetCursor(RenderControlMouseEventArgs e)
{
if (_selected && IsPointInsideRectangle(_rectangle, e.Location))
return StdCursor.Hand;
return StdCursor.NULL;
}
private static bool IsPointInsideRectangle(Rectangle rectangle, Point point)
{
return point.X >= rectangle.X && point.X <= rectangle.X + rectangle.Width && point.Y >= rectangle.Y && point.Y <= rectangle.Y + rectangle.Height;
}
}
