Once we’ve created a trend line we do things like extending the trend line or moving it programmatically. But how do we prevent that we accidentally move our line manually?

Locking and unlocking trend lines in MultiCharts .NET programmatically

The DrwTrendLine.Create() method creates a trend line and returns a reference to the trend line just created (MultiCharts, 2014; PowerLanguage .NET Help, n.d.). When we assign that returned value to an ITrendLineObject interface variable, we can access the trend line’s properties and methods through that variable to modify it after it’s been made.

One way to modify a drawing (trend line, arrow, or text box) is by locking it on the chart, which is done by setting the Locked property to true (MultiCharts, 2014; PowerLanguage .NET Help, n.d.). This way an accidental mouse click cannot move the trend line to another location.

Locked and unlocked trend lines in MultiCharts .NET

Trend lines are by default unlocked. So this trend line on a EUR/USD chart can be moved around with a mouse click:

Unlocked trend line in MultiCharts .NET

But when we click on the chart with Shift held down, the example indicator locks the line programmatically. Then it cannot be moved anymore:

Locked trend line in MultiCharts .NET

Programmatically locking trend lines with mouse clicks in MultiCharts .NET

We achieve that effect with the following code:

[SameAsSymbol(true), RecoverDrawings(false), MouseEvents(true)]
public class Example_LockingTrendLines : IndicatorObject
{
    public Example_LockingTrendLines(object _ctx) : base(_ctx) { }

    private ITrendLineObject lockedLine;

    protected override void CalcBar()
    {
        // Creating the trend line
        if (Bars.LastBarOnChart && lockedLine == null)
        {
            lockedLine = DrwTrendLine.Create(
                new ChartPoint(Bars.FullSymbolData.Time[55],
                    Bars.FullSymbolData.High[55]),
                new ChartPoint(Bars.FullSymbolData.Time[5],
                    Bars.FullSymbolData.Low[5]));

            // Change the line's appearance
            lockedLine.Size  = 2;
            lockedLine.Color = Color.DeepSkyBlue;
            lockedLine.Style = ETLStyle.ToolDashed;
        }
    }

    protected override void OnMouseEvent(MouseClickArgs arg)
    {
        if (lockedLine == null)
            return;

        // Toggle the trend line's locked state
        if (arg.keys == Keys.Shift)
        {
            lockedLine.Locked = true;
        }
        else if (arg.keys == Keys.Control)
        {
            lockedLine.Locked = false;
        }
    }
}

The example begins with setting several attributes. SameAsSymbol set to true displays the indicator on the data series. Setting RecoverDrawings to false prevents deletion of intra-bar generated drawings. And enabling mouse click processing is done with setting MouseEvents to true.

We then declare an ITrendLineObject interface variable. This lockedLine variable will hold a reference to the trend line at a later point, and thereby provides a way to modify the trend line.

Drawing a trend line when it doesn’t exist yet

An if statement in the CalcBar() method checks if the current bar is the last (then Bars.LastBarOnChart returns true; PowerLanguage .NET Help, n.d.) and whether lockedLine equals (==) null. This latter happens when this reference variable doesn’t point to an object (Albahari & Albahari, 2012), which in this context means it hasn’t been associated with a trend line yet.

When both conditions evaluate to true, a trend line is drawn with DrwTrendLine.Create() and this method’s returned value is assigned to the lockedLine variable. Two ChartPoint structs set the line’s begin and end coordinates. The starting point is the time and high of 55 bars ago, while the ending point is the time and low of 5 bars ago. These historical bars are accessed with the Bars.FullSymbolData property, which can access any price bar of the primary data series (see PowerLanguage .NET Help, n.d.) and is unaffected by the indicator’s MaxBarsBack limitation.

Once the trend line has been made, its visual appearance is changed by setting its Size, Color, and Style properties to different values to create a blue, dashed line.

Locking or unlocking a trend line with mouse clicks

The next part is the OnMouseEvent() method that processes clicks on the chart (see PowerLanguage .NET Help, n.d.). In it an if statement uses the equality operator (==) to see whether lockedLine is null. When it is, the return keyword is executed, causing this method to be exited prematurely (see Dorman, 2010). This prevents that we try to access the trend line with the lockedLine variable while there isn’t such a line on the chart, which would generate an ‘object reference not set to an instance of an object’ exception (Stellman & Greene, 2010).

An if/else statement then evaluates arg.keys. This variable holds the keyboard key that was pressed during the mouse click. We compare this variable with values from the Keys enumeration, which originates from the System.Windows.Forms namespace. That namespace is added to the top of the indicator’s source code with a using statement (see full code example below).

When arg.keys equals the Keys.Shift enumerated value (so a mouse click with Shift happened), the trend line’s Locked property is set to true. A click with Control (Keys.Control) on the other hand sets this property to false. This way we can toggle between locking and unlocking the trend line depending on which keyboard key was pressed during the click.

Other examples that combine trend lines with mouse clicks are drawing trend lines with mouse clicks, extending a trend line to the past and future, and change a trend line collection in a dictionary.

Summary

The DrwTrendLine.Create() method draws trend lines and returns a reference to the line made. With this reference, when assigned to an ITrendLineObject variable, we can set a trend line’s Locked property to true (to lock the trend line in place) or false (to unlock the line again). By default, MultiCharts .NET trend lines are unlocked.

Complete MultiCharts .NET indicator example

using System;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;
using System.Windows.Forms;     // For Keys enumeration

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

        private ITrendLineObject lockedLine;

        protected override void CalcBar()
        {
            // Creating the trend line
            if (Bars.LastBarOnChart && lockedLine == null)
            {
                lockedLine = DrwTrendLine.Create(
                    new ChartPoint(Bars.FullSymbolData.Time[55],
                        Bars.FullSymbolData.High[55]),
                    new ChartPoint(Bars.FullSymbolData.Time[5],
                        Bars.FullSymbolData.Low[5]));

                // Change the line's appearance
                lockedLine.Size  = 2;
                lockedLine.Color = Color.DeepSkyBlue;
                lockedLine.Style = ETLStyle.ToolDashed;
            }
        }

        protected override void OnMouseEvent(MouseClickArgs arg)
        {
            if (lockedLine == null)
                return;

            // Toggle the trend line's locked state
            if (arg.keys == Keys.Shift)
            {
                lockedLine.Locked = true;
            }
            else if (arg.keys == Keys.Control)
            {
                lockedLine.Locked = false;
            }
        }
    }
}

References

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

Dorman, S. (2010). Sams Teach Yourself Visual C# 2010 in 24 Hours. Indianapolis, IN: Sams/Pearson Education.

MultiCharts (2014). MultiCharts .NET Programming Guide (version 1.1). Retrieved from http://www.multicharts.com/downloads/MultiCharts.NET-ProgrammingGuide-v1.1.pdf

PowerLanguage .NET Help (n.d.). Retrieved on November 18, 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.