Situation
You want to know how to use mouse clicks to completely turn off a script or to only temporarily 'pause' it.

Programming example

using System;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;
using System.Windows.Forms;

namespace PowerLanguage.Indicator
{
    [SameAsSymbol(true), MouseEvents(true)]
    public class Example_StopWithMouseClicks : IndicatorObject
    {
        public Example_StopWithMouseClicks(object _ctx) : base(_ctx) { }

        private IPlotObject closePlot;
        private bool scriptEnabled = true;

        protected override void Create()
        {
            closePlot = AddPlot(new PlotAttributes("Close", EPlotShapes.Line, 
                Color.RoyalBlue, Color.Transparent, 3, EPlotStyle.Solid, false));
        }
        
        protected override void CalcBar()
        {
            if (!scriptEnabled)
                return;

            closePlot.Set(Bars.Close[0]);
        }

        protected override void OnMouseEvent(MouseClickArgs arg)
        {
            if (arg.buttons != MouseButtons.Left)
                return;

            if (scriptEnabled && arg.keys == Keys.Control)
            {
                Output.WriteLine("Received a mouse click with Control while the script is enabled.");
                Output.WriteLine("\r\tTurning the script off.");

                scriptEnabled = false;
                ExecControl.Recalculate();
            }
            else if (!scriptEnabled && arg.keys == Keys.Shift)
            {
                Output.WriteLine("Received a mouse click with Shift while the script is disabled.");
                Output.WriteLine("\r\tTurning the script back on.");

                scriptEnabled = true;
                ExecControl.Recalculate();
            }
            else if (arg.keys == (Keys.Control | Keys.Shift))
            {
                Output.WriteLine("Received a mouse click with both Control and Shift.");
                Output.WriteLine("\r\tTurning the script off completely.");

                ExecControl.Abort("Disabling the script.");
            }
        }
    }
}

Output of the programming example

The example generates an output like the following:

Received a mouse click with Control while the script is enabled.
    Turning the script off.
Received a mouse click with Shift while the script is disabled.
    Turning the script back on.
Received a mouse click with both Control and Shift.
    Turning the script off completely.

Working with mouse events in MultiCharts .NET

Programmatically processing mouse clicks is one way in which to control MultiCharts .NET and can, for example, be used to reload price data, recalculate a script, or place trading strategy orders.

See working with mouse events and combining mouse clicks with keyboard keys to learn more about working with mouse clicks.

Working with mouse click events in MultiCharts .NET has two requirements:

  • The MouseEvents attribute needs to be enabled;
  • And the OnMouseEvent() method, used for programmatically dealing with mouse clicks (see PowerLanguage .NET Help, n.d.), needs to be implemented.

Mouse events can be used, for example, to programmatically stop or abort a script.

Controlling a MultiCharts .NET calculations: aborting or ‘stopping’

The calculation process of a MultiCharts .NET script can be stopped in several ways (MultiCharts, 2013; PowerLanguage .NET Help, n.d.):

  • The ExecControl.Abort() method turns off a MultiCharts .NET script completely and triggers an error message. To re-enable the script, it needs to be manually turned on by the user.
  • The return keyword causes a method to exit immediately (Stellman & Greene, 2010). Using return in the CalcBar() override method ‘stops’ calculations because all statements following return are skipped. The CalcBar() method is still being called on every price bar though: return does not terminate a script (for more, see how to ‘stop’ a script).

Both are used in the example: a mouse click with Control and Shift turns off the indicator completely, a click with Control ‘stops’ a script while a click with Shift ‘reactivates’ it again.

MultiCharts .NET programming example

The example begins with setting the MultiCharts .NET attributes:

[SameAsSymbol(true), MouseEvents(true)]

Setting SameAsSymbol to true plots the indicator on the main price chart, while setting MouseEvents to true enables the processing of mouse events.

Variable declaration and plot creation in MultiCharts .NET

Then an IPlotObject and Boolean variable are declared:

private IPlotObject closePlot;
private bool scriptEnabled = true;

The scriptEnabled Boolean variable is used to determine if a mouse click enabled or disabled the script. The closePlot object is used to plot an indicator line and is instantiated in the Create() method:

protected override void Create()
{
    closePlot = AddPlot(new PlotAttributes("Close", EPlotShapes.Line, 
        Color.RoyalBlue, Color.Transparent, 3, EPlotStyle.Solid, false));
}

What these PlotAttributes arguments result in is discussed in setting plot options programmatically in MultiCharts .NET: a closer look at PlotAttributes.

Processing price bars in MultiCharts .NET

Next is the CalcBar() override method:

protected override void CalcBar()
{
    if (!scriptEnabled)
        return;

    closePlot.Set(Bars.Close[0]);
}

To learn more about how return can ‘stop’ a script, see how to ‘stop’ an indicator or strategy.

The if statement evaluates with the logical not operator (!) whether the scriptEnabled variable is false. When that is the case, the CalcBar() method is prematurely exited with the return keyword. That causes the statement which sets the plot value (line 28) not to be executed, so the line will not be plotted on that price bar.

Processing mouse clicks in MultiCharts .NET

The OnMouseEvent method is implemented as follows:

protected override void OnMouseEvent(MouseClickArgs arg)
{
    if (arg.buttons != MouseButtons.Left)
        return;

    if (scriptEnabled && arg.keys == Keys.Control)
    {
        Output.WriteLine("Received a mouse click with Control while the script is enabled.");
        Output.WriteLine("\r\tTurning the script off.");

        scriptEnabled = false;
        ExecControl.Recalculate();
    }
    else if (!scriptEnabled && arg.keys == Keys.Shift)
    {
        Output.WriteLine("Received a mouse click with Shift while the script is disabled.");
        Output.WriteLine("\r\tTurning the script back on.");

        scriptEnabled = true;
        ExecControl.Recalculate();
    }
    else if (arg.keys == (Keys.Control | Keys.Shift))
    {
        Output.WriteLine("Received a mouse click with both Control and Shift.");
        Output.WriteLine("\r\tTurning the script off completely.");

        ExecControl.Abort("Disabling the script.");
    }
}

The arg variable contains data from the MouseClickArgs struct (see line 31) and has several fields (such as buttons and keys) with information about the mouse click (see PowerLanguage .NET Help, n.d.).

By the way, to make referencing the Keys and MouseButtons enumerations easier, the System.Windows.Form namespace is included with the using keyword (line 5).

The if statement (lines 33-34) evaluates whether the mouse click button (arg.buttons) is unequal to a left mouse button (MouseButtons.Left). Since the indicator should only process left mouse clicks, for any other mouse button the return statement is called to skip the remainder of the OnMouseEvent() method.

The if-else statement (lines 36-58) consists out of three parts for disabling, re-enabling, and aborting the script. These are discussed in turn below.

Disabling a MultiCharts .NET script programmatically

The first part disables the script:

if (scriptEnabled && arg.keys == Keys.Control)
{
    Output.WriteLine("Received a mouse click with Control while the script is enabled.");
    Output.WriteLine("\r\tTurning the script off.");

    scriptEnabled = false;
    ExecControl.Recalculate();
}

The if statement evaluates two expressions: whether the script currently is enabled (in which case scriptEnabled evaluates to true) and if the keyboard key accompanying the mouse click (arg.keys) is the Control key (Keys.Control).

When both expressions evaluate to true, a message is printed to the Output Window with the Output.WriteLine() method. The \r\t escape character (line 39) is used to insert a Tab in the output.

Should ExecControl.Recalculate() not have been called (lines 42 and 50), the return keyword in the CalcBar() method (line 26) would only have affected the current bar and not previous, historical price bars.

Next the scriptEnabled variable is set to false followed by calling the ExecControl.Recalculate() method. This method will recalculate a script immediately, and since scriptEnabled is now false, the line will not be plotted (see lines 25-28).

Re-enabling a MultiCharts .NET script

The second part turns the script back on:

else if (!scriptEnabled && arg.keys == Keys.Shift)
{
    Output.WriteLine("Received a mouse click with Shift while the script is disabled.");
    Output.WriteLine("\r\tTurning the script back on.");

    scriptEnabled = true;
    ExecControl.Recalculate();
}

When the scriptEnabled variable is false and the Shift key (Keys.Shift) accompanied the mouse click, information is printed to the Output Window and the Boolean variable is set to true. Then the ExecControl.Recalculate() method is called to recalculate the indicator on all price bars again, this time with the scriptEnabled variable set to true.

Because the scriptEnabled variable is evaluated (lines 36 and 44) prior to changing it, unnecessary recalculations of the indicator with ExecControl.Recalculate() are prevented.

Terminating a MultiCharts .NET script completely

The third and last part of the OnMouseEvents() method aborts the indicator:

else if (arg.keys == (Keys.Control | Keys.Shift))
{
    Output.WriteLine("Received a mouse click with both Control and Shift.");
    Output.WriteLine("\r\tTurning the script off completely.");

    ExecControl.Abort("Disabling the script.");
}

The else-if statement evaluates whether the mouse click is accompanied with both the Control and Shift keys. Since Keys is an enumeration with the Flags attribute (which enables combining several enumerators; Albahari & Albahari, 2012), the bitwise OR operator needs to be used here.

Example of error message due to aborting a script

When both these keys go along the mouse click, a message is printed to the Output Window (lines 54-55) and the ExecControl.Abort() method is called to completely terminate a MultiCharts .NET script. The string argument of this method is the message displayed in the error message (see image).

Note that the script cannot be re-enabled programmatically when it has been turned off with the ExecControl.Abort() method.

Key points:

  • Working with mouse clicks requires adding the MouseEvents attribute and implementing the OnMouseEvents() method;
  • A script can be ‘turned off’ by calling the return keyword in the CalcBar() method to skip any remaining statements for that price bar. It can be ‘re-enabled’ by not calling return anymore;
  • An indicator or trading strategy can be completely turned off with the ExecControl.Abort() method.
References

Albahari, J. & Albahari, B. (2012). C# 5.0 in a Nutshell: The Definitive Reference (5th edition). Sebastopol, CA: O’Reilly Media.

MultiCharts (2013). MultiCharts .NET Programming Guide (version 1.0). Retrieved from http://www.multicharts.com/downloads/MultiCharts.NET-ProgrammingGuide-v1.0.pdf

PowerLanguage .NET Help (n.d.). Retrieved on May 16, 2014, from http://www.multicharts.com/downloads/PowerLanguage.NET.chm

Stellman, A. & Greene, J. (2010). Head First C#: A Brain-Friendly Guide (2nd edition). Sebastopol, CA: O’Reilly Media.